Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 40 additions & 18 deletions apps/desktop/src-tauri/src/captions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl Default for CaptionData {
lazy_static::lazy_static! {
static ref WHISPER_CONTEXT: Arc<Mutex<Option<Arc<WhisperContext>>>> = Arc::new(Mutex::new(None));
static ref MODEL_DOWNLOADS: Mutex<HashMap<String, ActiveModelDownload>> = Mutex::new(HashMap::new());
static ref TRANSCRIPTION_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
}

#[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
Expand Down Expand Up @@ -643,8 +644,14 @@ async fn extract_audio_from_video(video_path: &str, output_path: &PathBuf) -> Re
}
}

async fn get_whisper_context(model_path: &str) -> Result<Arc<WhisperContext>, String> {
let mut context_guard = WHISPER_CONTEXT.lock().await;
fn lock_transcription_worker_slot() -> std::sync::MutexGuard<'static, ()> {
TRANSCRIPTION_LOCK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
}

fn get_whisper_context_blocking(model_path: &str) -> Result<Arc<WhisperContext>, String> {
let mut context_guard = WHISPER_CONTEXT.blocking_lock();

if let Some(ref existing) = *context_guard {
log::info!("Reusing cached Whisper context");
Expand All @@ -661,6 +668,15 @@ async fn get_whisper_context(model_path: &str) -> Result<Arc<WhisperContext>, St
Ok(ctx_arc)
}

#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
fn release_whisper_context_after_transcription() {
let mut ctx = WHISPER_CONTEXT.blocking_lock();
*ctx = None;
}

#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
fn release_whisper_context_after_transcription() {}

fn is_special_token(token_text: &str) -> bool {
let trimmed = token_text.trim();
if trimmed.is_empty() {
Expand Down Expand Up @@ -1314,22 +1330,14 @@ pub async fn transcribe_audio(
TranscriptionEngine::Parakeet => {
log::info!("Using Parakeet TDT engine");
let model_dir = model_path.clone();
tokio::task::spawn_blocking(move || process_with_parakeet(&audio_path, &model_dir))
.await
.map_err(|e| format!("Parakeet task panicked: {e}"))?
tokio::task::spawn_blocking(move || {
let _guard = lock_transcription_worker_slot();
process_with_parakeet(&audio_path, &model_dir)
})
.await
.map_err(|e| format!("Parakeet task panicked: {e}"))?
}
TranscriptionEngine::Whisper => {
let context = match get_whisper_context(&model_path).await {
Ok(ctx) => {
log::info!("Whisper context ready");
ctx
}
Err(e) => {
log::error!("Failed to initialize Whisper context: {e}");
return Err(format!("Failed to initialize transcription model: {e}"));
}
};

let transcription_hints = GeneralSettingsStore::get(&app)
.ok()
.flatten()
Expand All @@ -1338,7 +1346,21 @@ pub async fn transcribe_audio(

log::info!("Starting Whisper transcription in blocking task...");
tokio::task::spawn_blocking(move || {
process_with_whisper(&audio_path, context, &language, &transcription_hints)
let _guard = lock_transcription_worker_slot();
let context = match get_whisper_context_blocking(&model_path) {
Ok(ctx) => {
log::info!("Whisper context ready");
ctx
}
Err(e) => {
log::error!("Failed to initialize Whisper context: {e}");
return Err(format!("Failed to initialize transcription model: {e}"));
}
};
let result =
process_with_whisper(&audio_path, context, &language, &transcription_hints);
release_whisper_context_after_transcription();
result
})
.await
.map_err(|e| format!("Whisper task panicked: {e}"))?
Expand Down Expand Up @@ -2311,7 +2333,7 @@ async fn parakeet_model_file_sizes(
let part_size = resp
.content_length()
.filter(|size| *size > 0)
.or_else(|| parakeet_known_part_size(*url))
.or_else(|| parakeet_known_part_size(url))
.unwrap_or(0);
file_size = file_size.saturating_add(part_size);
}
Expand Down
6 changes: 2 additions & 4 deletions apps/desktop/src-tauri/src/recording.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ use std::{
time::Duration,
};
use tauri::{AppHandle, Manager, path::BaseDirectory};
use tauri_plugin_global_shortcut::GlobalShortcutExt;
use tauri_plugin_dialog::{DialogExt, MessageDialogBuilder};
use tauri_plugin_global_shortcut::GlobalShortcutExt;
use tauri_specta::Event;
use tracing::*;

Expand Down Expand Up @@ -3015,9 +3015,7 @@ async fn handle_recording_end(
// so they don't reappear when the main window comes back.
let focus_manager = handle.try_state::<crate::target_select_overlay::WindowFocusManager>();
for (label, window) in handle.webview_windows() {
if let Ok(CapWindowId::TargetSelectOverlay { display_id }) =
CapWindowId::from_str(&label)
{
if let Ok(CapWindowId::TargetSelectOverlay { display_id }) = CapWindowId::from_str(&label) {
hide_overlay(&window);
if let Some(ref fm) = focus_manager {
fm.destroy(&display_id, handle.global_shortcut());
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src-tauri/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2378,7 +2378,6 @@ impl ShowCapWindow {
));
}


#[cfg(target_os = "macos")]
crate::platform::set_window_level(
window.as_ref().window(),
Expand Down
Loading