sermon-converter/src/main.rs

123 lines
4.9 KiB
Rust

use std::path::PathBuf;
use anyhow::Result;
use notify::{Watcher, RecursiveMode, Event, EventKind};
use tokio::sync::mpsc;
mod services;
use services::sermon_converter::VideoConverter;
#[tokio::main]
async fn main() -> Result<()> {
let watch_path = PathBuf::from("/home/rockvilleav/Sync/Sermons");
let output_path = PathBuf::from("/media/archive/jellyfin/sermons");
// Ensure directories exist
if !watch_path.exists() {
println!("Creating watch directory: {}", watch_path.display());
std::fs::create_dir_all(&watch_path)?;
}
if !output_path.exists() {
println!("Creating output directory: {}", output_path.display());
std::fs::create_dir_all(&output_path)?;
}
println!("Starting sermon converter service...");
println!("Watching directory: {}", watch_path.display());
println!("Output directory: {}", output_path.display());
let converter = VideoConverter::new(output_path);
// Process existing files first
println!("Checking for existing files...");
if let Ok(entries) = std::fs::read_dir(&watch_path) {
for entry in entries {
if let Ok(entry) = entry {
let path = entry.path();
if path.to_string_lossy().contains(".syncthing.") {
println!("Skipping temporary file: {}", path.display());
continue;
}
if let Some(ext) = path.extension() {
if ext == "mp4" {
println!("Processing existing MP4 file: {}", path.display());
if let Err(e) = converter.process_file(path).await {
eprintln!("Error processing existing file: {}", e);
}
}
}
}
}
}
// Set up file watcher
let (tx, mut rx) = mpsc::channel(100);
let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
let tx = tx.clone();
match res {
Ok(event) => {
match &event.kind {
EventKind::Create(_) => println!("File created: {:?}", event.paths),
EventKind::Modify(notify::event::ModifyKind::Name(mode)) => {
match mode {
notify::event::RenameMode::From => println!("File renamed from: {:?}", event.paths),
notify::event::RenameMode::To => println!("File renamed to: {:?}", event.paths),
notify::event::RenameMode::Both => println!("File renamed: {:?}", event.paths),
_ => println!("Other rename event: {:?}", event),
}
},
_ => println!("Other file event: {:?}", event),
}
if let Err(e) = tx.blocking_send(event) {
eprintln!("Error sending event: {}", e);
}
}
Err(e) => eprintln!("Watch error: {}", e),
}
})?;
watcher.watch(&watch_path, RecursiveMode::NonRecursive)?;
println!("Watcher started successfully");
while let Some(event) = rx.recv().await {
match event.kind {
EventKind::Create(_) |
EventKind::Modify(notify::event::ModifyKind::Name(notify::event::RenameMode::To)) => {
for path in event.paths {
// Skip temporary and non-MP4 files
if path.to_string_lossy().contains(".syncthing.") {
println!("Skipping temporary Syncthing file: {}", path.display());
continue;
}
if let Some(ext) = path.extension() {
if ext == "mp4" {
println!("New MP4 file detected: {}", path.display());
// Wait a short time to ensure file is fully written
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
println!("Starting processing for: {}", path.display());
if let Err(e) = converter.process_file(path.clone()).await {
eprintln!("Error processing file {}: {}", path.display(), e);
} else {
println!("Successfully processed: {}", path.display());
}
} else {
println!("Ignoring non-MP4 file: {}", path.display());
}
} else {
println!("Ignoring file without extension: {}", path.display());
}
}
}
_ => {
// Log other events at debug level
println!("Ignoring event: {:?}", event);
}
}
}
Ok(())
}