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

web-audio-api

v1.2.0

Published

Portable Web Audio API

Readme

web-audio-api test

Portable Web Audio API for any JS environment. 100% WPT conformance.

npm install web-audio-api

Use

import { AudioContext } from 'web-audio-api'

const ctx = new AudioContext()
await ctx.resume()

const osc = ctx.createOscillator()
osc.frequency.value = 440
osc.connect(ctx.destination)
osc.start()
// → plays through speakers

Audio output is built-in via audio-speaker — no extra packages needed.

Offline rendering

import { OfflineAudioContext } from 'web-audio-api'

const ctx = new OfflineAudioContext(2, 44100, 44100) // 1 second, stereo
const osc = ctx.createOscillator()
osc.frequency.value = 440
osc.connect(ctx.destination)
osc.start()

const buffer = await ctx.startRendering()
// buffer.getChannelData(0) → Float32Array of 44100 samples

Custom output stream

For piping to external tools or custom sinks, set outStream to any writable:

ctx.outStream = myWritableStream
node synth.js | aplay -f cd

Polyfill

Register Web Audio API globals for environments that lack them:

import 'web-audio-api/polyfill'

// AudioContext, OfflineAudioContext, GainNode, etc. are now global

Testing audio code

import { OfflineAudioContext } from 'web-audio-api'
import { test } from 'node:test'
import { strictEqual } from 'node:assert'

test('gain halves amplitude', async () => {
  const ctx = new OfflineAudioContext(1, 128, 44100)
  const src = ctx.createConstantSource()
  const gain = ctx.createGain()
  gain.gain.value = 0.5
  src.connect(gain).connect(ctx.destination)
  src.start()
  const buf = await ctx.startRendering()
  strictEqual(buf.getChannelData(0)[0], 0.5)
})

Examples

Run any example: node examples/<name>.js — real-time examples play sound through speakers.

| | Example | | |---|---------|---| | | speaker.js | Hello world — play a tone | | | sweep.js | Frequency sweep 100Hz → 4kHz | | | subtractive-synth.js | Sawtooth → filter sweep → ADSR | | | noise.js | AudioWorklet noise → bandpass filter | | | lfo.js | Tremolo via LFO modulation | | | spatial.js | PannerNode — sound moves left to right | | | sequencer.js | Step sequencer with precise scheduling | | | worklet.js | AudioWorkletProcessor with custom param | | | linked-params.js | ConstantSourceNode controlling multiple gains | | | fft.js | AnalyserNode — frequency spectrum | | | render-to-buffer.js | OfflineAudioContext → buffer | | | process-file.js | Read audio file → EQ + compress → render | | | pipe-stdout.js | Pipe PCM to system player |

Alternatives

| | web-audio-api | node-web-audio-api | standardized-audio-context | web-audio-api-rs | |---|---|---|---|---| | Language | JS | Rust (napi) | JS | Rust | | Runs in | Node, Bun, Deno, browser | Node only | Browser only | Rust / WASM | | Native deps | none | platform binary | none | Rust toolchain | | WPT compliance | 98% | partial | n/a (wraps native) | partial | | Install | npm install | npm install (downloads binary) | npm install | cargo add |

Choose this package when you need portable spec-compliant Web Audio in any JS environment — testing, offline rendering, SSR, or lightweight real-time playback. Choose node-web-audio-api when you need maximum DSP throughput on Node.js and can accept the native dependency. Choose standardized-audio-context when you target browsers and need a uniform API across vendor differences. Choose web-audio-api-rs for Rust-native or WASM projects (not an npm package).

Also: web-audio-engine — earlier pure-JS effort (archived 2019), inspiration for this project.

Rendering 1s of audio at 44.1kHz (npm run bench:all):

| Scenario | web-audio-api (JS) | node-web-audio-api (Rust) | Chrome (native) | |---|---|---|---| | OscillatorNode | 0.3ms | 0.3ms | 0.4ms | | Osc → Gain | 0.4ms | 0.2ms | 0.4ms | | Osc → BiquadFilter | 0.9ms | 0.4ms | 0.5ms | | DynamicsCompressor | 2.0ms | 0.5ms | 1.2ms | | ConvolverNode (128-tap) | 4.4ms | 1.6ms | 0.4ms | | 8-voice polyphony | 2.3ms | 1.8ms | 1.2ms |

All scenarios run faster than real-time. Pure JS matches Rust on simple graphs; heavier DSP (convolution, compression) is 2–4× slower — WASM kernels are planned for these paths.

Limitations

  • Performance — pure JS is fast for most use cases but won't match native implementations for sustained heavy real-time DSP (dozens of simultaneous convolver/panner nodes). WASM kernels are planned.
  • outStream — the only API surface outside the W3C spec. It's the bridge to custom audio output (stdout, streams). Default output uses audio-speaker and needs no configuration.
  • AudioWorklet threading — runs synchronously on the main thread. Browsers use a separate audio thread. Functionally identical, but no thread isolation.

FAQ

await ctx.close() // stops rendering, releases resources

Or with explicit resource management: using ctx = new AudioContext()

Per the W3C spec. Browsers require user activation before audio can play. Call await ctx.resume() to start, or use OfflineAudioContext which doesn't need it.

import { AudioContext } from 'web-audio-api'
import * as Tone from 'tone'
Tone.setContext(new AudioContext())
import { readFileSync } from 'node:fs'
const ctx = new OfflineAudioContext(2, 1, 44100)
const buffer = await ctx.decodeAudioData(readFileSync('track.mp3'))

Supports WAV, MP3, FLAC, OGG, AAC, and more.

import 'web-audio-api/polyfill' // registers AudioContext, OfflineAudioContext, etc. as globals

All nodes run faster than real-time on a single thread (npm run bench). For heavy real-time workloads (many convolvers/panners), consider node-web-audio-api which uses Rust.

Architecture

Pull-based audio graph. AudioDestinationNode pulls upstream via _tick(), 128-sample render quanta per the spec. DSP kernels separated from graph plumbing for future WASM swap.

EventTarget ← Emitter ← DspObject ← AudioNode ← concrete nodes
                                    ← AudioParam
EventTarget ← Emitter ← AudioPort ← AudioInput / AudioOutput

License

MIT