Open-source project
ricky0123/vad avatar
ricky0123/vad

ricky0123/vad: browser voice activity detection with Silero ONNX

Voice activity detector (VAD) for the browser with a simple API

2,077 stars270 forksTypeScriptNOASSERTION

At a glance

What is it?
ricky0123/vad wraps Silero VAD and ONNX Runtime Web so a page can emit speech segments as a Float32Array at sample rate 16000, with the model and runtime assets loaded from whichever CDN path you pass. The wrapper is the product here, and the README publishes no accuracy figure to judge it against.
Who is it for?
ricky0123/vad suits browser apps that need speech-triggered uploads, a live speaking indicator or a React recording flow, and it does not suit pipelines where raw audio has to stay on a server.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 56 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • ricky0123/vad2,077 ★ · +9
Star history
Repository2026-10-142026-11-07
ricky0123/vad2.1k2.1k

9 Stars in the last 24 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

MicVAD turns microphone permission into speech segment callbacks

Speech-to-text interfaces need to know when a person started and stopped talking, and ricky0123/vad makes that decision in the browser rather than on a server. The repository description calls it a voice activity detector for the browser with a simple API, and the README names three jobs for it: prompting for microphone permission, starting audio recording, and handing back only the segments that contain speech, either to upload for processing or to drive a speaking indicator.

Underneath the wrapper sits Silero VAD, the pre-trained detector credited in the README references, executed by ONNX Runtime Web inside the page or by ONNX Runtime Node.js outside it. The unit of output is fixed in the documented sample: onSpeechEnd receives a Float32Array of audio samples at sample rate 16000. Anything downstream, transcription or activity logging, therefore consumes 16000 sample rate chunks whatever capture settings the browser picked.

Silero ONNX weights are fetched from a path you pass

The model is not compiled into your JavaScript by default. MicVAD.new accepts two path options. onnxWASMBasePath points at the ONNX Runtime Web distribution that supplies the wasm runtime, and baseAssetPath points at the directory holding this package's own assets, which is where the Silero weights come from once the constructor runs. A deployment has to serve two directories and keep their versions matched.

Three generations of the same network sit at the repository root: silero_vad_legacy.onnx, silero_vad_v5.onnx and silero_vad_v6.onnx, with a shell script named check_vad_up_to_date.sh beside them. Nothing in the README states which of those files a build loads, or how to override the choice among the options shown in the quick start, so that decision has to be read out of the source before you depend on it. The topic list, onnxruntime and silero-vad next to web-audio-api, describes that data path accurately.

The script tag sample pins the runtime twice over

The quickest documented path is two script tags and no build step. The first loads the ONNX Runtime Web wasm bundle, the second loads the compiled browser bundle, and the options after them decide where those same files are fetched from at runtime:

html
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ort.wasm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@ricky0123/[email protected]/dist/bundle.min.js"></script>

The options passed to vad.MicVAD.new make the version pinning explicit:

js
onSpeechStart: () => {
        console.log("Speech start detected")
      },
      onSpeechEnd: (audio) => {
        // do something with `audio` (Float32Array of audio samples at sample rate 16000)...
      },
      onnxWASMBasePath:
        "https://cdn.jsdelivr.net/npm/[email protected]/dist/",
      baseAssetPath:
        "https://cdn.jsdelivr.net/npm/@ricky0123/[email protected]/dist/",

Count the repeated version strings before copying them. [email protected] appears in the first script tag and again inside onnxWASMBasePath, and @ricky0123/[email protected] appears in the second tag and again in baseAssetPath. Change one copy without the other and the page keeps running while its runtime and its assets drift apart. A call to myvad.start() then opens the callback stream, and that call is where the quick start stops: no package manager command appears in it, and node or React bundling is deferred to docs.vad.ricky0123.com.

Workspaces split a browser package from a React package

Contributing is a two-package npm workspace. The root manifest is marked private with version 0.0.0, so the top level orchestrates instead of shipping:

json
"workspaces": [
    "packages/web",
    "packages/react"
  ],

The build, test and clean scripts each fan out with `--workspaces --if-present`, which skips a workspace that has no such script rather than failing the run. Linting splits in two: `lint` calls `./scripts/lint.sh`, and `lint:fix` points `eslint.config.mts` at `packages/**/*.{ts,tsx}` and can rewrite files. `typecheck` runs `tsc --noEmit` three times, once each against `packages/web`, `packages/react` and `test-site`, so a type error in the React wrapper or in the browser test site fails the same command. Formatting runs prettier, pinned at `^2.6.2`, with `prettier-plugin-organize-imports` on top, while `./scripts/dev.sh` and `node scripts/sim/index.mjs` cover local development and the simulation harness.

Documentation builds through Poetry with a pinned redirect plugin

The documentation site is a separate Poetry project sharing the same repository. `pyproject.toml` sets `package-mode = false`, declares the interpreter as `^3.10`, and pulls in `mkdocs` at `^1.6.1` with `mkdocs-material` at `^9.5.42` and `pymdown-extensions` at `^10.12`. `mkdocs.yml` and `poetry.lock` sit at the root next to the TypeScript workspaces, and the README places the source of docs.vad.ricky0123.com in the ./docs directory.

One pin in that block is deliberate rather than accidental:

yaml
mkdocs-redirects = "1.2.2"
pymdown-extensions = "^10.12"

The comment above it records the reason: version 1.2.3 of `mkdocs-redirects` added a dependency on `properdocs`, a MkDocs fork, and prints a promo banner on every build, so the build stays on 1.2.2. That is the whole Python side of the tree, and it reaches contributors rather than npm consumers. For someone evaluating the library the useful consequence is narrower: docs and code live in one repository, so a documentation fix and a behaviour change travel in the same commit.

Three conflicting version numbers describe the same package

Three version numbers describe one codebase, and only two of them reach users. The root package.json carries version 0.0.0 with private true, and pyproject.toml names the repository package vad at version 0.1.0 for the documentation build, so neither number is what npm shows. What npm shows comes from the workspaces: @ricky0123/vad-web at 0.0.31 and @ricky0123/vad-react at 0.0.37.

The same gap runs through the licensing metadata: the root manifest declares ISC, while the repository is filed under a custom LICENSE file that GitHub's classifier cannot place, so anyone vendoring this code has to read that file rather than trust the manifest a package manager prints.

Timestamps tighten the picture. The last push was on 2026-09-12 at 18:53 UTC, and the two workspace packages took their new numbers two and four minutes after it, which shows the path a change takes before it reaches an application.

A browser VAD trades upload bandwidth for on-device inference

The ordinary alternative keeps the browser passive: stream microphone audio to a backend and let the backend decide where speech starts. That design needs no model in the page, and it ships every pause, every cough and every silent stretch across the network while a connection stays open for the length of the conversation.

ricky0123/vad moves the decision in front of the upload. Its stated purpose is sending segments of audio with speech to your server for processing, which only saves anything because segmentation has already happened in the page. Bytes crossing the wire are Float32Array samples at sample rate 16000 instead of a full capture stream. The cost moves with them: the page fetches the ONNX Runtime Web wasm bundle and the model assets before the first callback fires, so first-use delay belongs to the browser rather than the server.

Running Silero VAD yourself stays possible, because the repository keeps its weights as plain ONNX files. What this project adds is the microphone permission flow, the asset path plumbing, a fixed callback shape built on onSpeechStart and onSpeechEnd, and a React wrapper in `packages/react` published as @ricky0123/vad-react.

Missing benchmarks and CDN pinning define the adoption boundary

Two gaps decide whether this fits a project. The first is measurement: the README gives no accuracy, latency or memory figure for the browser build, and its only hard number is the sample rate handed to onSpeechEnd. Silero VAD is called a pre-trained enterprise-grade detector in the reference block, but that line belongs to the model authors, and nothing here measures what the wrapper costs on a low-end phone. The repository does carry a browser test site under test-site/ with its own build.sh and an http-server script, and `playwright` at `^1.53.0` sits in devDependencies, so the plumbing is exercised by the project itself while the README reports no accuracy number.

The second gap is rollback. Two npm packages move on their own schedules, and the README does not document check_vad_up_to_date.sh, so it cannot be relied on as a rollback procedure. If a bundled weight misbehaves in your build, pinning the two versions in the script tag is the only control on offer, and no documented option forces silero_vad_legacy.onnx or silero_vad_v5.onnx at runtime. The examples/ directory covers bundler, nextjs, react-bundler and script-tags, so integration shapes are answered; the model choice is not.

Editorial conclusion

ricky0123/vad suits browser apps that need speech-triggered uploads, a live speaking indicator or a React recording flow, and it does not suit pipelines where raw audio has to stay on a server. Before adopting, confirm two things: that you can host onnxruntime-web and the model assets on your own CDN instead of the jsdelivr paths in the quick start, and that the segmentation of 16000 sample rate audio is accurate enough for your use, since the README publishes no measurement to check it against.

Frequently asked questions

Does ricky0123/vad work offline, or does it need a CDN?

The quick start loads both [email protected] and @ricky0123/vad-web from jsdelivr, and passes the same two locations back through onnxWASMBasePath and baseAssetPath, so the sample as written needs network access. The repository carries examples/bundler/ and examples/script-tags/, and the README sends bundling questions to docs.vad.ricky0123.com without spelling out an offline layout.

What does onSpeechEnd give me in ricky0123/vad?

A Float32Array of audio samples at sample rate 16000, according to the comment in the quick start sample. onSpeechStart fires with no argument when the detector sees speech beginning.

Which npm packages does ricky0123/vad publish, and how are they related?

@ricky0123/vad-web at 0.0.31 and @ricky0123/vad-react at 0.0.37, both dated 2026-09-12. They are the two workspaces, packages/web and packages/react, declared in a root package.json that is private and carries version 0.0.0.

Do I need Python to run ricky0123/vad?

Not for the library itself. Python appears only in pyproject.toml, which is package-mode = false, declares the interpreter as ^3.10 and drives a MkDocs documentation build. The README quick start uses script tags and nothing else.

Can I choose which Silero model ricky0123/vad loads?

The repository keeps silero_vad_legacy.onnx, silero_vad_v5.onnx and silero_vad_v6.onnx at its root and ships check_vad_up_to_date.sh, but the README documents no model option and no rule for choosing between the three. That selection has to be read out of the source in packages/web.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. ricky0123/vad on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ricky0123-vad.svg)](https://hysenlabs.com/projects/ricky0123-vad)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/ricky0123-vad.svg)](https://hysenlabs.com/projects/ricky0123-vad)

Was this useful?