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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD024 -->
|
|
2
|
+
|
|
3
|
+
# Decibri npm Package Changelog
|
|
4
|
+
|
|
5
|
+
Changes to the decibri npm package, published to npmjs.com. Tags use the `npm-v*` pattern (e.g., `npm-v3.4.2`).
|
|
6
|
+
|
|
7
|
+
For other decibri packages, see:
|
|
8
|
+
|
|
9
|
+
- Rust crate: [crates/decibri/CHANGELOG.md](../../crates/decibri/CHANGELOG.md)
|
|
10
|
+
- Python wheel: [bindings/python/CHANGELOG.md](../../bindings/python/CHANGELOG.md)
|
|
11
|
+
|
|
12
|
+
## [Unreleased]
|
|
13
|
+
|
|
14
|
+
## [4.0.0] - 2026-05-30
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- BREAKING: the package now uses named exports. Import with `const { Microphone, Speaker, inputDevices, outputDevices, version } = require('decibri')` instead of the previous single default export.
|
|
19
|
+
- BREAKING: the capture class `Decibri` is now `Microphone`, and the playback class `DecibriOutput` is now `Speaker`. The browser capture class is `Microphone` too.
|
|
20
|
+
- BREAKING: the sample-encoding option `format` is now `dtype` (the `'int16'` and `'float32'` values are unchanged).
|
|
21
|
+
- BREAKING: the device-info types are now `MicrophoneInfo` and `SpeakerInfo` (were `DeviceInfo` and `OutputDeviceInfo`).
|
|
22
|
+
- BREAKING: voice activity detection is now a single `vad` option accepting `false`, `'silero'`, or `'energy'`. The `vad: true` plus `vadMode` pair is no longer accepted; pass the mode directly as `vad: 'silero'` or `vad: 'energy'`. The browser runs energy mode only.
|
|
23
|
+
- BREAKING: `version()` now returns `{ decibri, audioBackend, binding }` (was `{ decibri, portaudio }`). `audioBackend` replaces the inaccurate `portaudio` name, and `binding` reports the npm package version.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Error classes `DecibriError`, `DeviceError`, `OrtError`, and `OrtPathError`, each with a `code` property, for `instanceof` and `err.code` handling.
|
|
28
|
+
- `vadScore` getter on the capture class: the Silero probability in `'silero'` mode, the normalized RMS in `'energy'` mode, 0 when disabled.
|
|
29
|
+
- Module-level `inputDevices()`, `outputDevices()`, and `version()` free functions, alongside the static `Microphone.devices()` and `Speaker.devices()` methods.
|
|
30
|
+
|
|
31
|
+
## [3.4.2] - 2026-05-24
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- npm package now ships its Node.js-specific README to npmjs.com. The publish workflow previously copied the root README into the npm package directory at publish time, which meant the npmjs.com page for `decibri` showed a generic multi-language overview instead of the Node-focused documentation at `npm/decibri/README.md`. Removing the copy step lets the proper README ship.
|
|
36
|
+
|
|
37
|
+
## [3.4.1] - 2026-05-23
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Speaker example in `crates/decibri/README.md`: defined `pcm_int16_bytes` as `Vec<u8>` of 48000 zero bytes (1 second of int16 silence at 24kHz mono) so the example has a real value to send. Previously the example referenced `pcm_int16_bytes` without defining it, raising `error[E0425]: cannot find value 'pcm_int16_bytes' in this scope` on copy-paste.
|
|
42
|
+
- `npm/decibri/README.md`: replaced the accidental Rust crate README copy with a Node.js and browser focused README. Users on npmjs.com landing on the decibri package were previously shown Rust documentation (`cargo add decibri`, Rust feature flags, etc.) instead of Node.js installation and API documentation. The new README documents the actual Node.js API surface (`Decibri` capture stream, `DecibriOutput` playback stream, events, browser conditional export, VAD modes, device selection by index / name / stable per-host ID).
|
|
43
|
+
- `npm/decibri/examples/`: moved three runnable examples (`wav-capture.js`, `websocket-server.js`, `websocket-stream.js`) from the top-level `examples/` directory into the npm package directory, rewrote imports to use `require('decibri')`, and added `examples/` to `package.json` `files` so the examples ship in the published tarball. The Examples section in `npm/decibri/README.md` was previously removed in error during an audit pass that searched only `npm/decibri/examples/` rather than the top-level `examples/` where the files actually lived; this restoration corrects that and ensures `npm install decibri` users actually receive the example files.
|
|
44
|
+
|
|
45
|
+
## [3.4.0] - 2026-05-02
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- **`OnnxSession` trait abstraction in Rust core.** New internal `pub(crate) trait OnnxSession` inside `crates/decibri/src/onnx.rs` abstracts ONNX Runtime usage behind a backend-agnostic interface. `SileroVad` consumes the trait through `Box<dyn OnnxSession>`. The ORT-backed implementation is the only impl in 3.x.
|
|
50
|
+
- `DecibriError::OnnxBackendFailed { backend: &'static str, source: Box<dyn std::error::Error + Send + Sync> }` variant. Reserved on the `#[non_exhaustive]` enum. Additive; existing 8 ORT variants unchanged. `is_ort_path_error` continues to return false on the new variant.
|
|
51
|
+
- **`DecibriError::ForkAfterOrtInit { init_pid: u32, current_pid: u32 }` variant + runtime fork detection.** Linux-only failure-mode hardening: a process that forks after a successful `SileroVad::new` previously inherited `static ORT_INIT` flagged as set while the underlying ORT runtime state (allocators, thread pools) was unsafe to reuse, producing silent wrong probabilities, segfaults, or hangs in the child. 3.4.0 stamps the initializing pid into a paired `static ORT_INIT_PID: OnceLock<u32>` inside the same `init_ort_once` success path; a `pub(crate) fn check_pid_for_ort()` runs at the entry of `SileroVad::process()` and returns `Err(ForkAfterOrtInit { init_pid, current_pid })` on pid mismatch. The `Display` message embeds both pids and the two remediation options ("Use `multiprocessing.set_start_method('spawn')` or construct `Microphone(vad='silero')` inside each child process"). Single-check coverage at the outer entry point applies to every inference call without per-window overhead. macOS and Windows are unaffected by fork semantics. Additive on the `#[non_exhaustive]` `DecibriError` enum; mapped through to npm via the napi `_ =>` catch-all (`Status::GenericFailure` carrying `e.to_string()`) and to Python via an explicit `ForkAfterOrtInit(DecibriError)` subclass in the wheel.
|
|
52
|
+
|
|
53
|
+
### Internal
|
|
54
|
+
|
|
55
|
+
- `crates/decibri` 3.x public API stays byte-identical (`SileroVad`, `VadConfig`, `VadResult`, `DecibriError` keep their 3.3.x signatures). npm binding, Python binding, browser shim are unchanged.
|
|
56
|
+
- `vad::init_ort_once` visibility raised from private to `pub(crate)` so the `onnx` module's inline ORT-backed test can reuse the same process-global init path that `vad` tests use.
|
|
57
|
+
- `static ORT_INIT_PID: OnceLock<u32>` paired with the existing `ORT_INIT`, set inside the `OnceLock::get_or_init` callback so the pid stamp is paired with the successful ORT init rather than a speculative pre-init value. `pub(crate) fn check_pid_for_ort()` exposes the comparison to inference call sites within the crate. Linux-only `test_fork_safety.py` tests in the Python wheel pin the behavior end-to-end (gated `skipif sys.platform != "linux"`); they run on CI's `ubuntu-latest` job and skip on other hosts.
|
|
58
|
+
|
|
59
|
+
## [3.3.2] - 2026-04-26
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- **`crates/decibri/build.rs` rewrite to use Cargo.toml as primary source.** The previous build script (introduced in 3.3.1 to source the cpal version from a single point of truth) read the workspace `Cargo.lock` via a path traversal that worked in workspace builds but panicked in `cargo publish` verify because the published tarball is flat (`decibri-X.Y.Z/Cargo.toml` and `decibri-X.Y.Z/Cargo.lock` are siblings, not in workspace structure). The traversal landed at `target/Cargo.lock` (nonexistent) and aborted the build. **3.3.1's crates.io publish failed on this defect; 3.3.1 shipped to npm but not to crates.io.** 3.3.2 fixes the build.rs to read `CARGO_MANIFEST_DIR / Cargo.toml` directly, with belt-and-suspenders fallbacks: env-var override (`DECIBRI_CPAL_VERSION`), workspace `Cargo.toml` fallback for `{ workspace = true }` inherit form, hardcoded `"0.17"` constant fallback (with `cargo:warning=`) for unforeseen build contexts. Cargo.toml is unambiguously present in every build context because cargo guarantees `CARGO_MANIFEST_DIR` always points at the manifest's directory.
|
|
64
|
+
- **No functional change to user-visible API or error messages.** All 5 message refinements from 3.3.1 (`SampleRateOutOfRange`, `FramesPerBufferOutOfRange`, `AlreadyRunning`, `OrtInitFailed`, `OrtLoadFailed` / `OrtPathInvalid`, `PermissionDenied`) are preserved unchanged.
|
|
65
|
+
- **`decibri::CPAL_VERSION` byte-identity preserved across all four cargo-emitted dep forms.** Verified 2026-04-26 by walking through `find_cpal_in_dependencies` + `truncate_to_major_minor` against on-disk Cargo.toml content: Form 1 (`cpal = "0.17"` workspace.dependencies) -> `"0.17"`; Form 2 (`cpal = { version = "0.17", optional = true }` hypothetical inline-table) -> `"0.17"`; Form 3 (`cpal = { workspace = true, optional = true }` source crate) -> workspace fallback -> `"0.17"`; Form 4 (`[dependencies.cpal] version = "0.17"` published normalized) -> `"0.17"`. All four forms produce identical output to the v3.3.1 build.rs's Cargo.lock-resolved truncation because the workspace pin is at major.minor granularity already (`cpal = "0.17"` in `[workspace.dependencies]`).
|
|
66
|
+
- **`release-dryrun.yml` extended to exercise `cargo publish -p decibri --dry-run`.** The previous dryrun workflow ran the npm-side build matrix and `verify_pack` packaging gate but had no crates.io publish path coverage. The new step catches build.rs failures and any other publish-time issues that affect the Rust crate publish but not the npm packaging. Closes the procedural gap that allowed 3.3.1's defect to ship through CI green.
|
|
67
|
+
|
|
68
|
+
### Migration notes
|
|
69
|
+
|
|
70
|
+
- **Direct Rust crate consumers** of decibri: 3.3.1 was never published to crates.io. crates.io's decibri version history is 3.3.0 -> 3.3.2; 3.3.1 is skipped entirely on this registry. **npm consumers** see the standard 3.3.0 -> 3.3.1 -> 3.3.2 progression (3.3.1 shipped successfully on npm; only the cargo publish step in `release.yml` failed). The asymmetry is documented here for archaeological clarity.
|
|
71
|
+
- All 3.3.1 message refinements (per `[3.3.1]` entry above) are preserved in 3.3.2. Consumer-side migration from 3.3.0 to 3.3.2 is the same as 3.3.0 to 3.3.1 from the user-visible API perspective.
|
|
72
|
+
- **No npm migration required** for 3.3.1 -> 3.3.2. 3.3.2 publishes a new wheel set with the same user-visible behavior; bump-and-rebuild is sufficient.
|
|
73
|
+
|
|
74
|
+
## [3.3.1] - 2026-04-25
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- **Audience-neutral error message pass.** Five `DecibriError` `Display` strings refined to remove cross-binding and platform-specific awkwardness. No variant identity, layout, or count change; no API-surface change. Strict patch release.
|
|
79
|
+
- `SampleRateOutOfRange`: `"sampleRate must be between 1000 and 384000"` -> `"sample rate must be between 1000 and 384000"`. The previous camelCase form was Node-API-targeting and matched no other field-name convention in the rest of the Rust crate (snake_case fields throughout, natural-language rustdoc voice).
|
|
80
|
+
- `FramesPerBufferOutOfRange`: `"framesPerBuffer must be between 64 and 65536"` -> `"frames per buffer must be between 64 and 65536"`. Same rationale.
|
|
81
|
+
- `AlreadyRunning`: `"Decibri is already running. Call stop() first."` -> `"audio stream is already running. Call stop() first."`. Hardcoded class name was misleading when raised from `DecibriOutput`; "audio stream" matches the existing `error.rs` vocabulary ("capture stream", "output stream", "audio stream").
|
|
82
|
+
- `OrtInitFailed`: `"Either pass ort_library_path in VadConfig, ..."` -> `"Either pass ort_library_path when constructing the VAD, ..."`. Drops Rust-internal `VadConfig` type reference; phrasing now correct for Node, Python, and direct-Rust crate consumers alike.
|
|
83
|
+
- `OrtLoadFailed` and `OrtPathInvalid`: `"the bundled ORT may be missing from your platform package"` -> `"the bundled ONNX Runtime may be missing from your installation"`. Drops npm-internal "platform package" phrasing; "installation" works for npm platform packages, Python wheels, and direct-Rust crate use.
|
|
84
|
+
- `PermissionDenied`: macOS-specific `"Enable in System Preferences > Security & Privacy."` replaced with attribute-gated per-platform guidance. macOS hint extended to specifically reference `> Microphone`. Windows hint references the modern `Settings > Privacy & Security > Microphone` UX. Linux hint references PulseAudio / PipeWire (the user-facing audio control layer over cpal's ALSA backend).
|
|
85
|
+
- Lockstep updates to `bindings/node/src/lib.rs` (one duplicate `AlreadyRunning` message in the napi `start()` pre-running check), `npm/decibri/src/errors.js` (two prefix-match strings in the typed-error shim), `npm/decibri/src/decibri.js` (two thrown messages in client-side validation; line 101's `channels` message is already natural-language and unchanged), `npm/decibri/src/decibri-output.js` (one thrown message), `npm/decibri/src/browser/decibri-browser.js` (two thrown messages in browser-side validation), `tests/test-ci.js`, `tests/test-api.js`, `tests/test-output.js` (15 hardcoded message-substring assertions).
|
|
86
|
+
|
|
87
|
+
### Migration notes
|
|
88
|
+
|
|
89
|
+
Error message wording on shipped `DecibriError` variants has historically been stable across the 3.x line. 3.3.1 explicitly refines five messages to remove audience-leak issues: Node-API-targeted camelCase parameter names, class-name hardcoding in `AlreadyRunning`, a Rust-internal type reference (`VadConfig`) in `OrtInitFailed`, npm-internal phrasing ("platform package") in `OrtLoadFailed` / `OrtPathInvalid`, and macOS-only platform guidance in `PermissionDenied`. 3.3.1 is the consolidation point.
|
|
90
|
+
|
|
91
|
+
- **Direct Rust crate consumers** asserting on `DecibriError::Display` strings should update assertions for the five refined messages. Type-level matching on `DecibriError` variants is unaffected; only string-text assertions need updating.
|
|
92
|
+
- **Node consumers** using `e.message.includes(prefix)` or `e.message.startsWith(prefix)` patterns should update for `sampleRate` -> `sample rate`, `framesPerBuffer` -> `frames per buffer`, and the `AlreadyRunning` message text. Type-level matching on `RangeError` / `TypeError` is unaffected.
|
|
93
|
+
- **Python consumers**: the in-development Python wheel consumes `decibri@3.3.1`, so the messages it sees are the corrected forms.
|
|
94
|
+
|
|
95
|
+
## [3.3.0] - 2026-04-23
|
|
96
|
+
|
|
97
|
+
Groundwork release for upcoming P3 Python bindings. Adds a stable-ID form for audio device selection (`DeviceSelector::Id`), fixes a long-standing direction bug in `DecibriError::DeviceNotFound` when resolving output devices, exposes both in the Node binding, and extends the reference documentation with a Cargo feature flag guide plus additional crate-level rustdoc. No Node.js or browser API break. Direct Rust crate consumers pattern-matching on `DeviceSelector` or struct-literal-constructing `DeviceInfo` / `OutputDeviceInfo` need to update for the new `#[non_exhaustive]` attributes (see Migration notes below).
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- `DeviceSelector`, `DeviceInfo`, and `OutputDeviceInfo` are now `#[non_exhaustive]`. External Rust consumers pattern-matching on `DeviceSelector` must add a `_ =>` catch-all arm; consumers constructing `DeviceInfo` or `OutputDeviceInfo` via struct literal from outside the crate must switch to reading fields off instances returned by `enumerate_input_devices` / `enumerate_output_devices`. Field names and display strings are unchanged. This future-proofs the API: subsequent variant or field additions are source-compatible for consumers who include the catch-all.
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
|
|
105
|
+
- `DeviceSelector::Id(String)` for selecting audio devices by stable per-host identifier (WASAPI endpoint ID on Windows, CoreAudio UID on macOS, ALSA pcm_id on Linux). Unlike `DeviceSelector::Name` (case-insensitive substring) and `DeviceSelector::Index` (positional), `Id` survives across enumerations: display names can shift when other devices are plugged in but per-host IDs do not.
|
|
106
|
+
- `id: String` field on `DeviceInfo` and `OutputDeviceInfo`, populated from `cpal::DeviceId`'s `Display` output. Empty string if cpal cannot produce a stable ID for a given device (rare; some host backends cannot assign IDs to every enumerated device). Obtain the ID from these fields and pass to `DeviceSelector::Id`.
|
|
107
|
+
- `DecibriError::OutputDeviceNotFound(String)` variant, the output-device equivalent of `DeviceNotFound`. See Fixed below for the motivating bug.
|
|
108
|
+
- Node binding accepts `device: { id: string }` as a third form alongside `device: <number>` (index) and `device: <string>` (name substring). The JS wrapper passes it through to Rust unchanged; Rust resolves via cpal's `DeviceId`.
|
|
109
|
+
- `DeviceInfoJs.id` and `OutputDeviceInfoJs.id` fields on the Node binding types, mirroring the Rust `DeviceInfo.id` / `OutputDeviceInfo.id` additions. Visible in the auto-regenerated `npm/decibri/index.d.ts` and in the hand-authored `npm/decibri/src/decibri.d.ts`.
|
|
110
|
+
- `npm/decibri/src/errors.js` helper that re-wraps plain `Error` instances thrown from the native boundary as `TypeError` or `RangeError`, matching the JS wrapper's existing validation error classes. Brought in by `decibri.js` and `decibri-output.js` constructors to align Rust-originated errors with the JS wrapper's error class contract. Triggered only by code paths that reach Rust's `to_napi_error` (currently only `device: { id: ... }` selection); all other validation paths continue to throw from the JS wrapper directly with no behavior change.
|
|
111
|
+
- `docs/features.md`: comprehensive Cargo feature reference covering ORT distribution mode tradeoffs, execution-provider features, binding-author guidance, and feature compatibility constraints. Targeted at Rust crate consumers and FFI binding authors; lib.rs rustdoc now links to it for deep-dive reference.
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- `DecibriError::DeviceNotFound`'s display string hardcoded "No audio input device found matching..." regardless of whether the lookup was against input or output devices. Direct Rust consumers and the new `device: { id: ... }` Node path now receive the correct direction via `DecibriError::OutputDeviceNotFound` for output-device misses. No change visible through the Node binding for existing name- and index-based lookups: those are intercepted by the JS wrapper and always threw direction-correct messages from JS before reaching Rust.
|
|
116
|
+
|
|
117
|
+
### Internal
|
|
118
|
+
|
|
119
|
+
- `DeviceDirection` trait gains a `not_found_error(String) -> DecibriError` method so `resolve_device_generic`'s `Name` and `Id` arms produce direction-correct errors via the `Input` / `Output` impls.
|
|
120
|
+
- Unit tests for `Arc<Mutex<CaptureStream>>` confirming the wrapping is `Send + Sync` (compile-time assertion) and serializes concurrent access across two threads (runtime test with `Barrier`). Documents the wrapping strategy the P3 Python binding will apply to share `!Sync` capture streams across Python threads.
|
|
121
|
+
- Crate-level rustdoc additions in `lib.rs`: a section on ORT error construction FFI side effects (the `ortsys![CreateStatus]` dylib-load trigger that motivates the `OrtPathInvalid` split from `OrtLoadFailed`) and a section on fork safety (guidance for Python `multiprocessing` consumers to use `spawn` start method).
|
|
122
|
+
- `lib.rs` rustdoc "Feature flags" section cross-references `docs/features.md` for consumers wanting the deep-dive reference.
|
|
123
|
+
- Em-dash cleanup across 19 code locations in `lib.rs`, `capture.rs`, `output.rs`, `vad.rs`, `error.rs`, `vad_integration.rs`, and `vad_ort_load_failure.rs`. Per CLAUDE.md, the codebase forbids em dashes; these were pre-existing violations.
|
|
124
|
+
- CLAUDE.md corrections: validation-gate commands updated to the canonical set (`cargo clippy --workspace -- -D warnings`, `cargo fmt --all -- --check`, `cargo test-decibri`); stale `## [3.0.0] - Unreleased` reference replaced with a template placeholder.
|
|
125
|
+
- `ort` crate version unchanged at `2.0.0-rc.12`.
|
|
126
|
+
- Bundled ONNX Runtime version unchanged at `1.24.4`.
|
|
127
|
+
- No Node.js API signatures, event names, or error messages changed.
|
|
128
|
+
- TypeScript declaration files in both `npm/decibri/index.d.ts` (auto-regenerated) and `npm/decibri/src/decibri.d.ts` (hand-authored) updated for the new `id` field and extended `device` option type.
|
|
129
|
+
|
|
130
|
+
### Migration notes for direct Rust crate consumers
|
|
131
|
+
|
|
132
|
+
- Exhaustive matches on `DeviceSelector` will stop compiling. Add a `_ =>` catch-all arm. Display strings and existing variant names are unchanged; code using `to_string()` or only constructing variants (not matching them) continues to work unaffected.
|
|
133
|
+
- Struct literal construction of `DeviceInfo` and `OutputDeviceInfo` from outside the `decibri` crate will stop compiling (added `#[non_exhaustive]`, added `id: String` field). External consumers should read these structs from `enumerate_input_devices()` / `enumerate_output_devices()` rather than constructing them directly.
|
|
134
|
+
- Consumers matching specifically on `DecibriError::DeviceNotFound` for output-device misses should now also match `DecibriError::OutputDeviceNotFound`. The convenience predicate `DecibriError::is_ort_path_error` remains unchanged and already groups only ORT-path variants.
|
|
135
|
+
- MSRV unchanged at rustc 1.88.
|
|
136
|
+
|
|
137
|
+
## [3.2.0] - 2026-04-22
|
|
138
|
+
|
|
139
|
+
Refactor release. Public Node.js and browser APIs are unchanged. Direct
|
|
140
|
+
Rust crate consumers get a structured `DecibriError` taxonomy with full
|
|
141
|
+
error-chain preservation, a new stable FFI-ready stream-reading API on
|
|
142
|
+
`CaptureStream`, a declared minimum-supported-Rust-version, and a Windows
|
|
143
|
+
hang fix in VAD initialization. See migration notes below.
|
|
144
|
+
|
|
145
|
+
### Changed
|
|
146
|
+
|
|
147
|
+
- `DecibriError` is now `#[non_exhaustive]` and the `Other(String)`
|
|
148
|
+
catch-all variant has been removed. All previous `Other(...)` failures
|
|
149
|
+
now have dedicated typed variants: `DeviceEnumerationFailed`,
|
|
150
|
+
`CaptureStreamClosed`, `OutputStreamClosed`, `VadSampleRateUnsupported`,
|
|
151
|
+
`VadThresholdOutOfRange`, `OrtInitFailed`, `OrtLoadFailed`,
|
|
152
|
+
`OrtPathInvalid`, `OrtSessionBuildFailed`, `OrtThreadsConfigFailed`,
|
|
153
|
+
`VadModelLoadFailed`, `OrtInferenceFailed`, `OrtTensorCreateFailed`,
|
|
154
|
+
`OrtTensorExtractFailed`. Path-carrying variants use `PathBuf`; ORT
|
|
155
|
+
variants carry `#[source] ort::Error` so `error.source()` walks the
|
|
156
|
+
error chain. Display strings (and therefore `error.message` in Node
|
|
157
|
+
and `str(exception)` in future Python bindings) are byte-identical
|
|
158
|
+
to 3.1.0.
|
|
159
|
+
- `VadConfig` now has a public `validate()` method returning
|
|
160
|
+
`Result<usize, DecibriError>` where the `usize` is the Silero VAD
|
|
161
|
+
`window_size` for the validated sample rate. Called automatically by
|
|
162
|
+
`SileroVad::new`; can be called explicitly to fail-fast before paying
|
|
163
|
+
ORT-initialization cost.
|
|
164
|
+
- Device enumeration and resolution logic in `crates/decibri/src/device.rs`
|
|
165
|
+
consolidated into a shared direction-generic implementation (input and
|
|
166
|
+
output share code paths via an internal `DeviceDirection` trait). No
|
|
167
|
+
public API change.
|
|
168
|
+
- Workspace minimum-supported Rust version (MSRV) declared at rustc 1.88,
|
|
169
|
+
forced by `ort 2.0.0-rc.12` which requires `edition = "2024"`.
|
|
170
|
+
|
|
171
|
+
### Added
|
|
172
|
+
|
|
173
|
+
- `CaptureStream::try_next_chunk()`: non-blocking read, returns
|
|
174
|
+
`Result<Option<AudioChunk>, DecibriError>` with a three-state return
|
|
175
|
+
(`Some` chunk / `None` if no data yet / `Err(CaptureStreamClosed)` if
|
|
176
|
+
terminal). Declared stable across 3.x as part of decibri's canonical
|
|
177
|
+
FFI-consumer surface.
|
|
178
|
+
- `CaptureStream::next_chunk(timeout: Option<Duration>)`: blocking read
|
|
179
|
+
with optional timeout, same three-state return shape. Declared stable
|
|
180
|
+
across 3.x. Concurrent `stop()` unblocks a waiter within approximately
|
|
181
|
+
20 ms via internal polling.
|
|
182
|
+
- `DecibriError::is_ort_path_error()`: helper that returns true for both
|
|
183
|
+
`OrtLoadFailed` and `OrtPathInvalid`. Consumers handling path-level ORT
|
|
184
|
+
failures should match this rather than enumerating both variants
|
|
185
|
+
manually. The split between the two variants is a mechanical necessity
|
|
186
|
+
(constructing `ort::Error` under `ort-load-dynamic` triggers an ORT C
|
|
187
|
+
API call and would reintroduce the Windows hang).
|
|
188
|
+
- Crate-level rustdoc on `decibri`'s `lib.rs` covering capabilities,
|
|
189
|
+
feature flags, ORT distribution modes, an end-to-end capture-plus-VAD
|
|
190
|
+
example, the process-global ORT initialization constraint, thread-safety
|
|
191
|
+
summary, and the 3.x FFI-surface stability contract.
|
|
192
|
+
- Rust integration tests for the VAD / ORT pipeline in
|
|
193
|
+
`crates/decibri/tests/vad_integration.rs` (happy path, model-not-found,
|
|
194
|
+
config validation, end-to-end silence inference) and
|
|
195
|
+
`crates/decibri/tests/vad_ort_load_failure.rs` (load-failure path
|
|
196
|
+
isolation, feature-gated to `ort-load-dynamic`). All CI-safe; no audio
|
|
197
|
+
hardware required.
|
|
198
|
+
- Unit tests for `try_next_chunk` / `next_chunk` semantics (7 tests
|
|
199
|
+
covering empty-queue, chunk-available, buffered-flush-before-closed,
|
|
200
|
+
timeout, blocking-until-arrival, and polling-interval-correctness after
|
|
201
|
+
concurrent `stop()`).
|
|
202
|
+
- Pre-publish packaging gate in `.github/workflows/release.yml`:
|
|
203
|
+
ports the `verify_pack` function from `release-dryrun.yml` to run
|
|
204
|
+
`npm pack --dry-run` against all 5 packages before any `npm publish`
|
|
205
|
+
step. Closes the dryrun-skip honor-system gap: release-dryrun.yml
|
|
206
|
+
previously caught packaging bugs but only if it was actually run before
|
|
207
|
+
tagging.
|
|
208
|
+
|
|
209
|
+
### Fixed
|
|
210
|
+
|
|
211
|
+
- Windows hang in VAD initialization: passing a nonexistent or
|
|
212
|
+
directory path as `VadConfig::ort_library_path` (or via the Node
|
|
213
|
+
binding's `ortLibraryPath`) caused `ort::init_from` to hang
|
|
214
|
+
indefinitely on Windows against pyke/ort 2.0.0-rc.12 with
|
|
215
|
+
onnxruntime 1.24.4. `init_ort_once` now performs a filesystem-level
|
|
216
|
+
`Path::is_file()` pre-check before handing the path to ORT, returning
|
|
217
|
+
`DecibriError::OrtPathInvalid` immediately for any path that fails the
|
|
218
|
+
check. The pre-check never touches ORT symbols, so it cannot itself
|
|
219
|
+
trigger the dylib load it is designed to prevent.
|
|
220
|
+
|
|
221
|
+
### Migration notes for direct Rust crate consumers
|
|
222
|
+
|
|
223
|
+
- Matches against `DecibriError::Other(msg)` will stop compiling. Replace
|
|
224
|
+
with matches against the specific new variants. The `error.message`
|
|
225
|
+
text is unchanged; code using `.to_string()` rather than pattern
|
|
226
|
+
matching continues to work unaffected.
|
|
227
|
+
- `DecibriError` is now `#[non_exhaustive]`: match expressions against
|
|
228
|
+
it must include a `_ =>` catch-all arm. New variants added in future
|
|
229
|
+
releases are non-breaking under this constraint.
|
|
230
|
+
- Consumers handling "ORT path failed" should prefer
|
|
231
|
+
`err.is_ort_path_error()` or match both `OrtLoadFailed { .. }` and
|
|
232
|
+
`OrtPathInvalid { .. }`. The two variants represent the same
|
|
233
|
+
conceptual failure mode split for FFI-side-effect reasons.
|
|
234
|
+
- MSRV raised to rustc 1.88 (from effectively-unpinned in 3.1.x). This
|
|
235
|
+
is forced by `ort 2.0.0-rc.12` declaring `edition = "2024"`. Projects
|
|
236
|
+
on older rustc cannot build decibri 3.2.0 directly; stay on 3.1.x or
|
|
237
|
+
upgrade the toolchain.
|
|
238
|
+
- `VadConfig::validate()` was new in 3.2.0 (no 3.1.x public signature
|
|
239
|
+
to break) and has the final form `Result<usize, DecibriError>`. If you
|
|
240
|
+
only need pass/fail, call `.is_ok()` or `.map(|_| ())`.
|
|
241
|
+
|
|
242
|
+
Node.js and browser consumers: no API or behaviour change. `error.message`
|
|
243
|
+
text from the native addon is byte-identical to 3.1.0 (verified against
|
|
244
|
+
the 38-assertion CI suite).
|
|
245
|
+
|
|
246
|
+
### Internal
|
|
247
|
+
|
|
248
|
+
- `ort` crate version unchanged at `2.0.0-rc.12`.
|
|
249
|
+
- Bundled ONNX Runtime version unchanged at `1.24.4`.
|
|
250
|
+
- Node binding error mapping at `bindings/node/src/lib.rs::to_napi_error`
|
|
251
|
+
explicitly enumerates every variant (compiler-enforced exhaustive
|
|
252
|
+
during the refactor by temporarily removing `#[non_exhaustive]` and
|
|
253
|
+
the `_ =>` arm; both restored). New variants added upstream fall
|
|
254
|
+
through to `GenericFailure` at runtime rather than failing to compile.
|
|
255
|
+
- `CaptureStream._stream` field type changed from `cpal::Stream` to
|
|
256
|
+
`Option<cpal::Stream>` purely to enable unit-test construction without
|
|
257
|
+
a real audio device. Production always stores `Some(stream)`; drop
|
|
258
|
+
semantics are identical.
|
|
259
|
+
- docs.rs metadata added to target all 4 production platforms (Linux x64/ARM64,
|
|
260
|
+
macOS ARM64, Windows x64) for full platform-specific rustdoc rendering.
|
|
261
|
+
Aligns with the docs.rs change effective 2026-05-01 (which builds fewer
|
|
262
|
+
targets by default).
|
|
263
|
+
|
|
264
|
+
## [3.1.0] - 2026-04-22
|
|
265
|
+
|
|
266
|
+
Internal rearchitecture: ONNX Runtime is now loaded dynamically at runtime
|
|
267
|
+
instead of embedded statically at build time. Public Node.js and browser
|
|
268
|
+
APIs are unchanged. Direct Rust crate consumers see a behaviour change;
|
|
269
|
+
see migration notes below.
|
|
270
|
+
|
|
271
|
+
### Changed
|
|
272
|
+
|
|
273
|
+
- ORT integration switched from `ort/download-binaries` to `ort/load-dynamic`.
|
|
274
|
+
npm platform packages now bundle the ONNX Runtime shared library alongside
|
|
275
|
+
the native addon. No change to `npm install decibri` workflow or to
|
|
276
|
+
Decibri construction.
|
|
277
|
+
- Silero VAD now loads ONNX Runtime dynamically from the bundled shared
|
|
278
|
+
library inside the installed platform package. Path resolution is
|
|
279
|
+
automatic; the `ORT_DYLIB_PATH` environment variable is honoured as a
|
|
280
|
+
developer escape hatch when set before Node.js starts.
|
|
281
|
+
- Bundled ONNX Runtime pinned to 1.24.4 (matches `ort 2.0.0-rc.12`'s
|
|
282
|
+
`api-24` ABI target).
|
|
283
|
+
- Native addon size reduced from ~20 MB (3.0.x) to ~817 KB on Windows x64.
|
|
284
|
+
ORT runtime now shipped separately as a ~13.5 MB bundled dylib inside
|
|
285
|
+
the platform package. Net platform package size roughly unchanged, with
|
|
286
|
+
better separation of concerns.
|
|
287
|
+
- Error message text in `decibri-*` error variants has been normalized
|
|
288
|
+
for style consistency (em-dashes replaced with sentence splits). The
|
|
289
|
+
error message prefixes (e.g., `"device index out of range"`) are
|
|
290
|
+
unchanged, so consumers matching those prefixes are unaffected.
|
|
291
|
+
Consumers matching full error message strings may need to update.
|
|
292
|
+
|
|
293
|
+
### Added
|
|
294
|
+
|
|
295
|
+
- Cargo features on the `decibri` crate for direct Rust consumers:
|
|
296
|
+
`ort-load-dynamic` (default), `ort-download-binaries` (opt-in, restores
|
|
297
|
+
3.0.x zero-config build behaviour), and execution-provider passthroughs
|
|
298
|
+
`coreml`, `cuda`, `directml`, `rocm` (off by default).
|
|
299
|
+
- Rust unit tests for device enumeration (`is_default` correctness under
|
|
300
|
+
duplicate display names).
|
|
301
|
+
- Release pipeline hardening: version-match preflight, `curl --retry` on
|
|
302
|
+
ORT downloads, macOS code-signature verification, Windows DLL imports
|
|
303
|
+
inspection, stage-and-verify packaging validation in release-dryrun.
|
|
304
|
+
- Upstream dependency monitoring for Microsoft's ONNX Runtime releases
|
|
305
|
+
(notification-only; guards against ABI mismatch upgrades).
|
|
306
|
+
|
|
307
|
+
### Fixed
|
|
308
|
+
|
|
309
|
+
- Issue #14: when two audio devices share a display name (e.g. two USB
|
|
310
|
+
microphones both reporting "Microphone"), both were previously marked
|
|
311
|
+
`is_default: true`. Now uses cpal 0.17's `Device::id()` for stable
|
|
312
|
+
per-host device identity (WASAPI endpoint ID, CoreAudio UID, ALSA
|
|
313
|
+
PCM ID). Fix applies to both input and output device enumeration.
|
|
314
|
+
|
|
315
|
+
### Migration notes for direct Rust crate consumers
|
|
316
|
+
|
|
317
|
+
If you depend on `decibri` directly via `cargo add decibri` and use the
|
|
318
|
+
`vad` feature:
|
|
319
|
+
|
|
320
|
+
- **Option 1 (recommended for zero-config builds):** pin with
|
|
321
|
+
`--features ort-download-binaries` on the dependency, which restores
|
|
322
|
+
the 3.0.x behaviour (ORT downloaded at build time, embedded statically).
|
|
323
|
+
- **Option 2 (recommended for production deployments):** keep default
|
|
324
|
+
features and either set `ORT_DYLIB_PATH=/path/to/libonnxruntime.so`
|
|
325
|
+
before first use, or call `ort::init_from(path).commit()` at startup,
|
|
326
|
+
or pass `ort_library_path` on `VadConfig` when constructing `SileroVad`.
|
|
327
|
+
|
|
328
|
+
Known limitation: ONNX Runtime is initialized once per process. Multiple
|
|
329
|
+
`Decibri`/`SileroVad` instances constructed with different `ort_library_path`
|
|
330
|
+
values will silently use the first-constructed instance's path. Pick one
|
|
331
|
+
path and use it consistently.
|
|
332
|
+
|
|
333
|
+
Direct consumers using only `capture`, `output`, `denoise`, or `gain`
|
|
334
|
+
features (no `vad`) are unaffected.
|
|
335
|
+
|
|
336
|
+
### Internal
|
|
337
|
+
|
|
338
|
+
- `ort` crate version unchanged at `2.0.0-rc.12`.
|
|
339
|
+
- `tls-native` ORT feature removed (was only required for `download-binaries`'
|
|
340
|
+
HTTPS fetch).
|
|
341
|
+
|
|
342
|
+
## [3.0.0] - 2026-04-11
|
|
343
|
+
|
|
344
|
+
Complete rewrite from C++ (PortAudio) to Rust (cpal). One unified package for Node.js and browsers. Version jumps from 1.0.0 to 3.0.0 because this release replaces both `decibri` (v1) and `decibri-web` (v0.1.1). v2.x was never published.
|
|
345
|
+
|
|
346
|
+
### Changed
|
|
347
|
+
|
|
348
|
+
- Complete rewrite from C++ (PortAudio) to Rust (cpal)
|
|
349
|
+
- Native addon built with napi-rs (replaces node-gyp / prebuildify)
|
|
350
|
+
- JS API unchanged: drop-in replacement for v1.x consumers (verified against the in-house consumer surface)
|
|
351
|
+
|
|
352
|
+
### Added
|
|
353
|
+
|
|
354
|
+
- Audio output: `DecibriOutput` class (`Writable` stream, speaker playback)
|
|
355
|
+
- Browser support: unified package with conditional exports, AudioWorklet capture
|
|
356
|
+
- Silero VAD: ML-based voice activity detection via `vadMode: 'silero'`
|
|
357
|
+
- Full duplex: `mic.pipe(speaker)` for simultaneous capture and playback
|
|
358
|
+
- `format: 'float32'` output support alongside `'int16'`
|
|
359
|
+
- Output device enumeration: `DecibriOutput.devices()`
|
|
360
|
+
- TypeScript declarations for all APIs (Node.js capture, Node.js output, browser)
|
|
361
|
+
- `crates.io` publication as a Rust crate
|
|
362
|
+
|
|
363
|
+
### Removed
|
|
364
|
+
|
|
365
|
+
- PortAudio dependency (replaced by cpal)
|
|
366
|
+
- node-gyp / prebuildify build system (replaced by napi-rs)
|
|
367
|
+
- Source build fallback (Rust binaries are self-contained)
|
|
368
|
+
|
|
369
|
+
### Deprecated
|
|
370
|
+
|
|
371
|
+
- `decibri-web` npm package (use `decibri` with the browser conditional export instead)
|
|
372
|
+
|
|
373
|
+
## [1.0.0] - 2025-06-15
|
|
374
|
+
|
|
375
|
+
Initial release. C++ native addon wrapping PortAudio with pre-built binaries.
|
|
376
|
+
|
|
377
|
+
- Microphone capture as a Node.js `Readable` stream
|
|
378
|
+
- Pre-built binaries for Windows x64, macOS ARM64, Linux x64, Linux ARM64
|
|
379
|
+
- Energy-based voice activity detection (`vad`, `vadThreshold`, `vadHoldoff`)
|
|
380
|
+
- Device enumeration and selection by index or name
|
|
381
|
+
- Int16 PCM output (little-endian)
|
|
382
|
+
- Source build fallback via node-gyp
|
|
383
|
+
|
|
384
|
+
[3.2.0]: https://github.com/decibri/decibri/compare/v3.1.0...v3.2.0
|
|
385
|
+
[3.1.0]: https://github.com/decibri/decibri/compare/v3.0.0...v3.1.0
|
|
386
|
+
[3.0.0]: https://github.com/decibri/decibri/compare/v1.0.0...v3.0.0
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Migrating to decibri 4.0.0
|
|
2
|
+
|
|
3
|
+
decibri 4.0.0 renames the Node.js API to a shared microphone and speaker
|
|
4
|
+
vocabulary that matches the Rust and Python packages, and tidies several option
|
|
5
|
+
and return shapes. This guide lists every breaking change with before and after
|
|
6
|
+
code.
|
|
7
|
+
|
|
8
|
+
## Named exports
|
|
9
|
+
|
|
10
|
+
The package no longer has a single default export. Destructure what you need.
|
|
11
|
+
|
|
12
|
+
Before:
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
const Decibri = require('decibri');
|
|
16
|
+
const { DecibriOutput } = Decibri;
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
After:
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
const { Microphone, Speaker, inputDevices, outputDevices, version } = require('decibri');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Class renames
|
|
26
|
+
|
|
27
|
+
`Decibri` is now `Microphone`; `DecibriOutput` is now `Speaker`.
|
|
28
|
+
|
|
29
|
+
Before:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
const mic = new Decibri({ sampleRate: 16000 });
|
|
33
|
+
const speaker = new DecibriOutput({ sampleRate: 16000 });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
After:
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
const mic = new Microphone({ sampleRate: 16000 });
|
|
40
|
+
const speaker = new Speaker({ sampleRate: 16000 });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## The format option is now dtype
|
|
44
|
+
|
|
45
|
+
Before:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
new Microphone({ format: 'float32' });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
After:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
new Microphone({ dtype: 'float32' });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The accepted values (`'int16'`, `'float32'`) are unchanged.
|
|
58
|
+
|
|
59
|
+
## Device-info type renames
|
|
60
|
+
|
|
61
|
+
`DeviceInfo` is now `MicrophoneInfo`; `OutputDeviceInfo` is now `SpeakerInfo`.
|
|
62
|
+
|
|
63
|
+
Before:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { DeviceInfo, OutputDeviceInfo } from 'decibri';
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
After:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { MicrophoneInfo, SpeakerInfo } from 'decibri';
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## The vad option is now a single union
|
|
76
|
+
|
|
77
|
+
The `vad: true` plus `vadMode` pair is gone. Pass the mode directly.
|
|
78
|
+
|
|
79
|
+
Before:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
new Microphone({ vad: true, vadMode: 'silero' });
|
|
83
|
+
new Microphone({ vad: true, vadMode: 'energy' });
|
|
84
|
+
new Microphone({ vad: false });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
After:
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
new Microphone({ vad: 'silero' });
|
|
91
|
+
new Microphone({ vad: 'energy' });
|
|
92
|
+
new Microphone({ vad: false }); // unchanged; the default
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`vad: true` now throws a `TypeError` telling you to specify the mode.
|
|
96
|
+
`vadThreshold` (default 0.5 for silero, 0.01 for energy), `vadHoldoff`, and
|
|
97
|
+
`modelPath` are unchanged. A new `vadScore` getter returns the latest score for
|
|
98
|
+
the active mode (the Silero probability in silero mode, the normalized RMS in
|
|
99
|
+
energy mode, 0 when disabled).
|
|
100
|
+
|
|
101
|
+
## version() shape
|
|
102
|
+
|
|
103
|
+
Before:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
version(); // { decibri, portaudio }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
After:
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
version(); // { decibri, audioBackend, binding }
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`audioBackend` replaces the inaccurately named `portaudio` field; its value is
|
|
116
|
+
unchanged. `binding` is the new field reporting the npm package version.
|
|
117
|
+
|
|
118
|
+
## Error handling
|
|
119
|
+
|
|
120
|
+
4.0.0 adds error classes you can catch:
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
const { Microphone, DecibriError, DeviceError } = require('decibri');
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
new Microphone({ device: 'no such device' });
|
|
127
|
+
} catch (err) {
|
|
128
|
+
if (err instanceof DeviceError) {
|
|
129
|
+
console.log(err.code); // e.g. 'MICROPHONE_NOT_FOUND'
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`DeviceError`, `OrtError`, and `OrtPathError` all extend `DecibriError`, which
|
|
135
|
+
extends `Error`. Each carries a stable `code` string.
|
|
136
|
+
|
|
137
|
+
## Two deliberate differences from the Python package
|
|
138
|
+
|
|
139
|
+
If you use both the Node.js and Python packages, note these intended
|
|
140
|
+
differences:
|
|
141
|
+
|
|
142
|
+
1. An out-of-range device index throws a `RangeError` in Node.js, the idiomatic
|
|
143
|
+
type for a bad numeric index. The Python package groups the same condition
|
|
144
|
+
under its `DeviceError`. Argument-validation errors in Node.js (bad sample
|
|
145
|
+
rate, channels, dtype, or vad value) also stay built-in `RangeError` or
|
|
146
|
+
`TypeError`, not `DecibriError` subclasses.
|
|
147
|
+
2. The browser surface runs energy-mode VAD only, because Silero needs the
|
|
148
|
+
native runtime that ships with the Node.js build. The browser `vad` option
|
|
149
|
+
accepts `false` or `'energy'`, and the browser `version()` returns
|
|
150
|
+
`{ decibri }` only, because the browser has no native audio backend or a
|
|
151
|
+
separate binding version.
|