项目初始化完成 - 创建 cargos/tvai 项目结构 - 配置 Cargo.toml 依赖和工作空间 - 实现基础错误类型 TvaiError FFmpeg 管理模块 - 实现 FfmpegManager 结构体 - FFmpeg 路径检测和验证 (系统 vs Topaz) - 基础命令执行框架 - 支持 Windows/Linux/macOS 平台 核心处理引擎框架 - TvaiProcessor 主结构体 - TvaiConfig 配置管理和 Builder 模式 - 临时文件管理和自动清理 - GPU 检测和配置 模型和参数定义 - 16种超分辨率模型枚举 (Iris3, Nyx3, Thf4 等) - 4种插值模型枚举 (Apo8, Chr2 等) - 质量预设和编码设置 - 完整的参数结构体和验证 模块结构完整 - video/ 视频处理模块框架 - image/ 图片处理模块框架 - config/ 配置管理模块 - utils/ 工具函数模块 系统检测功能 - Topaz Video AI 安装检测 - GPU 支持检测 - FFmpeg 可用性检测 文档和示例 - 完整的 README 文档 - 基础使用示例 - API 文档注释 测试结果 - 编译通过 (cargo check) - 示例运行成功 - 检测到 Topaz Video AI 安装 - 所有模块结构就绪 下一步: 开始阶段二 - 核心处理引擎实现
224 lines
6.4 KiB
Rust
224 lines
6.4 KiB
Rust
//! Main processor for Topaz Video AI operations
|
|
|
|
use std::path::{Path, PathBuf};
|
|
use std::time::Duration;
|
|
use serde::{Deserialize, Serialize};
|
|
use uuid::Uuid;
|
|
|
|
use crate::core::{TvaiError, FfmpegManager};
|
|
|
|
/// Main processor for Topaz Video AI operations
|
|
#[derive(Debug)]
|
|
pub struct TvaiProcessor {
|
|
config: TvaiConfig,
|
|
ffmpeg_manager: FfmpegManager,
|
|
temp_dir: PathBuf,
|
|
}
|
|
|
|
/// Configuration for TvaiProcessor
|
|
#[derive(Debug, Clone)]
|
|
pub struct TvaiConfig {
|
|
/// Path to Topaz Video AI installation
|
|
pub topaz_path: PathBuf,
|
|
/// Whether to use GPU acceleration
|
|
pub use_gpu: bool,
|
|
/// Custom temporary directory (optional)
|
|
pub temp_dir: Option<PathBuf>,
|
|
/// Force use of Topaz FFmpeg even for non-AI operations
|
|
pub force_topaz_ffmpeg: bool,
|
|
}
|
|
|
|
/// Result of a processing operation
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ProcessResult {
|
|
/// Path to the output file
|
|
pub output_path: PathBuf,
|
|
/// Time taken for processing
|
|
pub processing_time: Duration,
|
|
/// Additional metadata about the processing
|
|
pub metadata: ProcessMetadata,
|
|
}
|
|
|
|
/// Metadata about a processing operation
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ProcessMetadata {
|
|
/// Unique operation ID
|
|
pub operation_id: String,
|
|
/// Input file path
|
|
pub input_path: PathBuf,
|
|
/// Processing parameters used
|
|
pub parameters: String,
|
|
/// Whether GPU was used
|
|
pub used_gpu: bool,
|
|
/// FFmpeg version used
|
|
pub ffmpeg_version: Option<String>,
|
|
}
|
|
|
|
impl TvaiConfig {
|
|
/// Create a new configuration builder
|
|
pub fn builder() -> TvaiConfigBuilder {
|
|
TvaiConfigBuilder::default()
|
|
}
|
|
|
|
/// Create a configuration with default settings
|
|
pub fn new(topaz_path: PathBuf) -> Self {
|
|
Self {
|
|
topaz_path,
|
|
use_gpu: true,
|
|
temp_dir: None,
|
|
force_topaz_ffmpeg: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Builder for TvaiConfig
|
|
#[derive(Debug, Default)]
|
|
pub struct TvaiConfigBuilder {
|
|
topaz_path: Option<PathBuf>,
|
|
use_gpu: Option<bool>,
|
|
temp_dir: Option<PathBuf>,
|
|
force_topaz_ffmpeg: Option<bool>,
|
|
}
|
|
|
|
impl TvaiConfigBuilder {
|
|
/// Set the Topaz Video AI installation path
|
|
pub fn topaz_path<P: AsRef<Path>>(mut self, path: P) -> Self {
|
|
self.topaz_path = Some(path.as_ref().to_path_buf());
|
|
self
|
|
}
|
|
|
|
/// Set whether to use GPU acceleration
|
|
pub fn use_gpu(mut self, use_gpu: bool) -> Self {
|
|
self.use_gpu = Some(use_gpu);
|
|
self
|
|
}
|
|
|
|
/// Set custom temporary directory
|
|
pub fn temp_dir<P: AsRef<Path>>(mut self, path: P) -> Self {
|
|
self.temp_dir = Some(path.as_ref().to_path_buf());
|
|
self
|
|
}
|
|
|
|
/// Set whether to force Topaz FFmpeg usage
|
|
pub fn force_topaz_ffmpeg(mut self, force: bool) -> Self {
|
|
self.force_topaz_ffmpeg = Some(force);
|
|
self
|
|
}
|
|
|
|
/// Build the configuration
|
|
pub fn build(self) -> Result<TvaiConfig, TvaiError> {
|
|
let topaz_path = self.topaz_path
|
|
.ok_or_else(|| TvaiError::InvalidParameter("topaz_path is required".to_string()))?;
|
|
|
|
if !topaz_path.exists() {
|
|
return Err(TvaiError::TopazNotFound(topaz_path.display().to_string()));
|
|
}
|
|
|
|
Ok(TvaiConfig {
|
|
topaz_path,
|
|
use_gpu: self.use_gpu.unwrap_or(true),
|
|
temp_dir: self.temp_dir,
|
|
force_topaz_ffmpeg: self.force_topaz_ffmpeg.unwrap_or(true),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl TvaiProcessor {
|
|
/// Create a new processor with the given configuration
|
|
pub fn new(config: TvaiConfig) -> Result<Self, TvaiError> {
|
|
let ffmpeg_manager = FfmpegManager::new(
|
|
Some(&config.topaz_path),
|
|
config.force_topaz_ffmpeg,
|
|
);
|
|
|
|
// Verify Topaz FFmpeg is available for AI operations
|
|
if !ffmpeg_manager.is_topaz_available() {
|
|
return Err(TvaiError::TopazNotFound(
|
|
config.topaz_path.display().to_string()
|
|
));
|
|
}
|
|
|
|
// Set up temporary directory
|
|
let temp_dir = match &config.temp_dir {
|
|
Some(dir) => {
|
|
std::fs::create_dir_all(dir)?;
|
|
dir.clone()
|
|
}
|
|
None => {
|
|
let temp_dir = std::env::temp_dir().join("tvai_temp");
|
|
std::fs::create_dir_all(&temp_dir)?;
|
|
temp_dir
|
|
}
|
|
};
|
|
|
|
Ok(Self {
|
|
config,
|
|
ffmpeg_manager,
|
|
temp_dir,
|
|
})
|
|
}
|
|
|
|
/// Get the configuration
|
|
pub fn config(&self) -> &TvaiConfig {
|
|
&self.config
|
|
}
|
|
|
|
/// Get the FFmpeg manager
|
|
pub fn ffmpeg_manager(&self) -> &FfmpegManager {
|
|
&self.ffmpeg_manager
|
|
}
|
|
|
|
/// Get the temporary directory
|
|
pub fn temp_dir(&self) -> &Path {
|
|
&self.temp_dir
|
|
}
|
|
|
|
/// Generate a unique operation ID
|
|
pub fn generate_operation_id(&self) -> String {
|
|
Uuid::new_v4().to_string()
|
|
}
|
|
|
|
/// Create a temporary file path with the given extension
|
|
pub fn create_temp_path(&self, operation_id: &str, suffix: &str) -> PathBuf {
|
|
self.temp_dir.join(format!("{}_{}", operation_id, suffix))
|
|
}
|
|
|
|
/// Clean up temporary files for an operation
|
|
pub fn cleanup_temp_files(&self, operation_id: &str) -> Result<(), TvaiError> {
|
|
let pattern = format!("{}_", operation_id);
|
|
|
|
if let Ok(entries) = std::fs::read_dir(&self.temp_dir) {
|
|
for entry in entries.flatten() {
|
|
if let Some(name) = entry.file_name().to_str() {
|
|
if name.starts_with(&pattern) {
|
|
let _ = std::fs::remove_file(entry.path());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check if GPU is available and enabled
|
|
pub fn is_gpu_enabled(&self) -> bool {
|
|
self.config.use_gpu && self.is_gpu_available()
|
|
}
|
|
|
|
/// Check if GPU is available on the system
|
|
pub fn is_gpu_available(&self) -> bool {
|
|
// This is a simplified check - in a real implementation,
|
|
// you might want to check for CUDA/OpenCL availability
|
|
self.config.use_gpu
|
|
}
|
|
}
|
|
|
|
impl Drop for TvaiProcessor {
|
|
fn drop(&mut self) {
|
|
// Clean up temporary directory if it was created by us
|
|
if self.config.temp_dir.is_none() {
|
|
let _ = std::fs::remove_dir_all(&self.temp_dir);
|
|
}
|
|
}
|
|
}
|