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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sherpaw/kws

v0.2.1

Published

Streaming keyword spotting with replaceable token vocabularies and standalone Sherpa-ONNX WASM

Readme

@sherpaw/kws

Local streaming keyword spotting with Sherpa-ONNX WASM. Runs in a Worker by default. You supply the model, encoded keyword tokens and mono PCM audio.

Quick start

pnpm add @sherpaw/kws

Download a model pack and serve its preload.data and preload.js.metadata files:

import { createKeywordSpotter } from '@sherpaw/kws'

const [data, metadata] = await Promise.all([
  fetch('/models/kws/preload.data'),
  fetch('/models/kws/preload.js.metadata'),
])

if (!data.ok || !metadata.ok)
  throw new Error('Model download failed')

const spotter = await createKeywordSpotter({
  model: {
    data: await data.arrayBuffer(),
    metadata: await metadata.json(),
  },
  // Tokens for the Chinese/English Zipformer model below.
  keywords: [{
    label: 'LIGHT UP',
    matches: [{ tokens: ['L', 'AY1', 'T', 'AH1', 'P'] }],
  }],
})

// Call from your audio capture code with mono PCM in [-1, 1].
async function onAudio(samples: Float32Array, sampleRate: number) {
  const hits = await spotter.processAudio(samples, sampleRate)

  for (const hit of hits)
    console.log(hit.label, hit.tokens, hit.startTime, hit.timestamps)
}

// When finished:
spotter.dispose()

Keywords and controls

Each keyword has a label and a matches array. Add alternative token sequences to matches for multiple pronunciations; all return the same label. Tokens must exist in the model's tokens.txt. Text-to-token conversion is not included.

Both keywords and individual matches accept score (default 1, positive) and threshold (default 0.25, in (0, 1]). Match settings override keyword settings.

| Method | Behavior | | --- | --- | | await spotter.processAudio(samples, sampleRate) | Returns detections. Caller buffers remain usable. | | await spotter.setKeywords(entries) | Replaces the entire vocabulary and resets audio state. Invalid updates preserve the previous vocabulary. [] pauses detection. | | await spotter.reset() | Starts a fresh audio stream with the same keywords. | | spotter.dispose() | Stops the Worker and rejects pending operations. |

Initialization requires at least one keyword. Keep the sample rate constant until a reset or vocabulary update. Detection timestamps are seconds within the decoder segment, not absolute recording positions. For audio files, append about one second of silence to flush the final detection.

Optional configuration includes signal for cancellation, maxActivePaths (default 4) for the search beam, and maxPendingAudio (default 4) for outstanding audio requests. Await audio processing to avoid exceeding the queue limit. See the types for details.

Other entrypoints

  • @sherpaw/kws/node: the same async interface using Node worker threads.
  • @sherpaw/kws/worker: import inside a custom Worker entry, then pass that Worker as createKeywordSpotter(config, { worker }). The detector owns and terminates it.
  • @sherpaw/kws/core: initKWSModule() initializes WASM asynchronously; createKeywordSpotter(module, config) creates a detector with synchronous audio processing for use with @sherpaw/preloader.

Vite 7 requires optimizeDeps: { exclude: ['@sherpaw/kws'] }. Vite 8 and Rspack support the default Worker setup.

Models

Models are downloaded separately:

Both packs provide install/bin/wasm/preload.data and preload.js.metadata. Japanese is not verified.

Try microphone input and editable keywords in the sandbox playground.