10 KiB
taterassistant.com
Train custom microWakeWord models in Docker with NVIDIA/CUDA acceleration, generated Piper samples, device-captured samples, reviewed false-wake negatives, live training logs, and prebuilt Tater firmware flashing.
Real samples come from device-captured wake audio, close misses, or manual uploads. Every saved sample is normalized to 16 kHz / mono / 16-bit PCM WAV before training.
Docker Image
docker pull ghcr.io/tatertotterson/microwakeword:latest
Tagged releases also publish matching immutable image tags:
docker pull ghcr.io/tatertotterson/microwakeword:v10
RTX 50-series / Blackwell GPUs use a separate image with CUDA 12.8 and a
Python 3.13 TensorFlow build for sm_120:
docker pull ghcr.io/tatertotterson/microwakeword:blackwell
docker pull ghcr.io/tatertotterson/microwakeword:v10-blackwell
Use the Blackwell image only for RTX 50-series cards. It includes the community-built TensorFlow wheel from chivitiH/tensorflow-blackwell-python313, which is unofficial and licensed CC BY-NC 4.0.
Run The Container
docker run -d \
--gpus all \
--network host \
-e REC_PORT=8789 \
-v $(pwd):/data \
ghcr.io/tatertotterson/microwakeword:latest
Use a version tag such as ghcr.io/tatertotterson/microwakeword:v10 when you want to pin a known release instead of tracking latest.
For RTX 50-series cards, use ghcr.io/tatertotterson/microwakeword:blackwell
or a pinned tag such as ghcr.io/tatertotterson/microwakeword:v10-blackwell
in the same docker run command.
The flags:
--gpus allenables GPU acceleration.--network hostlets the container receive mDNS/zeroconf traffic for device auto-detect.-e REC_PORT=8789sets the trainer web UI and captured-audio port. Change this value if8789is already in use.-v $(pwd):/datapersists models, downloaded voices, datasets, samples, and firmware caches.
Host networking is recommended for the Firmware tab's mDNS device discovery. Manual IP flashing and captured-audio uploads can still work without host networking if the trainer port is reachable, but auto-detect may not see devices from Docker bridge networking.
Open:
http://localhost:8789
If you change REC_PORT, open that port instead and use the same port in the satellite Trainer App URL.
What The UI Does
Trainerstarts a wake-word session, shows positive/negative sample counts, and launches training.Captured Audioreviews clips sent by Tater Native or ESPHome sats, including wake hits, close misses, and false wakes.Samplesplays, removes, clears, and manually imports personal or negative samples.Firmwarepulls verified prebuilt Tater firmware images from GitHub and flashes supported satellites over OTA.- Popup consoles show colorized training and firmware logs while long-running jobs are active.
Captured Audio Workflow
To collect samples from a sat, point its trainer feedback setting at this app. Tater Native satellites use the native settings popup in Tater. Older ESPHome satellites can still use their device entities.
For Tater Native satellites, enable trainer feedback in Tater:
Send Good Wakes To Trainertoggles upload of confirmed wake-word triggers.Send Close Misses To Trainertoggles upload of near misses.Trainer App URLsets the trainer address, for examplehttp://trainer.local:8789orhttp://<trainer-ip>:8789.
For older ESPHome firmware, the equivalent capture setup is exposed as device entities:
Capture Wake Audiotoggles upload of wake-word triggers.Capture Close Missestoggles upload of near misses.Trainer App URLsets the trainer address, for examplehttp://<trainer-ip>:8789.
Satellites send raw captured audio to:
/api/upload_captured_audio_raw
Keep the training app running and reachable at the Trainer App URL while capture is enabled. The sats upload clips live; if the app is stopped or the URL is wrong, captured audio will not be saved.
In the Captured Audio tab:
- play each clip from the inbox
- mark good wake-word clips as
This is good - mark bad triggers as
False wake - discard clips that should not be used
Approved clips move into:
/data/personal_samples/
False wakes move into:
/data/negative_samples/
Captured audio is boosted for easier playback in the UI, then kept in the correct training format.
Samples
The Samples tab is the sample library.
Personalsamples are positive examples of the wake word.Negativesamples are reviewed false wakes or hard negatives.- Both can be played back and removed one at a time.
- Manual upload is available here as an optional seed path.
Accepted manual upload formats include:
- WAV
- MP3
- M4A
- FLAC
- OGG
- AAC
- OPUS
- WEBM
Uploads are validated or converted with ffmpeg into:
16 kHz / mono / 16-bit PCM WAV
Starting a new session does not clear samples. Use the clear buttons in Samples if you want to remove saved personal or negative clips.
Training Flow
- Enter the wake phrase in
Trainer. - Choose the language.
- Optionally test pronunciation with
Test TTS. - Review the positive and negative sample counts.
- Click
Start training. - Watch the popup training console.
Personal samples are optional. Training can run with zero personal samples after confirmation, using generated TTS samples and the stock negative datasets.
Reviewed negative samples are converted into /data/work/reviewed_negative_features/ and inserted into the training YAML as a hard-negative feature set when present.
On RTX 50-series / Blackwell GPUs, the Blackwell Docker image keeps sample generation and augmentation in the normal Python 3.12 trainer environment, then runs only the TensorFlow training/export stage in /data/.venv-blackwell with Python 3.13 and the Blackwell-native TensorFlow wheel.
Language Support
The language picker is dynamic.
enis always available.- English keeps the existing dedicated generator model path.
- Non-English languages are discovered from the Piper voices catalog and any local Piper voice metadata.
- When a non-English language is selected, the trainer downloads all voices for that selected language only.
- Already-downloaded voices are reused.
- It does not download every language up front.
If the upstream Piper catalog is unavailable, already-installed local voices are used when available.
Dataset Behavior
The first training run downloads and prepares missing training assets into /data, including:
- Piper voices for the selected language
- negative datasets and background data
- the Python training environment
- generated samples and augmented feature caches
After those assets are prepared, later runs reuse the local copies unless the mounted /data contents are deleted.
Firmware Flashing
The Firmware tab flashes prebuilt Tater firmware for supported satellites.
- Downloads the latest prebuilt firmware manifest plus OTA and USB factory images from
TaterTotterson/Tater-Native-Firmware. - Verifies downloaded images by size and SHA before upload.
- Auto-detects compatible devices with mDNS when the container is running with host networking.
- Allows manual IP or hostname entry if discovery does not find the device.
- Saves the selected OTA target for each firmware family.
- Flashes the prebuilt factory image over Browser USB for first installs or recovery when opened in Chrome or Edge.
- Leaves Wi-Fi, Tater server, and pairing setup to the satellite setup portal after USB flash.
- Lists locally trained wake words from
/data/trained_wake_words/for live model switching. - Streams download, verification, and OTA upload progress in a colorized firmware console.
Tater only: these native firmware images connect to Tater. They are not Home Assistant or ESPHome satellite firmware.
You usually only flash for firmware updates. New satellites, or devices not already running Tater Native Firmware v1, need one USB flash first before OTA updates and live wake-word switching are available.
Output Files
Successful runs produce timestamped training output folders such as:
/data/output/<timestamp>-<wake_word>-<samples>-<steps>/<wake_word>.tflite
/data/output/<timestamp>-<wake_word>-<samples>-<steps>/<wake_word>.json
The trainer also syncs firmware-ready artifacts into:
/data/trained_wake_words/<wake_word>.tflite
/data/trained_wake_words/<wake_word>.json
The firmware tab uses /data/trained_wake_words/ to populate the wake-word dropdown.
The JSON keeps the standard microWakeWord fields for compatibility:
{
"micro": {
"probability_cutoff": 0.97,
"sliding_window_size": 5
}
}
It also includes Tater Native metadata used by newer satellites and the Tater settings UI:
{
"model_format": "tflite_stream_state_internal_quant",
"quantization": "int8",
"sample_rate": 16000,
"tater_native": {
"format_version": 1,
"wake_threshold": 0.97,
"wake_sliding_window": 5,
"close_miss_threshold": 0.78,
"frontend": {
"name": "tflm_microfrontend",
"sample_rate": 16000,
"feature_duration_ms": 30,
"feature_step_ms": 10,
"feature_size": 40
}
}
}
Calibration metrics are included under calibration so false accepts/hour and recall can be surfaced in the UI.
Resetting Everything
If you want a clean slate, stop the container and remove the contents of the mounted /data directory.
That removes:
- personal samples
- negative samples
- captured inbox clips
- downloaded Piper voices
- cached datasets
- training environments
- trained models
- downloaded firmware images
Important Notes
- Personal samples are optional.
- Negative samples are optional but useful for reducing false wakes.
- The UI server is
trainer_server.py. - The launcher is
run.sh. - Firmware capture settings live in Tater for Tater Native satellites, and on device entities for older ESPHome satellites.
Credits
Built on top of:
- microWakeWord
- piper-sample-generator
- tensorflow-blackwell-python313 for the optional RTX 50-series / Blackwell image