fix live analysis multi-device lock

这个提交包含在:
cryptocommuniums-afk
2026-03-16 18:05:58 +08:00
父节点 13e59b8e8a
当前提交 f9db6ef590
修改 7 个文件,包含 221 行新增28 行删除

查看文件

@@ -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 () => {