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.
- package/CHANGELOG.md +386 -0
- package/MIGRATION.md +151 -0
- package/README.md +81 -39
- package/examples/wav-capture.js +2 -2
- package/examples/websocket-stream.js +2 -2
- package/index.d.ts +1 -1
- package/index.js +52 -52
- package/package.json +9 -7
- package/src/browser/decibri-browser.js +37 -11
- package/src/browser/index.d.ts +28 -15
- package/src/browser/index.js +2 -2
- package/src/decibri-output.js +24 -29
- package/src/decibri.d.ts +81 -47
- package/src/decibri.js +106 -41
- package/src/errors.js +126 -23
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
const { Emitter } = require('./emitter.js');
|
|
4
4
|
const { WORKLET_SOURCE } = require('./worklet-inline.js');
|
|
5
5
|
|
|
6
|
-
|
|
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 {
|
|
18
|
-
* const mic = new
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
65
|
-
throw new TypeError("
|
|
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.
|
|
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.
|
|
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 = {
|
|
338
|
+
module.exports = { Microphone };
|
package/src/browser/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Information about an available audio input device (browser). */
|
|
2
|
-
export interface
|
|
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
|
|
14
|
+
/** decibri version. */
|
|
14
15
|
decibri: string;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
/** Constructor options for the browser `
|
|
18
|
-
export interface
|
|
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 `
|
|
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
|
|
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
|
-
|
|
53
|
+
dtype?: 'int16' | 'float32';
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
|
-
*
|
|
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?:
|
|
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 {
|
|
105
|
+
* import { Microphone } from 'decibri'; // browser entry via conditional export
|
|
99
106
|
*
|
|
100
|
-
* const mic = new
|
|
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
|
|
109
|
-
constructor(options?:
|
|
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<
|
|
141
|
+
static devices(): Promise<MicrophoneInfo[]>;
|
|
129
142
|
|
|
130
143
|
/** Version information. */
|
|
131
144
|
static version(): VersionInfo;
|
package/src/browser/index.js
CHANGED
package/src/decibri-output.js
CHANGED
|
@@ -4,11 +4,15 @@ const { Writable } = require('stream');
|
|
|
4
4
|
const { DecibriOutputBridge } = require('../index.js');
|
|
5
5
|
const { wrapNativeError } = require('./errors');
|
|
6
6
|
|
|
7
|
-
//
|
|
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
|
-
|
|
11
|
+
// ─── Speaker (Writable) ─────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
class Speaker extends Writable {
|
|
10
14
|
/**
|
|
11
|
-
* @param {import('./decibri').
|
|
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
|
|
29
|
-
if (
|
|
30
|
-
throw new TypeError("
|
|
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 === '
|
|
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
|
|
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.
|
|
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
|
|
138
|
-
* @returns {{ decibri: 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
|
-
|
|
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 =
|
|
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
|
|
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 `
|
|
26
|
+
/** Version strings returned by `Microphone.version()`. */
|
|
27
27
|
export interface VersionInfo {
|
|
28
|
-
/** decibri
|
|
28
|
+
/** decibri core version. */
|
|
29
29
|
decibri: string;
|
|
30
|
-
/** Audio
|
|
31
|
-
|
|
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 `
|
|
35
|
-
export interface
|
|
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 `
|
|
62
|
+
* - numeric index (from `MicrophoneInfo.index`)
|
|
61
63
|
* - case-insensitive name substring
|
|
62
|
-
* - `{ id: string }` for stable per-host device ID from `
|
|
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
|
|
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
|
-
|
|
76
|
+
dtype?: 'int16' | 'float32';
|
|
75
77
|
|
|
76
78
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
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?:
|
|
88
|
+
vad?: false | 'silero' | 'energy';
|
|
82
89
|
|
|
83
90
|
/**
|
|
84
|
-
*
|
|
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'
|
|
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 `
|
|
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
|
|
118
|
-
* const mic = new
|
|
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
|
|
126
|
-
constructor(options?:
|
|
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():
|
|
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
|
|
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 `
|
|
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 `
|
|
184
|
-
export interface
|
|
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
|
|
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
|
-
|
|
211
|
+
dtype?: 'int16' | 'float32';
|
|
206
212
|
|
|
207
213
|
/**
|
|
208
214
|
* Audio output device. One of:
|
|
209
|
-
* - numeric index (from `
|
|
215
|
+
* - numeric index (from `SpeakerInfo.index`)
|
|
210
216
|
* - case-insensitive name substring
|
|
211
|
-
* - `{ id: string }` for stable per-host device ID from `
|
|
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 {
|
|
224
|
-
* const speaker = new
|
|
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
|
|
230
|
-
constructor(options?:
|
|
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():
|
|
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
|
-
|
|
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
|
-
|
|
258
|
-
|
|
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 {}
|