diff --git a/python/voice_to_notes/services/pipeline.py b/python/voice_to_notes/services/pipeline.py index 2d1f66b..fe4bf04 100644 --- a/python/voice_to_notes/services/pipeline.py +++ b/python/voice_to_notes/services/pipeline.py @@ -110,27 +110,57 @@ class PipelineService: ) return result - # Step 2: Diarize + # Step 2: Diarize (with graceful fallback) write_message( progress_message(request_id, 50, "pipeline", "Starting speaker diarization...") ) - diarization = self._diarize_service.diarize( - request_id=request_id, - file_path=file_path, - num_speakers=num_speakers, - min_speakers=min_speakers, - max_speakers=max_speakers, - ) + diarization = None + try: + diarization = self._diarize_service.diarize( + request_id=request_id, + file_path=file_path, + num_speakers=num_speakers, + min_speakers=min_speakers, + max_speakers=max_speakers, + ) + except Exception as e: + print( + f"[sidecar] Diarization failed, falling back to transcription-only: {e}", + file=sys.stderr, + flush=True, + ) + write_message( + progress_message( + request_id, 80, "pipeline", + "Diarization unavailable, using transcription only..." + ) + ) - # Step 3: Merge - write_message( - progress_message(request_id, 90, "pipeline", "Merging transcript with speakers...") - ) - - result = self._merge_results(transcription, diarization.speaker_segments) - result.speakers = diarization.speakers - result.num_speakers = diarization.num_speakers + # Step 3: Merge (or skip if diarization failed) + if diarization is not None: + write_message( + progress_message(request_id, 90, "pipeline", "Merging transcript with speakers...") + ) + result = self._merge_results(transcription, diarization.speaker_segments) + result.speakers = diarization.speakers + result.num_speakers = diarization.num_speakers + else: + result = PipelineResult( + language=transcription.language, + language_probability=transcription.language_probability, + duration_ms=transcription.duration_ms, + ) + for seg in transcription.segments: + result.segments.append( + PipelineSegment( + text=seg.text, + start_ms=seg.start_ms, + end_ms=seg.end_ms, + speaker=None, + words=seg.words, + ) + ) elapsed = time.time() - start_time print( diff --git a/src-tauri/src/commands/transcribe.rs b/src-tauri/src/commands/transcribe.rs index 9e2239a..2f2e64a 100644 --- a/src-tauri/src/commands/transcribe.rs +++ b/src-tauri/src/commands/transcribe.rs @@ -1,4 +1,5 @@ use serde_json::{json, Value}; +use tauri::{AppHandle, Emitter}; use crate::sidecar::messages::IPCMessage; use crate::sidecar::sidecar; @@ -42,6 +43,7 @@ pub fn transcribe_file( /// Run the full transcription + diarization pipeline via the Python sidecar. #[tauri::command] pub fn run_pipeline( + app: AppHandle, file_path: String, model: Option, device: Option, @@ -71,7 +73,9 @@ pub fn run_pipeline( }), ); - let response = manager.send_and_receive(&msg)?; + let response = manager.send_and_receive_with_progress(&msg, |progress| { + let _ = app.emit("pipeline-progress", &progress.payload); + })?; if response.msg_type == "error" { return Err(format!( diff --git a/src-tauri/src/sidecar/mod.rs b/src-tauri/src/sidecar/mod.rs index dd60840..c8cc33e 100644 --- a/src-tauri/src/sidecar/mod.rs +++ b/src-tauri/src/sidecar/mod.rs @@ -115,8 +115,17 @@ impl SidecarManager { } /// Send a message to the sidecar and read the response. - /// This is a blocking call. + /// This is a blocking call. Progress messages are skipped. pub fn send_and_receive(&self, msg: &IPCMessage) -> Result { + self.send_and_receive_with_progress(msg, |_| {}) + } + + /// Send a message and read the response, calling on_progress for each progress message. + pub fn send_and_receive_with_progress( + &self, + msg: &IPCMessage, + on_progress: impl Fn(&IPCMessage), + ) -> Result { // Write to stdin { let mut stdin_guard = self.stdin.lock().map_err(|e| e.to_string())?; @@ -154,10 +163,11 @@ impl SidecarManager { let response: IPCMessage = serde_json::from_str(trimmed) .map_err(|e| format!("Parse error: {e}"))?; - // Skip progress messages, return the final result/error - if response.msg_type != "progress" { - return Ok(response); + if response.msg_type == "progress" { + on_progress(&response); + continue; } + return Ok(response); } } else { Err("Sidecar stdout not available".to_string()) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index a655c08..2112a61 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -10,6 +10,7 @@ padding: 0; background: #0a0a23; color: #e0e0e0; + color-scheme: dark; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; overflow: hidden; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 9b139a0..2260060 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,5 +1,6 @@