microWakeWord vs an online generator: custom wake words on the ESP32-S3
If you want wake-word detection on the device itself — an ESP32-S3, an ESPHome build, a Home Assistant Voice Preview Edition — microWakeWord is the community's answer. It's open source, its preset models are one YAML block away in ESPHome, and its INT8 TFLite models are genuinely tiny.
I run Voicute, an online wake-word generator, so I get asked how it compares. Since microWakeWord keeps coming up alongside openWakeWord as if they were one thing: they're two separate projects by different authors, from the same Home Assistant ecosystem. openWakeWord runs server-side; microWakeWord runs on the microcontroller. This post is only about the microcontroller side.
Where microWakeWord shines
For a supported preset wake word, it's hard to beat:
- Official ESPHome
micro_wake_wordcomponent — detection stays on-device, no audio streamed anywhere - Preset models already tuned for ESP32-S3-class hardware
- INT8 TFLite models small enough for flash and RAM budgets on an MCU
- An active community around Home Assistant Voice
If one of the preset words works for your product, use it. The rest of this post is about the case where it doesn't — your phrase isn't available, and you need a custom model.
What a custom microWakeWord model actually takes
The framework is open and the training docs are good. But "custom" means you assemble the whole data pipeline yourself:
- Generate synthetic positives with the Piper sample generator (free, open TTS)
- Collect real hard negatives — confusable phrases, TV, music, room noise from the target space
- Write the model config (JSON: features, architecture, quantization) by hand
- Train, export INT8 TFLite, flash, and evaluate on the actual microphone
- Iterate 1–4 until false accepts and recall both land where you need them
None of this is exotic — it's how wake-word models are built. It's just that every step is yours: every retrain cycle costs an afternoon of notebook-plus-desk time, and the quality ceiling is set by your data recipe.
Two recipe details decide most outcomes. First, synthetic positives only cover what TTS can say — Piper's voices have a recognizable character and a narrow accent range, and the gap between "Piper saying your phrase" and "a human saying it at 2 m through a MEMS mic" is where recall usually dies. Second, the negative set is what teaches rejection; generic background noise rarely contains the specific phrases your word actually gets confused with.
What an online generator changes
Again, full disclosure up front: I built Voicute, and its training platform is closed source. The inference engine and exported models are open (github.com/voicute/onnx-wakeword). Here's the honest side-by-side:
| microWakeWord | Voicute | |
|---|---|---|
| Code | fully open (framework + runtime) | training closed; engine + models open |
| Target | ESP32-S3-class MCUs (INT8 TFLite) | ONNX + TFLite — MCU, Python, Android, web, HA |
| Sample TTS | Piper (free) | commercial neural TTS |
| Real recordings | DIY — record, rebuild dataset, retrain | upload in browser, retrain is one click |
| Hard-negative mining | you curate the negative set | re-mined automatically on retrain |
| Config | model JSON written by hand | none — phrase in, model out |
| Multi-keyword | one model per phrase, stacked | 2–10 words in one model (~128 KB, <5 ms) |
| Languages | depends on available Piper voices/models | Chinese, English, German, French, Japanese workflows |
| Time to first model | hours–days (Colab ↔ device loop) | minutes to a testable model |
The three differences that matter in practice:
The record→retrain loop is minutes, not days. When the first model fails on real hardware — and a first model often fails — the microWakeWord path means rebuilding the dataset and running the training notebook again. In Voicute you record a small varied set of the real phrase, upload it, and retrain; hard negatives get re-mined for you. That loop speed is usually the difference between "we evaluated custom wake words" and "we shipped one."
Multi-keyword in one model. ESPHome-style runtimes load one model per phrase, so wake word plus a few commands means several models to train, manifest, and manage. Voicute trains 2–10 keywords into a single model, one inference pass, ~128 KB and under 5 ms on an ESP32-S3 — wake word and commands in the same budget as one standalone wake word.
TTS quality as a starting point. Piper is the right choice for a fully open pipeline; Voicute generates its synthetic positives with paid commercial-grade neural TTS instead. It's still synthetic audio — the synthetic-to-real gap exists for everyone — but starting closer to natural speech means fewer retrain cycles before the model survives a real room and a real accent.
When microWakeWord is still the right call
- A preset model fits, and you want zero new dependencies — ESPHome makes this a one-block change.
- The fully open stack (framework, runtime, training) is a hard requirement.
- Your team already has the data pipeline built and enjoys operating it.
When the generator earns its keep
- Your phrase isn't available as a preset, and non-English is often exactly this case.
- You need wake word + commands in one model on the device.
- The deadline is real and the person doing this is a firmware engineer, not an ML person.
- You want the first model testable in minutes, then decide whether it needs real recordings.
One thing that doesn't change on either path: the exported model is only half the system. The microphone, gain, enclosure, and feature pipeline decide as much as the weights do — test on the target hardware, measure recall and false accepts per hour, and never trust a single confidence score.
Disclaimer: I'm the creator of Voicute. microWakeWord is a genuinely well-built project and the ESPHome integration is excellent; if I've mischaracterized anything, tell me and I'll correct it.
Top comments (0)