Mot de réveil / Détection de mots-clés
Le module SpeechWakeWord exécute un détecteur de mots-clés sur appareil : vous enregistrez une liste de phrases, poussez des fragments audio et recevez les détections. Basé sur le transducteur Zipformer en streaming d'icefall (3,49 M paramètres, Apache-2.0), compilé en CoreML avec palettisation INT8.
Le checkpoint livré est le fine-tuning KWS sur gigaspeech. Les mots-clés non anglais nécessitent un fine-tuning icefall distinct et une ré-exportation.
Architecture
| Étape | Détails |
|---|---|
| fbank | compatible kaldi (25 ms / 10 ms, fenêtre Povey, 80 bins mel, high_freq=-400, pas de CMVN) |
| Encodeur | Zipformer2 causal à 6 étages (128-dim), entrée 45 trames mel → 8 trames de sortie (40 ms / trame) — 3,3 Mo INT8 |
| Décodeur | Transducteur sans état, vocabulaire BPE-500, taille de contexte 2 — 525 Ko FP16 |
| Joiner | Projection linéaire + tanh — 160 Ko INT8 |
| Décodage | Beam search modifié (beam=4) sur un ContextGraph Aho-Corasick des mots-clés utilisateur |
Taille compilée sur disque : ~4 Mo au total (encoder.mlmodelc + decoder.mlmodelc + joiner.mlmodelc). Mémoire d'exécution : ~6 Mo incluant les caches de l'encodeur.
Performance
| Métrique | Valeur | Remarques |
|---|---|---|
| RTF (CPU + Neural Engine) | 0,04 | 26× temps réel sur série M |
| Rappel (12 mots-clés) | 88 % | LibriSpeech test-clean, 158 énoncés positifs |
| Faux positifs / énoncé | 0,27 | 60 énoncés négatifs |
| CoreML INT8 vs PyTorch FP32 | 99 % | Accord des émissions |
Valeurs par défaut calibrées : acThreshold=0,15, contextScore=0,5, numTrailingBlanks=1. Les surcharges par mot-clé sont prises en charge.
Utilisation CLI
Forme à phrase simple (BPE glouton — fonctionne bien pour les mots courants) :
audio wake recording.wav --keywords "hey soniqo"
audio wake recording.wav --keywords "hey soniqo:0.15:0.5" "cancel"
Forme pré-tokenisée (style sherpa-onnx — recommandée lorsque vous connaissez la décomposition exacte sur laquelle le modèle a été entraîné) :
# Format: "phrase|piece1 piece2 ...:threshold:boost"
audio wake recording.wav \
--keywords "LIGHT UP|▁ L IGHT ▁UP:0.25:2.0"
# Multiple keywords + JSON output
audio wake recording.wav \
--keywords "LIGHT UP|▁ L IGHT ▁UP:0.25:2.0" \
"LOVELY CHILD|▁LOVE LY ▁CHI L D:0.25:2.0" \
--json
Ou un fichier de mots-clés, une entrée par ligne (# pour les commentaires) :
audio wake recording.wav --keywords-file keywords.txt
API Swift
import SpeechWakeWord
// Load the model with your keyword list.
let detector = try await WakeWordDetector.fromPretrained(
keywords: [
KeywordSpec(phrase: "hey soniqo", acThreshold: 0.15, boost: 0.5),
KeywordSpec(phrase: "cancel")
]
)
// Streaming: push chunks, consume detections as they fire.
let session = try detector.createSession()
for chunk in micAudioChunks { // Float32 @ 16 kHz
for detection in try session.pushAudio(chunk) {
print("[\(detection.time(frameShiftSeconds: 0.04))s] \(detection.phrase)")
}
}
// Batch: single shot over a full buffer.
let detections = try detector.detect(audio: samples, sampleRate: 16000)
KeywordSpec
| Champ | Signification |
|---|---|
phrase | Phrase d'affichage, p. ex. "hey soniqo". Sert aussi de source pour le codage BPE glouton lorsque tokens est nil. |
acThreshold | Probabilité acoustique moyenne requise sur la plage correspondante. 0 → utilise la valeur par défaut calibrée (0,15). |
boost | Boost de contexte par token. Les valeurs positives facilitent le déclenchement de la phrase. 0 → valeur par défaut calibrée (0,5). |
tokens | Liste explicite optionnelle de pièces BPE. Quand elle n'est pas nil, le détecteur recherche chaque pièce dans le tokens.txt du modèle et contourne l'encodeur BPE glouton. |
tokens pré-tokeniséLe vocabulaire KWS d'icefall est BPE en majuscules. La tokenisation gloutonne d'une phrase peut choisir une décomposition BPE différente de celle sur laquelle le modèle a été entraîné — "LIGHT UP" se code gloutonnement en ▁LI GHT ▁UP mais la décomposition d'entraînement est ▁ L IGHT ▁UP. Quand la détection sur audio synthétisé par TTS ou parole lue propre manque des correspondances évidentes, essayez la forme pré-tokenisée style sherpa-onnx.
Téléchargements du modèle
| Modèle | Paramètres | Taille | HuggingFace |
|---|---|---|---|
| KWS-Zipformer-3M | 3.49M | ~4 MB | aufklarer/KWS-Zipformer-3M-CoreML-INT8 |
Intégration dans la pipeline
Le module expose un protocole WakeWordProvider qui reflète StreamingVADProvider, permettant à une pipeline vocale de contrôler l'activation via VAD, mot de réveil, ou les deux. WakeWordStreamingAdapter encapsule un détecteur chargé + une session unique dans un objet provider réutilisable.
let adapter = try WakeWordStreamingAdapter(detector: detector)
// pipeline.configure(wakeWord: adapter)
Sources
- Sources/SpeechWakeWord — module Swift
- docs/models/kws-zipformer.md — notes d'architecture
- docs/inference/wake-word.md — pipeline d'inférence
- Upstream : recette KWS k2-fsa/icefall / pkufool/keyword-spotting-models