How to Play Sound in Reverse with Howler.js
This article explains how to play audio in reverse using Howler.js. Because Howler.js and the underlying HTML5 Audio specifications do not support negative playback rates, playing audio backward requires specific workarounds. We will cover the two most effective methods: pre-reversing your audio files for maximum compatibility, and programmatically reversing audio buffers at runtime using the Web Audio API alongside Howler.
Why Howler.js Cannot Play Audio Backward Natively
Howler.js relies on the Web Audio API and HTML5 Audio. The browser
standards for these technologies do not support a negative playback rate
(e.g., setting rate to -1 will either mute the
audio, throw an error, or have no effect).
To play a sound in reverse, you must use one of the two methods below.
Method 1: Pre-Reverse Your Audio (Recommended)
The most performant and reliable approach is to reverse your audio file before uploading it to your project. This avoids runtime processing overhead and ensures 100% compatibility across all browsers, including older mobile devices.
You can easily reverse audio files using free tools: *
Audacity: Import your file, select the entire track, go
to Effect > Reverse, and export. *
FFmpeg: Run the following command in your terminal:
bash ffmpeg -i input.mp3 -af reverse output.mp3
Once exported, load the reversed file into Howler.js like a standard track:
const reverseSound = new Howl({
src: ['audio/reversed-sound.mp3']
});
reverseSound.play();Method 2: Programmatic Reversal Using Web Audio API
If you must reverse audio dynamically at runtime, you can fetch the
audio file, decode it into an AudioBuffer, reverse the
channel array data, and play it back using Howler’s shared
AudioContext.
Here is how to implement programmatic audio reversal:
async function playReverse(url) {
// 1. Ensure Howler's Web Audio context is initialized
const ctx = Howler.ctx;
if (!ctx) {
console.error("Web Audio API is not supported or Howler is not initialized.");
return;
}
try {
// 2. Fetch the audio file as an ArrayBuffer
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
// 3. Decode the audio data into an AudioBuffer
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
// 4. Reverse the data for each audio channel
for (let i = 0; i < audioBuffer.numberOfChannels; i++) {
audioBuffer.getChannelData(i).reverse();
}
// 5. Play the reversed buffer using Howler's audio node chain
const source = ctx.createBufferSource();
source.buffer = audioBuffer;
// Connect to Howler's master gain node to respect Howler's global volume/mute
source.connect(Howler.masterGain);
source.start(0);
} catch (error) {
console.error("Error reversing and playing audio:", error);
}
}
// Example usage:
playReverse('audio/sound.mp3');Considerations for Programmatic Reversal
- CORS Policies: Since this method uses
fetch(), the audio files must be hosted on the same domain or served with appropriate Cross-Origin Resource Sharing (CORS) headers. - Memory Usage: Reversing large audio files in the browser can cause performance stuttering and high memory consumption. Keep this method restricted to short sound effects.