Why openWakeWord Custom Models Get Unstable Recall (25%–90%)
You train a custom wake word with openWakeWord, and the recall comes back anywhere from 25% to 90% depending on the word, the voice, or the day. That instability isn't your fault — it's baked into the architecture. Here's the mechanism, with the public issues to prove it.
The symptoms are on the record
- openWakeWord's own automated training notebook has produced models with 25.7% recall — a figure the project's manual-training path had to be used to fix (issue #110).
- The pretrained models that did hit 90%+ used a range of different hyperparameters, because "no single set works across all wake words" — the project's own words (discussion #171).
- An independent benchmark measured openWakeWord at 69% recall and 8.5 false triggers per hour.
- Non-English words (e.g. Korean) returned prediction scores of 0.0008–0.0015 — effectively unusable (issue #136).
The root cause: a frozen speaker-verification embedding
Every openWakeWord model is built the same way: a frozen Google speech_embedding — a 96-dimensional feature extractor — with a small per-word classification head bolted on top. The head is what gets trained; the embedding never changes.
Here's the problem. That embedding was trained for speaker verification: the task of recognizing who is speaking. To do that well, the network is explicitly rewarded for ignoring what is being said and capturing only the speaker's voice identity.
Wake-word detection is the opposite task: distinguish what is being said and ignore who is saying it. Using a speaker-embedding for that is an objective mismatch — you're asking a feature that was trained to throw away phonetic content to now discriminate phonetic content.
Three consequences
- Word-picking. In that frozen space, some words' phonemes sit far apart and some sit close together. Words that sit close can never be separated cleanly, no matter how you tune the head — which is exactly why "different words need different hyperparameters."
- Unstable recall. Change the TTS voice, add noise, or use a real speaker, and the embedding's separability for your word collapses. The same word that scored 90% can drop to 25%.
- English-only. The embedding is English-trained. German, French, Japanese, and Chinese phonemes aren't encoded, so scores collapse into the 0.001 range.
Why from-scratch training is stable
Voicute trains a TCN (temporal convolutional network) from scratch for each word. The filters learn "what this wake word sounds like" directly, instead of borrowing a feature space built for a different task. Convolutional inductive bias — local connections, weight sharing, translation invariance — makes the model data-efficient and stable under noise and speaker variation.
The result is what you'd expect: stable 90%+ recall, no word-picking, and native multi-language support (English, German, French, Japanese, Chinese) — with no per-word hyperparameter tuning.
| openWakeWord | Voicute | |
|---|---|---|
| Backbone | Frozen speaker-verification embedding | From-scratch TCN |
| Objective | Trained to ignore content | Trained to detect the word |
| Recall stability | 25%–90%, word-dependent | Stable 90%+ |
| Word-picking | Yes — per-word hyperparameters | No |
| Non-English | English-trained, ~0.001 scores | Native EN / DE / FR / JA / ZH |
FAQ
Why is my openWakeWord custom wake word sometimes not detected?
openWakeWord builds each word on a frozen English speaker-verification embedding that was trained to ignore what is being said. It only weakly separates different words, so recall swings from ~25% to ~90% depending on the word, voice, and noise.
Why do different openWakeWord wake words need different hyperparameters?
The frozen embedding separates some words' phonemes better than others. Words that sit close in that fixed space need aggressive head tuning — the project's own docs note that no single parameter set works across all wake words.
Why does openWakeWord fail on non-English wake words?
The embedding is English-trained. Non-English phonemes are poorly encoded, so prediction scores collapse to the 0.001 range for German, French, Japanese, Chinese, Korean, and others.
How do I get stable 90%+ wake word recall?
Train from scratch so the filters learn the target word directly. Voicute trains a from-scratch TCN from a typed word in 10–20 minutes — stable 90%+ recall, no per-word tuning, and no audio upload. See the openWakeWord alternative guide.
Train a stable wake word →