fix live analysis multi-device lock
这个提交包含在:
@@ -549,6 +549,7 @@ export default function LiveCamera() {
|
||||
const broadcastSessionIdRef = useRef<string | null>(null);
|
||||
const viewerPeerRef = useRef<RTCPeerConnection | null>(null);
|
||||
const viewerSessionIdRef = useRef<string | null>(null);
|
||||
const viewerRetryTimerRef = useRef<number>(0);
|
||||
const runtimeIdRef = useRef<number | null>(null);
|
||||
const heartbeatTimerRef = useRef<number>(0);
|
||||
const recorderRef = useRef<MediaRecorder | null>(null);
|
||||
@@ -883,6 +884,10 @@ export default function LiveCamera() {
|
||||
}, []);
|
||||
|
||||
const closeViewerPeer = useCallback(() => {
|
||||
if (viewerRetryTimerRef.current) {
|
||||
window.clearTimeout(viewerRetryTimerRef.current);
|
||||
viewerRetryTimerRef.current = 0;
|
||||
}
|
||||
viewerSessionIdRef.current = null;
|
||||
if (viewerPeerRef.current) {
|
||||
viewerPeerRef.current.ontrack = null;
|
||||
@@ -1026,15 +1031,22 @@ export default function LiveCamera() {
|
||||
await peer.setLocalDescription(offer);
|
||||
await waitForIceGathering(peer);
|
||||
|
||||
const answer = await signalMediaViewerSession(mediaSessionId, {
|
||||
sdp: peer.localDescription?.sdp || "",
|
||||
type: peer.localDescription?.type || "offer",
|
||||
});
|
||||
try {
|
||||
const answer = await signalMediaViewerSession(mediaSessionId, {
|
||||
sdp: peer.localDescription?.sdp || "",
|
||||
type: peer.localDescription?.type || "offer",
|
||||
});
|
||||
|
||||
await peer.setRemoteDescription({
|
||||
type: answer.type as RTCSdpType,
|
||||
sdp: answer.sdp,
|
||||
});
|
||||
await peer.setRemoteDescription({
|
||||
type: answer.type as RTCSdpType,
|
||||
sdp: answer.sdp,
|
||||
});
|
||||
} catch (error) {
|
||||
if (viewerPeerRef.current === peer) {
|
||||
closeViewerPeer();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}, [closeViewerPeer]);
|
||||
|
||||
const stopCamera = useCallback(() => {
|
||||
@@ -1087,11 +1099,27 @@ export default function LiveCamera() {
|
||||
|
||||
void startViewerStream(runtimeSession.mediaSessionId).catch((error: any) => {
|
||||
const message = error?.message || "同步画面连接失败";
|
||||
if (!/409/.test(message)) {
|
||||
setViewerError(message);
|
||||
if (/409|viewer stream not ready/i.test(message)) {
|
||||
setViewerError("持有端正在准备同步画面,正在自动重试...");
|
||||
if (!viewerRetryTimerRef.current) {
|
||||
viewerRetryTimerRef.current = window.setTimeout(() => {
|
||||
viewerRetryTimerRef.current = 0;
|
||||
void runtimeQuery.refetch();
|
||||
}, 1200);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setViewerError(message);
|
||||
});
|
||||
}, [cameraActive, closeViewerPeer, runtimeRole, runtimeSession?.mediaSessionId, startViewerStream]);
|
||||
}, [
|
||||
cameraActive,
|
||||
closeViewerPeer,
|
||||
runtimeQuery.refetch,
|
||||
runtimeQuery.dataUpdatedAt,
|
||||
runtimeRole,
|
||||
runtimeSession?.mediaSessionId,
|
||||
startViewerStream,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
||||
在新工单中引用
屏蔽一个用户