Fix progress feedback, diarization fallback, and dropdown readability
- Stream pipeline progress to frontend via Tauri events so the progress overlay updates in real time during transcription/diarization - Gracefully fall back to transcription-only when diarization fails (e.g. pyannote not installed) instead of erroring the whole pipeline - Add color-scheme: dark to fix native select/option elements rendering with unreadable white backgrounds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -110,11 +110,13 @@ 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 = None
|
||||
try:
|
||||
diarization = self._diarize_service.diarize(
|
||||
request_id=request_id,
|
||||
file_path=file_path,
|
||||
@@ -122,15 +124,43 @@ class PipelineService:
|
||||
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
|
||||
# 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(
|
||||
|
||||
@@ -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<String>,
|
||||
device: Option<String>,
|
||||
@@ -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!(
|
||||
|
||||
@@ -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<IPCMessage, String> {
|
||||
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<IPCMessage, String> {
|
||||
// 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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { invoke, convertFileSrc } from '@tauri-apps/api/core';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { open, save } from '@tauri-apps/plugin-dialog';
|
||||
import WaveformPlayer from '$lib/components/WaveformPlayer.svelte';
|
||||
import TranscriptEditor from '$lib/components/TranscriptEditor.svelte';
|
||||
@@ -89,6 +90,19 @@
|
||||
isTranscribing = true;
|
||||
transcriptionProgress = 0;
|
||||
transcriptionStage = 'Starting...';
|
||||
transcriptionMessage = 'Initializing pipeline...';
|
||||
|
||||
// Listen for progress events from the sidecar
|
||||
const unlisten = await listen<{
|
||||
percent: number;
|
||||
stage: string;
|
||||
message: string;
|
||||
}>('pipeline-progress', (event) => {
|
||||
const { percent, stage, message } = event.payload;
|
||||
if (typeof percent === 'number') transcriptionProgress = percent;
|
||||
if (typeof stage === 'string') transcriptionStage = stage;
|
||||
if (typeof message === 'string') transcriptionMessage = message;
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await invoke<{
|
||||
@@ -159,6 +173,7 @@
|
||||
console.error('Pipeline failed:', err);
|
||||
alert(`Pipeline failed: ${err}`);
|
||||
} finally {
|
||||
unlisten();
|
||||
isTranscribing = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user