From 7ed8a558f279cf5aaa5c40fc989c64ad9f53d403 Mon Sep 17 00:00:00 2001 From: Jackson <54308792+jacksongoode@users.noreply.github.com> Date: Sat, 28 Mar 2026 22:15:45 -0700 Subject: [PATCH] Load the VAD when model loads in parallel (#1177) Co-authored-by: CJ Pais --- src-tauri/src/actions.rs | 11 +++++++-- src-tauri/src/managers/audio.rs | 40 +++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src-tauri/src/actions.rs b/src-tauri/src/actions.rs index 4750324..3219caf 100644 --- a/src-tauri/src/actions.rs +++ b/src-tauri/src/actions.rs @@ -368,14 +368,21 @@ impl ShortcutAction for TranscribeAction { // Load model in the background let tm = app.state::>(); + let rm = app.state::>(); + + // Load ASR model and VAD model in parallel tm.initiate_model_load(); + let rm_clone = Arc::clone(&rm); + std::thread::spawn(move || { + if let Err(e) = rm_clone.preload_vad() { + debug!("VAD pre-load failed: {}", e); + } + }); let binding_id = binding_id.to_string(); change_tray_icon(app, TrayIconState::Recording); show_recording_overlay(app); - let rm = app.state::>(); - // Get the microphone mode to determine audio feedback timing let settings = get_settings(app); let is_always_on = settings.always_on_microphone; diff --git a/src-tauri/src/managers/audio.rs b/src-tauri/src/managers/audio.rs index b3378b7..24dd04f 100644 --- a/src-tauri/src/managers/audio.rs +++ b/src-tauri/src/managers/audio.rs @@ -263,6 +263,25 @@ impl AudioRecordingManager { } } + pub fn preload_vad(&self) -> Result<(), anyhow::Error> { + let mut recorder_opt = self.recorder.lock().unwrap(); + if recorder_opt.is_none() { + let vad_path = self + .app_handle + .path() + .resolve( + "resources/models/silero_vad_v4.onnx", + tauri::path::BaseDirectory::Resource, + ) + .map_err(|e| anyhow::anyhow!("Failed to resolve VAD path: {}", e))?; + *recorder_opt = Some(create_audio_recorder( + vad_path.to_str().unwrap(), + &self.app_handle, + )?); + } + Ok(()) + } + pub fn start_microphone_stream(&self) -> Result<(), anyhow::Error> { let mut open_flag = self.is_open.lock().unwrap(); if *open_flag { @@ -276,23 +295,6 @@ impl AudioRecordingManager { let mut did_mute_guard = self.did_mute.lock().unwrap(); *did_mute_guard = false; - let vad_path = self - .app_handle - .path() - .resolve( - "resources/models/silero_vad_v4.onnx", - tauri::path::BaseDirectory::Resource, - ) - .map_err(|e| anyhow::anyhow!("Failed to resolve VAD path: {}", e))?; - let mut recorder_opt = self.recorder.lock().unwrap(); - - if recorder_opt.is_none() { - *recorder_opt = Some(create_audio_recorder( - vad_path.to_str().unwrap(), - &self.app_handle, - )?); - } - // Get the selected device from settings, considering clamshell mode let settings = get_settings(&self.app_handle); let selected_device = self.get_effective_microphone_device(&settings); @@ -309,6 +311,10 @@ impl AudioRecordingManager { } } + // Ensure VAD is loaded if it wasn't for whatever reason + self.preload_vad()?; + + let mut recorder_opt = self.recorder.lock().unwrap(); if let Some(rec) = recorder_opt.as_mut() { rec.open(selected_device) .map_err(|e| anyhow::anyhow!("Failed to open recorder: {}", e))?;