# Training a custom "hey wivexx" wake-word model

Wivexx's best-in-class wake detection (v1.57, Tier 3) uses
[openWakeWord](https://github.com/dscripka/openWakeWord) — a dedicated on-device
DNN that scores the **sound** of the wake phrase, giving near-zero accidental
activations (the same class of tech Alexa/Google use). This is far more precise
than the older "transcribe the audio then look for the word" approach, which is
what used to make Wivexx wake up during ordinary talk (especially in Spanish).

**What already works out of the box:** the pretrained **`hey_jarvis`** model — and
"hey jarvis" is Wivexx's hidden wake alias — so with `openwakeword` installed you
get acoustic detection for "hey jarvis" immediately, no training required.

**What this doc is for:** the brand phrase **"hey wivexx"** is a coined word, so no
pretrained model exists. To get best-in-class acoustic detection for "hey wivexx"
(not just the alias), train a small custom model and drop it in. Until you do,
"hey wivexx" keeps working via the built-in Whisper path — nothing is missing, the
custom model is purely an upgrade.

---

## How Wivexx uses the model (no code changes needed)

`wivexx_wakeword.py` auto-loads **any** `*.onnx` file placed in a `wake_models/`
folder next to the app, alongside the pretrained `hey_jarvis`. So the entire
"install" of a trained model is:

```
Wivexx - AI/
└── wake_models/
    └── hey_wivexx.onnx     ← drop the trained file here, restart Wivexx
```

The model's file name (minus `.onnx`) is what shows in the logs when it fires.
Keep the detection threshold at the default 0.5 (tune in Settings/config if needed).

---

## Training recipe (openWakeWord "automatic" pipeline)

> **Where to run it:** training needs a Linux environment with an NVIDIA GPU —
> on Windows use **WSL2 (Ubuntu) + CUDA**. It is **not** run on the user's machine
> and is **not** part of the app; it's a one-time build step. Budget **4–8 hours**
> on a GPU. (Note: this PC's own GPU has a VRAM-saturation issue — prefer a
> different machine or a cloud GPU / Google Colab for the training run.)

### 1. Set up the trainer (WSL2 Ubuntu)
```bash
python -m venv oww-train && source oww-train/bin/activate
pip install openwakeword[full]        # pulls torch, tensorflow, speechbrain, piper, etc.
python -c "import openwakeword; from openwakeword.utils import download_models; download_models()"
```

### 2. Generate synthetic training data (Piper TTS)
openWakeWord trains on **100% synthetic speech** — you never record yourself.
The automatic notebook synthesizes thousands of "hey wivexx" clips across many
Piper voices, speeds (0.7–1.3×) and accents (include Spanish-accented voices so a
Spanish speaker saying "hey wivexx" is covered), then augments them with real-world
noise, music and room reverb. It also generates **negative** clips of *other*
phrases so the model learns what NOT to fire on.

Use the official pipeline (easiest path — a Colab notebook that does all of this):
- `openWakeWord/notebooks/automatic_model_training.ipynb`
  (https://github.com/dscripka/openWakeWord/blob/main/notebooks/automatic_model_training.ipynb)

Set the target phrase to **`hey wivexx`** (and optionally add `wivexx` alone).
Recommended: ~30–50k positive clips + a large negative/background set.

### 3. Train + export to ONNX
The pipeline trains a tiny classifier on top of openWakeWord's frozen shared
feature extractor and exports a **~200 KB `.onnx`** model. Rename it to
`hey_wivexx.onnx`.

### 4. Validate before shipping
Feed known clips through the model and check the score separation:
```python
from openwakeword.model import Model
m = Model(wakeword_models=["hey_wivexx.onnx"], inference_framework="onnx")
# "hey wivexx" clips should peak ≳0.7; ordinary/Spanish speech should stay ≲0.1
```
(Wivexx's own smoke test pattern lives in the repo's scratch tests — synth a phrase
with edge-tts, decode to 16 kHz mono s16le with the bundled `bin/ffmpeg.exe`, then
`wivexx_wakeword.scan_clip(pcm, 16000)`.)

### 5. Ship it
Drop `hey_wivexx.onnx` into `wake_models/`. To roll it out to everyone, bundle it
in the release (add `wake_models/` to `make_release.py`) and promote `openwakeword`
from optional to a default dependency in `requirements.txt`.

---

## FAQ

**Do users have to train this?** No. With `openwakeword` installed they already get
best-in-class detection for "hey jarvis"; "hey wivexx" works via the Whisper path.
The custom model is an optional upgrade the maintainer trains once and bundles.

**Does it work in Spanish?** Yes — the wake phrase is a name, so it's
language-independent, and the Whisper fallback path auto-detects the spoken
language (v1.57 Tier 1). For the acoustic model, include Spanish-accented Piper
voices in the synthetic data so accented "hey wivexx" is covered.

**Is it free?** Yes — openWakeWord is Apache-2.0, fully local, no API key. (The
alternative, Picovoice Porcupine, needs an account access key — that's why Wivexx
uses openWakeWord.)
