Files
gui-video-clipper/src-tauri/src/commands/export.rs
2026-09-21 11:21:53 -04:00

113 lines
3.6 KiB
Rust

use crate::models::{ExportConfig, ExportScope};
use crate::services::clip_exporter;
use serde::Serialize;
use tauri::ipc::Channel;
#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase", tag = "event", content = "data")]
pub enum ExportEvent {
Progress {
current: usize,
total: usize,
label: String,
},
Finished {
paths: Vec<String>,
},
Error {
message: String,
},
}
#[tauri::command]
pub async fn export_clips(
config: ExportConfig,
on_event: Channel<ExportEvent>,
) -> Result<Vec<String>, String> {
tokio::task::spawn_blocking(move || {
let ext = clip_exporter::get_extension(&config.source_file_path, &config.cut_mode);
match config.export_scope {
ExportScope::Individual => {
let total = config.clips.len();
let mut output_paths = Vec::new();
for (i, clip) in config.clips.iter().enumerate() {
let _ = on_event.send(ExportEvent::Progress {
current: i + 1,
total,
label: clip.label.clone(),
});
let output = clip_exporter::generate_output_path(
&config.output_directory,
&config.video_title,
&clip.label,
&ext,
);
clip_exporter::export_single_clip(
clip,
&config.source_file_path,
&output,
&config.cut_mode,
)?;
output_paths.push(output);
}
let _ = on_event.send(ExportEvent::Finished {
paths: output_paths.clone(),
});
Ok(output_paths)
}
ExportScope::Merged => {
let _ = on_event.send(ExportEvent::Progress {
current: 1,
total: 1,
label: "Merging clips".to_string(),
});
let output = clip_exporter::generate_output_path(
&config.output_directory,
&config.video_title,
"Merged",
&ext,
);
let temp_dir = std::env::temp_dir()
.join("video-clipper-merge")
.join(uuid::Uuid::new_v4().to_string());
std::fs::create_dir_all(&temp_dir)
.map_err(|e| format!("Failed to create temp dir: {e}"))?;
let mut sorted_clips = config.clips.clone();
sorted_clips.sort_by(|a, b| {
a.start_time
.partial_cmp(&b.start_time)
.unwrap_or(std::cmp::Ordering::Equal)
});
let temp_dir_str = temp_dir.to_string_lossy().to_string();
let merge_result = clip_exporter::export_merged(
&sorted_clips,
&config.source_file_path,
&output,
&config.cut_mode,
&temp_dir_str,
);
let _ = std::fs::remove_dir_all(&temp_dir);
merge_result?;
let paths = vec![output];
let _ = on_event.send(ExportEvent::Finished {
paths: paths.clone(),
});
Ok(paths)
}
}
})
.await
.map_err(|e| format!("Task failed: {e}"))?
}