npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

openwakeword-wasm-browser

v0.1.1

Published

Wake word detection for the browser using onnxruntime-web and OpenWakeWord models (hey_jarvis, hey_mycroft, alexa, etc).

Readme

OpenWakeWord WASM (browser)

Inspired by Miro Hristov’s Deep Core Labs write-up, 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.

Small 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.

Agents should read AGENTS.md to get details and onboarding instructions.

Installation

npm install file:../openwakeword_wasm
# or after publishing: npm install openwakeword-wasm-browser

Make sure the ONNX model files in models/ are hosted somewhere the browser can fetch them (for CRA/Vite you can copy the folder into public/openwakeword/models). If you self-host the ORT wasm files, pass ortWasmPath (e.g. /openwakeword/ort/).

Basic React usage

import { useEffect, useMemo, useState } from 'react';
import WakeWordEngine from 'openwakeword-wasm-browser';

export default function WakeWordDemo() {
  const [detected, setDetected] = useState(null);
  const engine = useMemo(() => new WakeWordEngine({
    baseAssetUrl: '/openwakeword/models', // where you host the .onnx files
    keywords: ['hey_jarvis'],             // or any of: alexa, hey_mycroft, hey_rhasspy, timer, weather
    detectionThreshold: 0.5,
    cooldownMs: 2000
  }), []);

  useEffect(() => {
    let unsub;
    engine.load().then(() => {
      unsub = engine.on('detect', ({ keyword, score }) => {
        setDetected(`${keyword} (${score.toFixed(2)})`);
      });
      engine.start(); // prompts for mic
    });
    return () => { unsub?.(); engine.stop(); };
  }, [engine]);

  return (
    <div>
      <p>Listening for hey_jarvis…</p>
      {detected && <p>Detected: {detected}</p>}
    </div>
  );
}

Vanilla example

import WakeWordEngine from 'openwakeword-wasm-browser';

const engine = new WakeWordEngine({
  baseAssetUrl: '/openwakeword/models',
  ortWasmPath: '/openwakeword/ort/',
  keywords: ['hey_jarvis', 'alexa'],
  detectionThreshold: 0.55,
});

await engine.load();
engine.on('speech-start', () => status.textContent = 'Speech detected');
engine.on('speech-end', () => status.textContent = 'Silence');
engine.on('detect', ({ keyword }) => playTone(keyword));
await engine.start({ deviceId: preferredMicId, gain: 1.3 });

document.querySelector('#stop').addEventListener('click', () => engine.stop());
document.querySelector('#keyword').addEventListener('change', (evt) => {
  engine.setActiveKeywords([evt.target.value]);
});

API reference

  • await engine.load() downloads ONNX models (mel, embedding, VAD, keyword heads) and infers keyword window sizes.
  • await engine.start({ deviceId?, gain? }) starts microphone streaming and posts 1280-sample chunks through the AudioWorklet.
  • await engine.stop() tears down the graph, stops tracks, and clears cooldowns.
  • engine.setGain(value) updates the GainNode while running.
  • await engine.runWav(arrayBuffer) runs the entire pipeline offline and returns the highest score seen.
  • engine.setActiveKeywords(name[]) gates which keywords are allowed to emit detect.

Events

  • ready fires once models finish loading.
  • detect surfaces { keyword, score, at } when score > threshold, VAD hangover is active, and cooldown is clear.
  • speech-start / speech-end mirror the VAD state transitions.
  • error emits any pipeline failures (getUserMedia, onnxruntime, decoding issues).

Asset layout

Example with Vite/CRA:

public/
  openwakeword/
    models/
      melspectrogram.onnx
      embedding_model.onnx
      silero_vad.onnx
      hey_jarvis_v0.1.onnx
      ...
    ort/
      ort-wasm.wasm
      ort-wasm-simd.wasm

Then 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.

Notes

  • The engine runs at 16 kHz with 80 ms frames, mirroring the reference demo in main.js.
  • VAD hangover is tuned to 12 frames to keep speech open long enough for the wake word score to peak.
  • Cooldown (cooldownMs) prevents multiple detections per utterance; lower if you want rapid-fire triggers.

Publishing / packaging tips

  • npm pack (or npm publish) includes src/, models/, and README.md via the files list so consumers get the engine and bundled assets.
  • Ship the ONNX assets alongside the package or document the public hosting location (baseAssetUrl). The React demo copies them into public/openwakeword/models.
  • Consider running engine.runWav() against hey_jarvis_11-2.wav before publishing to verify the scoring path still peaks near 1.0.