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

@webaudio-kit/react

v1.9.13

Published

React primitives for browser audio apps.

Readme

@webaudio-kit/react

React primitives for browser audio apps.

Install

npm install @webaudio-kit/core @webaudio-kit/react
pnpm add @webaudio-kit/core @webaudio-kit/react
yarn add @webaudio-kit/core @webaudio-kit/react

@webaudio-kit/core is a peer dependency of @webaudio-kit/react. Install both packages together so React hooks and any direct core imports share one explicit core version in your app.

Framework Install Snippets

Vite React

pnpm create vite my-audio-app --template react-ts
cd my-audio-app
pnpm add @webaudio-kit/core @webaudio-kit/react

Next App Router

Install in the app root, then keep audio controls inside a client component.

pnpm add @webaudio-kit/core @webaudio-kit/react
"use client";

import { AudioProvider, useTone } from "@webaudio-kit/react";

export function AudioControls() {
  return (
    <AudioProvider>
      <ToneButton />
    </AudioProvider>
  );
}

Plain React

import { createRoot } from "react-dom/client";
import { AudioProvider } from "@webaudio-kit/react";

createRoot(document.getElementById("root")!).render(
  <AudioProvider>
    <App />
  </AudioProvider>,
);

Example

import { AudioProvider, useTone } from "@webaudio-kit/react";

function App() {
  return (
    <AudioProvider>
      <ToneButton />
    </AudioProvider>
  );
}

function ToneButton() {
  const tone = useTone({ frequency: 440, gain: 0.2 });

  return (
    <button onClick={() => void tone.play()}>
      {tone.isPlaying ? "Restart" : "Play"}
    </button>
  );
}

Noise bursts use the same provider graph:

const noise = useNoise({ type: "pink", durationMs: 800, gain: 0.08 });

<button onClick={() => void noise.play()}>Play pink noise</button>;

Patterned cues can be supplied per play call, so alert profiles do not need construction-time placeholder hook options:

const alertTone = useTone();

<button
  onClick={() =>
    void alertTone.play({
      frequency: 880,
      durationMs: 120,
      gain: 0.12,
      type: "square",
      envelope: { attackMs: 8, releaseMs: 45 },
      pattern: { repeat: 3, gapMs: 90 },
    })
  }
>
  Play alert
</button>;

Envelope options are available on tone, sweep, and noise hooks:

const sweep = useFrequencySweep({
  from: 440,
  to: 880,
  durationMs: 500,
  gain: 0.12,
  envelope: { attackMs: 10, decayMs: 40, sustain: 0.7, releaseMs: 80 },
});

Filters and voices are useful for alert cue styling:

const warningTone = useTone({
  frequency: 660,
  durationMs: 220,
  gain: 0.15,
  type: "sawtooth",
  envelope: { attackMs: 8, releaseMs: 55 },
  filter: { frequency: 1800, q: 0.7 },
  voices: { count: 2, spreadCents: 10 },
});

Provider-level stop controls are available through useAudioContext():

import { useAudioContext, useVolume } from "@webaudio-kit/react";

function AlertControls() {
  const audio = useAudioContext();
  const volume = useVolume();

  return (
    <>
      <button onClick={() => audio.stopAll()}>Stop all cues</button>
      <button onClick={() => void volume.setGain(0)}>Mute output</button>
    </>
  );
}

stopAll() cancels active and scheduled React hook playback handles. Muting with useVolume().setGain(0) changes master output level, but it does not cancel already scheduled tones, sweeps, noise bursts, patterns, or test-mode steps.

Use useVolumeControl() for a controlled slider that treats provider gain as the source of truth. It exposes inputProps, clamps changes to safe bounds, and can persist a browser preference with storageKey:

import { useVolumeControl } from "@webaudio-kit/react";

function ControlledVolumeSlider() {
  const volume = useVolumeControl({
    maxGain: 0.5,
    storageKey: "app-master-gain",
  });

  return (
    <>
      <input {...volume.inputProps} />
      <span>{volume.gain.toFixed(2)}</span>
      <button onClick={() => void volume.resetGain()}>Reset volume</button>
    </>
  );
}

Keep separate app-level state only for preferences outside audio output, such as a policy mute toggle. For normal master volume, provider gain is the canonical controlled value.

Explicit browser audio unlock UX is available through useAudioUnlock():

import { useAudioUnlock } from "@webaudio-kit/react";

function EnableAudioButton() {
  const audio = useAudioUnlock();

  return (
    <>
      <button disabled={audio.isUnlocked} onClick={() => void audio.unlock()}>
        {audio.isUnlocked ? "Audio enabled" : "Enable Audio"}
      </button>
      <span>{audio.status}</span>
      {audio.error ? <span>unlock failed</span> : null}
    </>
  );
}

Call unlock() from a click, tap, or keyboard handler. status can be idle, unlocking, suspended, running, closed, or error, which lets an app separate browser autoplay policy from library behavior.

Audio test mode exposes both active and preview state. currentStep remains null before a run starts because it means the step actively playing right now. Use previewStep and previewStepIndex for initial UI that should show the first planned diagnostic step.

const testMode = useAudioTestMode();

<p>{testMode.previewStep?.label ?? "Idle"}</p>;

Provider-scoped playback helpers are available through useAudioEngine() when custom or layered sounds still need the shared master gain and analyser graph:

import { useAudioEngine } from "@webaudio-kit/react";

function LayeredAlertButton() {
  const engine = useAudioEngine();

  async function playLayeredAlert() {
    await engine.playTone({
      frequency: 880,
      durationMs: 160,
      gain: 0.1,
      type: "square",
    });
    await engine.playNoise({
      durationMs: 120,
      gain: 0.025,
      type: "pink",
    });
  }

  return (
    <>
      <button onClick={() => void playLayeredAlert()}>
        Play layered alert
      </button>
      <button onClick={() => engine.stopAll()}>Stop all</button>
    </>
  );
}

For lower-level work, engine.withAudioRuntime() provides the provider runtime so custom code can route through runtime.masterGain.

API

  • AudioProvider
  • useAudioContext
  • useAudioUnlock
  • useAudioEngine
  • useTone
  • useFrequencySweep
  • useNoise
  • useAudioTestMode
  • useVolume
  • useVolumeControl
  • useAnalyser
  • WaveformCanvas
  • SpectrumCanvas
  • createDefaultAudioTestModeSteps
  • re-exported helpers from @webaudio-kit/core

Responsive Visualizers

width and height set the canvas backing buffer that analyser data is drawn into. Use style, className, or other forwarded canvas attributes for CSS layout when the panel needs to stretch with its container.

import { SpectrumCanvas, WaveformCanvas } from "@webaudio-kit/react";

function AnalyserPanel() {
  return (
    <>
      <WaveformCanvas
        backgroundColor="#10110f"
        height={180}
        idleStrokeColor="#394135"
        lineWidth={2}
        strokeColor="#c8ea3a"
        style={{ width: "100%", height: 140 }}
        width={720}
      />
      <SpectrumCanvas
        backgroundColor="#10110f"
        barColor="#8ed8ff"
        barCount={48}
        barGap={2}
        height={140}
        idleBarColor="#394135"
        minBarHeight={2}
        style={{ width: "100%", height: 120 }}
        width={720}
      />
    </>
  );
}

Useful props:

  • WaveformCanvas: strokeColor, idleStrokeColor, backgroundColor, lineWidth, plus standard canvas props such as className and style.
  • SpectrumCanvas: barColor, idleBarColor, backgroundColor, barCount, barGap, minBarHeight, plus standard canvas props such as className and style.

Docs And Examples

  • API reference: https://webaudio-kit.afaqrashid.com/docs/api
  • Hooks vs Core: https://github.com/i-afaqrashid/webaudio-kit/blob/main/docs/hooks-vs-core.md
  • Scope and limitations: https://github.com/i-afaqrashid/webaudio-kit/blob/main/docs/scope-and-limitations.md
  • Recipes: https://webaudio-kit.afaqrashid.com/docs/recipes
  • Example apps: https://webaudio-kit.afaqrashid.com/docs/examples
  • Markdown docs: https://github.com/i-afaqrashid/webaudio-kit/tree/main/docs
  • LLM docs index: https://webaudio-kit.afaqrashid.com/llms.txt
  • Interactive demos: https://webaudio-kit.afaqrashid.com/demos

Release History

Every npm version maps to a GitHub tag and a CHANGELOG.md section.

  • Changelog: https://webaudio-kit.afaqrashid.com/changelog
  • GitHub Releases: https://github.com/i-afaqrashid/webaudio-kit/releases
  • npm versions: https://www.npmjs.com/package/@webaudio-kit/react?activeTab=versions

The published npm tarball includes CHANGELOG.md so version history is available with the package contents.

AudioProvider lazily creates and resumes AudioContext when playback starts. This matches browser autoplay rules and keeps import-time behavior safe.

This library is for browser audio interfaces and prototypes. It is not a certified audiology or medical testing system.