Play Sounds Sequentially in Howler.js
Playing audio files in a specific order is a common requirement in
game development, interactive storytelling, and web audio applications.
This article provides a straightforward guide on how to create a
sequence of sounds to play one after another using the howler.js
library. You will learn how to use the library’s built-in event
listeners—specifically the onend callback—to chain multiple
audio tracks together seamlessly.
While howler.js does not have a built-in playlist queue feature, you can easily implement sequential playback using a recursive function and an array of audio sources.
Step 1: Define Your Sound Queue
First, create an array containing the file paths of the audio tracks you want to play in sequence. You also need a variable to keep track of the current active index.
const audioQueue = [
'audio/sound1.mp3',
'audio/sound2.mp3',
'audio/sound3.mp3'
];
let currentIndex = 0;Step 2: Create the Playback Function
Next, write a function that instantiates a Howl object
for the current sound. The key to making the sounds play sequentially is
the onend callback. When the current sound finishes
playing, the onend event triggers, increments the index,
and calls the playback function again.
function playSequence() {
// Check if we have reached the end of the sequence
if (currentIndex >= audioQueue.length) {
console.log("Sequence finished.");
return;
}
// Initialize the Howl instance for the current sound
const sound = new Howl({
src: [audioQueue[currentIndex]],
autoplay: false,
onend: function() {
// Move to the next sound and play it
currentIndex++;
playSequence();
},
onloaderror: function(id, error) {
console.error("Error loading sound: ", error);
// Optionally skip to the next sound if one fails to load
currentIndex++;
playSequence();
}
});
// Play the sound
sound.play();
}Step 3: Start the Sequence
To begin playing your sequence, simply call the function. Because browser autoplay policies usually prevent audio from playing without user interaction, you should trigger this function via a user event like a button click.
const playButton = document.getElementById('start-sequence-btn');
playButton.addEventListener('click', () => {
// Reset index in case the sequence is being replayed
currentIndex = 0;
playSequence();
});Optimizing Transition Latency
Creating a new Howl instance on the fly can sometimes
introduce a small delay between tracks while the browser loads the next
file. If gapless playback is critical for your project, you can preload
all Howl instances in an array beforehand, and then chain
their playback using the same onend logic:
const playlist = [
new Howl({ src: ['audio/sound1.mp3'] }),
new Howl({ src: ['audio/sound2.mp3'] }),
new Howl({ src: ['audio/sound3.mp3'] })
];
let activeIndex = 0;
function playPreloadedSequence() {
if (activeIndex >= playlist.length) return;
const currentSound = playlist[activeIndex];
currentSound.once('end', () => {
activeIndex++;
playPreloadedSequence();
});
currentSound.play();
}