From aef0cb3e8992ce7fe3b799c71705db362622d455 Mon Sep 17 00:00:00 2001 From: Natalie Bridgers Date: Tue, 23 Jun 2026 17:46:28 -0500 Subject: [PATCH] fix(player): drop transportKey double-mount, silence hls debug noise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Toggling HLS <-> WebRTC remounted the backend twice: once via the conditional inside PlayerBackend (HLSPlayer vs WebRTCPlayer), then again because the useWebRTC effect bumped transportKey. The second remount tore down the just-negotiated peer connection and started a new one, so every toggle raced itself. Drop the key bump; the conditional already handles the swap. Also strip the hls-player debug noise: 13 console.logs, two no-op listener registrations ('already handled above'), and the Math.random < 0.1 video-state sampling. hls.js debug now only fires in dev. Kept the play() rejection warn — it's the only signal when the browser blocks autoplay on a fresh load. --- js/web/src/components/player/hls-player.tsx | 67 +-------------------- js/web/src/components/player/player.tsx | 23 ++----- 2 files changed, 8 insertions(+), 82 deletions(-) diff --git a/js/web/src/components/player/hls-player.tsx b/js/web/src/components/player/hls-player.tsx index f8734617..a770e0ea 100644 --- a/js/web/src/components/player/hls-player.tsx +++ b/js/web/src/components/player/hls-player.tsx @@ -68,20 +68,11 @@ export function HLSPlayer({ ); useEffect(() => { - console.log("[hls-player] useEffect firing", { - active, - src, - hasVideo: !!videoRef.current, - }); if (!active) return; const video = videoRef.current; - if (!video) { - console.log("[hls-player] no video element, bailing"); - return; - } + if (!video) return; if (Hls.isSupported()) { - console.log("[hls-player] hls.js supported, creating instance"); const hls = new Hls({ maxAudioFramesDrift: 20, lowLatencyMode: true, @@ -90,15 +81,11 @@ export function HLSPlayer({ maxLiveSyncPlaybackRate: 1.5, backBufferLength: 90, enableWorker: true, - debug: true, + debug: import.meta.env.DEV, }); hlsRef.current = hls; hls.on(Hls.Events.MANIFEST_PARSED, (_e, data) => { - console.log("[hls-player] MANIFEST_PARSED", { - levels: hls.levels.length, - firstLevel: data.firstLevel, - }); onQualitiesChange?.(buildQualities(hls.levels)); // Restore persisted quality preference. const saved = readQualityPreference(); @@ -111,17 +98,10 @@ export function HLSPlayer({ }); hls.on(Hls.Events.LEVEL_SWITCHED, (_event, data) => { - console.log("[hls-player] LEVEL_SWITCHED", data.level); onCurrentQualityChange?.(data.level); }); hls.on(Hls.Events.ERROR, (_event, data) => { - console.log("[hls-player] ERROR", { - type: data.type, - details: data.details, - fatal: data.fatal, - response: data.response, - }); if (!data.fatal) return; const status = (data.response as Response | undefined)?.status; if (status === 404) { @@ -143,41 +123,14 @@ export function HLSPlayer({ } }); - // Log all non-error events for debugging - hls.on(Hls.Events.FRAG_LOADED, (_e, data) => { - console.log("[hls-player] FRAG_LOADED", { - level: data.frag?.level, - sn: data.frag?.sn, - duration: data.frag?.duration, - }); - }); - hls.on(Hls.Events.ERROR, () => {}); // already handled above - hls.on(Hls.Events.BUFFER_APPENDED, (_e, data) => { - console.log("[hls-player] BUFFER_APPENDED", { type: data.type }); - }); - hls.on(Hls.Events.MANIFEST_PARSED, () => {}); // already handled above - - console.log("[hls-player] loading source:", src); hls.loadSource(src); try { - console.log("[hls-player] attaching media", { - readyState: video.readyState, - src: video.src, - currentSrc: video.currentSrc, - }); hls.attachMedia(video); - console.log("[hls-player] attachMedia done", { - readyState: video.readyState, - networkState: video.networkState, - error: video.error, - }); - } catch (err) { - console.log("[hls-player] attachMedia failed", err); + } catch { hls.stopLoad(); } return () => { - console.log("[hls-player] cleanup — destroying hls"); hls.destroy(); hlsRef.current = null; // hls.js destroy() does not release the video element's source. @@ -185,7 +138,6 @@ export function HLSPlayer({ video.srcObject = null; }; } else if (video.canPlayType("application/vnd.apple.mpegurl")) { - console.log("[hls-player] native HLS (Safari)"); video.src = src; const onCanPlay = () => { video.play().catch(() => {}); @@ -199,7 +151,6 @@ export function HLSPlayer({ video.load(); }; } else { - console.log("[hls-player] HLS not supported"); onError?.("Your browser doesn't support HLS playback."); } }, [ @@ -222,18 +173,6 @@ export function HLSPlayer({ const id = setInterval(() => { const video = videoRef.current; if (!video) return; - if (Math.random() < 0.1) { - console.log("[hls-player] video state", { - readyState: video.readyState, - paused: video.paused, - ended: video.ended, - currentTime: video.currentTime, - videoWidth: video.videoWidth, - videoHeight: video.videoHeight, - src: video.src?.substring(0, 80), - error: video.error?.message, - }); - } const hls = hlsRef.current; const playback = ( video as HTMLVideoElement & { diff --git a/js/web/src/components/player/player.tsx b/js/web/src/components/player/player.tsx index aaf4c1f5..9ecd9c36 100644 --- a/js/web/src/components/player/player.tsx +++ b/js/web/src/components/player/player.tsx @@ -194,28 +194,16 @@ export function Player({ setStats(null); }, [src, active]); - // When the user toggles transport (HLS <-> WebRTC) we want the source - // to re-load, so clear quality + playback state and force the backend - // to remount via a changing key. - const [transportKey, setTransportKey] = useState(0); + // When the user toggles transport (HLS <-> WebRTC) the backend child + // inside is a different component type, so React + // unmounts the old one and mounts the new one automatically. We just + // need to reset the chrome's per-transport state. useEffect(() => { - console.log("[player] useWebRTC changed", { useWebRTC, transportKey }); setQualities([]); setCurrentQuality(-1); setStats(null); - setTransportKey((k) => k + 1); }, [useWebRTC]); - useEffect(() => { - console.log("[player] render", { - src, - active, - useWebRTC, - transportKey, - error, - }); - }); - // Mirror the video element's state into React. useEffect(() => { const video = videoRef.current; @@ -319,7 +307,6 @@ export function Player({ {active && ( void; ref: RefObject; }) { - let [sona, resetSona] = useSonare(); + const [sona, resetSona] = useSonare(); useEffect(() => { resetSona(); }, [src]); -- 2.51.2