decibri
Cross-platform audio capture, output, and processing for Node.js and browsers.
Installation
One package for Node.js and browsers. Node.js gets a native addon (Rust via napi-rs). Browsers get a JavaScript AudioWorklet implementation. Platform-specific binaries are installed automatically.
Requires Node.js >= 18. TypeScript definitions are bundled.
Using from Rust
Most users want the npm package above. If you're building a Rust
application directly against the decibri crate on crates.io:
The vad feature (enabled by default) uses ONNX Runtime via the
ort crate. From 3.1.0 onwards, ort is
configured with load-dynamic by default, meaning ONNX Runtime is loaded
from a shared library at runtime. Choose one of:
-
Zero-config builds. Opt into the download-binaries mode:
= { = "3.1", = ["ort-download-binaries"], = false }Add back any other features you need (
capture,output,vad,denoise,gain). ORT is downloaded duringcargo buildand embedded in your binary (the 3.0.x behaviour). -
Production deployments with bundled ORT. Take default features, then either set
ORT_DYLIB_PATH=/path/to/libonnxruntime.{so,dylib,dll}before first use, or callort::init_from(path).commit()at startup. ONNX Runtime is initialized once per process. If your app creates multipleSileroVadinstances with different paths, the first one wins and later paths are silently ignored. Pick one path and reuse it.
If you only need capture, output, or DSP (no Silero VAD), you won't pull
in ort at all:
= { = "3.1", = ["capture", "output"], = false }
See the ort crate linking docs
for runtime-loading details.
Quick Start
Capture audio
const Decibri = require;
const mic = ;
mic.;
setTimeout;
Play audio
const = require;
const speaker = ;
speaker.;
speaker.;
Browser capture
import from 'decibri'; // browser entry via conditional export
const mic = ;
mic.;
await mic.; // requires user gesture in Safari
Pipe capture to playback (echo)
const mic = ;
const speaker = ;
mic.;
API: Decibri (Capture)
new Decibri(options?)
Creates a Readable stream that captures from the microphone.
| Option | Type | Default | Description |
|---|---|---|---|
sampleRate |
number | 16000 |
Samples per second (1000–384000) |
channels |
number | 1 |
Input channels (1–32) |
framesPerBuffer |
number | 1600 |
Frames per chunk (64–65536). At 16kHz mono, 1600 = 100ms = 3200 bytes |
device |
number | string | system default | Device index or case-insensitive name substring |
format |
'int16' | 'float32' |
'int16' |
Sample encoding |
vad |
boolean | false |
Enable voice activity detection |
vadMode |
'energy' | 'silero' |
'energy' |
VAD engine: RMS threshold or Silero ML model |
vadThreshold |
number | 0.01 / 0.5 |
Speech threshold. Default depends on vadMode |
vadHoldoff |
number | 300 |
Silence holdoff in ms |
Standard ReadableOptions (e.g. highWaterMark) are also accepted.
Methods
| Method | Description |
|---|---|
mic.stop() |
Stop capture and end stream. Safe to call multiple times |
Decibri.devices() |
List available input devices |
Decibri.version() |
Version info: { decibri: '3.0.0', portaudio: 'cpal 0.17' } |
Properties
| Property | Type | Description |
|---|---|---|
mic.isOpen |
boolean | true while capturing |
Events
| Event | Payload | Description |
|---|---|---|
'data' |
Buffer |
Audio chunk (Int16 LE or Float32 LE) |
'backpressure' |
- | Internal buffer full, consumer too slow |
'speech' |
- | VAD: audio crosses threshold |
'silence' |
- | VAD: audio below threshold for vadHoldoff ms |
'end' |
- | Stream ended |
'error' |
Error |
An error occurred |
API: DecibriOutput (Playback)
new DecibriOutput(options?)
Creates a Writable stream for speaker playback.
| Option | Type | Default | Description |
|---|---|---|---|
sampleRate |
number | 16000 |
Playback sample rate (1000–384000) |
channels |
number | 1 |
Output channels (1–32) |
format |
'int16' | 'float32' |
'int16' |
Sample encoding of incoming data |
device |
number | string | system default | Output device index or name substring |
Standard WritableOptions (e.g. highWaterMark) are also accepted.
| Method / Property | Description |
|---|---|
speaker.write(chunk) |
Write PCM data for playback |
speaker.end() |
Signal end. Drains remaining audio, then emits 'finish' |
speaker.stop() |
Immediate stop. Discards remaining audio |
speaker.isPlaying |
true while audio is being output |
DecibriOutput.devices() |
List available output devices |
DecibriOutput.version() |
Same as Decibri.version() |
API: Browser
The browser API uses getUserMedia and AudioWorklet. It differs from the Node.js API because browser audio is fundamentally async.
new Decibri(options?)
Same options as Node.js, plus:
| Option | Type | Default | Description |
|---|---|---|---|
device |
string | system default | Device ID from Decibri.devices() (not index) |
echoCancellation |
boolean | true |
Browser echo cancellation |
noiseSuppression |
boolean | true |
Browser noise suppression |
workletUrl |
string | inline blob | Custom worklet URL for strict CSP |
Key differences from Node.js
| Aspect | Node.js | Browser |
|---|---|---|
| Start | Automatic on first read | await mic.start() |
| Base class | Readable stream |
Custom Emitter |
| Data type | Buffer |
Int16Array / Float32Array |
devices() |
Sync, returns array | Async, returns Promise |
| Sample rate | Direct via cpal | Resampled from native rate |
Voice Activity Detection
Energy mode (default)
Lightweight RMS energy threshold. No model required.
const mic = ;
mic.;
mic.;
Silero mode
ML-based detection using the Silero VAD v5 ONNX model. More accurate than energy mode, especially in noisy environments.
const mic = ;
mic.;
mic.;
The Silero model (~2MB) ships inside the npm package. No downloads or API keys required.
Device Selection
// System default
const mic = ;
// By name (case-insensitive substring match)
const mic = ;
// By index
const devices = ;
const mic = ;
;
// [
// { index: 0, name: 'Microphone', maxInputChannels: 2, defaultSampleRate: 48000, isDefault: true },
// { index: 1, name: 'USB Headset', maxInputChannels: 1, defaultSampleRate: 44100, isDefault: false }
// ]
Examples
Runnable examples are in examples/.
# Capture to WAV file (no dependencies)
# Stream to WebSocket (requires: npm install ws)
Integration guides for OpenAI, Deepgram, AssemblyAI, and other providers are at decibri.com/docs.
Platform Support
| Platform | Architecture | Audio Backend |
|---|---|---|
| Windows | x64 | WASAPI |
| macOS | arm64 | CoreAudio |
| Linux | x64 | ALSA |
| Linux | arm64 | ALSA |
| Browser | - | Web Audio API (AudioWorklet) |
How It Works
decibri is a Rust library using cpal for cross-platform audio I/O. The Rust core compiles to a Node.js native addon via napi-rs and ships pre-built binaries for each platform. Browser support uses a JavaScript AudioWorklet implementation with the same event-driven API.
Audio flows from the OS audio device through cpal's callback, into a crossbeam channel, through frame-exact buffering (guarantees consistent chunk sizes), and into Node.js via a threadsafe function. The JavaScript layer wraps this in a standard Readable stream.
License
Apache-2.0 © decibri