Detección de actividad vocal

Hay dos modelos de VAD disponibles: Pyannote segmentation para procesamiento offline por lotes con alta precisión, y Silero VAD v5 para detección en streaming de baja latencia. Ambos se ejecutan completamente en el dispositivo.

Pyannote (offline)

Pyannote segmentation-3.0 proporciona VAD de alta precisión utilizando una arquitectura PyanNet. Procesa el audio en ventanas deslizantes de 10 segundos con un paso de 1 segundo, luego agrega las predicciones solapadas y aplica suavizado por histéresis.

Arquitectura

EtapaDetalles
SincNet40 filtros pasa-banda aprendidos (80 en total: 40 cos + 40 sin)
BiLSTM4 capas, hidden=128, bidireccional (salida de 256 dim)
Linear2 capas lineales con LeakyReLU (negative_slope=0.01)
SalidaSoftmax de 7 clases con post-procesamiento por histéresis

Tamaño del modelo: ~1,49M parámetros, ~5,7 MB en disco.

Umbrales por defecto

Uso desde la CLI

# VAD offline
.build/release/audio vad recording.wav

# Salida JSON
.build/release/audio vad recording.wav --json

# Umbrales personalizados
.build/release/audio vad recording.wav --onset 0.6 --offset 0.3

Silero VAD v5 (streaming)

Silero VAD v5 es un modelo ligero de streaming que procesa chunks de 512 muestras (32 ms a 16 kHz). Se ejecuta a 23x el tiempo real en modo release, lo que lo hace adecuado para aplicaciones de audio en vivo.

Arquitectura

EtapaDetalles
STFTConv1d (de 1 a 258 canales), reflection pad a la derecha de 64
Encoder4x Conv1d + ReLU
LSTMHidden size 128, estado mantenido entre chunks
DecoderConv1d (de 128 a 1) sobre el estado oculto del LSTM, salida sigmoide

Tamaño del modelo: ~309K parámetros, ~1,2 MB en disco.

Máquina de estados en streaming

El procesador VAD en streaming usa una máquina de 4 estados para producir segmentos de voz limpios:

  1. silence — no se detecta voz
  2. pendingSpeech — se cruzó el umbral de onset, esperando la duración mínima de voz
  3. speech — segmento de voz confirmado en curso
  4. pendingSilence — se cruzó el umbral de offset, esperando la duración mínima de silencio

Umbrales por defecto

Uso desde la CLI

# VAD en streaming
.build/release/audio vad-stream recording.wav

# Umbrales personalizados
.build/release/audio vad-stream recording.wav --onset 0.6 --offset 0.3

# Duraciones mínimas
.build/release/audio vad-stream recording.wav --min-speech 0.5 --min-silence 0.2

# Elegir motor
.build/release/audio vad-stream recording.wav --engine coreml

Opciones

OpciónAplica aDescripción
--onsetAmbosUmbral de probabilidad de inicio de voz
--offsetAmbosUmbral de probabilidad de fin de voz
--min-speechStreamingDuración mínima del segmento de voz (segundos)
--min-silenceStreamingDuración mínima de silencio para terminar un segmento (segundos)
--engineStreamingMotor de inferencia: mlx o coreml
--jsonAmbosFormato de salida JSON
Importante

Para aplicaciones en tiempo real, usa audio vad-stream con Silero VAD. El modelo Pyannote requiere el archivo de audio completo y es más adecuado para procesamiento offline por lotes donde la precisión es la prioridad.

Descargas de modelos

ModeloBackendTamañoHuggingFace
Silero-VAD-v5MLX~1,2 MBaufklarer/Silero-VAD-v5-MLX
Silero-VAD-v5CoreML~1,2 MBaufklarer/Silero-VAD-v5-CoreML
Pyannote-Segmentation-3.0MLX~5,7 MBaufklarer/Pyannote-Segmentation-MLX

API Swift

import SpeechVAD

// VAD offline (Pyannote)
let pyannote = try await PyannoteVAD.loadFromHub()
let segments = try await pyannote.detectSpeech(audioFile: "recording.wav")
for segment in segments {
    print("\(segment.start)s - \(segment.end)s")
}

// VAD en streaming (Silero)
let silero = try await SileroVAD.loadFromHub()
let processor = StreamingVADProcessor(model: silero, config: .sileroDefault)
for chunk in audioChunks {
    if let segment = try processor.process(chunk: chunk) {
        print("Speech: \(segment.start)s - \(segment.end)s")
    }
}

También disponible en Android y Linux vía ONNX Runtime.