From 91a367321979a8cca46e5f4f820f23b55c257bc0 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 11 Jul 2025 16:50:25 +0800 Subject: [PATCH] fix --- scripts/test_video_loading.py | 211 +++++++++++++++++++++++++++++++++ src/components/VideoPlayer.tsx | 113 ++++++++++++++++-- 2 files changed, 314 insertions(+), 10 deletions(-) create mode 100644 scripts/test_video_loading.py diff --git a/scripts/test_video_loading.py b/scripts/test_video_loading.py new file mode 100644 index 0000000..770c13b --- /dev/null +++ b/scripts/test_video_loading.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +""" +测试视频文件加载的脚本 +检查视频文件的存在性、可访问性和格式 +""" + +import sys +import os +import json +from pathlib import Path + +# 添加项目根目录到Python路径 +project_root = Path(__file__).parent.parent +sys.path.insert(0, str(project_root)) + +from python_core.services.media_manager import MediaManager +from python_core.config import settings + +def check_video_files(): + """检查视频文件的存在和可访问性""" + print("🎬 检查视频文件...") + + # 获取所有视频片段 + media_manager = MediaManager() + segments = media_manager.get_all_segments() + + if not segments: + print("❌ 没有找到任何视频片段") + return + + print(f"📊 找到 {len(segments)} 个视频片段") + + # 检查每个视频文件 + for i, segment in enumerate(segments[:10]): # 只检查前10个 + file_path = segment.get('file_path', '') + filename = segment.get('filename', 'Unknown') + + print(f"\n{i+1}. {filename}") + print(f" 路径: {file_path}") + + if not file_path: + print(" ❌ 文件路径为空") + continue + + # 检查文件是否存在 + path_obj = Path(file_path) + if path_obj.exists(): + print(" ✅ 文件存在") + + # 检查文件大小 + size = path_obj.stat().st_size + print(f" 📏 文件大小: {size:,} 字节 ({size/1024/1024:.2f} MB)") + + # 检查文件权限 + readable = os.access(file_path, os.R_OK) + print(f" 🔓 可读权限: {'是' if readable else '否'}") + + # 检查文件扩展名 + extension = path_obj.suffix.lower() + supported_formats = ['.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm', '.m4v'] + is_supported = extension in supported_formats + print(f" 🎞️ 文件格式: {extension} ({'支持' if is_supported else '不支持'})") + + else: + print(" ❌ 文件不存在") + + # 检查父目录是否存在 + parent_dir = path_obj.parent + if parent_dir.exists(): + print(f" 📁 父目录存在: {parent_dir}") + # 列出父目录中的文件 + try: + files = list(parent_dir.glob("*")) + print(f" 📋 父目录包含 {len(files)} 个文件") + if files: + print(" 📄 文件列表:") + for f in files[:5]: # 只显示前5个 + print(f" - {f.name}") + except Exception as e: + print(f" ❌ 无法读取父目录: {e}") + else: + print(f" ❌ 父目录不存在: {parent_dir}") + +def check_storage_directories(): + """检查存储目录结构""" + print("\n📁 检查存储目录结构...") + + # 检查主要目录 + directories = [ + settings.temp_dir, + settings.temp_dir / "cache", + settings.temp_dir / "video_segments", + settings.temp_dir / "original_videos", + settings.temp_dir / "thumbnails" + ] + + for directory in directories: + print(f"\n📂 {directory}") + if directory.exists(): + print(" ✅ 目录存在") + + # 统计文件数量 + try: + files = list(directory.glob("*")) + video_files = [f for f in files if f.suffix.lower() in ['.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm', '.m4v']] + + print(f" 📊 总文件数: {len(files)}") + print(f" 🎬 视频文件数: {len(video_files)}") + + if video_files: + print(" 🎞️ 视频文件示例:") + for vf in video_files[:3]: + size = vf.stat().st_size + print(f" - {vf.name} ({size/1024/1024:.2f} MB)") + + except Exception as e: + print(f" ❌ 无法读取目录内容: {e}") + else: + print(" ❌ 目录不存在") + +def test_video_info_extraction(): + """测试视频信息提取""" + print("\n🔍 测试视频信息提取...") + + media_manager = MediaManager() + segments = media_manager.get_all_segments() + + if not segments: + print("❌ 没有视频片段可测试") + return + + # 测试第一个存在的视频文件 + for segment in segments[:5]: + file_path = segment.get('file_path', '') + if file_path and Path(file_path).exists(): + print(f"\n🎬 测试文件: {segment.get('filename', 'Unknown')}") + print(f" 路径: {file_path}") + + try: + # 尝试获取视频信息 + video_info = media_manager._get_video_info(file_path) + print(f" ✅ 视频信息提取成功:") + print(f" 时长: {video_info.get('duration', 'N/A')} 秒") + print(f" 分辨率: {video_info.get('width', 'N/A')}x{video_info.get('height', 'N/A')}") + print(f" 帧率: {video_info.get('fps', 'N/A')} fps") + print(f" 编码: {video_info.get('codec', 'N/A')}") + break + + except Exception as e: + print(f" ❌ 视频信息提取失败: {e}") + continue + else: + print("❌ 没有找到可用的视频文件进行测试") + +def suggest_fixes(): + """建议修复方案""" + print("\n🔧 修复建议:") + + print("\n1. 如果视频文件不存在:") + print(" - 检查导入过程是否正确完成") + print(" - 确认文件没有被意外删除") + print(" - 重新导入视频素材") + + print("\n2. 如果文件存在但无法播放:") + print(" - 检查文件格式是否支持") + print(" - 验证文件是否损坏") + print(" - 尝试使用其他播放器测试文件") + + print("\n3. 如果路径问题:") + print(" - 检查路径中是否包含特殊字符") + print(" - 确认路径分隔符正确(Windows vs Unix)") + print(" - 验证文件权限设置") + + print("\n4. 浏览器播放问题:") + print(" - 检查Tauri配置中的asset protocol设置") + print(" - 验证CSP策略是否允许视频播放") + print(" - 尝试不同的视频加载方法") + + print("\n5. 调试步骤:") + print(" - 启用浏览器开发者工具") + print(" - 查看网络请求和错误信息") + print(" - 检查控制台日志") + print(" - 测试convertFileSrc和data URL方法") + +def main(): + """主函数""" + print("🎬 视频加载问题诊断") + print("=" * 50) + + try: + # 1. 检查视频文件 + check_video_files() + + # 2. 检查存储目录 + check_storage_directories() + + # 3. 测试视频信息提取 + test_video_info_extraction() + + # 4. 提供修复建议 + suggest_fixes() + + print("\n✅ 诊断完成!") + + except Exception as e: + print(f"❌ 诊断过程中出现错误: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + main() diff --git a/src/components/VideoPlayer.tsx b/src/components/VideoPlayer.tsx index 134da03..fd80875 100644 --- a/src/components/VideoPlayer.tsx +++ b/src/components/VideoPlayer.tsx @@ -40,17 +40,11 @@ const VideoPlayer: React.FC = ({ return } - // 文件存在,转换为安全URL - const src = convertFileSrc(videoPath) - console.log('Video path conversion:', { - originalPath: videoPath, - convertedSrc: src, - fileExists: exists - }) - setFileExists(true) setErrorMessage('') - setVideoSrc(src) + + // 尝试多种方法加载视频 + await tryLoadVideo(videoPath) } catch (error) { console.error('Error checking file:', error) setFileExists(false) @@ -62,6 +56,98 @@ const VideoPlayer: React.FC = ({ checkFileAndSetSrc() }, [isOpen, videoPath]) + // 尝试多种方法加载视频 + const tryLoadVideo = async (path: string) => { + const methods = [ + { + name: 'convertFileSrc', + load: () => { + const src = convertFileSrc(path) + console.log('Trying convertFileSrc:', { originalPath: path, convertedSrc: src }) + return src + } + }, + { + name: 'dataUrl', + load: async () => { + console.log('Trying data URL method for:', path) + const dataUrl = await invoke('read_video_as_data_url', { filePath: path }) + console.log('Data URL method successful, length:', dataUrl.length) + return dataUrl + } + } + ] + + for (const method of methods) { + try { + console.log(`Attempting video load with method: ${method.name}`) + const src = await method.load() + + // 测试视频源是否可用 + const testResult = await testVideoSource(src, method.name) + if (testResult) { + setVideoSrc(src) + return + } + } catch (error) { + console.warn(`Method ${method.name} failed:`, error) + continue + } + } + + // 所有方法都失败了 + setErrorMessage('无法加载视频:所有加载方法都失败了') + } + + // 测试视频源是否可用 + const testVideoSource = (src: string, methodName: string): Promise => { + return new Promise((resolve) => { + const testVideo = document.createElement('video') + + const cleanup = () => { + testVideo.removeEventListener('canplay', onCanPlay) + testVideo.removeEventListener('error', onError) + testVideo.removeEventListener('loadstart', onLoadStart) + } + + const onCanPlay = () => { + console.log(`${methodName} method successful - video can play`) + cleanup() + resolve(true) + } + + const onError = (e: any) => { + console.log(`${methodName} method failed - video error:`, { + error: e, + networkState: testVideo.networkState, + readyState: testVideo.readyState + }) + cleanup() + resolve(false) + } + + const onLoadStart = () => { + console.log(`${methodName} method - load started`) + } + + testVideo.addEventListener('canplay', onCanPlay) + testVideo.addEventListener('error', onError) + testVideo.addEventListener('loadstart', onLoadStart) + + // 设置超时 + setTimeout(() => { + if (testVideo.readyState < 2) { // HAVE_CURRENT_DATA + console.log(`${methodName} method timeout`) + cleanup() + resolve(false) + } + }, 5000) + + testVideo.src = src + testVideo.load() + }) + } + useEffect(() => { const video = videoRef.current if (!video) return @@ -200,7 +286,14 @@ const VideoPlayer: React.FC = ({ networkState: e.currentTarget.networkState, readyState: e.currentTarget.readyState }) - setErrorMessage('视频加载失败,请检查文件格式和路径') + // 如果当前视频源失败,尝试重新加载 + if (videoPath) { + console.log('Video error detected, attempting reload...') + tryLoadVideo(videoPath).catch(err => { + console.error('Reload failed:', err) + setErrorMessage('视频加载失败:文件可能损坏或格式不支持') + }) + } }} onLoadStart={() => { console.log('Video load started:', videoSrc)