decibri 3.4.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,10 @@
3
3
  const { Emitter } = require('./emitter.js');
4
4
  const { WORKLET_SOURCE } = require('./worklet-inline.js');
5
5
 
6
- const VERSION = '3.0.0';
6
+ // Browser build version. Keep in sync with package.json on each release; the
7
+ // browser bundle cannot read package.json at runtime the way the Node wrapper
8
+ // does, so this is a maintained constant.
9
+ const VERSION = '4.0.0';
7
10
 
8
11
  /**
9
12
  * Browser microphone capture.
@@ -14,14 +17,14 @@ const VERSION = '3.0.0';
14
17
  * Ported from decibri-web decibri.ts. Logic identical, types removed.
15
18
  *
16
19
  * @example
17
- * const { Decibri } = require('decibri'); // browser entry via conditional export
18
- * const mic = new Decibri({ sampleRate: 16000 });
20
+ * const { Microphone } = require('decibri'); // browser entry via conditional export
21
+ * const mic = new Microphone({ sampleRate: 16000 });
19
22
  * mic.on('data', (chunk) => { // chunk is Int16Array });
20
23
  * await mic.start();
21
24
  * // later...
22
25
  * mic.stop();
23
26
  */
24
- class Decibri extends Emitter {
27
+ class Microphone extends Emitter {
25
28
  constructor(options = {}) {
26
29
  super();
27
30
 
@@ -35,9 +38,22 @@ class Decibri extends Emitter {
35
38
  this._stopRequested = false;
36
39
 
37
40
  // ── VAD state ─────────────────────────────────────────────────────────
38
- this._vad = options.vad ?? false;
41
+ // Single vad union: false (disabled, default) or 'energy'. The browser
42
+ // runs energy VAD only; Silero needs ONNX Runtime, which is Node-only. The
43
+ // legacy vad: true form is rejected with a migration error.
44
+ const vad = options.vad ?? false;
45
+ if (vad === false) {
46
+ this._vad = false;
47
+ } else if (vad === true) {
48
+ throw new TypeError("vad: true is no longer supported. Specify the mode explicitly: vad: 'energy'.");
49
+ } else if (vad === 'energy') {
50
+ this._vad = true;
51
+ } else {
52
+ throw new TypeError(`Invalid vad value: ${JSON.stringify(vad)}. Expected false or 'energy'.`);
53
+ }
39
54
  this._vadThreshold = options.vadThreshold ?? 0.01;
40
55
  this._vadHoldoff = options.vadHoldoff ?? 300;
56
+ this._vadScore = 0;
41
57
  this._isSpeaking = false;
42
58
  this._silenceTimer = null;
43
59
 
@@ -46,7 +62,7 @@ class Decibri extends Emitter {
46
62
  this._channels = options.channels ?? 1;
47
63
  this._framesPerBuffer = options.framesPerBuffer ?? 1600;
48
64
  this._device = options.device;
49
- this._format = options.format ?? 'int16';
65
+ this._dtype = options.dtype ?? 'int16';
50
66
  this._echoCancellation = options.echoCancellation ?? true;
51
67
  this._noiseSuppression = options.noiseSuppression ?? true;
52
68
  this._workletUrl = options.workletUrl;
@@ -61,8 +77,8 @@ class Decibri extends Emitter {
61
77
  if (this._framesPerBuffer < 64 || this._framesPerBuffer > 65536) {
62
78
  throw new TypeError(`frames per buffer must be between 64 and 65536, got ${this._framesPerBuffer}`);
63
79
  }
64
- if (this._format !== 'int16' && this._format !== 'float32') {
65
- throw new TypeError("format must be 'int16' or 'float32'");
80
+ if (this._dtype !== 'int16' && this._dtype !== 'float32') {
81
+ throw new TypeError("dtype must be 'int16' or 'float32'");
66
82
  }
67
83
  if (this._vadThreshold < 0 || this._vadThreshold > 1) {
68
84
  throw new TypeError(`vadThreshold must be between 0 and 1, got ${this._vadThreshold}`);
@@ -143,6 +159,15 @@ class Decibri extends Emitter {
143
159
  return this._started;
144
160
  }
145
161
 
162
+ /**
163
+ * Most recent VAD score: the normalized RMS of the last chunk in `'energy'`
164
+ * mode, or 0 when VAD is disabled or before the first chunk is processed.
165
+ * @returns {number}
166
+ */
167
+ get vadScore() {
168
+ return this._vadScore;
169
+ }
170
+
146
171
  /**
147
172
  * List available audio input devices.
148
173
  * Device labels may be empty until microphone permission is granted.
@@ -217,7 +242,7 @@ class Decibri extends Emitter {
217
242
  this._workletNode = new AudioWorkletNode(this._audioContext, 'decibri-processor', {
218
243
  processorOptions: {
219
244
  framesPerBuffer: this._framesPerBuffer,
220
- format: this._format,
245
+ format: this._dtype,
221
246
  nativeSampleRate,
222
247
  targetSampleRate: this._sampleRate,
223
248
  },
@@ -226,7 +251,7 @@ class Decibri extends Emitter {
226
251
  // 5. Wire up data from worklet
227
252
  this._workletNode.port.onmessage = (event) => {
228
253
  const buffer = event.data;
229
- const chunk = this._format === 'int16'
254
+ const chunk = this._dtype === 'int16'
230
255
  ? new Int16Array(buffer)
231
256
  : new Float32Array(buffer);
232
257
 
@@ -272,6 +297,7 @@ class Decibri extends Emitter {
272
297
 
273
298
  _processVad(chunk) {
274
299
  const rms = this._computeRms(chunk);
300
+ this._vadScore = rms;
275
301
 
276
302
  if (rms >= this._vadThreshold) {
277
303
  if (this._silenceTimer !== null) {
@@ -309,4 +335,4 @@ class Decibri extends Emitter {
309
335
  }
310
336
  }
311
337
 
312
- module.exports = { Decibri };
338
+ module.exports = { Microphone };
@@ -1,5 +1,5 @@
1
1
  /** Information about an available audio input device (browser). */
2
- export interface DeviceInfo {
2
+ export interface MicrophoneInfo {
3
3
  /** Opaque device identifier (pass to constructor as `device`). */
4
4
  deviceId: string;
5
5
  /** Human-readable device name. May be empty until permission is granted. */
@@ -8,14 +8,15 @@ export interface DeviceInfo {
8
8
  groupId: string;
9
9
  }
10
10
 
11
- /** Version information. */
11
+ /** Version information (browser). The browser surface has no native audio
12
+ * backend, so it reports only the decibri version. */
12
13
  export interface VersionInfo {
13
- /** decibri package version (e.g. `"3.0.0"`). */
14
+ /** decibri version. */
14
15
  decibri: string;
15
16
  }
16
17
 
17
- /** Constructor options for the browser `Decibri` class. */
18
- export interface DecibriOptions {
18
+ /** Constructor options for the browser `Microphone` class. */
19
+ export interface MicrophoneOptions {
19
20
  /**
20
21
  * Target sample rate in Hz. Browser captures at native rate and resamples.
21
22
  * @default 16000
@@ -38,24 +39,30 @@ export interface DecibriOptions {
38
39
  framesPerBuffer?: number;
39
40
 
40
41
  /**
41
- * Audio input device. Pass a deviceId string from `Decibri.devices()`.
42
+ * Audio input device. Pass a deviceId string from `Microphone.devices()`.
42
43
  * Omit to use the system default input device.
43
44
  */
44
45
  device?: string;
45
46
 
46
47
  /**
47
- * Sample encoding format.
48
+ * Sample encoding data type.
48
49
  * - `'int16'`: Int16Array of PCM samples
49
50
  * - `'float32'`: Float32Array of samples in [-1, 1]
50
51
  * @default 'int16'
51
52
  */
52
- format?: 'int16' | 'float32';
53
+ dtype?: 'int16' | 'float32';
53
54
 
54
55
  /**
55
- * Enable energy-based voice activity detection.
56
+ * Voice activity detection mode. One of:
57
+ * - `false`: disabled (default)
58
+ * - `'energy'`: RMS energy threshold
59
+ *
60
+ * The browser runs energy VAD only; Silero is Node-only. When enabled, emits
61
+ * `'speech'` and `'silence'` events and updates `vadScore`. The legacy
62
+ * `vad: true` form is rejected; specify the mode explicitly.
56
63
  * @default false
57
64
  */
58
- vad?: boolean;
65
+ vad?: false | 'energy';
59
66
 
60
67
  /**
61
68
  * RMS energy threshold for speech detection (VAD mode only).
@@ -95,9 +102,9 @@ export interface DecibriOptions {
95
102
  *
96
103
  * @example
97
104
  * ```js
98
- * import { Decibri } from 'decibri'; // browser entry via conditional export
105
+ * import { Microphone } from 'decibri'; // browser entry via conditional export
99
106
  *
100
- * const mic = new Decibri({ sampleRate: 16000 });
107
+ * const mic = new Microphone({ sampleRate: 16000 });
101
108
  * mic.on('data', (chunk) => {
102
109
  * // chunk is an Int16Array of PCM samples
103
110
  * });
@@ -105,8 +112,8 @@ export interface DecibriOptions {
105
112
  * mic.stop();
106
113
  * ```
107
114
  */
108
- export declare class Decibri {
109
- constructor(options?: DecibriOptions);
115
+ export declare class Microphone {
116
+ constructor(options?: MicrophoneOptions);
110
117
 
111
118
  /**
112
119
  * Start microphone capture.
@@ -121,11 +128,17 @@ export declare class Decibri {
121
128
  /** Whether the microphone is currently capturing. */
122
129
  readonly isOpen: boolean;
123
130
 
131
+ /**
132
+ * Most recent VAD score: the normalized RMS of the last chunk in `'energy'`
133
+ * mode, or 0 when VAD is disabled or before the first chunk is processed.
134
+ */
135
+ readonly vadScore: number;
136
+
124
137
  /**
125
138
  * List available audio input devices.
126
139
  * Labels may be empty until microphone permission is granted.
127
140
  */
128
- static devices(): Promise<DeviceInfo[]>;
141
+ static devices(): Promise<MicrophoneInfo[]>;
129
142
 
130
143
  /** Version information. */
131
144
  static version(): VersionInfo;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { Decibri } = require('./decibri-browser.js');
3
+ const { Microphone } = require('./decibri-browser.js');
4
4
  const { Emitter } = require('./emitter.js');
5
5
 
6
- module.exports = { Decibri, Emitter };
6
+ module.exports = { Microphone, Emitter };
@@ -4,11 +4,15 @@ const { Writable } = require('stream');
4
4
  const { DecibriOutputBridge } = require('../index.js');
5
5
  const { wrapNativeError } = require('./errors');
6
6
 
7
- // ─── DecibriOutput (Writable) ───────────────────────────────────────────────
7
+ // The npm package version, reported as `binding` by version(). Read from
8
+ // package.json so it tracks the published package and cannot drift.
9
+ const PACKAGE_VERSION = require('../package.json').version;
8
10
 
9
- class DecibriOutput extends Writable {
11
+ // ─── Speaker (Writable) ─────────────────────────────────────────────────────
12
+
13
+ class Speaker extends Writable {
10
14
  /**
11
- * @param {import('./decibri').DecibriOutputOptions} [options]
15
+ * @param {import('./decibri').SpeakerOptions} [options]
12
16
  */
13
17
  constructor(options = {}) {
14
18
  super({ highWaterMark: options.highWaterMark || 16384 });
@@ -25,33 +29,23 @@ class DecibriOutput extends Writable {
25
29
  throw new RangeError('channels must be between 1 and 32');
26
30
  }
27
31
 
28
- const format = options.format ?? 'int16';
29
- if (format !== 'int16' && format !== 'float32') {
30
- throw new TypeError("format must be 'int16' or 'float32'");
32
+ const dtype = options.dtype ?? 'int16';
33
+ if (dtype !== 'int16' && dtype !== 'float32') {
34
+ throw new TypeError("dtype must be 'int16' or 'float32'");
31
35
  }
32
36
 
33
37
  // ── Resolve device ──────────────────────────────────────────────────────
34
38
 
39
+ // Name and multi-match resolution are delegated to the core, which owns
40
+ // the renamed-vocabulary errors (SpeakerNotFound / MultipleDevicesMatch).
41
+ // A string name and an { id } object are passed straight through to the
42
+ // native addon. Only the numeric index keeps a client-side bounds check,
43
+ // for a clean Node-side RangeError without a round-trip.
35
44
  let resolvedDevice = options.device;
36
- if (typeof options.device === 'string') {
37
- const lower = options.device.toLowerCase();
38
- const matches = DecibriOutputBridge.devices().filter(d =>
39
- d.name.toLowerCase().includes(lower)
40
- );
41
- if (matches.length === 0) {
42
- throw new TypeError(`No audio output device found matching "${options.device}"`);
43
- }
44
- if (matches.length > 1) {
45
- const names = matches.map(d => ` [${d.index}] ${d.name}`).join('\n');
46
- throw new TypeError(
47
- `Multiple devices match "${options.device}":\n${names}\nUse a more specific name or pass the device index directly.`
48
- );
49
- }
50
- resolvedDevice = matches[0].index;
51
- } else if (typeof options.device === 'number') {
45
+ if (typeof options.device === 'number') {
52
46
  const devices = DecibriOutputBridge.devices();
53
47
  if (options.device < 0 || options.device >= devices.length) {
54
- throw new RangeError('device index out of range. Call DecibriOutput.devices() to list available devices');
48
+ throw new RangeError('device index out of range. Call Speaker.devices() to list available devices');
55
49
  }
56
50
  resolvedDevice = options.device;
57
51
  } else if (
@@ -69,7 +63,7 @@ class DecibriOutput extends Writable {
69
63
 
70
64
  // ── Store config ───────────────────────────────────────────────────────
71
65
 
72
- this._format = format;
66
+ this._dtype = dtype;
73
67
  this._started = false;
74
68
 
75
69
  // ── Create native bridge ───────────────────────────────────────────────
@@ -78,7 +72,7 @@ class DecibriOutput extends Writable {
78
72
  this._native = new DecibriOutputBridge({
79
73
  sampleRate,
80
74
  channels,
81
- format,
75
+ format: dtype,
82
76
  device: resolvedDevice,
83
77
  });
84
78
  } catch (err) {
@@ -134,12 +128,13 @@ class DecibriOutput extends Writable {
134
128
  }
135
129
 
136
130
  /**
137
- * Version information for decibri and the audio runtime.
138
- * @returns {{ decibri: string, portaudio: string }}
131
+ * Version information for decibri, the audio backend, and this binding.
132
+ * @returns {{ decibri: string, audioBackend: string, binding: string }}
139
133
  */
140
134
  static version() {
141
- return DecibriOutputBridge.version();
135
+ const v = DecibriOutputBridge.version();
136
+ return { decibri: v.decibri, audioBackend: v.audioBackend, binding: PACKAGE_VERSION };
142
137
  }
143
138
  }
144
139
 
145
- module.exports = DecibriOutput;
140
+ module.exports = Speaker;
package/src/decibri.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Readable, ReadableOptions, Writable, WritableOptions } from 'stream';
2
2
 
3
3
  /** Information about an available audio input device. */
4
- export interface DeviceInfo {
4
+ export interface MicrophoneInfo {
5
5
  /** Device index (pass to constructor as `device`). */
6
6
  index: number;
7
7
  /** Human-readable device name from the OS. */
@@ -23,16 +23,18 @@ export interface DeviceInfo {
23
23
  isDefault: boolean;
24
24
  }
25
25
 
26
- /** Version strings returned by `Decibri.version()`. */
26
+ /** Version strings returned by `Microphone.version()`. */
27
27
  export interface VersionInfo {
28
- /** decibri package version (e.g. `"3.0.0"`). */
28
+ /** decibri core version. */
29
29
  decibri: string;
30
- /** Audio runtime version string (e.g. `"cpal 0.17"`). */
31
- portaudio: string;
30
+ /** Audio backend version string (e.g. `"cpal 0.17"`). */
31
+ audioBackend: string;
32
+ /** This binding's npm package version. */
33
+ binding: string;
32
34
  }
33
35
 
34
- /** Constructor options for `Decibri`. */
35
- export interface DecibriOptions extends ReadableOptions {
36
+ /** Constructor options for `Microphone`. */
37
+ export interface MicrophoneOptions extends ReadableOptions {
36
38
  /**
37
39
  * Sample rate in Hz.
38
40
  * @default 16000
@@ -57,53 +59,50 @@ export interface DecibriOptions extends ReadableOptions {
57
59
 
58
60
  /**
59
61
  * Audio input device. One of:
60
- * - numeric index (from `DeviceInfo.index`)
62
+ * - numeric index (from `MicrophoneInfo.index`)
61
63
  * - case-insensitive name substring
62
- * - `{ id: string }` for stable per-host device ID from `DeviceInfo.id`
64
+ * - `{ id: string }` for stable per-host device ID from `MicrophoneInfo.id`
63
65
  *
64
66
  * Omit to use the system default input device.
65
67
  */
66
68
  device?: number | string | { id: string };
67
69
 
68
70
  /**
69
- * Sample encoding format.
71
+ * Sample encoding data type.
70
72
  * - `'int16'`: 16-bit signed integer, little-endian (2 bytes per sample)
71
73
  * - `'float32'`: 32-bit IEEE 754 float, little-endian (4 bytes per sample)
72
74
  * @default 'int16'
73
75
  */
74
- format?: 'int16' | 'float32';
76
+ dtype?: 'int16' | 'float32';
75
77
 
76
78
  /**
77
- * Enable energy-based voice activity detection.
78
- * When enabled, emits `'speech'` and `'silence'` events.
79
+ * Voice activity detection mode. One of:
80
+ * - `false`: disabled (default)
81
+ * - `'silero'`: Silero VAD v5 ML model (more accurate, ~1ms inference)
82
+ * - `'energy'`: RMS energy threshold (lightweight)
83
+ *
84
+ * When enabled, emits `'speech'` and `'silence'` events and updates `vadScore`.
85
+ * The legacy `vad: true` form is rejected; specify the mode explicitly.
79
86
  * @default false
80
87
  */
81
- vad?: boolean;
88
+ vad?: false | 'silero' | 'energy';
82
89
 
83
90
  /**
84
- * RMS energy threshold for speech detection (VAD mode only).
85
- * @default 0.01
91
+ * Speech-detection threshold for the active VAD mode.
92
+ * @default 0.5 for `'silero'`, 0.01 for `'energy'`
86
93
  * @range 0–1
87
94
  */
88
95
  vadThreshold?: number;
89
96
 
90
97
  /**
91
- * Milliseconds of sub-threshold audio before emitting `'silence'` (VAD mode only).
98
+ * Milliseconds of sub-threshold audio before emitting `'silence'`.
92
99
  * @default 300
93
100
  */
94
101
  vadHoldoff?: number;
95
102
 
96
- /**
97
- * VAD engine to use.
98
- * - `'energy'`: RMS energy threshold (default, lightweight)
99
- * - `'silero'`: Silero VAD v5 ML model (more accurate, ~1ms inference)
100
- * @default 'energy'
101
- */
102
- vadMode?: 'energy' | 'silero';
103
-
104
103
  /**
105
104
  * Path to the Silero VAD ONNX model file.
106
- * Only used when `vadMode` is `'silero'`.
105
+ * Only used when `vad` is `'silero'`.
107
106
  * Defaults to `models/silero_vad.onnx` relative to the package.
108
107
  */
109
108
  modelPath?: string;
@@ -114,16 +113,16 @@ export interface DecibriOptions extends ReadableOptions {
114
113
  *
115
114
  * @example
116
115
  * ```js
117
- * const Decibri = require('decibri');
118
- * const mic = new Decibri({ sampleRate: 16000, channels: 1 });
116
+ * const { Microphone } = require('decibri');
117
+ * const mic = new Microphone({ sampleRate: 16000, channels: 1 });
119
118
  * mic.on('data', (chunk) => {
120
119
  * // chunk is a Buffer of Int16 LE PCM samples
121
120
  * });
122
121
  * setTimeout(() => mic.stop(), 5000);
123
122
  * ```
124
123
  */
125
- declare class Decibri extends Readable {
126
- constructor(options?: DecibriOptions);
124
+ export declare class Microphone extends Readable {
125
+ constructor(options?: MicrophoneOptions);
127
126
 
128
127
  /** Stop microphone capture and end the stream. Safe to call multiple times. */
129
128
  stop(): void;
@@ -131,8 +130,15 @@ declare class Decibri extends Readable {
131
130
  /** Whether the microphone is currently capturing audio. */
132
131
  readonly isOpen: boolean;
133
132
 
133
+ /**
134
+ * Most recent VAD score for the active mode: the Silero speech probability in
135
+ * `'silero'` mode, the normalized RMS of the last chunk in `'energy'` mode.
136
+ * 0 when VAD is disabled or before the first chunk is processed.
137
+ */
138
+ readonly vadScore: number;
139
+
134
140
  /** List all available audio input devices. */
135
- static devices(): DeviceInfo[];
141
+ static devices(): MicrophoneInfo[];
136
142
 
137
143
  /** Version information for decibri and the audio runtime. */
138
144
  static version(): VersionInfo;
@@ -162,13 +168,13 @@ declare class Decibri extends Readable {
162
168
  }
163
169
 
164
170
  /** Information about an available audio output device. */
165
- export interface OutputDeviceInfo {
171
+ export interface SpeakerInfo {
166
172
  /** Device index (pass to constructor as `device`). */
167
173
  index: number;
168
174
  /** Human-readable device name from the OS. */
169
175
  name: string;
170
176
  /**
171
- * Stable per-host device ID. See `DeviceInfo.id` for format and fallback
177
+ * Stable per-host device ID. See `MicrophoneInfo.id` for format and fallback
172
178
  * semantics; identical rules for output devices.
173
179
  */
174
180
  id: string;
@@ -180,8 +186,8 @@ export interface OutputDeviceInfo {
180
186
  isDefault: boolean;
181
187
  }
182
188
 
183
- /** Constructor options for `DecibriOutput`. */
184
- export interface DecibriOutputOptions extends WritableOptions {
189
+ /** Constructor options for `Speaker`. */
190
+ export interface SpeakerOptions extends WritableOptions {
185
191
  /**
186
192
  * Sample rate in Hz.
187
193
  * @default 16000
@@ -197,18 +203,18 @@ export interface DecibriOutputOptions extends WritableOptions {
197
203
  channels?: number;
198
204
 
199
205
  /**
200
- * Sample encoding format of incoming data.
206
+ * Sample encoding data type of incoming data.
201
207
  * - `'int16'`: 16-bit signed integer, little-endian (2 bytes per sample)
202
208
  * - `'float32'`: 32-bit IEEE 754 float, little-endian (4 bytes per sample)
203
209
  * @default 'int16'
204
210
  */
205
- format?: 'int16' | 'float32';
211
+ dtype?: 'int16' | 'float32';
206
212
 
207
213
  /**
208
214
  * Audio output device. One of:
209
- * - numeric index (from `OutputDeviceInfo.index`)
215
+ * - numeric index (from `SpeakerInfo.index`)
210
216
  * - case-insensitive name substring
211
- * - `{ id: string }` for stable per-host device ID from `OutputDeviceInfo.id`
217
+ * - `{ id: string }` for stable per-host device ID from `SpeakerInfo.id`
212
218
  *
213
219
  * Omit to use the system default output device.
214
220
  */
@@ -220,14 +226,14 @@ export interface DecibriOutputOptions extends WritableOptions {
220
226
  *
221
227
  * @example
222
228
  * ```js
223
- * const { DecibriOutput } = require('decibri');
224
- * const speaker = new DecibriOutput({ sampleRate: 16000, channels: 1 });
229
+ * const { Speaker } = require('decibri');
230
+ * const speaker = new Speaker({ sampleRate: 16000, channels: 1 });
225
231
  * speaker.write(pcmBuffer);
226
232
  * speaker.end();
227
233
  * ```
228
234
  */
229
- declare class DecibriOutput extends Writable {
230
- constructor(options?: DecibriOutputOptions);
235
+ export declare class Speaker extends Writable {
236
+ constructor(options?: SpeakerOptions);
231
237
 
232
238
  /** Immediate stop. Discards remaining buffered audio. */
233
239
  stop(): void;
@@ -236,7 +242,7 @@ declare class DecibriOutput extends Writable {
236
242
  readonly isPlaying: boolean;
237
243
 
238
244
  /** List all available audio output devices. */
239
- static devices(): OutputDeviceInfo[];
245
+ static devices(): SpeakerInfo[];
240
246
 
241
247
  /** Version information for decibri and the audio runtime. */
242
248
  static version(): VersionInfo;
@@ -252,8 +258,36 @@ declare class DecibriOutput extends Writable {
252
258
  on(event: string | symbol, listener: (...args: any[]) => void): this;
253
259
  }
254
260
 
255
- export = Decibri;
261
+ /** List all available audio input devices. */
262
+ export declare function inputDevices(): MicrophoneInfo[];
263
+
264
+ /** List all available audio output devices. */
265
+ export declare function outputDevices(): SpeakerInfo[];
256
266
 
257
- declare namespace Decibri {
258
- export { DecibriOutput };
267
+ /** Version information for decibri and the audio runtime. */
268
+ export declare function version(): VersionInfo;
269
+
270
+ /**
271
+ * Base class for errors raised by the decibri native bindings.
272
+ *
273
+ * Catch this to handle any decibri device or ONNX Runtime failure generically;
274
+ * catch a subclass for finer control. Argument validation (bad sample rate,
275
+ * channels, frames, dtype, vad) throws built-in `RangeError` / `TypeError`, not
276
+ * a `DecibriError`.
277
+ */
278
+ export declare class DecibriError extends Error {
279
+ /** Stable string code identifying the specific failure. */
280
+ readonly code: string;
259
281
  }
282
+
283
+ /**
284
+ * Device enumeration or selection failure: an unmatched device name, an
285
+ * ambiguous name match, or missing hardware.
286
+ */
287
+ export declare class DeviceError extends DecibriError {}
288
+
289
+ /** ONNX Runtime setup or inference failure (Silero VAD). */
290
+ export declare class OrtError extends DecibriError {}
291
+
292
+ /** A specific ONNX Runtime library path could not be loaded. */
293
+ export declare class OrtPathError extends OrtError {}