fix: WebSocket connection leaked on WebRTC player cleanup

The connect() function creates a WebSocket but never stores the
reference. The useEffect cleanup only closes the RTCPeerConnection
via pcRef, leaving the WebSocket open.

Each time the component re-renders with changed deps (camera switch,
playback toggle, microphone toggle), a new WebSocket is created
without closing the previous one. This leaks connections until the
browser garbage-collects them or the server times out.

Store the WebSocket in a ref and close it in the cleanup function.
This commit is contained in:
ryzendigo 2026-03-16 14:42:46 +08:00
parent 5a214eb0d1
commit 3690b62e62

View File

@ -52,6 +52,7 @@ export default function WebRtcPlayer({
// camera states
const pcRef = useRef<RTCPeerConnection | undefined>(undefined);
const wsRef = useRef<WebSocket | null>(null);
const videoRef = useRef<HTMLVideoElement | null>(null);
const [bufferTimeout, setBufferTimeout] = useState<NodeJS.Timeout>();
const videoLoadTimeoutRef = useRef<NodeJS.Timeout>(undefined);
@ -129,7 +130,8 @@ export default function WebRtcPlayer({
}
pcRef.current = await aPc;
const ws = new WebSocket(wsURL);
wsRef.current = new WebSocket(wsURL);
const ws = wsRef.current;
ws.addEventListener("open", () => {
pcRef.current?.addEventListener("icecandidate", (ev) => {
@ -183,6 +185,10 @@ export default function WebRtcPlayer({
connect(aPc);
return () => {
if (wsRef.current) {
wsRef.current.close();
wsRef.current = null;
}
if (pcRef.current) {
pcRef.current.close();
pcRef.current = undefined;