Wake-Word / Schlüsselworterkennung
Das Modul SpeechWakeWord führt eine Schlüsselworterkennung direkt auf dem Gerät aus: Sie registrieren eine Liste von Phrasen, schieben Audio-Chunks hinein und erhalten Erkennungen. Basiert auf dem Streaming Zipformer-Transducer aus icefall (3,49 Mio. Parameter, Apache-2.0), kompiliert zu CoreML mit INT8-Palettierung.
Das ausgelieferte Checkpoint ist das gigaspeech-KWS-Fine-Tuning. Nicht-englische Schlüsselwörter benötigen ein separates icefall-Fine-Tuning und einen erneuten Export.
Architektur
| Stufe | Details |
|---|---|
| fbank | kaldi-kompatibel (25 ms / 10 ms, Povey-Fenster, 80 Mel-Bins, high_freq=-400, kein CMVN) |
| Encoder | 6-stufiger kausaler Zipformer2 (128-dim), 45 Mel-Frames rein → 8 Frames raus (40 ms / Frame) — 3,3 MB INT8 |
| Decoder | Zustandsloser Transducer, BPE-500-Vokabular, Kontextgröße 2 — 525 KB FP16 |
| Joiner | Lineare + tanh-Ausgabeprojektion — 160 KB INT8 |
| Dekodierung | Modifizierte Beam-Suche (beam=4) über einen Aho-Corasick-ContextGraph der Benutzer-Schlüsselwörter |
Kompilierte Größe auf dem Datenträger: ~4 MB insgesamt (encoder.mlmodelc + decoder.mlmodelc + joiner.mlmodelc). Laufzeitspeicher: ~6 MB inklusive Encoder-Cache.
Leistung
| Metrik | Wert | Anmerkungen |
|---|---|---|
| RTF (CPU + Neural Engine) | 0,04 | 26× Echtzeit auf M-Serie |
| Recall (12 Schlüsselwörter) | 88 % | LibriSpeech test-clean, 158 positive Äußerungen |
| Falschpositive pro Äußerung | 0,27 | 60 negative Äußerungen |
| CoreML INT8 vs. PyTorch FP32 | 99 % | Übereinstimmung der Emissionen |
Abgestimmte Standardwerte: acThreshold=0,15, contextScore=0,5, numTrailingBlanks=1. Per-Keyword-Überschreibungen werden unterstützt.
CLI-Nutzung
Einfache Phrasenform (gieriges BPE — funktioniert gut für gängige Wörter):
audio wake recording.wav --keywords "hey soniqo"
audio wake recording.wav --keywords "hey soniqo:0.15:0.5" "cancel"
Vorgetokenisierte Form (sherpa-onnx-Stil — empfohlen, wenn Sie die genaue Zerlegung kennen, auf die das Modell trainiert wurde):
# 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
Oder eine Schlüsselwortdatei, ein Eintrag pro Zeile (# für Kommentare):
audio wake recording.wav --keywords-file keywords.txt
Swift-API
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
| Feld | Bedeutung |
|---|---|
phrase | Anzeigephrase, z. B. "hey soniqo". Wird auch als Quelle für die gierige BPE-Kodierung verwendet, wenn tokens nil ist. |
acThreshold | Durchschnittliche akustische Wahrscheinlichkeit, die über der getroffenen Spanne erforderlich ist. 0 → abgestimmter Standard (0,15). |
boost | Per-Token-Kontext-Boost. Positive Werte erleichtern das Auslösen der Phrase. 0 → abgestimmter Standard (0,5). |
tokens | Optionale explizite BPE-Stückliste. Wenn nicht nil, schlägt der Detektor jedes Stück in der tokens.txt des Modells nach und umgeht den gierigen BPE-Encoder. |
tokens vorgegeben werden solltenDas icefall-KWS-Vokabular ist Großbuchstaben-BPE. Die gierige Tokenisierung einer Phrase kann eine andere BPE-Zerlegung wählen als die, auf die das Modell trainiert wurde — "LIGHT UP" wird gierig zu ▁LI GHT ▁UP kodiert, die Trainings-Zerlegung ist jedoch ▁ L IGHT ▁UP. Wenn die Erkennung bei TTS-synthetisierter oder sauberer Lesesprache offensichtliche Treffer verpasst, probieren Sie die sherpa-onnx-artige vorgetokenisierte Form.
Modell-Downloads
| Modell | Parameter | Größe | HuggingFace |
|---|---|---|---|
| KWS-Zipformer-3M | 3.49M | ~4 MB | aufklarer/KWS-Zipformer-3M-CoreML-INT8 |
Pipeline-Integration
Das Modul stellt ein WakeWordProvider-Protokoll bereit, das StreamingVADProvider nachbildet, sodass eine Sprach-Pipeline die Aktivierung über VAD, Wake-Word oder beides steuern kann. WakeWordStreamingAdapter kapselt einen geladenen Detektor + eine einzelne Session in ein wiederverwendbares Provider-Objekt.
let adapter = try WakeWordStreamingAdapter(detector: detector)
// pipeline.configure(wakeWord: adapter)
Quellen
- Sources/SpeechWakeWord — Swift-Modul
- docs/models/kws-zipformer.md — Architektur-Notizen
- docs/inference/wake-word.md — Inferenz-Pipeline
- Upstream: k2-fsa/icefall KWS-Rezept / pkufool/keyword-spotting-models