Skip to content


Switch branches/tags



This repo provides low-latency web audio playback examples for programatically decoding audio in chunks with the Web Audio API and the new Fetch & Streams APIs. Traditionally, decodeAudioData() is used for programmatic decoding but requires the complete file to be downloaded, and chunk-based decoding is not supported. These Streams examples will show how to sidestep that limitation. Media Source Extensions could also be used to play audio and that example may be integrated here one day.

The examples demonstrate:

  1. Opus Streaming opus-stream-decoder is used to decode an Opus file in a Web Worker with WebAssembly. This simulates a real-world use case of streaming compressed audio over the web with the Web Audio API. (MP3 is old and outdated for those of us who grew up with WinPlay3. Opus is the new gold standard). This example is ideal because it allows for small, high-quality files with Opus.
  2. WAV Streaming A WAV file is streamed and decoded by a Web Worker. Chunks are scheduled into a read buffer before sending to encoder to ensure decoder receives complete, decodable chunks. JavaScript (not WebAssembly) is used for decoding. This example requires a much larger file.

Opus Playback Tests

Opus file playback can be tested at throttled download speeds and varkous encoding/bitrate qualities (Issue #14 will add to UI):

opusBitrate = 96; throttle = nolimit
opusBitrate = 96; throttle = 1mbps
opusBitrate = 96; throttle = 104kbps
opusBitrate = 96; throttle = 100kbps
opusBitrate = 64; throttle = 72kbps
opusBitrate = 60; throttle = 64kbps
opusBitrate = 53; throttle = 56kbps
opusBitrate = 32; throttle = 40kbps
opusBitrate = 28; throttle = 32kbps
opusBitrate = 12; throttle = 16kbps

Back-End Nginx Server

To use the config files, create symblink fetch-stream-audio, e.g.:

$ ln -s [LOCATION_TO_THIS_REPO]/.conf/nginx /etc/nginx/fetch-stream-audio

Then, include this repo's nginx config file into your server {} block, e.g.:

server {

  disable_symlinks off;
  include fetch-stream-audio/include-server.conf;

Throttled Bandwidth Endpoints

All /audio/* URIs are configured to intentionally limit download speeds and control response packet sizes for testing the decoding behavior (defined in include-server.conf). For example:

All Throttled Endpoints
Speed Example URL
16 kbps
24 kbps
32 kbps
40 kbps
56 kbps
64 kbps
72 kbps
80 kbps
88 kbps
96 kbps
100 kbps
104 kbps
112 kbps
120 kbps
128 kbps
160 kbps
192 kbps
256 kbps
384 kbps
512 kbps
768 kbps
1 mbps
4 mbps
5 mbps
2 mbps
3 mbps
4 mbps
5 mbps
6 mbps
7 mbps
8 mbps
9 mbps
10 mbps

Development & Building

Please remember that this is a proof-of-concept demo intended to show developers alternative (and possibly better) ways to play web audio. Currently, there's no formal package or release (see #21), so you'll need to improvise a little to get this working in your apps or websites.

I prefer Yarn, and you'll need Yarn or NodeJS installed to build the project. app.js is the entry point for starting with the code.

# clone repo and install dependencies
$ git clone
$ cd fetch-stream-audio
$ yarn install
# run the development server in "watch" mode to automatically re-build your changes
$ yarn dev
# build the project formally with minification
$ yarn build


Thanks to @bjornm for pointing me to @mohayonao's WAV decoder: