Browser API

Decibri includes browser support via conditional exports. When imported in a browser bundle (webpack, vite, etc.), it uses getUserMedia and AudioWorklet to capture raw PCM audio chunks in real-time. Same API as the Node.js version, same npm package.

Quickstart

Environment Backend Entry point
Node.js Rust native addon (cpal) Resolved via conditional export
Browser Web Audio API Resolved via conditional export

Install

$ npm install decibri

Quick start

Capture microphone audio and log the chunk size:

import { Decibri } from 'decibri';

const mic = new Decibri({ sampleRate: 16000 });

mic.on('data', (chunk) => {
  console.log(`Received ${chunk.length} samples`);
});

await mic.start();

start() must be called from a user gesture (click/tap) in Safari. Each chunk contains 100 ms of audio by default (1,600 frames at 16 kHz).

Permission handling

Microphone access requires HTTPS (or localhost). The browser will show a permission prompt when start() is called.

Stopping and cleanup

mic.stop();

stop() releases all resources: MediaStream tracks are stopped, AudioContext is closed, all nodes are disconnected, references are nulled. Safe for React/Vue component unmount cycles. Safe to call multiple times or before start().

To restart after stopping:

await mic.start(); // creates a fresh audio pipeline

Device selection

// Start first to trigger permission, then enumerate with labels
await mic.start();
const devices = await Decibri.devices();
console.log(devices);
// [{ deviceId: 'abc123', label: 'Built-in Microphone', groupId: 'g1' }, ...]

// Use a specific device
const usbMic = new Decibri({ device: devices[1].deviceId });
await usbMic.start();

Output formats

// Int16 PCM (default) - ready for most STT engines
const mic = new Decibri({ format: 'int16' });
mic.on('data', (chunk) => {
  // chunk is an Int16Array
});

// Float32 - native browser format, no conversion
const mic2 = new Decibri({ format: 'float32' });
mic2.on('data', (chunk) => {
  // chunk is a Float32Array
});

Voice activity detection

Enable the built-in VAD to receive 'speech' and 'silence' events based on RMS energy thresholding:

const mic = new Decibri({
  sampleRate: 16000,
  vad: true,
  vadThreshold: 0.01,
  vadHoldoff: 300,
});

mic.on('speech', () => console.log('Speaking...'));
mic.on('silence', () => console.log('Silence'));

await mic.start();

WebSocket streaming

const ws = new WebSocket('wss://your-server.com/audio');
const mic = new Decibri({ sampleRate: 16000, format: 'int16' });

mic.on('data', (chunk) => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(chunk.buffer);
  }
});

document.getElementById('start').onclick = () => mic.start();
document.getElementById('stop').onclick = () => mic.stop();

Browser support

Requires HTTPS (or localhost) for microphone access.

Browser Minimum Version
Chrome 66+
Firefox 76+
Safari 14.1+ (requires user gesture)
Edge 79+
iOS Safari 14.5+
Android Chrome 66+

CSP-restricted environments

By default, decibri loads its AudioWorklet processor via an inline Blob URL. If your Content Security Policy blocks blob: URLs:

const mic = new Decibri({
  workletUrl: '/static/decibri-worklet.js',
});

Copy the worklet file from node_modules/decibri/dist/worklet.js to your static assets directory and pass the URL.

API reference

Constructor

new Decibri(options?)

Creates a new capture instance. Does not start capture. Call start() to begin.

import { Decibri } from 'decibri';
const mic = new Decibri(options?);
Option Type Default Description
sampleRate number 16000 Target sample rate in Hz (1,000 to 384,000)
channels number 1 Number of channels (browsers reliably support 1)
framesPerBuffer number 1600 Frames per chunk. 1,600 at 16 kHz = 100 ms chunks (64 to 65,536)
device string system default deviceId string from Decibri.devices()
format 'int16' | 'float32' 'int16' Sample encoding format
vad boolean false Enable voice activity detection
vadThreshold number 0.01 RMS energy threshold for speech detection (0 to 1)
vadHoldoff number 300 Milliseconds of sub-threshold audio before 'silence' is emitted
echoCancellation boolean true Browser echo cancellation. Set false for music/tuner apps
noiseSuppression boolean true Browser noise suppression. Set false for raw signal
workletUrl string (inline Blob URL) URL for AudioWorklet processor file. Override if CSP blocks blob: URLs

Methods

mic.start()

Returns Promise<void>. Requests microphone permission and begins capture. Must be called from a user gesture in Safari. No-op if already started. Rejects with a clear error on permission denial.

mic.stop()

Stops capture and releases all resources (tracks, context, nodes). Safe to call anytime, including before start() or multiple times. Emits 'end' then 'close'.

Properties

mic.isOpen

boolean (read-only). Returns true while actively capturing audio.

Static methods

Decibri.devices()

Returns Promise<DeviceInfo[]>. Lists available audio input devices. Labels may be empty before microphone permission is granted.

const devices = await Decibri.devices();
console.log(devices);
// [
//   { deviceId: 'abc123', label: 'Built-in Microphone', groupId: 'g1' },
//   ...
// ]

Decibri.version()

Returns version information for decibri.

Decibri.version();
// { decibri: '3.0.0' }

Events

Event Payload Description
'data' Int16Array or Float32Array Audio chunk. Format depends on format option. Emitted ~10 times/sec at default settings.
'error' Error Permission denied, worklet load failure, AudioContext creation failure.
'end' (none) Emitted after stop().
'close' (none) Emitted after stop(), after 'end'.
'speech' (none) VAD: RMS energy crossed threshold. Requires vad: true.
'silence' (none) VAD: sub-threshold audio for vadHoldoff ms. Requires vad: true.

Types

// DeviceInfo
{
  deviceId: string,
  label: string,
  groupId: string,
}

// VersionInfo
{
  decibri: string,
}

Differences from Decibri (Node.js)

Feature Node.js decibri decibri (browser) Notes
Class name Decibri Decibri Identical
Constructor Sync, capture starts on read Sync, requires await start() Browser needs async permission
'data' payload Buffer Int16Array / Float32Array Different types, same PCM data
devices() Sync Async (returns Promise) Browser API is async
device option Number index or name substring String deviceId only Browser uses opaque device IDs
version() { decibri, portaudio } (portaudio key kept for compat) { decibri } Different runtime info
echoCancellation N/A boolean (default true) Browser-only option
noiseSuppression N/A boolean (default true) Browser-only option
'backpressure' event Available Not available No browser equivalent
pipe() / streams Full Readable stream Not available Browser has no Node streams
sampleRate Any (cpal resamples) Any (AudioWorklet resamples) Same behavior
format 'int16' or 'float32' 'int16' or 'float32' Identical
VAD (speech/silence) RMS-based RMS-based (same algorithm) Identical