From 5274ca54602c85611a3e4aacc38f1a6043089bdd Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Tue, 14 Apr 2026 09:45:16 -0400 Subject: [PATCH] feat: redesign VideoPreview with dark broadcast monitor frame --- frontend/src/components/VideoPreview.tsx | 78 +++++++++++++++--------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/frontend/src/components/VideoPreview.tsx b/frontend/src/components/VideoPreview.tsx index 0d843f1..971ce43 100644 --- a/frontend/src/components/VideoPreview.tsx +++ b/frontend/src/components/VideoPreview.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import Hls from 'hls.js'; interface VideoPreviewProps { @@ -8,60 +8,82 @@ interface VideoPreviewProps { export function VideoPreview({ portIndex }: VideoPreviewProps) { const videoRef = useRef(null); const hlsRef = useRef(null); + const [hasSignal, setHasSignal] = useState(false); useEffect(() => { const src = `/hls/port_${portIndex}.m3u8`; + setHasSignal(false); - if (!videoRef.current) { - return; - } + if (!videoRef.current) return; if (Hls.isSupported()) { - const hls = new Hls({ - enableWorker: true, - lowLatencyMode: true, - }); - + const hls = new Hls({ enableWorker: true, lowLatencyMode: true }); hlsRef.current = hls; hls.loadSource(src); hls.attachMedia(videoRef.current); - hls.on(Hls.Events.MANIFEST_PARSED, () => { - videoRef.current?.play().catch((err) => { - console.error('Failed to autoplay video:', err); - }); + setHasSignal(true); + videoRef.current?.play().catch(console.error); }); - - hls.on(Hls.Events.ERROR, (event, data) => { - console.error('HLS.js error:', data); + hls.on(Hls.Events.ERROR, (_event, data) => { + if (data.fatal) setHasSignal(false); }); } else if (videoRef.current.canPlayType('application/vnd.apple.mpegurl')) { - // Safari native HLS support videoRef.current.src = src; - videoRef.current.play().catch((err) => { - console.error('Failed to autoplay video:', err); - }); - } else { - console.error('HLS streaming is not supported in this browser'); + videoRef.current.addEventListener('canplay', () => setHasSignal(true), { once: true }); + videoRef.current.play().catch(console.error); } return () => { - if (hlsRef.current) { - hlsRef.current.destroy(); - hlsRef.current = null; - } + hlsRef.current?.destroy(); + hlsRef.current = null; }; }, [portIndex]); return ( -
+