Détection d'activité vocale
Deux modèles VAD sont disponibles : Pyannote segmentation pour le traitement par batch hors ligne avec une haute précision, et Silero VAD v5 pour une détection streaming à faible latence. Les deux s'exécutent entièrement sur l'appareil.
Pyannote (hors ligne)
Pyannote segmentation-3.0 fournit une VAD haute précision via une architecture PyanNet. Il traite l'audio dans des fenêtres glissantes de 10 secondes avec un pas de 1 seconde, puis agrège les prédictions chevauchantes et applique un lissage par hystérésis.
Architecture
| Étape | Détails |
|---|---|
| SincNet | 40 filtres passe-bande appris (80 au total : 40 cos + 40 sin) |
| BiLSTM | 4 couches, hidden=128, bidirectionnel (sortie 256 dim) |
| Linéaire | 2 couches linéaires avec LeakyReLU (negative_slope=0.01) |
| Sortie | Softmax à 7 classes avec post-traitement par hystérésis |
Taille du modèle : ~1,49M paramètres, ~5,7 Mo sur disque.
Seuils par défaut
- Onset :
0.767— probabilité au-dessus de laquelle la parole est détectée - Offset :
0.377— probabilité en dessous de laquelle la parole se termine
Utilisation en CLI
# VAD hors ligne
.build/release/audio vad recording.wav
# Sortie JSON
.build/release/audio vad recording.wav --json
# Seuils personnalisés
.build/release/audio vad recording.wav --onset 0.6 --offset 0.3
Silero VAD v5 (streaming)
Silero VAD v5 est un modèle streaming léger qui traite des chunks de 512 échantillons (32 ms à 16 kHz). Il s'exécute à 23× le temps réel en mode release, ce qui le rend adapté aux applications audio en direct.
Architecture
| Étape | Détails |
|---|---|
| STFT | Conv1d (1 vers 258 canaux), padding de réflexion à droite seulement de 64 |
| Encodeur | 4× Conv1d + ReLU |
| LSTM | Taille cachée 128, état porté entre chunks |
| Décodeur | Conv1d (128 vers 1) sur l'état caché LSTM, sortie sigmoïde |
Taille du modèle : ~309K paramètres, ~1,2 Mo sur disque.
Machine à états streaming
Le processeur VAD streaming utilise une machine à 4 états pour produire des segments de parole propres :
- silence — aucune parole détectée
- pendingSpeech — seuil onset franchi, en attente de la durée minimum de parole
- speech — segment de parole confirmé en cours
- pendingSilence — seuil offset franchi, en attente de la durée minimum de silence
Seuils par défaut
- Onset :
0.5 - Offset :
0.35 - Durée minimum de parole :
0.25s - Durée minimum de silence :
0.1s
Utilisation en CLI
# VAD streaming
.build/release/audio vad-stream recording.wav
# Seuils personnalisés
.build/release/audio vad-stream recording.wav --onset 0.6 --offset 0.3
# Durées minimum
.build/release/audio vad-stream recording.wav --min-speech 0.5 --min-silence 0.2
# Choisir le moteur
.build/release/audio vad-stream recording.wav --engine coreml
Options
| Option | S'applique à | Description |
|---|---|---|
--onset | Les deux | Seuil de probabilité d'onset de la parole |
--offset | Les deux | Seuil de probabilité d'offset de la parole |
--min-speech | Streaming | Durée minimum de segment de parole (secondes) |
--min-silence | Streaming | Durée minimum de silence pour terminer un segment (secondes) |
--engine | Streaming | Moteur d'inférence : mlx ou coreml |
--json | Les deux | Format de sortie JSON |
Pour les applications temps réel, utilisez audio vad-stream avec Silero VAD. Le modèle Pyannote requiert le fichier audio complet et convient mieux au traitement par batch hors ligne où la précision est la priorité.
Téléchargements des modèles
| Modèle | Backend | Taille | HuggingFace |
|---|---|---|---|
| Silero-VAD-v5 | MLX | ~1,2 Mo | aufklarer/Silero-VAD-v5-MLX |
| Silero-VAD-v5 | CoreML | ~1,2 Mo | aufklarer/Silero-VAD-v5-CoreML |
| Pyannote-Segmentation-3.0 | MLX | ~5,7 Mo | aufklarer/Pyannote-Segmentation-MLX |
API Swift
import SpeechVAD
// VAD hors ligne (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 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")
}
}
Également disponible sur Android et Linux via ONNX Runtime.