use std::path::PathBuf; use anyhow::{Result, anyhow}; use video_processing::{ VideoProcessingConfig, VideoConverter as SharedVideoConverter, FileProcessor }; pub struct VideoConverter { output_path: PathBuf, config: VideoProcessingConfig, video_converter: SharedVideoConverter, } impl VideoConverter { pub fn new(output_path: PathBuf) -> Self { let config = VideoProcessingConfig::from_env(); let video_converter = SharedVideoConverter::new(config.clone()); VideoConverter { output_path, config, video_converter, } } pub async fn process_file(&self, path: PathBuf) -> Result<()> { // Early checks if path.to_string_lossy().contains(".syncthing.") { return Err(anyhow!("Skipping Syncthing temporary file")); } if path.extension().and_then(|ext| ext.to_str()) != Some("mp4") { return Err(anyhow!("Ignoring non-MP4 file")); } if !path.exists() { return Err(anyhow!("File no longer exists: {}", path.display())); } println!("Processing sermon: {}", path.display()); // Get the filename and keep it exactly the same let filename = path.file_name() .ok_or_else(|| anyhow!("Invalid filename"))?; // Output file has same name as input let output_file = self.output_path.join(filename); println!("Converting to AV1 and saving to: {}", output_file.display()); // Convert video using shared crate self.video_converter.convert_video(&path, &output_file).await?; println!("Successfully converted {} to AV1", path.display()); // Handle original file based on configuration if !self.config.preserve_original_files { println!("Deleting original file: {}", path.display()); tokio::fs::remove_file(path).await?; } else { println!("Preserving original file: {}", path.display()); } Ok(()) } } #[async_trait::async_trait] impl FileProcessor for VideoConverter { async fn process_file(&self, path: PathBuf) -> Result<()> { self.process_file(path).await } async fn should_skip_existing_file(&self, _path: &PathBuf) -> bool { // For sermons, we don't have a simple duplicate check like livestreams // Let the process_file method handle duplicate detection false } }