diff --git a/k-tv-frontend/app/(main)/tv/components/video-player.tsx b/k-tv-frontend/app/(main)/tv/components/video-player.tsx index 537e2b8..89b2791 100644 --- a/k-tv-frontend/app/(main)/tv/components/video-player.tsx +++ b/k-tv-frontend/app/(main)/tv/components/video-player.tsx @@ -18,6 +18,8 @@ interface VideoPlayerProps { subtitleTrack?: number; onStreamError?: () => void; onSubtitleTracksChange?: (tracks: SubtitleTrack[]) => void; + /** Called when the browser blocks autoplay and user interaction is required. */ + onNeedsInteraction?: () => void; } const VideoPlayer = forwardRef( @@ -30,6 +32,7 @@ const VideoPlayer = forwardRef( subtitleTrack = -1, onStreamError, onSubtitleTracksChange, + onNeedsInteraction, }, ref, ) => { @@ -69,7 +72,7 @@ const VideoPlayer = forwardRef( hlsRef.current = hls; hls.on(Hls.Events.MANIFEST_PARSED, () => { - video.play().catch(() => {}); + video.play().catch(() => onNeedsInteraction?.()); }); hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, (_event, data) => { @@ -95,7 +98,7 @@ const VideoPlayer = forwardRef( "loadedmetadata", () => { if (initialOffset > 0) video.currentTime = initialOffset; - video.play().catch(() => {}); + video.play().catch(() => onNeedsInteraction?.()); }, { once: true }, ); diff --git a/k-tv-frontend/app/(main)/tv/page.tsx b/k-tv-frontend/app/(main)/tv/page.tsx index cbdf8a0..ecfc205 100644 --- a/k-tv-frontend/app/(main)/tv/page.tsx +++ b/k-tv-frontend/app/(main)/tv/page.tsx @@ -56,6 +56,9 @@ export default function TvPage() { // Stream error recovery const [streamError, setStreamError] = useState(false); + // Autoplay blocked by browser — cleared on first interaction via resetIdle + const [needsInteraction, setNeedsInteraction] = useState(false); + // Subtitles const [subtitleTracks, setSubtitleTracks] = useState([]); const [activeSubtitleTrack, setActiveSubtitleTrack] = useState(-1); @@ -141,6 +144,7 @@ export default function TvPage() { const resetIdle = useCallback(() => { setShowOverlays(true); + setNeedsInteraction(false); if (idleTimer.current) clearTimeout(idleTimer.current); idleTimer.current = setTimeout(() => { setShowOverlays(false); @@ -325,6 +329,7 @@ export default function TvPage() { subtitleTrack={activeSubtitleTrack} onSubtitleTracksChange={setSubtitleTracks} onStreamError={handleStreamError} + onNeedsInteraction={() => setNeedsInteraction(true)} /> ); } @@ -348,6 +353,15 @@ export default function TvPage() { {/* ── Base layer ─────────────────────────────────────────────── */}
{renderBase()}
+ {/* ── Autoplay blocked prompt ─────────────────────────────────── */} + {needsInteraction && ( +
+
+

Click or move the mouse to play

+
+
+ )} + {/* ── Overlays — only when channels available ─────────────────── */} {channel && ( <>