import React, { useState, useRef, useEffect } from 'react' import { Play, Pause, Volume2, VolumeX, Maximize2, X, AlertCircle } from 'lucide-react' import { convertFileSrc, invoke } from '@tauri-apps/api/core' interface VideoPlayerProps { videoPath: string isOpen: boolean onClose: () => void title?: string } const VideoPlayer: React.FC = ({ videoPath, isOpen, onClose, title = '视频播放' }) => { const videoRef = useRef(null) const [isPlaying, setIsPlaying] = useState(false) const [isMuted, setIsMuted] = useState(false) const [currentTime, setCurrentTime] = useState(0) const [duration, setDuration] = useState(0) const [volume, setVolume] = useState(1) const [isFullscreen, setIsFullscreen] = useState(false) const [videoSrc, setVideoSrc] = useState('') const [fileExists, setFileExists] = useState(true) const [errorMessage, setErrorMessage] = useState('') const [loadingMethod, setLoadingMethod] = useState<'convertFileSrc' | 'dataUrl'>('convertFileSrc') useEffect(() => { const checkFileAndSetSrc = async () => { if (isOpen && videoPath) { try { // 首先检查文件是否存在 const exists = await invoke('check_file_exists', { filePath: videoPath }) console.log('File exists check:', { videoPath, exists }) if (!exists) { setFileExists(false) setErrorMessage(`文件不存在: ${videoPath}`) return } setFileExists(true) setErrorMessage('') // 尝试多种方法加载视频 await tryLoadVideo(videoPath) } catch (error) { console.error('Error checking file:', error) setFileExists(false) setErrorMessage(`文件检查失败: ${error}`) } } } checkFileAndSetSrc() }, [isOpen, videoPath]) // 尝试多种方法加载视频 const tryLoadVideo = async (path: string) => { // 根据路径类型选择不同的加载策略 const videoPath = path.split('\\').filter(it => it.length > 0).join('/') console.log(`try load video videoPath`, {videoPath, path}) const src = convertFileSrc(videoPath) console.log(`try load video src`, src) setVideoSrc(src) setLoadingMethod('convertFileSrc') return } useEffect(() => { const video = videoRef.current if (!video) return const handleTimeUpdate = () => setCurrentTime(video.currentTime) const handleDurationChange = () => setDuration(video.duration) const handleEnded = () => setIsPlaying(false) const handlePlay = () => setIsPlaying(true) const handlePause = () => setIsPlaying(false) video.addEventListener('timeupdate', handleTimeUpdate) video.addEventListener('durationchange', handleDurationChange) video.addEventListener('ended', handleEnded) video.addEventListener('play', handlePlay) video.addEventListener('pause', handlePause) return () => { video.removeEventListener('timeupdate', handleTimeUpdate) video.removeEventListener('durationchange', handleDurationChange) video.removeEventListener('ended', handleEnded) video.removeEventListener('play', handlePlay) video.removeEventListener('pause', handlePause) } }, [videoSrc]) const handlePlayPause = () => { const video = videoRef.current if (!video) return if (isPlaying) { video.pause() } else { video.play().catch(err => { console.error('Failed to play video:', err) }) } } const handleSeek = (e: React.ChangeEvent) => { const video = videoRef.current if (!video) return const newTime = parseFloat(e.target.value) video.currentTime = newTime setCurrentTime(newTime) } const handleVolumeChange = (e: React.ChangeEvent) => { const video = videoRef.current if (!video) return const newVolume = parseFloat(e.target.value) video.volume = newVolume setVolume(newVolume) setIsMuted(newVolume === 0) } const handleMuteToggle = () => { const video = videoRef.current if (!video) return if (isMuted) { video.volume = volume setIsMuted(false) } else { video.volume = 0 setIsMuted(true) } } const handleFullscreen = () => { const video = videoRef.current if (!video) return if (!isFullscreen) { if (video.requestFullscreen) { video.requestFullscreen() setIsFullscreen(true) } } else { if (document.exitFullscreen) { document.exitFullscreen() setIsFullscreen(false) } } } const formatTime = (time: number) => { const minutes = Math.floor(time / 60) const seconds = Math.floor(time % 60) return `${minutes}:${seconds.toString().padStart(2, '0')}` } if (!isOpen) return null return (
{/* 关闭按钮 */} {/* 标题 */}

{title}

{/* 视频容器 */}
{!fileExists || errorMessage ? ( /* 错误显示 */

视频加载失败

{errorMessage}

文件路径: {videoPath}

当前加载方法: {loadingMethod}

{loadingMethod === 'convertFileSrc' && ( )}
) : (
) } export default VideoPlayer