Offline Voice Commands on Linux with Python and ONNX
For a robot, kiosk, media controller, or industrial tool with a fixed command set, full speech recognition is often unnecessary. A compact multi-keyword model can call local Python functions immediately and keep audio off the network.
Architecture
microphone → 16 kHz PCM → Mel features → ONNX model
→ detection filters → command callback → local actionThe model only decides which configured keyword was heard. Your application remains responsible for permissions, business logic, and safe action execution.
Install the runtime
sudo apt install python3-venv portaudio19-dev
git clone https://github.com/voicute/onnx-wakeword.git
cd onnx-wakeword
python3 -m venv .venv
source .venv/bin/activate
pip install onnxruntime numpy pyaudioTest the audio device
python python/mic_test.py --list-devicesConfirm the intended input is visible before debugging the model. USB microphones can change device indexes after reboot, so production code should select a stable device name where possible.
Connect detections to actions
from python.wakeword_engine import WakeWordEngine
def on_command(word, probability, info):
actions = {
"lights on": turn_lights_on,
"lights off": turn_lights_off,
"next": show_next_item,
"stop": stop_current_job,
}
action = actions.get(word)
if action:
action()
engine = WakeWordEngine()
engine.load("models/model_info.json", "models/melspectrogram.onnx")
engine.start(on_command)Do not pass recognized text to a shell
Map known model labels to predeclared functions. Avoid building shell commands from callback strings, and require confirmation for deletion, door control, payments, or safety-related machinery.
Service deployment
Once the foreground microphone test works, wrap the process as a systemd service with a dedicated unprivileged user. Give it access only to the microphone and devices it actually controls. Log detections and errors, but do not retain raw audio unless users explicitly opt in.
Raspberry Pi note
The Python path is suitable for 64-bit ARM when ONNX Runtime is available. The repository also contains a TFLite inference script for 32-bit Raspberry Pi. A dedicated Pi guide should include real Pi OS installation and timing results before making performance claims.