/** * VideoPlayer Component * * A reusable video player component with full controls and customization options. * Uses the useVideoPlayer hook for state management and provides a clean interface. */ import React, { forwardRef, useState, useEffect } from 'react'; import { useVideoPlayer } from '../hooks/useVideoPlayer'; import { videoApiService } from '../services/videoApi'; import { type VideoPlayerProps } from '../types'; import { formatDuration, getVideoMimeType } from '../utils/videoUtils'; export const VideoPlayer = forwardRef(({ fileId, autoPlay = false, controls = true, width = '100%', height = 'auto', className = '', onPlay, onPause, onEnded, onError, }, forwardedRef) => { const [videoInfo, setVideoInfo] = useState<{ filename?: string; mimeType: string }>({ mimeType: 'video/mp4' // Default to MP4 }); const { state, actions, ref } = useVideoPlayer({ autoPlay, onPlay, onPause, onEnded, onError, }); // Combine refs React.useImperativeHandle(forwardedRef, () => ref.current!, [ref]); const streamingUrl = videoApiService.getStreamingUrl(fileId); // Fetch video info to determine MIME type useEffect(() => { const fetchVideoInfo = async () => { try { const info = await videoApiService.getVideoInfo(fileId); if (info.file_id) { // Extract filename from file_id or use a default pattern const filename = info.file_id.includes('.') ? info.file_id : `${info.file_id}.mp4`; const mimeType = getVideoMimeType(filename); setVideoInfo({ filename, mimeType }); } } catch (error) { console.warn('Could not fetch video info, using default MIME type:', error); // Keep default MP4 MIME type } }; fetchVideoInfo(); }, [fileId]); const handleSeek = (e: React.MouseEvent) => { if (!ref.current) return; const rect = e.currentTarget.getBoundingClientRect(); const clickX = e.clientX - rect.left; const percentage = clickX / rect.width; const newTime = percentage * state.duration; actions.seek(newTime); }; const handleVolumeChange = (e: React.ChangeEvent) => { actions.setVolume(parseFloat(e.target.value)); }; return (
{/* Video Element */} {/* Loading Overlay */} {state.isLoading && (
Loading...
)} {/* Error Overlay */} {state.error && (
Playback Error
{state.error}
)} {/* Custom Controls */} {controls && (
{/* Progress Bar */}
0 ? (state.currentTime / state.duration) * 100 : 0}%` }} />
{/* Control Bar */}
{/* Left Controls */}
{/* Play/Pause Button */} {/* Skip Backward */} {/* Skip Forward */} {/* Time Display */}
{formatDuration(state.currentTime)} / {formatDuration(state.duration)}
{/* Right Controls */}
{/* Volume Control */}
{/* Fullscreen Button */}
)}
); }); VideoPlayer.displayName = 'VideoPlayer';