Desktop voice helper that listens for a primary wake word, records a short command, and transcribes locally. It also supports zero-shot command wakewords (ONNX models) that map directly to Home Assistant actions via an optional Hub API.
Audio stays on-device for wake word detection and transcription.
- Wake word detection (openWakeWord)
- Optional zero-shot command wakewords (ONNX) -> Hub action
- Local speech-to-text (faster-whisper)
- Optional Hub API for Home Assistant control (FastAPI + MCP)
- Python 3.10/3.11
- A working microphone
ffmpegrecommended for faster-whisper- PortAudio for
sounddevice
macOS: upgrade Python if needed
Check your Python version:
python3 --versionIf it's below 3.10, install a newer Python with Homebrew:
brew install python@3.11
python3.11 --versionSystem deps:
sounddeviceneeds PortAudiofaster-whisperworks best withffmpeginstalled
Ubuntu
sudo apt-get update
sudo apt-get install -y portaudio19-dev ffmpegmacOS
brew install portaudio ffmpegpython3.11 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txtCreate a per-machine .env:
cp .env.example .envEdit .env (see .env.example for the full list):
Core settings:
WAKEWORD: model name (e.g.hey_mycroft,hey_jarvis) or a local.onnxpath.THRESH: detection threshold (higher = fewer false positives).COOLDOWN: seconds to ignore repeat triggers after a detection.COMMAND_SECONDS: how long to record after the wake word.WHISPER_MODEL: faster-whisper model (e.g.tiny,base,small).WHISPER_DEVICE:cpuorcuda(if supported).WHISPER_COMPUTE_TYPE: e.g.int8,float16.
Zero-shot command wakewords:
COMMAND_WAKEWORDS: comma-separated list of ONNX paths for command models.COMMAND_THRESH: detection threshold for command models.COMMAND_COOLDOWN: cooldown seconds for command models.
Hub forwarding (optional):
HUB_URL: Hub API base URL (actions are POSTed to/hub/action).HUB_API_KEY: optional header sent asX-API-Key(server does not enforce by default).HUB_TIMEOUT: request timeout in seconds.
Home Assistant (Hub API host only):
HA_URL: Home Assistant base URL (example:http://192.168.122.195:8123).HA_TOKEN: long-lived access token.HA_LANGUAGE: language for HA Assist (defaulten).
- Put ONNX models in
models/(or any path you prefer). - Set
COMMAND_WAKEWORDSto those model paths. - Ensure each model's filename stem matches an entry in
desktopvoice/hub_routes.pyACTION_MAP. - Keep
ZERO_SHOT_ACTIONSindesktopvoice/main.pyaligned withACTION_MAP(if you use the local allowlist).
Example:
models/main_on.onnx-> action keymain_onACTION_MAP["main_on"] = {"domain": "light", "service": "turn_on", ...}
source .venv/bin/activate
python -m desktopvoiceRequirements:
uvxavailable on the Hub host (install viapipx install uvorpip install uv).ha-mcpavailable touvx(used by the MCP client to talk to Home Assistant).
Start the API server:
uvicorn desktopvoice.hub:app --host 0.0.0.0 --port 8000 --reloadSmoke test:
curl http://192.168.1.160:8000/hub/health
curl -X POST http://192.168.1.160:8000/hub/action \
-H "Content-Type: application/json" \
-d '{"action":"main_on"}'Customize ACTION_MAP in desktopvoice/hub_routes.py to match your scripts and entities.
- Slow STT: use a smaller model (
WHISPER_MODEL=tinyorbase) and/or reduceCOMMAND_SECONDS. - Wake word not triggering: lower
THRESH, check microphone input, or setWAKEWORDto a local.onnxfile. - Zero-shot action not firing: confirm the ONNX filename stem matches
ACTION_MAPand the entry exists. - Hub errors: verify
HA_URL,HA_TOKEN, and thatuvx ha-mcpruns on the Hub host.