'use client'; import { useEffect, useRef, useState } from 'react'; import Hls from 'hls.js'; interface HLSPlayerProps { src: string; autoPlay?: boolean; loop?: boolean; muted?: boolean; } export default function HLSPlayer({ src, autoPlay = true, loop = true, muted = true, }: HLSPlayerProps) { const videoRef = useRef(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const hlsRef = useRef(null); useEffect(() => { const video = videoRef.current; if (!video) return; let mounted = true; const initializePlayer = () => { if (Hls.isSupported()) { const hls = new Hls({ enableWorker: true, lowLatencyMode: true, }); hlsRef.current = hls; hls.loadSource(src); hls.attachMedia(video); hls.on(Hls.Events.MANIFEST_PARSED, () => { if (mounted) { setIsLoading(false); if (autoPlay) { video.play().catch((err) => { console.error('Autoplay failed:', err); }); } } }); hls.on(Hls.Events.ERROR, (event, data) => { console.error('HLS error:', data); if (data.fatal && mounted) { switch (data.type) { case Hls.ErrorTypes.NETWORK_ERROR: setError('Network error - attempting to recover'); hls.startLoad(); break; case Hls.ErrorTypes.MEDIA_ERROR: setError('Media error - attempting to recover'); hls.recoverMediaError(); break; default: setError('Fatal error - cannot recover'); hls.destroy(); break; } } }); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { // For Safari native HLS support video.src = src; const handleLoadedMetadata = () => { if (mounted) { setIsLoading(false); if (autoPlay) { video.play().catch((err) => { console.error('Autoplay failed:', err); }); } } }; video.addEventListener('loadedmetadata', handleLoadedMetadata); return () => { video.removeEventListener('loadedmetadata', handleLoadedMetadata); }; } else if (mounted) { setError('HLS is not supported in this browser'); setIsLoading(false); } }; initializePlayer(); return () => { mounted = false; if (hlsRef.current) { hlsRef.current.destroy(); hlsRef.current = null; } }; }, [src, autoPlay]); return (
); }