Why openWakeWord Custom Models Get Unstable Recall (25%–90%)

August 2026 · Voicute

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

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

  1. 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."
  2. 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%.
  3. 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.

openWakeWordVoicute
BackboneFrozen speaker-verification embeddingFrom-scratch TCN
ObjectiveTrained to ignore contentTrained to detect the word
Recall stability25%–90%, word-dependentStable 90%+
Word-pickingYes — per-word hyperparametersNo
Non-EnglishEnglish-trained, ~0.001 scoresNative 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 →