Decibri (Rust)
Cross-platform audio capture, playback, and voice activity detection for Rust applications.
This is the Rust core of decibri. The same core powers decibri's Python and Node.js packages; see the main README for cross-language context.
Add to Cargo.toml
Or directly:
[]
= "4"
The default feature set (capture, playback, vad, ort-load-dynamic) covers most use cases. See Feature flags below for opt-in or trimmed configurations.
Quick start
The two primary types are Microphone for input and Speaker for output. Each follows the same shape: build a config, construct the object, then start() it to open the device and get a stream.
Capture and detect speech
use Duration;
use ;
MicrophoneStream::next_chunk returns a three-state Result: Ok(Some(chunk)) with data, Ok(None) on a timeout while the stream is still open, and Err(DecibriError::MicrophoneStreamClosed) once the stream ends.
Speaker output
use ;
let speaker = new?;
let stream = speaker.start?;
// f32 samples in [-1.0, 1.0]; here, one second of silence at 16 kHz mono.
let samples: = vec!;
stream.send?;
stream.drain; // block until everything queued has played
stream.stop; // immediate; discards anything remaining
SpeakerStream::send takes a Vec<f32> of samples in the range [-1.0, 1.0]. drain blocks until the device has finished playing the queue; stop is immediate and discards what remains.
List devices
use Microphone;
for device in devices?
Speaker::devices() is the playback equivalent. The free functions decibri::input_devices() and decibri::output_devices() return the same lists.
Without ONNX Runtime
If you do not need Silero VAD, disable the vad feature to drop the ONNX Runtime dependency entirely.
Feature flags
| Flag | Default | Purpose |
|---|---|---|
capture |
on | Microphone input stream support |
playback |
on | Speaker output stream support |
vad |
on | Silero voice-activity detection (pulls in ONNX Runtime) |
ort-load-dynamic |
on | ONNX Runtime loaded at runtime from a path you control |
ort-download-binaries |
off | ONNX Runtime downloaded at build time and embedded |
ort-load-dynamic and ort-download-binaries are mutually exclusive; selecting both is a compile error.
Execution-provider passthrough features (off by default; opt in for GPU acceleration on specific platforms): coreml, cuda, directml, rocm. See docs/features.md for the full reference.
Common configurations
Zero-config builds (ONNX Runtime downloaded at cargo build, embedded):
= { = "4", = ["ort-download-binaries"], = false }
Add back the other features you want (capture, playback, vad).
Production deployments with a bundled runtime (default; ONNX Runtime loaded at runtime from a path you control):
= "4"
Then either set ORT_DYLIB_PATH=/path/to/libonnxruntime.{so,dylib,dll} before first use, or call ort::init_from(path).commit() at startup. ONNX Runtime initializes exactly once per process; the first successful path wins and later constructions silently reuse it.
Capture and playback without VAD (no ONNX Runtime dependency at all):
= { = "4", = ["capture", "playback"], = false }
ONNX Runtime configuration
Under ort-load-dynamic (default), the ONNX Runtime shared library is located at runtime via a VadConfig::ort_library_path, the ORT_DYLIB_PATH environment variable, or a process-wide ort::init_from(...).commit() call. decibri performs a filesystem-level path check before handing the path off, so a missing or wrong-arch library surfaces as DecibriError::OrtPathInvalid rather than hanging on dynamic load.
See the ONNX Runtime linking docs for the full runtime-loading reference.
Fork safety (Linux)
ONNX Runtime initialized in a parent process does not survive fork() cleanly: internal threads, memory pools, and device handles belonging to the parent may misbehave in the child. Python consumers should use multiprocessing.set_start_method('spawn', force=True) before importing decibri. Node.js consumers using child_process or worker_threads are unaffected.
Public API surface
The stable 4.x surface includes:
microphone::Microphone,microphone::MicrophoneConfig,microphone::MicrophoneStream(try_next_chunk,next_chunk,is_open,stop)speaker::Speaker,speaker::SpeakerConfig,speaker::SpeakerStream(send,drain,is_playing,stop)vad::SileroVad,vad::VadConfig,vad::VadResultdevicemodule:input_devices()/output_devices(),MicrophoneInfo/SpeakerInfo, and selection by index, case-insensitive name substring, or stable per-host IDerror::DecibriError:#[non_exhaustive]enum covering capture, playback, device, ONNX Runtime, and fork-detection error variants
The common types are re-exported at the crate root, so use decibri::Microphone; works directly. Full API reference: docs.rs/decibri.
Thread safety
All public types are Send and suitable for cross-thread handoff. MicrophoneStream and SpeakerStream are !Sync because they hold a live platform audio stream internally; wrap them in a mutex or move them into a dedicated thread for shared access.
Platform support
| Platform | Architecture | Audio Backend |
|---|---|---|
| Windows | x64 | WASAPI |
| macOS | arm64 (Apple Silicon) | CoreAudio |
| Linux | x64 (gnu) | ALSA |
| Linux | arm64 (gnu) | ALSA |
Source builds work on additional targets (Intel macOS, Windows arm64, musl Linux) but are not part of the npm and PyPI binary release matrix. The crate itself has no per-target restriction beyond what the platform audio host supports.
Cross-references
- Project home: github.com/decibri/decibri
- Python package: bindings/python/README.md
- Node.js and browser package: npm/decibri/README.md
- Full Rust API: docs.rs/decibri
- Migration from 3.x: MIGRATION.md
- Changelog: CHANGELOG.md
- ONNX Runtime linking docs: ort.pyke.io/setup/linking
License
Apache-2.0 (c) 2026 Decibri.