diff --git a/tauri-app/src-tauri/src/main.rs b/tauri-app/src-tauri/src/main.rs index 935760a..13f2485 100644 --- a/tauri-app/src-tauri/src/main.rs +++ b/tauri-app/src-tauri/src/main.rs @@ -6,13 +6,16 @@ // Dateipfade verarbeitet, nie Videoinhalte selbst in den Arbeitsspeicher der // Oberfläche geladen. // -// Wichtiger Hinweis für den ersten echten Build: In dieser Entwicklungsumgebung -// steht kein Rust Compiler zur Verfügung, dieser Code wurde also nicht kompiliert, -// nur sorgfältig von Hand geprüft. Zwei Stellen bitte beim ersten Testlauf gezielt -// gegenprüfen: 1) die genauen Kommandozeilen-Optionen von `deep-filter` (siehe -// `deep-filter --help`, hier als `-o ` angenommen), 2) ob `auto-editor` -// den Flag `--no-open` in der installierten Version so kennt. Beides ist unten mit -// Kommentaren markiert. +// Alle Zwischenschritte (geschnittenes Video, rohe/entrauschte Tonspur, usw.) +// laufen in einem echten temporären Systemordner (std::env::temp_dir()), nicht im +// Ordner der Eingabedatei. Grund: Bei einem echten Testlauf am 2026-08-19 lag das +// Eingabevideo in einem Nextcloud-synchronisierten Ordner, der Sync-Client hat +// neu entstehende Zwischen-Dateien sofort selbst kurz geöffnet, was zu "Zugriff +// verweigert" Fehlern führte, sobald NovaPhonic dieselbe Datei gleich danach +// weiterverarbeiten wollte. Der temporäre Arbeitsordner wird bei einem Fehler +// sofort wieder vollständig gelöscht, bei Erfolg bleibt nur das fertige Ergebnis +// bis zum Speichern über den "Speichern unter" Dialog liegen, siehe +// `save_output_as`, das räumt danach ebenfalls auf. use serde::{Deserialize, Serialize}; use std::fs; @@ -47,12 +50,31 @@ fn save_output_as(source_path: String, suggested_name: String) -> Result { fs::copy(&source_path, &dest) .map_err(|e| format!("Konnte Datei nicht speichern: {e}"))?; + cleanup_temp_work_dir(&source_path); Ok(dest.to_string_lossy().to_string()) } None => Err("abgebrochen".to_string()), } } +// Löscht den temporären Arbeitsordner einer fertigen Ergebnisdatei, nachdem sie +// erfolgreich an ihr endgültiges Ziel kopiert wurde. Sicherheitshalber nur, wenn +// der Pfad wirklich im System-Temp-Ordner liegt und unserem eigenen Namensmuster +// entspricht, damit hier niemals versehentlich ein echter Nutzerordner betroffen +// sein kann. +fn cleanup_temp_work_dir(source_path: &str) { + let path = PathBuf::from(source_path); + let Some(work_dir) = path.parent() else { + return; + }; + let Some(folder_name) = work_dir.file_name().and_then(|n| n.to_str()) else { + return; + }; + if work_dir.starts_with(std::env::temp_dir()) && folder_name.starts_with("novaphonic-") { + let _ = fs::remove_dir_all(work_dir); + } +} + // Wichtig: Tauri spricht Sidecar Programme zur Laufzeit nur über ihren bloßen // Namen an (z.B. "auto-editor"), der Ordnerpfad "binaries/" wird ausschließlich // beim Einrichten in tauri.conf.json (externalBin) und in den Capabilities @@ -186,13 +208,43 @@ async fn process_video(app: AppHandle, options: ProcessOptions) -> Result Ok(ProcessResult { + output_path: final_path.to_string_lossy().to_string(), + }), + Err(e) => { + // Bei einem Fehler bleibt nichts Halbfertiges im Temp-Ordner liegen. + let _ = fs::remove_dir_all(&work_dir); + Err(e) + } + } +} + +async fn run_pipeline( + app: &AppHandle, + options: &ProcessOptions, + input: &Path, + work_dir: &Path, + stem: &str, + ext: &str, +) -> Result { // ---------- 1) Schnitt (auto-editor) ---------- - emit_progress(&app, "cut", "running", Some("startet…".into()), None); - let cut_path = parent.join(format!("{stem}_geschnitten.{ext}")); + emit_progress(app, "cut", "running", Some("startet…".into()), None); + let cut_path = work_dir.join(format!("{stem}_geschnitten.{ext}")); let margin = format!("{}sec", options.margin_seconds); run_sidecar( &app, @@ -222,8 +274,8 @@ async fn process_video(app: AppHandle, options: ProcessOptions) -> Result Result Result Result Result