feat: 扩展TVAI高级参数并修复编译错误
主要功能: - 将TVAI可控参数从5个扩展到34个 (+29个新参数) - 支持完整的FFmpeg编码参数控制 - 添加高级TVAI AI增强参数 (preblur, noise, details, halo, blur等) - 支持输出尺寸控制和音频处理模式 技术改进: - 重新设计VideoUpscaleParams结构体 - 添加智能默认值和预设系统 - 优化参数验证和错误处理 - 改进FFmpeg滤镜构建逻辑 修复编译错误: - 修复E0063结构体字段缺失错误 (6处) - 修复E0597生命周期错误 (3处) - 消除未使用代码警告 (2处) - 确保向后兼容性 文档: - 详细的高级参数使用指南 - 完整的编译错误修复总结 - 34个参数的分类和说明
This commit is contained in:
@@ -67,6 +67,7 @@ impl PresetManager {
|
||||
compression: 0.0,
|
||||
blend: 0.1,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
..Default::default()
|
||||
}),
|
||||
interpolation: None,
|
||||
});
|
||||
@@ -128,6 +129,7 @@ impl PresetManager {
|
||||
compression: 0.0,
|
||||
blend: 0.1,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
..Default::default()
|
||||
}),
|
||||
interpolation: Some(InterpolationParams {
|
||||
input_fps: 24,
|
||||
|
||||
@@ -201,6 +201,7 @@ pub struct OperationMonitor {
|
||||
operation_type: String,
|
||||
input_size_mb: f64,
|
||||
start_time: Instant,
|
||||
#[allow(dead_code)]
|
||||
enable_monitoring: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,65 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::core::{TvaiError, ProcessResult, TvaiProcessor, ProgressCallback};
|
||||
use crate::config::{UpscaleModel, InterpolationModel, QualityPreset};
|
||||
|
||||
/// 音频处理模式
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum AudioMode {
|
||||
/// 保留原音频
|
||||
Keep,
|
||||
/// 移除音频
|
||||
Remove,
|
||||
/// 重新编码音频
|
||||
Reencode { codec: String, bitrate: u32 },
|
||||
}
|
||||
|
||||
/// Parameters for video upscaling
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VideoUpscaleParams {
|
||||
// 基础参数
|
||||
pub scale_factor: f32,
|
||||
pub model: UpscaleModel,
|
||||
pub compression: f32,
|
||||
pub blend: f32,
|
||||
pub quality_preset: QualityPreset,
|
||||
|
||||
// 高级TVAI参数
|
||||
pub preblur: f32, // 预模糊 (0-100)
|
||||
pub noise: f32, // 噪点减少 (0-100)
|
||||
pub details: f32, // 细节恢复 (0-100)
|
||||
pub halo: f32, // 光晕减少 (0-100)
|
||||
pub blur: f32, // 模糊减少 (0-100)
|
||||
pub estimate: u32, // 估算质量 (1-20)
|
||||
pub device: i32, // 设备ID (-2=auto, -1=CPU, 0+=GPU)
|
||||
pub vram: u32, // VRAM使用 (0-1)
|
||||
pub instances: u32, // 实例数量 (1-4)
|
||||
|
||||
// 输出尺寸控制
|
||||
pub target_width: Option<u32>, // 目标宽度
|
||||
pub target_height: Option<u32>, // 目标高度
|
||||
pub maintain_aspect: bool, // 保持宽高比
|
||||
pub pad_color: String, // 填充颜色
|
||||
|
||||
// 编码参数
|
||||
pub codec: Option<String>, // 编码器 (h264_nvenc, hevc_nvenc, libx264等)
|
||||
pub profile: Option<String>, // 编码配置文件
|
||||
pub pixel_format: String, // 像素格式
|
||||
pub gop_size: u32, // GOP大小
|
||||
pub preset: Option<String>, // 编码预设
|
||||
pub tune: Option<String>, // 调优选项
|
||||
pub rate_control: String, // 码率控制模式
|
||||
pub quality_param: u32, // 质量参数 (CRF/QP)
|
||||
pub lookahead: u32, // 前瞻帧数
|
||||
pub spatial_aq: bool, // 空间自适应量化
|
||||
pub aq_strength: u32, // AQ强度
|
||||
pub bitrate: u32, // 目标码率 (0=VBR)
|
||||
pub buffer_frames: u32, // 缓冲帧数
|
||||
|
||||
// 音频处理
|
||||
pub audio_mode: AudioMode, // 音频处理模式
|
||||
|
||||
// 元数据
|
||||
pub preserve_metadata: bool, // 保留元数据
|
||||
pub custom_metadata: Option<String>, // 自定义元数据
|
||||
}
|
||||
|
||||
/// Parameters for frame interpolation
|
||||
@@ -36,6 +87,58 @@ pub struct VideoEnhanceParams {
|
||||
pub interpolation: Option<InterpolationParams>,
|
||||
}
|
||||
|
||||
impl Default for VideoUpscaleParams {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
// 基础参数
|
||||
scale_factor: 2.0,
|
||||
model: UpscaleModel::Iris3,
|
||||
compression: 0.0,
|
||||
blend: 0.0,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
|
||||
// 高级TVAI参数
|
||||
preblur: 0.0,
|
||||
noise: 0.0,
|
||||
details: 0.0,
|
||||
halo: 0.0,
|
||||
blur: 0.0,
|
||||
estimate: 8,
|
||||
device: -2, // 自动选择
|
||||
vram: 1,
|
||||
instances: 1,
|
||||
|
||||
// 输出尺寸控制
|
||||
target_width: None,
|
||||
target_height: None,
|
||||
maintain_aspect: true,
|
||||
pad_color: "black".to_string(),
|
||||
|
||||
// 编码参数
|
||||
codec: None, // 自动选择
|
||||
profile: Some("high".to_string()),
|
||||
pixel_format: "yuv420p".to_string(),
|
||||
gop_size: 30,
|
||||
preset: Some("p7".to_string()),
|
||||
tune: Some("hq".to_string()),
|
||||
rate_control: "constqp".to_string(),
|
||||
quality_param: 18,
|
||||
lookahead: 20,
|
||||
spatial_aq: true,
|
||||
aq_strength: 15,
|
||||
bitrate: 0, // VBR
|
||||
buffer_frames: 0,
|
||||
|
||||
// 音频处理
|
||||
audio_mode: AudioMode::Keep,
|
||||
|
||||
// 元数据
|
||||
preserve_metadata: true,
|
||||
custom_metadata: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoUpscaleParams {
|
||||
/// Create parameters optimized for old video content
|
||||
pub fn for_old_video() -> Self {
|
||||
@@ -44,7 +147,12 @@ impl VideoUpscaleParams {
|
||||
model: UpscaleModel::Thf4,
|
||||
compression: 0.3,
|
||||
blend: 0.2,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
preblur: 0.0,
|
||||
noise: 20.0,
|
||||
details: 30.0,
|
||||
halo: 10.0,
|
||||
blur: 15.0,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,10 +163,16 @@ impl VideoUpscaleParams {
|
||||
model: UpscaleModel::Ghq5,
|
||||
compression: 0.0,
|
||||
blend: 0.0,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
preblur: 0.0,
|
||||
noise: 0.0,
|
||||
details: 50.0,
|
||||
halo: 0.0,
|
||||
blur: 0.0,
|
||||
quality_param: 15, // 更高质量
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Create parameters optimized for animation
|
||||
pub fn for_animation() -> Self {
|
||||
Self {
|
||||
@@ -66,10 +180,15 @@ impl VideoUpscaleParams {
|
||||
model: UpscaleModel::Iris3,
|
||||
compression: -0.1,
|
||||
blend: 0.1,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
preblur: 0.0,
|
||||
noise: 5.0,
|
||||
details: 25.0,
|
||||
halo: 5.0,
|
||||
blur: 10.0,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Create parameters optimized for portrait video
|
||||
pub fn for_portrait() -> Self {
|
||||
Self {
|
||||
@@ -77,7 +196,52 @@ impl VideoUpscaleParams {
|
||||
model: UpscaleModel::Nyx3,
|
||||
compression: -0.2,
|
||||
blend: 0.1,
|
||||
quality_preset: QualityPreset::HighQuality,
|
||||
preblur: 0.0,
|
||||
noise: 15.0,
|
||||
details: 40.0,
|
||||
halo: 20.0,
|
||||
blur: 25.0,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create parameters for maximum quality (slow processing)
|
||||
pub fn for_maximum_quality() -> Self {
|
||||
Self {
|
||||
scale_factor: 2.0,
|
||||
model: UpscaleModel::Ahq12,
|
||||
compression: 0.0,
|
||||
blend: 0.0,
|
||||
preblur: 0.0,
|
||||
noise: 30.0,
|
||||
details: 60.0,
|
||||
halo: 30.0,
|
||||
blur: 40.0,
|
||||
estimate: 20, // 最高估算质量
|
||||
quality_param: 12, // 最高质量
|
||||
lookahead: 32,
|
||||
instances: 1, // 单实例确保质量
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create parameters for fast processing
|
||||
pub fn for_fast_processing() -> Self {
|
||||
Self {
|
||||
scale_factor: 2.0,
|
||||
model: UpscaleModel::Alqs2,
|
||||
compression: 0.2,
|
||||
blend: 0.0,
|
||||
preblur: 0.0,
|
||||
noise: 10.0,
|
||||
details: 20.0,
|
||||
halo: 5.0,
|
||||
blur: 10.0,
|
||||
estimate: 4, // 较低估算质量
|
||||
quality_param: 22, // 较低质量但更快
|
||||
preset: Some("p1".to_string()), // 最快预设
|
||||
instances: 2, // 多实例加速
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,6 +394,7 @@ pub async fn quick_upscale_video(
|
||||
compression: 0.0,
|
||||
blend: 0.0,
|
||||
quality_preset: crate::config::QualityPreset::HighQuality,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Perform upscaling
|
||||
@@ -272,6 +437,7 @@ pub async fn auto_enhance_video(
|
||||
compression: 0.0,
|
||||
blend: 0.1,
|
||||
quality_preset: crate::config::QualityPreset::HighQuality,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -45,23 +45,24 @@ impl TvaiProcessor {
|
||||
"-vf", &upscale_filter,
|
||||
];
|
||||
|
||||
// Add encoding settings
|
||||
let (codec, preset) = params.quality_preset.get_encoding_settings(self.is_gpu_enabled());
|
||||
let quality = params.quality_preset.get_quality_value(self.is_gpu_enabled());
|
||||
// 构建所有参数字符串
|
||||
let mut all_args = Vec::new();
|
||||
|
||||
if self.is_gpu_enabled() {
|
||||
args.extend_from_slice(&[
|
||||
"-c:v", codec,
|
||||
"-preset", preset,
|
||||
"-global_quality", quality,
|
||||
"-pix_fmt", "yuv420p",
|
||||
]);
|
||||
} else {
|
||||
args.extend_from_slice(&[
|
||||
"-c:v", codec,
|
||||
"-preset", preset,
|
||||
"-crf", quality,
|
||||
]);
|
||||
// 添加编码参数
|
||||
let encoding_args = self.build_encoding_args(¶ms)?;
|
||||
all_args.extend(encoding_args);
|
||||
|
||||
// 添加音频参数
|
||||
let audio_args = self.build_audio_args(¶ms.audio_mode)?;
|
||||
all_args.extend(audio_args);
|
||||
|
||||
// 添加元数据参数
|
||||
let metadata_args = self.build_metadata_args(¶ms)?;
|
||||
all_args.extend(metadata_args);
|
||||
|
||||
// 转换为&str并添加到args
|
||||
for arg in &all_args {
|
||||
args.push(arg.as_str());
|
||||
}
|
||||
|
||||
args.push(output_path.to_str().unwrap());
|
||||
@@ -104,9 +105,10 @@ impl TvaiProcessor {
|
||||
|
||||
/// Validate upscaling parameters
|
||||
fn validate_upscale_params(&self, params: &VideoUpscaleParams) -> Result<(), TvaiError> {
|
||||
if params.scale_factor < 1.0 || params.scale_factor > 4.0 {
|
||||
// 验证基础参数
|
||||
if params.scale_factor < 0.0 || params.scale_factor > 4.0 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Scale factor must be between 1.0 and 4.0, got {}", params.scale_factor)
|
||||
format!("Scale factor must be between 0.0 and 4.0, got {}", params.scale_factor)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -122,9 +124,65 @@ impl TvaiProcessor {
|
||||
));
|
||||
}
|
||||
|
||||
// 验证TVAI参数
|
||||
if params.preblur < 0.0 || params.preblur > 100.0 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Preblur must be between 0.0 and 100.0, got {}", params.preblur)
|
||||
));
|
||||
}
|
||||
|
||||
if params.noise < 0.0 || params.noise > 100.0 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Noise must be between 0.0 and 100.0, got {}", params.noise)
|
||||
));
|
||||
}
|
||||
|
||||
if params.details < 0.0 || params.details > 100.0 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Details must be between 0.0 and 100.0, got {}", params.details)
|
||||
));
|
||||
}
|
||||
|
||||
if params.halo < 0.0 || params.halo > 100.0 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Halo must be between 0.0 and 100.0, got {}", params.halo)
|
||||
));
|
||||
}
|
||||
|
||||
if params.blur < 0.0 || params.blur > 100.0 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Blur must be between 0.0 and 100.0, got {}", params.blur)
|
||||
));
|
||||
}
|
||||
|
||||
if params.estimate < 1 || params.estimate > 20 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Estimate must be between 1 and 20, got {}", params.estimate)
|
||||
));
|
||||
}
|
||||
|
||||
if params.instances < 1 || params.instances > 4 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Instances must be between 1 and 4, got {}", params.instances)
|
||||
));
|
||||
}
|
||||
|
||||
// 验证编码参数
|
||||
if params.quality_param > 51 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Quality parameter must be <= 51, got {}", params.quality_param)
|
||||
));
|
||||
}
|
||||
|
||||
if params.aq_strength > 15 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("AQ strength must be <= 15, got {}", params.aq_strength)
|
||||
));
|
||||
}
|
||||
|
||||
// Check if model forces a specific scale
|
||||
if let Some(forced_scale) = params.model.forces_scale() {
|
||||
if (params.scale_factor - forced_scale).abs() > 0.01 {
|
||||
if params.scale_factor > 0.0 && (params.scale_factor - forced_scale).abs() > 0.01 {
|
||||
return Err(TvaiError::InvalidParameter(
|
||||
format!("Model {} forces scale factor {}, but {} was requested",
|
||||
params.model.as_str(), forced_scale, params.scale_factor)
|
||||
@@ -137,14 +195,185 @@ impl TvaiProcessor {
|
||||
|
||||
/// Build Topaz upscaling filter string
|
||||
fn build_upscale_filter(&self, params: &VideoUpscaleParams) -> Result<String, TvaiError> {
|
||||
let filter = format!(
|
||||
"tvai_up=model={}:scale={}:estimate=8:compression={}:blend={}",
|
||||
params.model.as_str(),
|
||||
params.scale_factor,
|
||||
params.compression,
|
||||
params.blend
|
||||
);
|
||||
let mut filter_parts = Vec::new();
|
||||
|
||||
Ok(filter)
|
||||
// 构建TVAI upscale滤镜
|
||||
let mut tvai_params = vec![
|
||||
format!("model={}", params.model.as_str()),
|
||||
format!("scale={}", if params.scale_factor == 0.0 { 0 } else { params.scale_factor as u32 }),
|
||||
format!("preblur={}", params.preblur),
|
||||
format!("noise={}", params.noise),
|
||||
format!("details={}", params.details),
|
||||
format!("halo={}", params.halo),
|
||||
format!("blur={}", params.blur),
|
||||
format!("compression={}", params.compression),
|
||||
format!("estimate={}", params.estimate),
|
||||
format!("blend={}", params.blend),
|
||||
format!("device={}", params.device),
|
||||
format!("vram={}", params.vram),
|
||||
format!("instances={}", params.instances),
|
||||
];
|
||||
|
||||
// 如果指定了目标尺寸,添加宽高参数
|
||||
if let (Some(width), Some(height)) = (params.target_width, params.target_height) {
|
||||
tvai_params.push(format!("w={}", width));
|
||||
tvai_params.push(format!("h={}", height));
|
||||
}
|
||||
|
||||
let tvai_filter = format!("tvai_up={}", tvai_params.join(":"));
|
||||
filter_parts.push(tvai_filter);
|
||||
|
||||
// 如果需要额外的缩放和填充
|
||||
if let (Some(width), Some(height)) = (params.target_width, params.target_height) {
|
||||
if params.maintain_aspect {
|
||||
// 添加缩放滤镜保持宽高比
|
||||
let scale_filter = format!(
|
||||
"scale=w={}:h={}:flags=lanczos:threads=0:force_original_aspect_ratio=decrease",
|
||||
width, height
|
||||
);
|
||||
filter_parts.push(scale_filter);
|
||||
|
||||
// 添加填充滤镜
|
||||
let pad_filter = format!(
|
||||
"pad={}:{}:-1:-1:color={}",
|
||||
width, height, params.pad_color
|
||||
);
|
||||
filter_parts.push(pad_filter);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(filter_parts.join(","))
|
||||
}
|
||||
|
||||
/// Build encoding arguments
|
||||
fn build_encoding_args(&self, params: &VideoUpscaleParams) -> Result<Vec<String>, TvaiError> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
// 确定编码器
|
||||
let codec = params.codec.as_deref().unwrap_or_else(|| {
|
||||
if self.is_gpu_enabled() {
|
||||
"h264_nvenc"
|
||||
} else {
|
||||
"libx264"
|
||||
}
|
||||
});
|
||||
|
||||
args.extend_from_slice(&["-c:v".to_string(), codec.to_string()]);
|
||||
|
||||
// 添加编码配置文件
|
||||
if let Some(profile) = ¶ms.profile {
|
||||
args.extend_from_slice(&["-profile:v".to_string(), profile.clone()]);
|
||||
}
|
||||
|
||||
// 添加像素格式
|
||||
args.extend_from_slice(&["-pix_fmt".to_string(), params.pixel_format.clone()]);
|
||||
|
||||
// 添加GOP大小
|
||||
args.extend_from_slice(&["-g".to_string(), params.gop_size.to_string()]);
|
||||
|
||||
if codec.contains("nvenc") {
|
||||
// NVIDIA GPU编码器参数
|
||||
if let Some(preset) = ¶ms.preset {
|
||||
args.extend_from_slice(&["-preset".to_string(), preset.clone()]);
|
||||
}
|
||||
if let Some(tune) = ¶ms.tune {
|
||||
args.extend_from_slice(&["-tune".to_string(), tune.clone()]);
|
||||
}
|
||||
args.extend_from_slice(&["-rc".to_string(), params.rate_control.clone()]);
|
||||
args.extend_from_slice(&["-qp".to_string(), params.quality_param.to_string()]);
|
||||
args.extend_from_slice(&["-rc-lookahead".to_string(), params.lookahead.to_string()]);
|
||||
|
||||
if params.spatial_aq {
|
||||
args.extend_from_slice(&["-spatial_aq".to_string(), "1".to_string()]);
|
||||
args.extend_from_slice(&["-aq-strength".to_string(), params.aq_strength.to_string()]);
|
||||
}
|
||||
|
||||
if params.bitrate > 0 {
|
||||
args.extend_from_slice(&["-b:v".to_string(), params.bitrate.to_string()]);
|
||||
} else {
|
||||
args.extend_from_slice(&["-b:v".to_string(), "0".to_string()]);
|
||||
}
|
||||
|
||||
if params.buffer_frames > 0 {
|
||||
args.extend_from_slice(&["-bf".to_string(), params.buffer_frames.to_string()]);
|
||||
} else {
|
||||
args.extend_from_slice(&["-bf".to_string(), "0".to_string()]);
|
||||
}
|
||||
} else {
|
||||
// CPU编码器参数
|
||||
if let Some(preset) = ¶ms.preset {
|
||||
args.extend_from_slice(&["-preset".to_string(), preset.clone()]);
|
||||
}
|
||||
if let Some(tune) = ¶ms.tune {
|
||||
args.extend_from_slice(&["-tune".to_string(), tune.clone()]);
|
||||
}
|
||||
args.extend_from_slice(&["-crf".to_string(), params.quality_param.to_string()]);
|
||||
}
|
||||
|
||||
// 添加帧率模式
|
||||
args.extend_from_slice(&["-fps_mode:v".to_string(), "passthrough".to_string()]);
|
||||
|
||||
// 添加MOV标志
|
||||
args.extend_from_slice(&[
|
||||
"-movflags".to_string(),
|
||||
"frag_keyframe+empty_moov+delay_moov+use_metadata_tags+write_colr".to_string()
|
||||
]);
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
/// Build audio arguments
|
||||
fn build_audio_args(&self, audio_mode: &crate::video::AudioMode) -> Result<Vec<String>, TvaiError> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
match audio_mode {
|
||||
crate::video::AudioMode::Keep => {
|
||||
// 保留音频,复制流
|
||||
args.extend_from_slice(&["-c:a".to_string(), "copy".to_string()]);
|
||||
}
|
||||
crate::video::AudioMode::Remove => {
|
||||
// 移除音频
|
||||
args.push("-an".to_string());
|
||||
}
|
||||
crate::video::AudioMode::Reencode { codec, bitrate } => {
|
||||
// 重新编码音频
|
||||
args.extend_from_slice(&["-c:a".to_string(), codec.clone()]);
|
||||
args.extend_from_slice(&["-b:a".to_string(), format!("{}k", bitrate)]);
|
||||
}
|
||||
}
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
/// Build metadata arguments
|
||||
fn build_metadata_args(&self, params: &VideoUpscaleParams) -> Result<Vec<String>, TvaiError> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
if params.preserve_metadata {
|
||||
args.extend_from_slice(&["-map_metadata".to_string(), "0".to_string()]);
|
||||
args.extend_from_slice(&["-map_metadata:s:v".to_string(), "0:s:v".to_string()]);
|
||||
}
|
||||
|
||||
// 添加自定义元数据
|
||||
if let Some(custom_metadata) = ¶ms.custom_metadata {
|
||||
args.extend_from_slice(&["-metadata".to_string(), custom_metadata.clone()]);
|
||||
} else {
|
||||
// 添加默认的VideoAI元数据
|
||||
let metadata = format!(
|
||||
"videoai=Enhanced using {}; mode: auto; revert compression at {}; recover details at {}; sharpen at {}; reduce noise at {}; dehalo at {}; anti-alias/deblur at {}; focus fix Off; and recover original detail at {}. Changed resolution to {}x{}",
|
||||
params.model.as_str(),
|
||||
params.compression,
|
||||
params.details,
|
||||
params.blur,
|
||||
params.noise,
|
||||
params.halo,
|
||||
params.blur,
|
||||
params.blend * 100.0,
|
||||
params.target_width.unwrap_or(0),
|
||||
params.target_height.unwrap_or(0)
|
||||
);
|
||||
args.extend_from_slice(&["-metadata".to_string(), metadata]);
|
||||
}
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user