openWakeWord Not Detecting? A Step-by-Step Low-Recall Checklist
A custom model that “does nothing” is not automatically a bad model. The failure may be in microphone capture, resampling, frame boundaries, feature extraction, the activation threshold, or a mismatch between synthetic training speech and real users. Test the pipeline in that order.
1. Prove that the model file is loaded
Start with a known WAV clip and call predict_clip() before opening the microphone. Use the exact model exported by training and print the returned model label and score. A wrong relative path, an older cached model, or an ONNX/TFLite mix-up can look exactly like zero recall.
from openwakeword.model import Model
model = Model(wakeword_models=["my_wakeword.onnx"])
print(model.predict_clip("positive_test.wav"))
2. Verify the audio contract
openWakeWord expects 16-bit, 16 kHz PCM audio. Its documentation recommends frames in multiples of 80 ms. Stereo input, float samples interpreted as integers, silent channels, unexpected resampling, or frames with the wrong byte order can suppress every score.
- Save five seconds of the exact runtime stream to a WAV file and listen to it.
- Print sample rate, channel count, sample type, frame length, minimum and maximum amplitude.
- Disable automatic gain control, noise suppression and echo cancellation temporarily.
- Confirm that speech is not clipped and is not close to digital silence.
3. Watch scores, not only trigger events
The included openWakeWord models commonly start around a 0.5 threshold, but the project recommends tuning it for each environment. Record the peak score for at least 20 intended utterances and several minutes of ordinary speech. Lowering the threshold can recover misses, but it also increases false activations.
| Observed behavior | Likely next step |
|---|---|
| Score always near zero | Check model loading, audio type, sample rate and feature pipeline |
| Correct phrase peaks just below threshold | Evaluate a lower threshold against negative audio |
| Works from WAV, fails from microphone | Compare capture/resampling and frame buffering |
| Works for one speaker only | Add speaker and pronunciation diversity to validation/training |
| Works in quiet, fails at distance | Add realistic noise, room response and far-field tests |
4. Separate missed detection from timing logic
A cooldown, VAD gate, debounce layer or requirement for several consecutive positive frames can block a valid model score. Turn these layers off for diagnosis, then restore them one by one. Keep a timestamped log of model score, VAD score, threshold decision and cooldown state.
5. Test outside the synthetic training distribution
A model trained mainly on clean TTS may learn standard pronunciation, clean timing and limited voice characteristics. Build a small holdout set using real target hardware: several speakers, normal and fast speech, near and far distances, quiet and noisy rooms. Do not tune on the same recordings used for training.
6. Improve the training data
- Use more than one TTS voice and vary speed, pitch and loudness.
- Add room impulse responses and background audio that resemble deployment.
- Include confusing phrases and phonetic neighbours as hard negatives.
- Add carefully segmented real recordings when a particular accent or user is missed.
- Evaluate both recall and false activations; optimizing only one moves the problem.
How Voicute reduces recall variation
Voicute does not treat a headline recall number as a universal guarantee. Its workflow trains a compact target-word model, expands synthetic speech across acoustic variations, applies noise and timing augmentation, and offers a voice-enhanced path that mixes selected real recordings with synthetic data. This reduces the gap between clean generated speech and actual microphones. The exported ONNX/TFLite model still needs threshold validation on the target device.