'use client'; import React, {useEffect, useRef, useState} from 'react'; import Hls from 'hls.js'; import {PlayIcon, SpeakerWaveIcon, SpeakerXMarkIcon} from '@heroicons/react/24/solid'; import {AltBadge} from './AltBadge'; interface VideoPlayerProps { playlist: string; thumbnail?: string; alt?: string; aspectRatio?: {width: number; height: number}; } export function VideoPlayer({playlist, thumbnail, alt, aspectRatio}: VideoPlayerProps) { const videoRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [isMuted, setIsMuted] = useState(true); const [isHovered, setIsHovered] = useState(false); useEffect(() => { const video = videoRef.current; if (!video) return; let hls: Hls | null = null; if (Hls.isSupported()) { hls = new Hls({ capLevelToPlayerSize: true, }); hls.loadSource(playlist); hls.attachMedia(video); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = playlist; } return () => { if (hls) { hls.destroy(); } }; }, [playlist]); const togglePlay = (e: React.MouseEvent) => { e.stopPropagation(); const video = videoRef.current; if (!video) return; if (isPlaying) { video.pause(); } else { video.play().catch(console.error); } setIsPlaying(!isPlaying); }; const toggleMute = (e: React.MouseEvent) => { e.stopPropagation(); const video = videoRef.current; if (!video) return; video.muted = !isMuted; setIsMuted(!isMuted); }; const ratio = aspectRatio ? aspectRatio.height / aspectRatio.width : 9 / 16; const paddingBottom = `${ratio * 100}%`; return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} aria-label={alt || 'Video player'} role="application" >
); }