fix(audio): use WebRTC VAD on iOS

This commit is contained in:
Edison Jwa
2026-05-31 22:30:28 +09:00
parent c02d4e6df3
commit 6f7063971d
6 changed files with 119 additions and 189 deletions
+14 -11
View File
@@ -1,11 +1,12 @@
//! Voice activity detection backends and helpers.
//!
//! iOS capture feeds VoiceProcessingIO-processed microphone frames into
//! this module. The production path prefers a model-backed detector when
//! available, and otherwise uses the realtime-safe fallback below so
//! this module and uses the realtime-safe WebRTC fallback. Other
//! platforms may use a model-backed detector when available so
//! VoiceActivity mode never collapses back to Continuous transmit.
pub mod resampler;
#[cfg(not(target_os = "ios"))]
pub mod silero_onnx;
use std::sync::atomic::{AtomicU64, Ordering};
@@ -15,6 +16,7 @@ use crate::frame::{f32_to_i16, i16_to_f32};
use crate::AudioError;
use resampler::{Downsampler48to16, INPUT_FRAME_10MS};
#[cfg(not(target_os = "ios"))]
pub use silero_onnx::SileroOnnxVad;
/// Voice activity detector output for one 10 ms frame.
@@ -111,11 +113,11 @@ fn silero_model_path_override() -> &'static RwLock<Option<String>> {
SILERO_MODEL_PATH_OVERRIDE.get_or_init(|| RwLock::new(None))
}
/// Configure the preferred Silero ONNX model path.
/// Configure the preferred Silero ONNX model path on supported platforms.
///
/// The path is validated eagerly. A successful call increments the
/// model epoch so running audio backends can reload the model without
/// an app restart.
/// model epoch so running non-iOS audio backends can reload the model
/// without an app restart.
pub fn set_silero_model_path(path: &str) -> Result<(), AudioError> {
let path = path.trim();
if path.is_empty() {
@@ -141,13 +143,13 @@ pub fn silero_model_epoch() -> u64 {
SILERO_MODEL_EPOCH.load(Ordering::Relaxed)
}
/// Return the expected path of the Silero VAD v6 ONNX model.
/// Return the expected path of the Silero VAD v6 ONNX model on
/// supported platforms.
/// The model is shipped as a Flutter asset and copied to the app's
/// data directory by the Dart-side asset loader.
///
/// On iOS/Android the model lives in the app's Documents/files
/// directory. On desktop, the caller should set the path explicitly
/// via `set_silero_model_path`.
/// Android and macOS may use app data/Documents locations. Desktop
/// callers can set the path explicitly via `set_silero_model_path`.
pub fn silero_model_bundle_path() -> String {
if let Ok(guard) = silero_model_path_override().read() {
if let Some(path) = guard.as_ref() {
@@ -155,8 +157,9 @@ pub fn silero_model_bundle_path() -> String {
}
}
// iOS: Documents directory (written by Flutter asset loader).
// macOS: same Documents pattern.
// macOS: Documents directory (written by Flutter asset loader).
// iOS keeps this fallback only for API compatibility; the ONNX
// detector is not compiled into iOS builds.
#[cfg(any(target_os = "ios", target_os = "macos"))]
{
if let Ok(home) = std::env::var("HOME") {