«Гектор» — tiny Ukrainian wake word for ESP32

Release v1.0 · October 2026

A tiny on-device model trained specifically to detect the Ukrainian word «Гектор» (Hektor) on an ESP32 microcontroller. It needs no cloud and no PC, takes 87 KB of flash and about 34 KB of RAM, and is estimated to listen continuously at a few percent of one ESP32-S3 core.

Built with microWakeWord as an int8 streaming network for TensorFlow Lite Micro. It works with ESPHome's micro_wake_word out of the box.

It is the wake word of Hektor, a six-legged walking robot: ESP32-S3 spine, INMP441 microphones, 18 servos, and a voice assistant (Deepgram STT → LLM → TTS over WebRTC). The robot only listens after it hears its name.

Wake word «Гектор», «Гекторе», «Гектор, »
Model MixedNet, streaming, int8 — 87 KB flash
RAM tensor arena 33.8 KB (30.6 KB minimum)
Compute ~39 k MAC per 30 ms step ≈ 1.3 MMAC/s
Input 16 kHz mono, 40 mel bins, 10 ms step
Default cutoff 0.8, sliding window 5 (150 ms)

Quick start

ESPHome

micro_wake_word:
  models:
    - model: https://huggingface.co/MartynU/hektor-micro-wakeword-esp32/resolve/main/manifest.json

Python (desktop, Raspberry Pi)

from huggingface_hub import snapshot_download
from pymicro_wakeword import MicroWakeWord, MicroWakeWordFeatures

path = snapshot_download("MartynU/hektor-micro-wakeword-esp32")
model = MicroWakeWord.from_config(f"{path}/manifest.json")
features = MicroWakeWordFeatures()

def on_audio(chunk: bytes):  # 16 kHz, mono, int16
    for f in features.process_streaming(chunk):
        if model.process_streaming(f):
            print("Гектор!")
            model.reset()

Evaluation

Test speakers and voices are held out from training. "Live" is the author speaking to the robot, captured by the robot's own INMP441 microphone and sent over Wi-Fi, i.e. the real deployment path.

Cutoff 0.8, sliding window 5:

Test set n Result
Recall, live voice via robot mic 22 95.5 % (21/22)
Recall, live voice + command 23 95.7 %
Recall, tempo-augmented speech (0.6–0.85×) 978 83.6 %
Recall, voice clones (FireRed) 355 68.5 %
Recall, Piper TTS voices 3000 55.5 %
Recall, cloud TTS voices (Cartesia, ElevenLabs, Gemini) 160 33.8 %
Recall, all held-out positives 4518 62.1 %
False accepts, negative clips 2146 4.2 %
False accepts, near-homophone «гектар» 71 1.4 %
False accepts / hour, DiPCo dinner-party speech 5.3 h 1.5
False accepts / hour, robot room ambient 14 min 0

Choosing a cutoff

Cutoff Live recall FA/h DiPCo
0.7 95.5 % 3.7
0.8 (default) 95.5 % 1.5
0.9 90.9 % 0.4
0.95 86.4 % 0

Full numbers for every group and both window sizes are in eval.json.

How it was built and tested

Test method

Every number on this page comes from an evaluation that copies how the model runs on the chip. Each clip is padded with 1 s of −60 dBFS noise before and 0.5 s after. It then goes through the micro-frontend (40 mel bins, 30 ms window, 10 ms step) and the streaming int8 model in 30 ms steps. A sliding average of the last N outputs fires when it crosses the cutoff, the same way ESPHome does it.

  • Recall is measured on held-out voices that were never used in training. The key set is the author's live voice recorded through the robot's own microphone and Wi-Fi link.
  • False accepts per hour come from streaming 5.3 h of DiPCo dinner-party conversation (one trigger per rising edge, 1 s refractory). A second figure comes from 14 minutes of the robot's room recorded through its own ears and checked with Whisper to contain no wake word.
  • All three training runs below were re-scored on the same final test set.

Three training runs

Run 1: baseline (6 Oct 2026). The microWakeWord training notebook with tweaks taken from a published Russian wake word trainer: class weights 1.5 / 1, SpecAugment, residual connections, background SNR −5…20 dB and never-silent padding. Only 9 live clips existed, oversampled ×3. The checkpoint was chosen by recall against false accepts on dinner-party speech. Synthetic voices worked, but live recall was 59 %. The model knew TTS but not a real person through a real microphone.

Run 2: push live recall (6 Oct 2026). Live clips oversampled ×5. Piper TTS negatives removed. The checkpoint and cutoff chosen on room noise recorded through the robot's ears. Live recall rose to 73 %, but false accepts on conversation jumped to 42 per hour. Validating only on a quiet room taught the model that "not silence" means "Гектор". Lesson learned: removing negatives and tuning on silence is a trap.

Run 3: more real data, balanced validation (7 Oct 2026) → this release.

  • 93 live recordings (70 for training, 23 held out), collected with a recording bot that runs through the robot's own ears.
  • Three phrase forms: «Гектор», «Гекторе» and «Гектор, ».
  • Piper negatives restored, plus 347 new hard negatives.
  • Live clips make up about 10 % of positives in each batch, with a 3× loss weight.
  • Validation set: robot room noise plus 1 h of dinner-party speech. The checkpoint was chosen for ≤ 0.5 false accepts per hour first, then for maximum recall.
  • 10 000 steps, 38 minutes on a Colab T4.

Result: live recall 95.5 %, 1.5 false accepts per hour on conversation, 0 in the room.

Run Cutoff Live recall FA/h DiPCo FA/h room
1 0.6 59.1 % 0 0
2 0.5 72.7 % 42.6 4.3
3 (v1.0) 0.8 95.5 % 1.5 0

Before microWakeWord

Before microWakeWord the project went through nine openWakeWord versions. Synthetic TTS voices were easy for them, but the author's live voice through the robot microphone was not. On the same 22 live test clips, the best openWakeWord model (v4d) caught 41 % at a low 0.2 threshold, against 95.5 % for this model. The gap came from the robot's microphone chain, the distance and real fast speech. Moving to microWakeWord, giving live and re-recorded clips more weight, and adding tempo augmentation closed it.

Training data

About 10.3 k positive training clips of three phrases: «Гектор», «Гекторе» and «Гектор, »:

  • Piper TTS voices and cloud TTS (Cartesia, ElevenLabs, Gemini) with varied emotion and speed;
  • voice clones of the author made with FireRed;
  • tempo augmentation 0.6–0.85×, because live speech is faster than TTS (0.5–0.7 s vs 0.8–1.2 s per word);
  • re-recordings through the robot's ears: TTS played back in a room and captured by the robot's INMP441 microphone at 1.5 m and 3 m;
  • 70 live recordings of the author through the robot, with a 3× loss weight.

Negatives: about 10.5 k own clips (similar-sounding words, everyday phrases and commands from TTS, Piper, the author's speech and robot-mic recordings) plus the precomputed negative spectrograms from kahrendt/microwakeword (speech, dinner party, no-speech). Augmentation used MIT room impulse responses, AudioSet and FMA background, and the robot's own room noise.

Every clip has a provenance record (source, TTS model, voice, phrase, date). Raw audio is not published.

The code behind all of this — clip generation, the three training runs with their configs, the evaluation scripts and the recording bots — is open source: hexapod-hektor/hektor-micro-wakeword-esp32.

Training: microWakeWord @4665173, 10 000 steps, batch 128, lr 0.001, class weights 1.5 / 1.0, SpecAugment 2×5 time and frequency. The checkpoint was selected for ≤ 0.5 false accepts per hour on room ambient, then for maximum recall. Trained on a Google Colab T4. Full config: training_parameters.yaml.

Limitations

  • Speaker-dependent. The live test set is a single speaker (the author), 22 clips. On unseen synthetic voices recall drops to 62 %. Expect lower recall for other speakers, children and different accents until the model is trained on more real voices.
  • Bare «Гектор» is harder than «Гекторе» (55 % vs 78 % on held-out synthetic voices at 0.8). The vocative form with its extra syllable triggers more reliably.
  • The room-ambient false-accept figure comes from only 14 minutes of audio.
  • Running on the robot's own ESP32-S3 is the next step. Today Hektor runs this model on the host (via pymicro-wakeword) on audio streamed from the ESP32-S3 microphone. On-device timing is estimated from the MAC count and will be measured on the chip in the next release.

License

CC BY-NC 4.0. The model was trained with negative data from kahrendt/microwakeword, which is licensed CC BY-NC 4.0, so this model is for non-commercial use. For a commercial wake word, the same pipeline can be retrained on commercially licensed negatives.

Author

Martyn: backend engineer moving into embedded systems. Hektor is built from scratch: hardware, ESP-IDF firmware, the voice pipeline and this model. Pipeline code: GitHub.

Downloads last month
19
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Collection including MartynU/hektor-micro-wakeword-esp32

Evaluation results

  • Recall, live speech via robot mic (n=22, cutoff 0.8) on Hektor held-out test set (live, robot microphone)
    self-reported
    95.500
  • False accepts / hour, DiPCo dinner-party speech (5.3 h) on Hektor held-out test set (live, robot microphone)
    self-reported
    1.500
  • False accepts / hour, robot room ambient (14 min) on Hektor held-out test set (live, robot microphone)
    self-reported
    0.000