Web Audio API
The Web Audio API represents audio processing as a graph of connected nodes. Sources generate or provide samples; processing nodes transform them; a destination receives the output. Begin with one small signal path and a clear lifecycle before adding synthesis, effects or live input.
Separate signal correctness from playback behavior. An offline graph can verify generated samples without using speakers, while audible playback also depends on user activation, context state, browser policy and the device path. Microphone capture introduces a separate permission boundary.
TL;DR
- Build and inspect a small source-to-processing-to-destination graph.
- Schedule audio against the context timeline rather than assuming JavaScript timers are precise.
- Use bounded gain and an intentional start/stop lifecycle.
- Test autoplay, suspension, device changes and any capture permission separately.
- Treat offline render results as signal evidence rather than speaker-latency evidence.
Quick Example
This complete function renders a short tone into an in-memory buffer using OfflineAudioContext. Call await renderTone() from a supported browser module or an async UI handler. It uses one channel, 4,800 frames at 48,000 samples per second, and a bounded gain of 0.2. It does not connect to speakers or request microphone permission.
The local browser check returned a rendered 4,800-frame buffer with finite samples and a nonzero peak within the stated bound. The tone ends at 0.05 seconds inside a 0.1-second buffer. This is not an audible listening test, an AudioWorklet test or a latency benchmark.
Core Concepts
Nodes and graphs
The graph connects sample-producing and sample-processing nodes. Keep channel count, sample rate, gain and connection ownership visible. A graph that produces no audible sound might be disconnected, suspended or routed through a silent processing path; inspect each boundary before changing everything.
Offline rendering has a different destination
OfflineAudioContext renders into an AudioBuffer rather than audio hardware. Its completed buffer is useful for bounded sample-level checks. The Web Audio specification defines this separately from the real-time hardware path. Offline context
Real-time playback has browser policy
Chrome documents autoplay restrictions affecting Web Audio; applications should handle context state and resume playback in an appropriate user interaction. Do not assume that loading a page or resolving a JavaScript promise permits audible output. Other supported browsers require their own verification. Chrome autoplay policy
Schedule the sound, then manage its lifecycle
For a timed sound, use the context’s time coordinate system for source start/stop and parameter automation. JavaScript callbacks can arrive late because they share other work; repeatedly changing values from a busy UI timer is a poor substitute for an audio schedule.
Choose the intended start, duration and envelope before connecting a real-time destination. Abrupt discontinuities can create unwanted artifacts. A production design should define appropriate gain ramps, maximum output behavior and how overlapping voices are limited. The fixture uses a simple bounded oscillator to keep the sample check inspectable.
Make ownership clear when a view is removed or a track ends. Stop owned sources, release capture tracks if used, remove listeners and close contexts when the application no longer needs them. Recreating a context for every tiny UI action can make lifecycle management harder than reusing an intentionally owned graph.
Define what happens when the document is backgrounded, output becomes unavailable or playback is interrupted. The correct UI should reflect the observed state and offer an appropriate user-controlled recovery path. A progress indicator must not claim that a sound played merely because a start request was issued.
Use worklets for a specific processing need
AudioWorklet provides a place for custom audio processing in the audio rendering environment. Its code must respect that environment’s timing and resource constraints. Fetching data, allocating without bounds or performing heavy unpredictable work in a processing callback can undermine the graph’s real-time behavior. Consult the supported API and actual engine behavior for the target. Web Audio processing model
Before choosing a worklet, check whether standard nodes already express the operation. Built-in nodes can make the graph easier to inspect and reduce custom code. When custom processing is necessary, define channel handling, parameter ranges, message protocol, initialization and shutdown.
Test silence, maximum intended signal, invalid input handling, parameter transitions and prolonged processing. Compare offline numerical behavior where useful, but retain separate real-time deadline and device tests. A worklet that produces correct samples in a small fixture can still miss deadlines under a busy application workload.
Keep UI communication bounded. Send the information the audio processor needs, not an uncontrolled stream of application objects. Decide how stale parameter messages are handled and which values must be scheduled precisely on the audio timeline.
Separate permissions, latency and user experience
Generating a tone does not require microphone capture. If capture is part of the feature, request it in context and handle denial, absence and ended tracks. Explain the purpose and show the current capture state. Do not treat an unrelated sound-control click as permission to collect microphone input.
Define the latency question precisely. Graph processing delay, browser buffering, operating-system output, device transport and a person’s perceived timing are different scopes. Record which path a measurement covers rather than turning one context property into a universal end-to-end latency claim.
For interactive sound, test the actual target devices, headphones/speakers, background behavior and representative application load. Include the UI path for blocked playback and a reliable stop/mute control. Keep output levels intentional; a successful API call is not evidence that the listening experience is appropriate.
Choose the simplest graph that satisfies the feature, then verify the untested boundaries that matter to users. If the product needs precise live input/output timing, an offline waveform check is only the beginning of that acceptance work.
Best Practices
Keep signal tests bounded
Use small buffers and explicit expected properties. Avoid large spread operations or unbounded sample retention in real application code.
Make playback state visible
Observe context state and handle blocked or interrupted playback. Resume only through an appropriate user action and supported policy.
Release what the feature owns
Define source, context, node and capture-track lifetimes. Verify that leaving the feature does not leave unwanted processing or capture running.
Common Mistakes
Bad: Calling the offline render a speaker test.
Correct: Treat it as buffer-level evidence and separately test audible output and device behavior.
Bad: Assuming a page load authorizes sound or capture.
Correct: Handle playback policy and request any capture permission explicitly in feature context.
Bad: Scheduling every audio event with UI timers.
Correct: Use the audio context timeline and test real-time behavior under representative load.
FAQ
Does the example make a sound through speakers?
No. It renders only into an in-memory AudioBuffer. This keeps the signal check independent of audible output and device permissions.
Why is the buffer longer than the oscillator duration?
The 0.1-second buffer contains a tone scheduled to stop at 0.05 seconds. That provides a bounded tail region without claiming an acoustic result.
Does every audio feature need a worklet?
No. Start with standard nodes. Use custom processing when the feature requires it and test both numerical behavior and real-time resource constraints.
Related Topics
- Frontend Development — Integrate media with application lifecycle and UI.
- Lit — Connect a capability to an explicit component action.
- WebCodecs — Compare another low-level browser media boundary.