@fluidinference/fluidvad

中文文档
0.2.0发布于 2026/07/16MITTypeScriptES Module零依赖近 30 天下载 2.9万

Silero VAD (v6) compiled to WebAssembly — model bundled, zero config, no runtime downloads. Browser + Node.

原始使用文档
文档目录6 节
  1. Microphone (browser / Electron renderer)
  2. Buffers (Node / Electron main / browser)
  3. Electron
  4. Configuration
  5. Development
  6. License

FluidVad

Voice activity detection for npm — Silero VAD (v6) compiled to WebAssembly. Model bundled, zero config, no runtime downloads. Works in the browser, Node, and Electron (both processes) on macOS and Windows.

  • No native modules — pure wasm. Nothing to electron-rebuild, no per-arch prebuilds, no onnxruntime peer dependency, no extra binaries to sign.
  • Model embedded — the 1.3 MB Silero v6 16 kHz graph ships inside the .wasm (5.3 MB raw, 2.3 MB gzipped total). npm install and go; nothing fetched at runtime, fully offline.
  • Streaming + offline — SpeechStart/SpeechEnd events with hysteresis, or whole-buffer segmentation. ~150× real-time; a 32 ms frame costs well under a millisecond.
npm i @fluidinference/fluidvad

Microphone (browser / Electron renderer)

import { MicVad } from "@fluidinference/fluidvad/mic";

const mic = new MicVad({
  onSpeechStart: (t) => console.log("speech started", t),
  onSpeechEnd: (audio, start, end) => {
    // audio: Float32Array, 16 kHz mono, whole utterance incl. pre-roll
    console.log(`utterance ${start.toFixed(2)}s → ${end.toFixed(2)}s`);
  },
});
await mic.start();

Buffers (Node / Electron main / browser)

import { createVad } from "@fluidinference/fluidvad";

const vad = await createVad({ threshold: 0.5 });

// streaming: push any chunk size, get boundary events
const events = vad.push(samples); // Float32Array, 16 kHz mono
// [{ isStart: true, sampleIndex: 15872, timeSeconds: 0.99 }, ...]

// offline: segment a whole buffer
const segments = vad.segment(samples);
// [{ startTime: 0.9, endTime: 4.21 }, ...]

Input is always 16 kHz mono f32 in [-1, 1]. The model consumes 512-sample frames (32 ms); push buffers partial frames internally.

Electron

Runnable example in examples/electron (mic UI + headless smoke mode, CI-tested on macOS and Windows).

  • Main / preload (Node env): createVad() works as-is; the wasm is read from disk (asar-transparent).
  • Renderer with contextIsolation: the renderer cannot fetch() file:// URLs, so hand the wasm bytes over from the preload:
// preload.cjs
const wasmPath = require.resolve("@fluidinference/fluidvad/dist/fluidvad_bg.wasm");
contextBridge.exposeInMainWorld("fluidvad", { wasmBytes: new Uint8Array(fs.readFileSync(wasmPath)) });

// renderer
const mic = new MicVad({ load: { wasm: window.fluidvad.wasmBytes }, onSpeechEnd: ... });
  • CSP: add 'wasm-unsafe-eval' to script-src (compiles wasm without enabling JS eval).
  • macOS mic: call systemPreferences.askForMediaAccess("microphone") from main and set NSMicrophoneUsageDescription when packaging.

Configuration

OptionDefaultMeaning
threshold0.5entry threshold (frame is speech at ≥)
negativeThresholdthreshold - 0.15exit threshold (hysteresis)
minSpeechDuration0.15 sdrop shorter speech runs
minSilenceDuration0.75 ssilence needed to close a segment
maxSpeechDuration14 sforce-split longer segments at the best silence
speechPadding0.1 spadding around each segment

Development

The wasm is built from a Rust core (src/) using tract for CPU inference — no onnxruntime anywhere.

Upstream Silero ONNX contains If nodes whose branches disagree on rank — onnxruntime broadcasts through it, strict runtimes cannot. We bake sr = 16000 as a constant, fix the input shapes, and constant-fold with onnxruntime's basic optimizer, which eliminates every If (scripts/prepare_model.py, bit-exact with upstream). The result is pre-compiled to NNEF (examples/export_nnef.rs) so the shipped wasm only carries tract's lightweight loader. Per-frame parity vs onnxruntime is asserted in tests (tests/model_parity.rs); the hysteresis / segmentation state machines (adapted from FluidAudio) are unit-tested with synthetic probability sequences.

cargo test --release              # core + parity tests
./scripts/build_npm.sh            # build the npm package into npm/
python3 scripts/prepare_model.py  # regenerate model artifacts (needs onnx, onnxruntime)
cd examples/electron && npm i && FLUIDVAD_SMOKE=1 npx electron .   # headless check

License

MIT. The bundled Silero VAD model is © Silero Team, MIT-licensed (SILERO_LICENSE, snakers4/silero-vad).

版本与发布记录

@fluidinference/fluidvad 共发布 2 个版本,首次发布于 2026/07/16;过去 12 个月发布了 2 个版本。

版本发布日期距今
0.2.0latest2026/07/164 个月前
0.1.02026/07/164 个月前

关于 @fluidinference/fluidvad 的常见问题

@fluidinference/fluidvad 是什么?

Silero VAD (v6) compiled to WebAssembly — model bundled, zero config, no runtime downloads. Browser + Node.

如何安装 @fluidinference/fluidvad?

在项目目录运行 npm install @fluidinference/fluidvad,或使用 pnpm add / yarn add / bun add。

@fluidinference/fluidvad 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@fluidinference/fluidvad 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@fluidinference/fluidvad 可以商用吗?

@fluidinference/fluidvad 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@fluidinference/fluidvad 的下载量有多少?

根据 npm 官方下载统计,@fluidinference/fluidvad 在 2026/10/15 – 2026/11/13 这 30 天内被下载 29,491 次,日均约 983 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fluidinference/fluidvad 还在维护吗?

最新版本 0.2.0 发布于 2026/07/16(4 个月前);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/07/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。