Node Web Audio API
Node Web Audio API provides a robust and specification-compliant implementation of the W3C Web Audio API for Node.js environments. Currently at version 1.0.9, it leverages a performant Rust backend (`web-audio-api-rs`) and `napi-rs` bindings to offer core audio processing capabilities, including `AudioContext`, `OscillatorNode`, and `GainNode`, suitable for server-side audio generation and manipulation. While a strict release cadence isn't published, updates align with improvements in its underlying Rust components. Key differentiators include its high performance and strict adherence to the Web Audio API specification, which is crucial for developers porting browser-based audio applications or building new audio services in Node.js. An accompanying `isomorphic-web-audio-api` package is available for cross-platform development.
Common errors
-
DeviceNotAvailable
cause Attempting to create a new `AudioContext` instance in an environment (e.g., Docker, CI/CD) that lacks a physical audio output device without specifying a 'none' sink.fixInitialize the audio context with `new AudioContext({ sinkId: { type: 'none' } })` to indicate it should run without an audio output device. -
Error: Could not find prebuilt binary for node-web-audio-api
cause The current platform or architecture does not have a precompiled binary available, or the local environment is preventing its detection (e.g., network issues during install, permission problems).fixFirst, ensure `npm install` ran successfully. If the error persists, you may need to compile the package from source. Install the Rust toolchain (`rustup install stable`) and then navigate to the package's `node_modules` directory (`cd node_modules/node-web-audio-api`) and run `npm run build`. -
error: linking with `cc` failed: exit status: 1
cause This error typically indicates missing C/C++ build tools required by the Rust compiler for native module compilation, common on Linux (e.g., `build-essential`) or macOS (Xcode Command Line Tools).fixOn Debian/Ubuntu, install `build-essential` via `sudo apt-get install build-essential`. On macOS, install Xcode Command Line Tools via `xcode-select --install`. Ensure your Rust toolchain is also up-to-date (`rustup update`).
Warnings
- gotcha The `AudioBuffer#getChannelData` method can be unreliable in certain situations. It is strongly recommended to use `AudioBuffer#copyToChannel` and `AudioBuffer#copyFromChannel` for safe and consistent sample manipulation.
- gotcha Support for MediaStream features (beyond a minimal audio input stream and `MediaStreamSourceNode`) is limited. The library primarily focuses on the core Web Audio API specification, not the broader MediaStream API.
- gotcha When running in environments without audio output devices (e.g., Docker containers, headless servers), creating an `AudioContext` without specific configuration will result in a `DeviceNotAvailable` error and crash the application.
- gotcha Prebuilt binaries for Linux platforms are built with the `jack` flag and require either a properly configured JACK Audio Connection Kit or `pipewire-jack` backend to function correctly. Without these, the library may fail to initialize or produce audio.
- gotcha If prebuilt binaries are not available for your specific platform/architecture, or if you wish to modify the source, a Rust toolchain must be installed on your system to compile the native modules. This is a common requirement for `napi-rs` based packages.
Install
-
npm install node-web-audio-api -
yarn add node-web-audio-api -
pnpm add node-web-audio-api
Imports
- AudioContext
const AudioContext = require('node-web-audio-api').AudioContext;import { AudioContext } from 'node-web-audio-api'; - OscillatorNode
const OscillatorNode = require('node-web-audio-api').OscillatorNode;import { OscillatorNode } from 'node-web-audio-api'; - GainNode
import GainNode from 'node-web-audio-api/GainNode';
import { GainNode } from 'node-web-audio-api';
Quickstart
import { AudioContext, OscillatorNode, GainNode } from 'node-web-audio-api';
const audioContext = new AudioContext();
console.log('Generating audio for 10 seconds...');
const stopTime = audioContext.currentTime + 10;
const intervalId = setInterval(() => {
if (audioContext.currentTime >= stopTime) {
clearInterval(intervalId);
console.log('Audio generation stopped.');
audioContext.close(); // Important to close context to release resources
return;
}
const now = audioContext.currentTime;
const frequency = 200 + Math.random() * 2800; // Random frequency between 200Hz and 3000Hz
const env = new GainNode(audioContext, { gain: 0 });
env.connect(audioContext.destination);
env.gain
.setValueAtTime(0, now)
.linearRampToValueAtTime(0.2, now + 0.02)
.exponentialRampToValueAtTime(0.0001, now + 1);
const osc = new OscillatorNode(audioContext, { frequency });
osc.connect(env);
osc.start(now);
osc.stop(now + 1);
}, 80);