mixvideo-v2/cargos/tvai-v2/examples/test_4x_slowmo.rs

251 lines
8.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use tvai_sdk::TvaiSdk;
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
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);
}
}
}
}