[Tool] openwakeword-train — train your own wake words locally (TTS examples + real mic negatives, .onnx/.tflite export)

Reality check: everything here was vibe-coded (even this post — I’m lazy). The trainer is a byproduct of another project I’m working on: it does what I need, so don’t expect regular updates — I’ll only jump in on the first functional-bug reports.

What it is

openwakeword-train is a self-contained, fully local pipeline to train custom openWakeWord models for your own wake phrase — the thing you say to wake up the assistant (e.g. “yo Ève” or “Pixi”) instead of relying on the prebuilt models.

It’s the training side only: it produces the model files that openWakeWord consumes, ready for Home Assistant, ESPHome or an ESP32. It has no dependency on a bigger assistant ecosystem and runs entirely on your machine.

Why you’d want it

The default openWakeWord models cover a fixed set of phrases. If you’d rather use your own wake word — a family name, a shorter word, anything — you have to train it yourself. The catch is usually collecting enough negative examples so the model doesn’t fire every time someone talks. This tool automates that:

  • Positives — generates the target phrase with edge-tts (several voices × prosody variants), so you don’t record dozens of samples by hand.
  • Negatives — everyday sentences in the target language + noise, and crucially real microphone recordings (read a paragraph + room ambience) that become real negatives and background context. That’s what gets rid of false positives in real use.
  • Augmentation — audiomentations (noise, pitch, speed, distortion).
  • Same feature pipeline and architecture openWakeWord uses (1536→32→32→1, LayerNorm+ReLU), trained in numpy then exported.

Output

Each training produces in openwakeword/:

File Use
<name>.onnx the wake word model (openWakeWord / Python runtime)
<name>.tflite int8 quantized — ESP32 / ESPHome (lightweight)
<name>_float32.tflite float32 — Home Assistant (max fidelity)
<name>.calib.npy training embeddings used as int8 calibration
<name>.json metadata (phrase, threshold)

If you already have a .onnx and want the .tflite variants without re-training, there’s a post-creation converter (onnx_to_tflite.py) that auto-uses the saved .calib.npy for a faithful int8 (no need to pass it by hand).

Multilingual

Negative sentences, TTS voices, the vosk read-aloud text, and the vosk model are all language-aware. Currently shipped: English, French, German, Spanish — adding a language is a few dictionary entries.

Testing note: so far only French has been validated end-to-end (a model was actually trained and tested in real use). English, German and Spanish are implemented but not yet fully validated in real conditions — expect to polish them (or report issues) before relying on them.

Installation

git clone https://github.com/kinder85/openwakeword-train.git
cd openwakeword-train
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements-train.txt
# optional, only if you want the .tflite export (heavy ~600 MB):
# python -m pip install "onnx2tf[tensorflow]" tf-keras

Usage

One-time per language (downloads vosk model + asks for the two mic recordings):

python first_run_train.py --lang en

GUI (generate → listen to each sample → train & export):

python trainer_gui.py

Headless:

python trainer.py "hey there" --lang en

Notes

  • The exported model is auto-discovered by the openWakeWord runtime; this repo just produces the files.
  • Network is needed for TTS generation and the first-time model downloads; training itself runs fully local.

Feedback, issues and PRs welcome. GitHub - kinder85/openwakeword-train · GitHub

Thank you for being transparent about AI usage! That makes me far more likely to check into this :)