This commit is contained in:
root 2025-07-11 16:50:25 +08:00
parent fa81b06fc4
commit 91a3673219
2 changed files with 314 additions and 10 deletions

View File

@ -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()

View File

@ -40,17 +40,11 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
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<VideoPlayerProps> = ({
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<string>('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<boolean> => {
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<VideoPlayerProps> = ({
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)