diff --git a/src-tauri/src/task.rs b/src-tauri/src/task.rs index 64a0fa7..0c6cf25 100644 --- a/src-tauri/src/task.rs +++ b/src-tauri/src/task.rs @@ -1,6 +1,10 @@ use std::{ fs, path::{Path, PathBuf}, + sync::{ + atomic::{AtomicU32, Ordering}, + Arc, + }, }; use anyhow::{Context, Result}; @@ -235,6 +239,10 @@ async fn run_pipeline( set_status(&window, &app_state, &mut task, TaskStatus::Transcribing, 30.0, "正在执行 Whisper")?; + // Shared progress state between concurrent transcribing and translating + let transcribing_pct: Arc = Arc::new(AtomicU32::new(0)); + let translating_pct: Arc = Arc::new(AtomicU32::new(0)); + // Setup concurrent translation: as whisper emits segments, send them to // the translation worker so it can start translating immediately in batches let app_handle = app.clone(); @@ -250,6 +258,8 @@ async fn run_pipeline( let task_id_for_worker = task.id.clone(); let target_lang_for_worker = task.target_lang.clone(); let app_handle_for_worker = app_handle.clone(); + let tp_for_worker = transcribing_pct.clone(); + let tap_for_worker = translating_pct.clone(); let handle = tauri::async_runtime::spawn(async move { let state = app_handle_for_worker.state::(); if let Err(error) = incremental_translate( @@ -259,6 +269,8 @@ async fn run_pipeline( &state, &task_id_for_worker, &target_lang_for_worker, + &tp_for_worker, + &tap_for_worker, ) .await { @@ -278,6 +290,8 @@ async fn run_pipeline( let app_state_for_segment = app_state.clone(); let app_state_for_reset = app_state.clone(); let seg_tx_for_callback = segment_tx.clone(); + let tp_for_callback = transcribing_pct.clone(); + let tap_for_callback = translating_pct.clone(); let _segments = whisper.infer_segments( &wav_path, &task.id, @@ -286,12 +300,18 @@ async fn run_pipeline( should_translate, &speech_ranges, |ratio| { - let progress = 30.0 + ratio.clamp(0.0, 1.0) * 40.0; + let ratio = ratio.clamp(0.0, 1.0); + tp_for_callback.store((ratio * 100.0) as u32, Ordering::Release); + let translating = tap_for_callback.load(Ordering::Acquire) as f32 / 100.0; + // translation progress must not exceed transcription progress + let translating_capped = translating.min(ratio); + + let progress = 30.0 + ratio * 40.0 + translating_capped * 25.0; let sub = SubStageProgress { extracting: 100.0, vad: 100.0, - transcribing: ratio.clamp(0.0, 1.0) * 100.0, - translating: 0.0, + transcribing: ratio * 100.0, + translating: translating_capped * 100.0, }; window.emit( "task:progress", @@ -344,7 +364,8 @@ async fn run_pipeline( |message| emit_log(&window, &task_id_for_log, message), )?; - // Close channel to signal translation worker to flush and finish + // Signal that transcribing is complete, then close channel to flush translation worker + transcribing_pct.store(100, Ordering::Release); drop(segment_tx); drop(seg_tx_for_callback); if let Some(handle) = translate_join_handle { @@ -370,6 +391,8 @@ async fn incremental_translate( app_state: &AppState, task_id: &str, target_lang: &TargetLanguage, + transcribing_pct: &AtomicU32, + translating_pct: &AtomicU32, ) -> Result<()> { let batch_size = translator.batch_size().clamp(3, 60); let context_size = translator.context_size().min(5); @@ -383,19 +406,29 @@ async fn incremental_translate( } else { 0.0 }; - let overall = 70.0 + ratio * 25.0; + translating_pct.store((ratio * 100.0) as u32, Ordering::Release); + let transcribing = transcribing_pct.load(Ordering::Acquire) as f32 / 100.0; + // translation progress must not exceed transcription progress + let translating_capped = ratio.min(transcribing); + + let overall = 30.0 + transcribing * 40.0 + translating_capped * 25.0; let sub = SubStageProgress { extracting: 100.0, vad: 100.0, - transcribing: 100.0, - translating: ratio * 100.0, + transcribing: (transcribing * 100.0).min(100.0), + translating: translating_capped * 100.0, + }; + let status = if transcribing >= 1.0 { + TaskStatus::Translating + } else { + TaskStatus::Transcribing }; window.emit( "task:progress", ProgressEvent { task_id: task_id.to_string(), - status: TaskStatus::Translating, - progress: overall, + status, + progress: overall.min(95.0), message: "正在生成译文".to_string(), sub_stage_progress: sub, }, @@ -490,6 +523,7 @@ async fn incremental_translate( } // Translation complete + translating_pct.store(100, Ordering::Release); let sub = SubStageProgress { extracting: 100.0, vad: 100.0,