Skip to content

WebAudioBackend

Web Audio pipeline backend. Routes all audio through a AudioContext graph. Crossfade uses GainNode.gain.linearRampToValueAtTime for sample-accurate ramps.

Kind: 'webaudio'

Activation

TypeScript
player.setup({ backend: 'webaudio' });

Or switch at runtime:

TypeScript
await player.backend('webaudio');

Audio graph

The backend constructs a graph rooted at the AudioContext:

4
MediaElementAudioSourceNodeWebAudioBackend

Source node. Always wraps the <audio> element via createMediaElementSource(), for both HLS and non-HLS sources.

3
GainNode (primary volume)WebAudioBackend

Controls playback volume and executes crossfade ramps via linearRampToValueAtTime.

2
Backend output nodeWebAudioBackend

Tap point for AudioGraphPlugin effect chains. Connect custom analyser or effect nodes here.

1
AudioContext.destinationWeb Audio API

Final sink routed to the device speakers or headphones.

When AudioGraphPlugin is registered, it connects its effect chain between the outputNode() and AudioContext.destination.

Source node

WebAudioBackend always routes through a <audio> element and wraps it with createMediaElementSource(). This applies to both HLS streams and direct file URLs (MP3, AAC, FLAC, OGG). hls.js attaches to the same <audio> element, so there is no separate code path per format.

Crossfade implementation

crossfade(durationMs):

  1. Primary GainNode.gain ramps from current volume to 0 via linearRampToValueAtTime
  2. Secondary GainNode.gain ramps from 0 to current volume via linearRampToValueAtTime
  3. Both ramps complete at AudioContext.currentTime + durationMs / 1000
  4. At completion, the secondary becomes the primary; the old primary is disconnected and its buffer released

Accuracy: Sample-accurate. No RAF loop, no jitter.

Volume changes are smoothed with GainNode.gain.setTargetAtTime (time constant 10 ms) to prevent clicks on mute/unmute or abrupt volume changes.

iOS considerations

On iOS and in some mobile Chrome contexts, AudioContext creation may be suspended until a user gesture. If audioContext().state === 'suspended', call audioContext().resume() inside a user interaction handler before starting playback.

Graph access

TypeScript
const audioCtx = player.audioContext(); // AudioContext | undefined

if (audioCtx) {
const analyser = audioCtx.createAnalyser();
const backend = player.backend();

backend.outputNode(audioCtx).connect(analyser);
analyser.connect(audioCtx.destination);
}

See also