Train custom microWakeWord models on Apple Silicon with a local web UI, multilingual samples from a modern OmniVoice/Qwen3/MOSS ensemble, device-captured samples, reviewed false-wake negatives, live training logs, and local wake-word links for Tater Native satellites.
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.
- The entire interface is reactive Vue 3 + TypeScript, following the same typed component pattern as Tater's newer UI surfaces.
Trainerstarts a wake-word session, shows positive/negative sample counts, and launches training.Auto Trainingtranscribes wake triggers, files phrase-misses as reviewed negatives, retrains on a schedule, and requests a satellite model refresh through Tater.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.Wake Wordslists locally trained JSON/model links for live wake-word switching in Tater.- Popup consoles show colorized training logs while long-running jobs are active.
The production bundle is committed under static/ui, so the web launcher and signed macOS app do not need Node.js. To change the UI, edit frontend/src and rebuild it:
cd frontend
npm install
npm run buildnpm run build type-checks every Vue component before writing the offline bundle used by trainer_server.py.
The easiest way to run the trainer on Apple Silicon is the signed macOS app from the GitHub releases page:
Download WakeWord Trainer for macOS
The app wraps the same local web UI, keeps the capture server running from the menu bar, and opens the trainer in a native macOS window. It stores captured audio, samples, generated models, caches, and local environments in:
~/.taterwakewordtrainer/
Use the manual clone flow below if you want to develop the trainer, run directly from source, or inspect the scripts.
git clone https://github.com/TaterTotterson/microWakeWord-Trainer-AppleSilicon.git
cd microWakeWord-Trainer-AppleSilicon./run.shThe launcher:
- requires Python
3.11by default at/opt/homebrew/bin/python3.11 - creates or reuses
~/.taterwakewordtrainer/recorder-venv - installs the UI dependencies
- serves the app on
0.0.0.0:8789so satellites can send captured audio
Running from a Git clone still keeps datasets, samples, generated features, models, logs, caches, and local environments under ~/.taterwakewordtrainer. The source checkout is not used as a training-data directory.
Open:
http://127.0.0.1:8789
Useful overrides:
REC_HOST=127.0.0.1 ./run.sh
REC_PORT=8790 ./run.sh
REC_PYTHON_BIN=/path/to/python3.11 ./run.shIf you change REC_PORT, use that same port in the satellite Trainer App URL.
The native app lives in:
macos/WakeWordTrainer/
It wraps the same local web UI, keeps the capture server running from a menu bar item, and opens the trainer in an embedded macOS window. On first launch it copies the bundled trainer source into:
~/.taterwakewordtrainer/app/current
Captured audio, samples, generated models, caches, and local virtual environments stay in that support folder so app updates do not wipe training data.
Build locally:
macos/WakeWordTrainer/scripts/build_app.shBuild the updater zip and manifest:
macos/WakeWordTrainer/scripts/package_update.shBuild the drag-to-Applications installer DMG:
macos/WakeWordTrainer/scripts/build_dmg.shTagged releases matching the app version, for example v15, run .github/workflows/macos-release.yml. The workflow builds the updater zip, installer DMG, update manifest, uploads them as workflow/GitHub release assets, and commits the generated release files back to main.
Update WHATS_NEW.md before creating a release tag. The workflow prepends that curated section to GitHub's automatically generated release notes.
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:
personal_samples/
False wakes move into:
negative_samples/
Captured audio is boosted for easier playback in the UI, then kept in the correct training format.
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.
- Enter the wake phrase in
Trainer. - Choose the language.
- Choose the TTS source.
Four-provider ensembleis recommended when Piper is available. - Optionally preview the phrase with the Mac system voice. This preview is separate from the training engines.
- 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 included as a separate hard-negative feature set when present, so false wakes from your real devices can make the next model more selective.
Auto Training is disabled until it is configured in its own tab.
- Enter the active wake phrase, STT language, and local STT engine.
- Choose how often training may run and how many new negatives are required.
- Set the Tater URL (normally
http://127.0.0.1:8501when Tater runs on the same Mac), clickLink Tater, and enter the short-lived code shown in Tater Voice Settings. After training, the trainer tells Tater which new wake-word JSON is active and Tater broadcasts it to every satellite. - Save and enable Auto Training.
New wake-trigger captures are transcribed locally with the engine selected in Auto Training. Faster Whisper is the recommended default, Parakeet ONNX provides a multilingual ONNX option, and MLX Whisper remains available for users who prefer it. A normal wake trigger moves to negative_samples/ only when STT returns text and the configured wake phrase is absent. By default, confirmed phrase matches stay in Captured Audio for review.
Two optional cleanup rules are available:
Delete confirmed good wakesremoves normal wake-trigger clips after STT confirms the configured phrase.Promote confirmed close misseschecks close misses that passed VAD and moves them to the personal positive samples only when STT confirms the configured phrase.
A close miss that was blocked by VAD, has an empty transcript, or does not contain the configured phrase stays in Captured Audio; it is never turned into a negative automatically. Captures for another configured wake word also stay out of the automatic path. The transcript and auto-review reason remain in sample or Auto Training state metadata for auditing.
Saving Auto Training settings also scans existing eligible captures. Enabling close-miss promotion reviews previous unreviewed close misses, while enabling cleanup removes previously confirmed good wakes without transcribing them a second time.
The UI intentionally exposes only the STT engine. The trainer manages the matching model and runtime settings: Faster Whisper uses small.en for English and small for other languages, MLX Whisper uses the matching managed base model, and Parakeet uses the INT8 nemo-parakeet-tdt-0.6b-v3 model. Models download on first use into auto_train_models/ and are reused. Scheduled training only starts after the configured number of new auto-reviewed negatives has accumulated. A successful automatic run securely publishes the trained wake-word name and JSON URL to the linked Tater instance. Tater saves it as the global satellite wake word and pushes the updated setting to every connected satellite.
Use Review inbox now, Train now, and Publish current wake word now to run each stage manually while testing the setup.
The language picker is built from the live OmniVoice catalog and the installed modern/legacy engines.
- OmniVoice supplies the broad multilingual route (hundreds of catalog languages).
- Qwen3-TTS joins the ensemble for Chinese, English, Japanese, Korean, German, French, Russian, Portuguese, Spanish, and Italian.
- MOSS-TTS-Nano joins the ensemble for its published multilingual set.
- Languages covered by all three engines are marked
Recommended; smaller ensembles are markedSupportedorExperimental. - Qwen, OmniVoice, and Piper generate final corpus takes directly. MOSS Nano is clone-only, so each MOSS take uses a different already-accepted direct take as its carrier instead of cycling a small profile bank.
- Qwen exposes 18,750 balanced voice conditions before any instruction repeats, while fresh sampling seeds add further variation. Piper uses the full speaker set in its installed model.
- Every candidate is checked for static, broadband/high-frequency noise, silence, clipping, excessive duration/rambling, and exact duplication before it can enter training. Failed provider shares are filled by a safer provider.
Model environments and weights download on first use and are cached under ~/.taterwakewordtrainer/app/current. The Qwen and MOSS paths use MLX-Audio on Apple Silicon; OmniVoice uses PyTorch MPS. These environments are isolated from the TensorFlow training environment.
Four-provider ensemble uses OmniVoice, Qwen, MOSS, and Piper when a compatible Piper model exists, and safely falls back to the modern providers where it does not. Modern only excludes Piper, and Piper only preserves the legacy comparison route.
The first training run downloads and prepares the training datasets when they are missing. After the datasets are prepared, later runs reuse the local copies.
Model downloads, completed generated corpora, and feature caches are reused when the selected language, wake word, TTS mode, and sample inputs have not changed.
The Wake Words tab lists locally trained wake-word packages from trained_wake_words/.
- Copy the JSON URL into the Tater Native satellite settings to switch wake words live.
- Open the JSON or model links directly for quick inspection.
- The JSON includes the matching model path plus Tater tuning metadata.
- No firmware flashing happens from this trainer app anymore.
Use the main Tater app for satellite firmware updates and USB flashing.
Successful runs produce firmware-ready artifacts in:
trained_wake_words/<wake_word>.tflite
trained_wake_words/<wake_word>.json
The Wake Words tab uses this folder to populate the local wake-word links.
Wake-word links now advertise a LAN-reachable address instead of copying the browser's 127.0.0.1 host. The trainer uses this order:
Trainer public URLfrom the Auto Training tabREC_PUBLIC_BASE_URL- an automatically discovered LAN IPv4 address and
REC_PORT
Set the public URL explicitly if the Mac has multiple network interfaces or the satellites reach it through a different hostname.
The JSON keeps the standard microWakeWord fields for compatibility:
{
"micro": {
"probability_cutoff": 0.97,
"sliding_window_size": 6
}
}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": 6,
"close_miss_threshold": 0.80,
"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.
Calibration evaluates thresholds from 0.95 through 1.00 with sliding windows of 5, 6, and 7. Among candidates within 0.5 percentage points of the best recall, it prefers the lowest measured ambient false-accept rate. If calibration cannot complete, packaging uses the conservative 0.97 threshold and a window of 6.
Intermediate training files are created under:
trained_models/
Run the Apple Silicon training pipeline directly:
./train_microwakeword_macos.sh "hey_tater"The direct script defaults to the four-provider route and generates every final corpus take directly. Compatibility examples:
./train_microwakeword_macos.sh "hey_tater" 50000 8 --language en --tts-mode hybrid
./train_microwakeword_macos.sh "hey_tater" 50000 8 --language en --tts-mode modern
./train_microwakeword_macos.sh "hey_tater" 50000 100 --language en --tts-mode piperIf personal_samples/*.wav or negative_samples/*.wav exists, those samples are included automatically.
- 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. - Trainer feedback settings live in Tater for Tater Native satellites, and on device entities for older ESPHome satellites.
Built on top of:
- microWakeWord
- OmniVoice
- Qwen3-TTS
- MOSS-TTS
- MLX-Audio
- piper-sample-generator (optional legacy mode)