use tvai_sdk::TvaiSdk; use std::fs; fn main() -> Result<(), Box> { println!("🎬 测试 4倍慢动作模板转换为 FFmpeg 命令"); println!("==========================================\n"); // 创建 SDK 实例 let sdk = TvaiSdk::new(); // 读取模板文件 let template_path = "template/4x slow motion.json"; println!("📁 读取模板文件: {}", template_path); let template_content = fs::read_to_string(template_path) .map_err(|e| format!("无法读取模板文件: {}", e))?; // 解析模板 let template: tvai_sdk::Template = serde_json::from_str(&template_content) .map_err(|e| format!("解析模板失败: {}", e))?; println!("✓ 模板解析成功"); println!(" 名称: {}", template.name); println!(" 描述: {}", template.description); println!(" 作者: {}", template.author); println!(); // 分析模板设置 println!("🔍 模板设置分析:"); let settings = &template.settings; println!(" 增强 (enhance): {}", if settings.enhance.active { "启用" } else { "禁用" }); if settings.enhance.active { println!(" 模型: {}", settings.enhance.model); } println!(" 慢动作 (slowmo): {}", if settings.slow_motion.active { "启用" } else { "禁用" }); if settings.slow_motion.active { println!(" 模型: {}", settings.slow_motion.model); println!(" 倍数: {}x", settings.slow_motion.factor); println!(" 重复帧检测: {}", settings.slow_motion.duplicate); println!(" 重复帧阈值: {}", settings.slow_motion.duplicate_threshold); } println!(" 稳定化 (stabilize): {}", if settings.stabilize.active { "启用" } else { "禁用" }); println!(" 运动模糊 (motionblur): {}", if settings.motion_blur.active { "启用" } else { "禁用" }); println!(" 颗粒 (grain): {}", if settings.grain.active { "启用" } else { "禁用" }); println!(" 输出设置 (output): {}", if settings.output.active { "启用" } else { "禁用" }); if settings.output.active { println!(" 尺寸方法: {}", settings.output.out_size_method); println!(" 输出FPS: {}", settings.output.out_fps); println!(" 裁剪适应: {}", settings.output.crop_to_fit); } println!(); // 验证模板 println!("✅ 验证模板:"); match sdk.ffmpeg_generator.validate_template(&template) { Ok(_) => println!(" ✓ 模板验证通过"), Err(e) => { println!(" ✗ 模板验证失败: {}", e); return Err(e.into()); } } println!(); // 生成 FFmpeg 命令 println!("⚙️ 生成 FFmpeg 命令:"); let input_file = "input_30fps.mp4"; let output_file = "output_4x_slowmo.mp4"; let ffmpeg_command = sdk.generate_ffmpeg_command(&template, input_file, output_file)?; println!(" 输入文件: {}", input_file); println!(" 输出文件: {}", output_file); println!(); println!("📋 生成的 FFmpeg 命令:"); println!("{}", ffmpeg_command); println!(); // 分析生成的命令 println!("🔍 命令分析:"); analyze_ffmpeg_command(&ffmpeg_command); println!(); // 检查命令是否有问题 println!("🔧 命令检查:"); check_ffmpeg_command(&ffmpeg_command, &template); println!(); // 测试不同的输出格式 println!("🎯 测试不同输出格式:"); let test_outputs = [ ("output_4x_slowmo.mp4", "MP4"), ("output_4x_slowmo.mov", "MOV"), ("output_4x_slowmo.mkv", "MKV"), ]; for (output, format) in &test_outputs { match sdk.generate_ffmpeg_command(&template, input_file, output) { Ok(cmd) => { println!(" ✓ {} 格式: 命令生成成功", format); // 检查是否包含适当的编码器 if cmd.contains("-c:v") { println!(" 包含视频编码器设置"); } if cmd.contains("-c:a") { println!(" 包含音频编码器设置"); } }, Err(e) => println!(" ✗ {} 格式: {}", format, e), } } println!(); // 测试自动编码器选择 println!("🚀 测试自动编码器选择:"); let platforms = [ ("windows", Some("nvidia"), "Windows + NVIDIA"), ("osx", Some("appleIntel"), "macOS + Intel"), ("linux", None, "Linux 软件编码"), ]; for (os, gpu, desc) in &platforms { match sdk.ffmpeg_generator.generate_with_auto_encoder(&template, input_file, output_file, os, *gpu) { Ok(_) => println!(" ✓ {}: 自动编码器选择成功", desc), Err(e) => println!(" ✗ {}: {}", desc, e), } } println!("\n🎉 测试完成!"); Ok(()) } fn analyze_ffmpeg_command(command: &str) { let parts: Vec<&str> = command.split_whitespace().collect(); println!(" 命令长度: {} 字符", command.len()); println!(" 参数数量: {} 个", parts.len()); // 检查关键组件 if command.contains("ffmpeg") { println!(" ✓ 包含 ffmpeg 可执行文件"); } if command.contains("-i") { println!(" ✓ 包含输入文件参数"); } if command.contains("tvai_fi") { println!(" ✓ 包含 TVAI 帧插值滤镜"); // 分析帧插值参数 if let Some(fi_part) = command.split("tvai_fi=").nth(1) { if let Some(params) = fi_part.split_whitespace().next() { println!(" 帧插值参数: {}", params); if params.contains("model=") { println!(" ✓ 包含模型参数"); } if params.contains("slowmo=") { println!(" ✓ 包含慢动作倍数参数"); } if params.contains("rdt=") { println!(" ✓ 包含重复帧检测参数"); } } } } if command.contains("-c:v") { println!(" ✓ 包含视频编码器设置"); } if command.contains("-c:a") { println!(" ✓ 包含音频编码器设置"); } } fn check_ffmpeg_command(command: &str, template: &tvai_sdk::Template) { let mut issues = Vec::new(); let mut warnings = Vec::new(); // 检查基本结构 if !command.starts_with("ffmpeg") { issues.push("命令不以 'ffmpeg' 开头"); } if !command.contains("-i") { issues.push("缺少输入文件参数 (-i)"); } // 检查慢动作设置 if template.settings.slow_motion.active { if !command.contains("tvai_fi") { issues.push("启用了慢动作但缺少 tvai_fi 滤镜"); } else { // 检查慢动作参数 if !command.contains("slowmo=4") { warnings.push("慢动作倍数可能不正确,期望 4x"); } if !command.contains("model=chr-2") { warnings.push("模型映射可能不正确,apo-8 应该映射到 chr-2"); } } } // 检查输出设置 if template.settings.output.active { if template.settings.output.out_fps == 0.0 { warnings.push("输出FPS为0,可能需要设置目标帧率"); } } // 检查编码器设置 if !command.contains("-c:v") { warnings.push("没有明确指定视频编码器"); } if !command.contains("-c:a") { warnings.push("没有明确指定音频编码器"); } // 检查滤镜链 let filter_count = command.matches("-vf").count(); if filter_count > 1 { issues.push("存在多个 -vf 参数,可能导致滤镜冲突"); } // 输出结果 if issues.is_empty() && warnings.is_empty() { println!(" ✅ 命令检查通过,未发现问题"); } else { if !issues.is_empty() { println!(" ❌ 发现严重问题:"); for issue in &issues { println!(" - {}", issue); } } if !warnings.is_empty() { println!(" ⚠️ 发现警告:"); for warning in &warnings { println!(" - {}", warning); } } } }