feat: add Silero VAD toggle to audio pipeline

Integrates @ricky0123/vad-web's MicVAD as an optional voice activity detector
alongside the noise gate. When enabled, the Silero ONNX model classifies each
audio frame as speech or silence; silence frames mute the worklet's output via
a new VAD gate message. VAD is wired into Publisher.ts alongside the existing
noise gate transformer. Vite is configured to copy the worklet bundle, ONNX
model, and ORT WASM files to /vad/ so they're reachable at runtime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mk
2026-03-23 23:29:43 -03:00
parent 0788e56c51
commit 428b76db25
9 changed files with 386 additions and 6 deletions

185
yarn.lock
View File

@@ -3841,6 +3841,79 @@ __metadata:
languageName: node
linkType: hard
"@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2":
version: 1.1.2
resolution: "@protobufjs/aspromise@npm:1.1.2"
checksum: 10c0/a83343a468ff5b5ec6bff36fd788a64c839e48a07ff9f4f813564f58caf44d011cd6504ed2147bf34835bd7a7dd2107052af755961c6b098fd8902b4f6500d0f
languageName: node
linkType: hard
"@protobufjs/base64@npm:^1.1.2":
version: 1.1.2
resolution: "@protobufjs/base64@npm:1.1.2"
checksum: 10c0/eec925e681081af190b8ee231f9bad3101e189abbc182ff279da6b531e7dbd2a56f1f306f37a80b1be9e00aa2d271690d08dcc5f326f71c9eed8546675c8caf6
languageName: node
linkType: hard
"@protobufjs/codegen@npm:^2.0.4":
version: 2.0.4
resolution: "@protobufjs/codegen@npm:2.0.4"
checksum: 10c0/26ae337c5659e41f091606d16465bbcc1df1f37cc1ed462438b1f67be0c1e28dfb2ca9f294f39100c52161aef82edf758c95d6d75650a1ddf31f7ddee1440b43
languageName: node
linkType: hard
"@protobufjs/eventemitter@npm:^1.1.0":
version: 1.1.0
resolution: "@protobufjs/eventemitter@npm:1.1.0"
checksum: 10c0/1eb0a75180e5206d1033e4138212a8c7089a3d418c6dfa5a6ce42e593a4ae2e5892c4ef7421f38092badba4040ea6a45f0928869989411001d8c1018ea9a6e70
languageName: node
linkType: hard
"@protobufjs/fetch@npm:^1.1.0":
version: 1.1.0
resolution: "@protobufjs/fetch@npm:1.1.0"
dependencies:
"@protobufjs/aspromise": "npm:^1.1.1"
"@protobufjs/inquire": "npm:^1.1.0"
checksum: 10c0/cda6a3dc2d50a182c5865b160f72077aac197046600091dbb005dd0a66db9cce3c5eaed6d470ac8ed49d7bcbeef6ee5f0bc288db5ff9a70cbd003e5909065233
languageName: node
linkType: hard
"@protobufjs/float@npm:^1.0.2":
version: 1.0.2
resolution: "@protobufjs/float@npm:1.0.2"
checksum: 10c0/18f2bdede76ffcf0170708af15c9c9db6259b771e6b84c51b06df34a9c339dbbeec267d14ce0bddd20acc142b1d980d983d31434398df7f98eb0c94a0eb79069
languageName: node
linkType: hard
"@protobufjs/inquire@npm:^1.1.0":
version: 1.1.0
resolution: "@protobufjs/inquire@npm:1.1.0"
checksum: 10c0/64372482efcba1fb4d166a2664a6395fa978b557803857c9c03500e0ac1013eb4b1aacc9ed851dd5fc22f81583670b4f4431bae186f3373fedcfde863ef5921a
languageName: node
linkType: hard
"@protobufjs/path@npm:^1.1.2":
version: 1.1.2
resolution: "@protobufjs/path@npm:1.1.2"
checksum: 10c0/cece0a938e7f5dfd2fa03f8c14f2f1cf8b0d6e13ac7326ff4c96ea311effd5fb7ae0bba754fbf505312af2e38500250c90e68506b97c02360a43793d88a0d8b4
languageName: node
linkType: hard
"@protobufjs/pool@npm:^1.1.0":
version: 1.1.0
resolution: "@protobufjs/pool@npm:1.1.0"
checksum: 10c0/eda2718b7f222ac6e6ad36f758a92ef90d26526026a19f4f17f668f45e0306a5bd734def3f48f51f8134ae0978b6262a5c517c08b115a551756d1a3aadfcf038
languageName: node
linkType: hard
"@protobufjs/utf8@npm:^1.1.0":
version: 1.1.0
resolution: "@protobufjs/utf8@npm:1.1.0"
checksum: 10c0/a3fe31fe3fa29aa3349e2e04ee13dc170cc6af7c23d92ad49e3eeaf79b9766264544d3da824dba93b7855bd6a2982fb40032ef40693da98a136d835752beb487
languageName: node
linkType: hard
"@radix-ui/number@npm:1.1.1":
version: 1.1.1
resolution: "@radix-ui/number@npm:1.1.1"
@@ -5022,6 +5095,15 @@ __metadata:
languageName: node
linkType: hard
"@ricky0123/vad-web@npm:^0.0.30":
version: 0.0.30
resolution: "@ricky0123/vad-web@npm:0.0.30"
dependencies:
onnxruntime-web: "npm:^1.17.0"
checksum: 10c0/c91e69fb65879d54eb3eeab3cdadca95b9d1fffe3fbecf8c7ab1d59f418b79ad6e1cd0e67df25db26cf286e8fa86e030ce95ee51a749727e344f7c588d689770
languageName: node
linkType: hard
"@rolldown/pluginutils@npm:1.0.0-beta.27":
version: 1.0.0-beta.27
resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27"
@@ -5840,6 +5922,15 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:>=13.7.0":
version: 25.5.0
resolution: "@types/node@npm:25.5.0"
dependencies:
undici-types: "npm:~7.18.0"
checksum: 10c0/70c508165b6758c4f88d4f91abca526c3985eee1985503d4c2bd994dbaf588e52ac57e571160f18f117d76e963570ac82bd20e743c18987e82564312b3b62119
languageName: node
linkType: hard
"@types/node@npm:^24.0.0":
version: 24.10.13
resolution: "@types/node@npm:24.10.13"
@@ -7387,7 +7478,7 @@ __metadata:
languageName: node
linkType: hard
"chokidar@npm:^3.5.3":
"chokidar@npm:^3.5.3, chokidar@npm:^3.6.0":
version: 3.6.0
resolution: "chokidar@npm:3.6.0"
dependencies:
@@ -8303,6 +8394,7 @@ __metadata:
"@radix-ui/react-slider": "npm:^1.1.2"
"@radix-ui/react-visually-hidden": "npm:^1.0.3"
"@react-spring/web": "npm:^10.0.0"
"@ricky0123/vad-web": "npm:^0.0.30"
"@sentry/react": "npm:^8.0.0"
"@sentry/vite-plugin": "npm:^3.0.0"
"@stylistic/eslint-plugin": "npm:^3.0.0"
@@ -8380,6 +8472,7 @@ __metadata:
vite-plugin-generate-file: "npm:^0.3.0"
vite-plugin-html: "npm:^3.2.2"
vite-plugin-node-stdlib-browser: "npm:^0.2.1"
vite-plugin-static-copy: "npm:^4.0.0"
vite-plugin-svgr: "npm:^4.0.0"
vitest: "npm:^4.0.18"
vitest-axe: "npm:^1.0.0-pre.3"
@@ -9542,6 +9635,13 @@ __metadata:
languageName: node
linkType: hard
"flatbuffers@npm:^25.1.24":
version: 25.9.23
resolution: "flatbuffers@npm:25.9.23"
checksum: 10c0/957c4ae2a02be1703c98b36b4dc8ceb81613cf8e2333026afc95a7b68b088bed5458056dc29d0ab7ce8bc403b8c003732b0968d24aba46f5e7c8f71789a6bd9e
languageName: node
linkType: hard
"flatted@npm:^3.2.9":
version: 3.3.1
resolution: "flatted@npm:3.3.1"
@@ -9958,6 +10058,13 @@ __metadata:
languageName: node
linkType: hard
"guid-typescript@npm:^1.0.9":
version: 1.0.9
resolution: "guid-typescript@npm:1.0.9"
checksum: 10c0/fa0a2b2b4e06e0976a81c947b74e114b92f6647e84b52e24ab0981d2fdbaa1a640641d8fd269004dd7c581baebeb4f9d9782b74391e717e47c9b822bea4b3be6
languageName: node
linkType: hard
"gulp-sort@npm:^2.0.0":
version: 2.0.0
resolution: "gulp-sort@npm:2.0.0"
@@ -11228,6 +11335,13 @@ __metadata:
languageName: node
linkType: hard
"long@npm:^5.0.0, long@npm:^5.2.3":
version: 5.3.2
resolution: "long@npm:5.3.2"
checksum: 10c0/7130fe1cbce2dca06734b35b70d380ca3f70271c7f8852c922a7c62c86c4e35f0c39290565eca7133c625908d40e126ac57c02b1b1a4636b9457d77e1e60b981
languageName: node
linkType: hard
"loose-envify@npm:^1.4.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"
@@ -11932,6 +12046,27 @@ __metadata:
languageName: node
linkType: hard
"onnxruntime-common@npm:1.24.3":
version: 1.24.3
resolution: "onnxruntime-common@npm:1.24.3"
checksum: 10c0/3160a08a8addf7b1c8f2ff0c12c126c84847d5b36f8c047cf05560d05faf7605fe4c3366c725cfbd305d4399d0930c632a22bd6a600488ac2c6f9ee3e2aebe25
languageName: node
linkType: hard
"onnxruntime-web@npm:^1.17.0":
version: 1.24.3
resolution: "onnxruntime-web@npm:1.24.3"
dependencies:
flatbuffers: "npm:^25.1.24"
guid-typescript: "npm:^1.0.9"
long: "npm:^5.2.3"
onnxruntime-common: "npm:1.24.3"
platform: "npm:^1.3.6"
protobufjs: "npm:^7.2.4"
checksum: 10c0/7975ad03fed7017a84b64e8038187dc52ec383628fd4ac380a9dee628c1aee7959f8398c0ffe3e503b4565d381d9f8ef8863f942386f56ff5ee0915e38f828c3
languageName: node
linkType: hard
"optionator@npm:^0.9.3":
version: 0.9.4
resolution: "optionator@npm:0.9.4"
@@ -12076,6 +12211,13 @@ __metadata:
languageName: node
linkType: hard
"p-map@npm:^7.0.4":
version: 7.0.4
resolution: "p-map@npm:7.0.4"
checksum: 10c0/a5030935d3cb2919d7e89454d1ce82141e6f9955413658b8c9403cfe379283770ed3048146b44cde168aa9e8c716505f196d5689db0ae3ce9a71521a2fef3abd
languageName: node
linkType: hard
"p-retry@npm:7":
version: 7.0.0
resolution: "p-retry@npm:7.0.0"
@@ -12328,6 +12470,13 @@ __metadata:
languageName: node
linkType: hard
"platform@npm:^1.3.6":
version: 1.3.6
resolution: "platform@npm:1.3.6"
checksum: 10c0/69f2eb692e15f1a343dd0d9347babd9ca933824c8673096be746ff66f99f2bdc909fadd8609076132e6ec768349080babb7362299f2a7f885b98f1254ae6224b
languageName: node
linkType: hard
"playwright-core@npm:1.58.2":
version: 1.58.2
resolution: "playwright-core@npm:1.58.2"
@@ -12883,6 +13032,26 @@ __metadata:
languageName: node
linkType: hard
"protobufjs@npm:^7.2.4":
version: 7.5.4
resolution: "protobufjs@npm:7.5.4"
dependencies:
"@protobufjs/aspromise": "npm:^1.1.2"
"@protobufjs/base64": "npm:^1.1.2"
"@protobufjs/codegen": "npm:^2.0.4"
"@protobufjs/eventemitter": "npm:^1.1.0"
"@protobufjs/fetch": "npm:^1.1.0"
"@protobufjs/float": "npm:^1.0.2"
"@protobufjs/inquire": "npm:^1.1.0"
"@protobufjs/path": "npm:^1.1.2"
"@protobufjs/pool": "npm:^1.1.0"
"@protobufjs/utf8": "npm:^1.1.0"
"@types/node": "npm:>=13.7.0"
long: "npm:^5.0.0"
checksum: 10c0/913b676109ffb3c05d3d31e03a684e569be91f3bba8613da4a683d69d9dba948daa2afd7d2e7944d1aa6c417890c35d9d9a8883c1160affafb0f9670d59ef722
languageName: node
linkType: hard
"proxy-from-env@npm:^1.1.0":
version: 1.1.0
resolution: "proxy-from-env@npm:1.1.0"
@@ -15337,6 +15506,20 @@ __metadata:
languageName: node
linkType: hard
"vite-plugin-static-copy@npm:^4.0.0":
version: 4.0.0
resolution: "vite-plugin-static-copy@npm:4.0.0"
dependencies:
chokidar: "npm:^3.6.0"
p-map: "npm:^7.0.4"
picocolors: "npm:^1.1.1"
tinyglobby: "npm:^0.2.15"
peerDependencies:
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: 10c0/05b42b6f942e81b838f828c596fc6d00f72c0b5e1c4d68df13aaa4405c96d71333a082cc1bba96d0153134191addff8b2fe9134ed2e725b3b808e3b8470497c8
languageName: node
linkType: hard
"vite-plugin-svgr@npm:^4.0.0":
version: 4.5.0
resolution: "vite-plugin-svgr@npm:4.5.0"