Complete reference for the decibri Node.js API. For installation and basic usage, see Getting started.
new Microphone(options?)Creates a Node.js Readable stream that captures raw PCM audio from the system microphone.
| Option | Type | Default | Description |
|---|---|---|---|
sampleRate |
number |
16000 |
Samples per second (1,000 to 384,000 Hz) |
channels |
number |
1 |
Mono only. The only accepted value is 1; any other value throws RangeError (multichannel capture is not supported). The option is kept for forward compatibility |
framesPerBuffer |
number |
1600 |
Frames per audio callback. Controls chunk size and latency (64 to 65,536) |
device |
number | string | { id: string } |
system default | Device index or case-insensitive name substring from Microphone.devices(), or { id } with a stable per-host device id |
dtype |
'int16' | 'float32' |
'int16' |
Sample encoding format |
vad |
false | 'energy' | 'silero' | VadOptions |
false |
Voice activity detection. false disables it. 'energy' uses RMS thresholding. 'silero' uses the bundled Silero v5 ONNX model for ML-based detection. Pass a VadOptions object to tune the threshold and holdoff |
modelPath |
string |
(bundled) | Path to a custom Silero VAD ONNX model. Only used when vad is 'silero'. When omitted, uses the model bundled with the package |
dcRemoval |
boolean |
false |
Remove a constant DC offset from the captured audio. See Audio Capture Engine |
denoise |
'fastenhancer-t' |
off | Neural speech enhancement using the bundled model. Unknown value throws TypeError. See Audio Capture Engine |
highpass |
80 | 100 |
off | Butterworth high-pass cutoff in Hz. Any other value throws RangeError. See Audio Capture Engine |
agc |
number |
off | Automatic gain control target in dBFS, -40 to -3. Out-of-range throws RangeError. See Audio Capture Engine |
limiter |
number |
off | Peak limiter ceiling in dBFS, -3.0 to 0.0. Out-of-range throws RangeError. See Audio Capture Engine |
The five conditioning options (dcRemoval, denoise, highpass, agc, limiter) are off by default and run as a fixed chain before each chunk is delivered. They are documented in full on the Audio Capture Engine page.
Standard Node.js ReadableOptions (e.g., highWaterMark) are also accepted. Voice activity detection (the vad and modelPath options) is documented in the Voice activity detection section below.
To construct without blocking the event loop on the open work (notably the Silero model load when vad: 'silero' is set), use the Microphone.open() async factory.
Microphone.open(options?)Static async factory. Returns Promise<Microphone>. Runs the open work (device resolution, and the Silero model load when vad: 'silero' is set) on the native thread pool instead of the event loop, then resolves to a ready instance. The synchronous constructor blocks for roughly 100 to 500 milliseconds on a cold Silero load; open() does not. Options are identical to the constructor. A failed open rejects with the matching error: RangeError or TypeError for invalid options, or DeviceError, OrtError, or OrtPathError for native failures.
const mic = await Microphone.open({ vad: 'silero' });
mic.on('data', (chunk) => { /* ... */ });
mic.stop()Stops microphone capture and ends the stream. Safe to call multiple times; subsequent calls are no-ops.
Microphone.devices()Returns an array of available audio input devices on the system.
const devices = Microphone.devices();
console.log(devices);
// [
// { index: 0, name: 'Built-in Microphone', id: '...', maxInputChannels: 1,
// defaultSampleRate: 44100, isDefault: true },
// ...
// ]
Each device object contains:
| Property | Type | Description |
|---|---|---|
index |
number |
Device index, used as options.device |
name |
string |
Human-readable device name reported by the OS |
id |
string |
Stable per-host device ID (WASAPI endpoint ID on Windows, CoreAudio UID on macOS, ALSA PCM identifier on Linux). Pass via device: { id }. Empty string when the backend cannot produce a stable ID |
maxInputChannels |
number |
Maximum number of input channels supported |
defaultSampleRate |
number |
Device's native/preferred sample rate in Hz |
isDefault |
boolean |
Whether this is the current system default input device |
Microphone.version()Returns version information for decibri and the audio backend. The audioBackend field reports the cpal version, and the binding field reports the npm package version.
Microphone.version();
// { decibri: '5.0.0', audioBackend: 'cpal 0.17', binding: '5.0.0' }
mic.isOpenboolean (read-only). Returns true while the microphone is actively capturing audio.
mic.vadScorenumber (read-only). Most recent VAD score for the active mode: the Silero speech probability in 'silero' mode, the normalised RMS of the last chunk in 'energy' mode. 0 when VAD is disabled or before the first chunk is processed. This is the raw per-chunk view; the debounced speaking state is surfaced through the 'speech' and 'silence' events. See Voice activity detection.
mic.overrunCountnumber (read-only). Number of capture buffers dropped because the consumer could not keep pace. 0 while the consumer keeps up, or before capture starts. A rising value means audio is being dropped to bound memory.
Microphone extends Node.js Readable, so all standard stream events are available:
'data': emitted when audio data is available (callback receives Buffer)'end': emitted when the stream ends (after stop())'error': emitted on microphone errors, including device disconnection (for example unplugging the microphone). When a device fails, isOpen becomes false and the 'error' event fires, rather than capture freezing silently.'close': emitted when the stream is closedWhen vad is enabled, the stream additionally emits 'speech' and 'silence'. Those are documented in the Voice activity detection section.
'backpressure'Emitted when the stream's internal buffer is full and the consumer is reading too slowly. Because a microphone cannot be paused, audio chunks continue to arrive. Drain the stream or drop data to avoid unbounded memory growth.
mic.on('backpressure', () => {
console.warn('Consumer is too slow, audio may be lost');
});
Decibri ships two VAD modes plus a disabled default, selected with the vad option on the Microphone constructor. When VAD is enabled, the microphone emits 'speech' and 'silence' events and updates the vadScore property. Both the energy detector and the Silero model run locally; there is no cloud call.
| Mode | Description | Default threshold | Threshold range |
|---|---|---|---|
false |
VAD disabled. No 'speech' or 'silence' events; vadScore stays 0. |
n/a | n/a |
'energy' |
Lightweight RMS-energy threshold computed natively over each chunk. | 0.01 | 0.0 to 1.0 |
'silero' |
ML-based detector using the bundled Silero v5 ONNX model, run through ONNX Runtime. | 0.5 | 0.0 to 1.0 |
VadOptions objectTo tune the threshold or holdoff, pass a VadOptions object as the vad option instead of a bare mode string. The vad: 'silero' and vad: 'energy' shorthands are equivalent to the object with its default tuning.
| Field | Type | Default | Description |
|---|---|---|---|
model |
'silero' | 'energy' |
required | Which detector to run |
threshold |
number |
mode default | Speech-detection threshold in [0, 1]. Defaults to 0.5 for 'silero' and 0.01 for 'energy'. A value outside the range throws RangeError |
holdoffMs |
number |
300 |
Milliseconds of sub-threshold audio after a speech period before 'silence' is emitted. A negative value throws RangeError |
const mic = new Microphone({ vad: { model: 'silero', threshold: 0.6, holdoffMs: 200 } });
'speech' and 'silence' eventsNode surfaces speaking state through events rather than a polled boolean. 'speech' fires when the VAD score crosses the configured threshold. 'silence' fires when the score then stays below the threshold for holdoffMs milliseconds after a speech period. Both require vad to be enabled. Because Microphone is a Readable stream, attach a 'data' listener (or otherwise consume the stream) so audio keeps flowing and the detector runs.
const mic = new Microphone({ sampleRate: 16000, vad: 'energy' });
mic.on('speech', () => console.log('Speech detected'));
mic.on('silence', () => console.log('Silence detected'));
mic.on('data', () => {}); // keep the stream flowing so VAD runs
For the raw per-chunk signal, read the mic.vadScore property documented above. vadScore is the underlying score; the 'speech' and 'silence' events are the debounced state derived from it via the threshold and holdoff.
The Silero VAD ONNX model and ONNX Runtime ship inside the npm package. No separate download, no API key, and no system onnxruntime dependency are required for vad: 'silero'. To use a different Silero ONNX variant, pass an absolute path on the modelPath option; it is consulted only when vad is 'silero'.
Each 2 bytes represents one 16-bit signed integer sample, little-endian. Range: -32,768 to 32,767.
mic.on('data', (chunk) => {
const samples = new Int16Array(chunk.buffer, chunk.byteOffset, chunk.length / 2);
});
Each 4 bytes represents one 32-bit IEEE 754 float sample, little-endian. Range: approximately -1.0 to 1.0.
const mic = new Microphone({ sampleRate: 16000, channels: 1, dtype: 'float32' });
mic.on('data', (chunk) => {
const samples = new Float32Array(chunk.buffer, chunk.byteOffset, chunk.length / 4);
});
new Speaker(options?)Creates a Node.js Writable stream for speaker playback. Extends Writable from the stream module.
const { Speaker } = require('decibri');
const speaker = new Speaker(options?);
| Option | Type | Default | Description |
|---|---|---|---|
sampleRate |
number |
16000 |
Samples per second (1,000 to 384,000 Hz) |
channels |
number |
1 |
Number of output channels (1 to 32) |
dtype |
'int16' | 'float32' |
'int16' |
Encoding of incoming PCM data |
device |
number | string | { id: string } |
system default | Output device index, case-insensitive name substring, or { id } with a stable per-host device id from Speaker.devices() |
highWaterMark |
number |
16384 |
Writable stream buffer size in bytes |
Standard Node.js WritableOptions are also accepted.
speaker.write(chunk)Writes PCM data for playback. Returns boolean. If false, the buffer is full; wait for the 'drain' event before writing more.
speaker.writeAsync(chunk)Returns Promise<void>. Writes PCM audio without blocking the event loop, performing the backpressure wait (when the native playback queue is full) on the native thread pool, and resolves when the samples are queued. This is an opt-in alternative to write(); do not interleave it with write() or pipe() on the same instance, and await calls sequentially to preserve sample order.
speaker.end([chunk])Graceful stop. Plays all remaining buffered audio, then emits 'finish'. Optionally accepts a final chunk to write before ending.
speaker.drainAsync()Returns Promise<void>. Waits for all queued audio to finish playing without blocking the event loop, resolving when the buffer has drained (immediately if nothing was written). Pair with writeAsync() for a fully non-blocking playback path.
speaker.stop()Immediate stop. Discards remaining buffered audio and releases resources. Does not emit 'finish'. Safe to call multiple times.
Speaker.open(options?)Static async factory, symmetric with Microphone.open(). Returns Promise<Speaker>. The speaker loads no model, so the only open work is device resolution; the factory is provided so async callers can use one construction pattern across both classes. A failed open (for example an unknown device) rejects with the matching error.
Speaker.devices()Returns an array of available audio output devices on the system.
const { Speaker } = require('decibri');
const devices = Speaker.devices();
console.log(devices);
// [
// { index: 0, name: 'Speakers', id: '...', maxOutputChannels: 2,
// defaultSampleRate: 48000, isDefault: true },
// ...
// ]
Each device object contains:
| Property | Type | Description |
|---|---|---|
index |
number |
Device index, used as options.device |
name |
string |
Human-readable device name reported by the OS |
id |
string |
Stable per-host device ID, with the same format and fallback rules as the input-device id. Pass via device: { id } |
maxOutputChannels |
number |
Maximum number of output channels supported |
defaultSampleRate |
number |
Preferred sample rate for this device |
isDefault |
boolean |
Whether this is the system default output device |
Speaker.version()Returns version information. Same as Microphone.version().
speaker.isPlayingboolean (read-only). Returns true while audio is being output to the speaker.
| Event | Payload | Description |
|---|---|---|
'drain' |
(none) | Writable buffer has space, safe to write again. |
'finish' |
(none) | All data flushed after end(). Every buffered sample has been played. |
'error' |
Error |
Speaker errors. |
'close' |
(none) | Stream closed, all resources released. |
Convenience functions exported directly from the decibri package.
inputDevices()Shortcut for Microphone.devices(). Returns a MicrophoneInfo[].
outputDevices()Shortcut for Speaker.devices(). Returns a SpeakerInfo[].
version()Returns the same VersionInfo ({ decibri, audioBackend, binding }) as Microphone.version().
const { inputDevices, outputDevices, version } = require('decibri');
const inputs = inputDevices();
const outputs = outputDevices();
console.log(version());
Decibri surfaces failures in three ways in Node, depending on when they occur.
Invalid options throw a built-in RangeError or TypeError synchronously from the constructor (and reject the Microphone.open() or Speaker.open() promise), before any device is opened.
| Condition | Error |
|---|---|
sampleRate outside 1,000 to 384,000 |
RangeError |
channels other than 1 (multichannel capture is not supported) |
RangeError |
framesPerBuffer outside 64 to 65,536 |
RangeError |
dtype not 'int16' or 'float32' |
TypeError |
vad not false, a valid mode, or a valid config object. vad: true is no longer supported; specify the mode explicitly |
TypeError |
vad threshold outside [0, 1], or holdoffMs negative |
RangeError |
denoise not 'fastenhancer-t' |
TypeError |
highpass not 80 or 100 |
RangeError |
agc outside -40 to -3, or limiter outside -3.0 to 0.0 |
RangeError |
device index out of range, or device.id not a string |
RangeError / TypeError |
Failures from the native layer throw DecibriError or one of its subclasses, each carrying a stable string code. These are thrown from the synchronous constructor and rejected from Microphone.open() or Speaker.open().
| Class | Extends | Cause |
|---|---|---|
DecibriError |
Error |
Base class for native device and ONNX Runtime failures. Carries a code string. |
DeviceError |
DecibriError |
Device enumeration or selection failure: an unmatched device name, an ambiguous match, or missing hardware. |
OrtError |
DecibriError |
ONNX Runtime setup or inference failure (the Silero VAD or denoise stages). |
OrtPathError |
OrtError |
A specific ONNX Runtime library path could not be loaded. |
Catch DecibriError to handle any native failure generically, or a subclass for finer control. Argument validation (above) throws built-in RangeError or TypeError, not a DecibriError. If the bundled Silero or denoise model file cannot be located at construction, a plain Error is thrown.
Errors after capture has started, such as a mid-stream device disconnect (unplugging the microphone), are surfaced through the 'error' event rather than thrown. When a device fails, isOpen becomes false and the 'error' event fires, rather than capture freezing silently.