horchd xyz
v0.1 · early · Linux only

horchd_

a daemon that listens.

Native Linux multi-wakeword detection. Loads N user-defined .onnx classifiers in parallel, listens to your mic, and broadcasts a D-Bus Detected signal the moment any of them fires. Anything that speaks the session bus can subscribe.

# clone, install dynamic-ort variant $ cargo install --git https://codeberg.org/NewtTheWolf/horchd horchd \ --no-default-features --features dynamic-onnxruntime $ systemctl --user enable --now horchd
session bus → xyz.horchd.Daemon1.Detected · CLOCK_MONOTONIC
Signal path

From microphone capture to D-Bus signal in one frame.

Every stage is the same one openWakeWord uses, ported to Rust + ONNX Runtime. The two universal models load once and feed every detector; adding the N-th wakeword costs one classifier evaluation per frame, not a second audio thread.

01
mic
16 kHz mono cpal capture
02
frame
1280 samples 80 ms hop
03
melspec.onnx
32 mel bins universal
04
embed.onnx
96-d / 80 ms universal
05
window
16 frames 1.28 s
06
classifier
(1, 16, 96) → (1, 1)
07
Detected
name · score timestamp
Instrument readout

Lean enough to run on whatever hardware you already own.

Numbers from a release build on consumer x86. Wakeword detection is the kind of always-on background work that should be invisible — these budgets are the reason `horchd` aims to be.

Frame rate
12.5 fps
one classifier eval per 80 ms input frame · sub-1 ms each
CPU at idle
≈1 %
single core, modern x86 · scales linearly with unique models
Binary
5.2 MB
dynamic ort · 28.9 MB with onnxruntime bundled
Inference
≤1 ms
per model per frame · 1.5 MB shared + 80 KB per wakeword
Three principles

What `horchd` is, in one paragraph each.

№ I

Native to the metal.

Single Rust 2024 binary. No Python interpreter at runtime, no virtualenv to bootstrap, no GPU required. Boots in well under a hundred milliseconds, fits in the systemd user-unit lifecycle without ceremony.

Rust · ONNX Runtime · cpal
№ II

N wakewords. One pipeline.

The two universal preprocessing models load exactly once. Every additional [[wakeword]] block adds one classifier evaluation per 80 ms — not a duplicate audio thread, not a duplicate ONNX session. Cost scales with unique model files, not detector instances.

openWakeWord · multi-model
№ III

Speaks D-Bus, not a custom port.

Every Linux desktop already runs a session bus. horchd registers xyz.horchd.Daemon1 there, broadcasts a typed Detected signal, and lets anything subscribe — Home Assistant bridges, shell scripts, the bundled horchctl monitor, the tray app. No HTTP listener, no auth to invent, no protocol to maintain.

session bus · no policy file