{"_id":"@edyrkaj/openwakeword-wasm-browser","_rev":"2-4d7ef9e0186f2fae437f892ee41b5899","name":"@edyrkaj/openwakeword-wasm-browser","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@edyrkaj/openwakeword-wasm-browser","version":"1.0.0","keywords":["wake-word","onnxruntime","web","speech","hey-jarvis"],"license":"MIT","_id":"@edyrkaj/openwakeword-wasm-browser@1.0.0","maintainers":[{"name":"edyrkaj","email":"edyrkaj@gmail.com"}],"homepage":"https://github.com/edyrkaj/openwakeword_wasm#readme","bugs":{"url":"https://github.com/edyrkaj/openwakeword_wasm/issues"},"dist":{"shasum":"ef440ec0bd60a98f378b336b052a1e1c790dcac4","tarball":"https://registry.npmjs.org/@edyrkaj/openwakeword-wasm-browser/-/openwakeword-wasm-browser-1.0.0.tgz","fileCount":4,"integrity":"sha512-rmtBWWBg3oq+xo0fJ2jOCsUr37oaUP7fXT323l8Vj4zx7oWhTpD8lS5aKTAL3g8j0jfC26Jz256kciUm7CRY1g==","signatures":[{"sig":"MEUCIQDgtX/9BSu3YCJ5LeeGyWperhy3OOVtOCLAAPUSKZLQzwIgHA7DdJV/pbpG+XodbJ48d7i8rxnlq9OCuLPYP+0yMAE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25505},"main":"src/index.js","type":"module","module":"src/index.js","gitHead":"2c17bd13fde991b2d77e3f9f9cbd4a4609b5ed28","scripts":{"lint":"echo \"no lint configured\"","test":"echo \"no tests configured\"","prepack:check":"node scripts/prepublish-check.mjs"},"_npmUser":{"name":"edyrkaj","email":"edyrkaj@gmail.com"},"repository":{"url":"git+https://github.com/edyrkaj/openwakeword_wasm.git","type":"git"},"_npmVersion":"11.9.0","description":"Wake word detection for the browser using onnxruntime-web and OpenWakeWord models (hey_jarvis, hey_mycroft, alexa, etc).","directories":{},"_nodeVersion":"25.6.1","dependencies":{"onnxruntime-web":"^1.23.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/openwakeword-wasm-browser_1.0.0_1784201865809_0.0854967919095353","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@edyrkaj/openwakeword-wasm-browser","version":"1.0.1","description":"Wake word detection for the browser using onnxruntime-web and OpenWakeWord models (hey_jarvis, hey_mycroft, alexa, etc).","main":"src/index.js","type":"module","module":"src/index.js","repository":{"type":"git","url":"git+https://github.com/edyrkaj/openwakeword_wasm.git"},"homepage":"https://github.com/edyrkaj/openwakeword_wasm#readme","bugs":{"url":"https://github.com/edyrkaj/openwakeword_wasm/issues"},"scripts":{"lint":"echo \"no lint configured\"","test":"echo \"no tests configured\"","prepack:check":"node scripts/prepublish-check.mjs"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"dependencies":{"onnxruntime-web":"^1.23.2"},"license":"MIT","keywords":["wake-word","onnxruntime","web","speech","hey-jarvis"],"gitHead":"65616d55bf56e5e383e106635ba248fb4516c592","_id":"@edyrkaj/openwakeword-wasm-browser@1.0.1","_nodeVersion":"22.23.1","_npmVersion":"12.0.1","dist":{"integrity":"sha512-cxnhwehyoo8p6aF5bk7qMo9x6+y+ez5UVB/IuRG2ORmfQmRjHc5krxQQG35XcVqvn09ZWlij3zEInYCjizgfoA==","shasum":"e2277cc660a076092df625730607207bce4477c7","tarball":"https://registry.npmjs.org/@edyrkaj/openwakeword-wasm-browser/-/openwakeword-wasm-browser-1.0.1.tgz","fileCount":4,"unpackedSize":25524,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@edyrkaj%2fopenwakeword-wasm-browser@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDohsbBhIjjeYAXLMdzEpanYkAOyv4w6DqjNPJkfhhidwIhAPznSKXBPjia5R8/YqAcXBjzrHtdkgTX7SXUA9DO6lVB"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ccaabaf7-3249-4075-85ed-50e5eb9032ab"}},"directories":{},"maintainers":[{"name":"edyrkaj","email":"edyrkaj@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openwakeword-wasm-browser_1.0.1_1784202950809_0.7314692449139109"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-16T11:37:45.613Z","modified":"2026-07-16T11:55:51.393Z","1.0.0":"2026-07-16T11:37:45.953Z","1.0.1":"2026-07-16T11:55:51.003Z"},"bugs":{"url":"https://github.com/edyrkaj/openwakeword_wasm/issues"},"license":"MIT","homepage":"https://github.com/edyrkaj/openwakeword_wasm#readme","keywords":["wake-word","onnxruntime","web","speech","hey-jarvis"],"repository":{"type":"git","url":"git+https://github.com/edyrkaj/openwakeword_wasm.git"},"description":"Wake word detection for the browser using onnxruntime-web and OpenWakeWord models (hey_jarvis, hey_mycroft, alexa, etc).","maintainers":[{"name":"edyrkaj","email":"edyrkaj@gmail.com"}],"readme":"# OpenWakeWord WASM (browser)\n\nInspired by [Miro Hristov’s Deep Core Labs write-up](https://deepcorelabs.com/open-wake-word-on-the-web/), this package brings the same browser-only wake-word pipeline into a reusable npm module. A full React sandbox lives in this repo as well: [openwakeword_wasm_react_demo](https://github.com/edyrkaj/openwakeword_wasm/tree/main/openwakeword_wasm_react_demo).\n\nSmall browser-first wrapper around the OpenWakeWord models using `onnxruntime-web`. It exposes a `WakeWordEngine` class you can drop into a React app to listen for wake words like `hey_jarvis` directly in Chrome, no native layer required.\n\nAgents should read AGENTS.md to get details and onboarding instructions.\n\n**Package:** `[@edyrkaj/openwakeword-wasm-browser](https://www.npmjs.com/package/@edyrkaj/openwakeword-wasm-browser)` — library code only. ONNX models are **not** published on npm; copy them from this repo’s `models/` folder (or host them yourself) and point `baseAssetUrl` at that location.\n\n## Installation\n\n```bash\nnpm install @edyrkaj/openwakeword-wasm-browser\n```\n\nFor local development against this repo:\n\n```bash\nnpm install file:../openwakeword_wasm\n```\n\nCopy the ONNX files from `models/` somewhere the browser can fetch them (for CRA/Vite: `public/openwakeword/models`). If you self-host the ORT wasm files, pass `ortWasmPath` (e.g. `/openwakeword/ort/`).\n\n## Basic React usage\n\n```jsx\nimport { useEffect, useMemo, useState } from 'react';\nimport WakeWordEngine from '@edyrkaj/openwakeword-wasm-browser';\n\nexport default function WakeWordDemo() {\n  const [detected, setDetected] = useState(null);\n  const engine = useMemo(() => new WakeWordEngine({\n    baseAssetUrl: '/openwakeword/models', // where you host the .onnx files\n    keywords: ['hey_jarvis'],             // or any of: alexa, hey_mycroft, hey_rhasspy, timer, weather\n    detectionThreshold: 0.5,\n    cooldownMs: 2000\n  }), []);\n\n  useEffect(() => {\n    let unsub;\n    engine.load().then(() => {\n      unsub = engine.on('detect', ({ keyword, score }) => {\n        setDetected(`${keyword} (${score.toFixed(2)})`);\n      });\n      engine.start(); // prompts for mic\n    });\n    return () => { unsub?.(); engine.stop(); };\n  }, [engine]);\n\n  return (\n    <div>\n      <p>Listening for hey_jarvis…</p>\n      {detected && <p>Detected: {detected}</p>}\n    </div>\n  );\n}\n```\n\n\n\n### Vanilla example\n\n```js\nimport WakeWordEngine from '@edyrkaj/openwakeword-wasm-browser';\n\nconst engine = new WakeWordEngine({\n  baseAssetUrl: '/openwakeword/models',\n  ortWasmPath: '/openwakeword/ort/',\n  keywords: ['hey_jarvis', 'alexa'],\n  detectionThreshold: 0.55,\n});\n\nawait engine.load();\nengine.on('speech-start', () => status.textContent = 'Speech detected');\nengine.on('speech-end', () => status.textContent = 'Silence');\nengine.on('detect', ({ keyword }) => playTone(keyword));\nawait engine.start({ deviceId: preferredMicId, gain: 1.3 });\n\ndocument.querySelector('#stop').addEventListener('click', () => engine.stop());\ndocument.querySelector('#keyword').addEventListener('change', (evt) => {\n  engine.setActiveKeywords([evt.target.value]);\n});\n```\n\n\n\n### External weight files (`externalDataFiles`) (new)\n\n`externalDataFiles` — optional map of ONNX filename → string URL **or** `{ path, data }` for ORT Web external weights.\n\n- `path` must match the protobuf external `location`.\n- `data` is an absolute URL, or a path relative to `baseAssetUrl`.\n- A bare string is treated as both `path` and `data`.\n- Used only when a model is split into graph + external weight file; it does **not** replace `baseAssetUrl` for normal `.onnx` hosting.\n\n```js\nimport WakeWordEngine from '@edyrkaj/openwakeword-wasm-browser';\n\nconst engine = new WakeWordEngine({\n  baseAssetUrl: '/openwakeword/models',\n  externalDataFiles: {\n    // only needed for models that ship external weight blobs\n    'some_model.onnx': {\n      path: 'some_model.onnx.data',      // protobuf external location\n      data: 'some_model.onnx.data',      // fetch URL (rel. to baseAssetUrl OK)\n    },\n    // equivalent shorthand (path and data are the same string):\n    // 'other_model.onnx': 'other_model.onnx.data',\n  },\n});\n```\n\n\n\n## API reference\n\n- `await engine.load()` downloads ONNX models (mel, embedding, VAD, keyword heads) and infers keyword window sizes.\n- `await engine.start({ deviceId?, gain? })` starts microphone streaming and posts 1280-sample chunks through the AudioWorklet.\n- `await engine.stop()` tears down the graph, stops tracks, and clears cooldowns.\n- `engine.setGain(value)` updates the `GainNode` while running.\n- `await engine.runWav(arrayBuffer)` runs the entire pipeline offline and returns the highest score seen.\n- `engine.setActiveKeywords(name[])` gates which keywords are allowed to emit `detect`.\n- Constructor option `externalDataFiles` — see [External weight files](#external-weight-files-externaldatafiles).\n\n\n\n### Events\n\n- `ready` fires once models finish loading.\n- `detect` surfaces `{ keyword, score, at }` when score > threshold, VAD hangover is active, and cooldown is clear.\n- `speech-start` / `speech-end` mirror the VAD state transitions.\n- `error` emits any pipeline failures (getUserMedia, onnxruntime, decoding issues).\n\n\n\n### Asset layout\n\nExample with Vite/CRA (copy ONNX from this repo’s `models/` — they are not inside the npm tarball):\n\n```\npublic/\n  openwakeword/\n    models/\n      melspectrogram.onnx\n      embedding_model.onnx\n      silero_vad.onnx\n      hey_jarvis_v0.1.onnx\n      ...\n    ort/\n      ort-wasm.wasm\n      ort-wasm-simd.wasm\n```\n\nThen instantiate with `baseAssetUrl: '/openwakeword/models'` and `ortWasmPath: '/openwakeword/ort'` if you host the wasm yourself. If `ortWasmPath` is omitted, `onnxruntime-web` uses its default CDN.\n\n### Notes\n\n- The engine runs at 16 kHz with 80 ms frames, mirroring the reference demo in `main.js`.\n- VAD hangover is tuned to 12 frames to keep speech open long enough for the wake word score to peak.\n- Cooldown (`cooldownMs`) prevents multiple detections per utterance; lower if you want rapid-fire triggers.\n\n\n\n### Publishing / packaging\n\n- The published package includes `src/` and `README.md` only (library-only). Models stay in the git repo for demos and self-hosting.\n- Releases: push an annotated tag `vX.Y.Z` matching `package.json` `version`; GitHub Actions runs pack/docs gates and `npm publish --access public`.\n- Before a release, run `npm run prepack:check` (or `npm pack`) and confirm the tarball has no `models/`.\n- Consider running `engine.runWav()` against `hey_jarvis_11-2.wav` before tagging to verify scoring still peaks near 1.0.\n\n","readmeFilename":"README.md"}