Track Audio Load Progress in Howler.js

Tracking the loading progress of audio files in Howler.js is essential for creating accurate preloaders and progress bars in web applications. Because Howler.js does not provide a built-in progress event, you must calculate the loading percentage by fetching the audio file manually using native browser APIs before passing it to Howler. This article explains how to use XMLHttpRequest to track download progress and load the cached file into a Howler instance.

The Challenge with Howler.js

By default, Howler.js only provides an onload event, which fires once the entire audio file has finished loading. It does not expose real-time buffer progress. To get around this limitation, you can download the audio file as a binary Blob using an XMLHttpRequest (XHR) and monitor its progress, then feed that Blob directly to Howler.js.

Step-by-Step Implementation

Here is the most reliable method to calculate and display the load percentage of a sound file in Howler.js.

1. Fetch the Audio and Track Progress

Create an XMLHttpRequest pointing to your audio file. Set the responseType to 'blob' so the browser handles the download as a binary object. Inside the onprogress event, calculate the percentage by dividing the bytes loaded by the total bytes.

const audioUrl = 'https://example.com/audio.mp3';
const xhr = new XMLHttpRequest();

xhr.open('GET', audioUrl, true);
xhr.responseType = 'blob';

// Calculate and track progress
xhr.onprogress = function(event) {
    if (event.lengthComputable) {
        const percentLoaded = (event.loaded / event.total) * 100;
        console.log(`Loading: ${percentLoaded.toFixed(2)}%`);
        // Update your UI progress bar here
    }
};

2. Pass the Loaded Blob to Howler.js

Once the download is complete, use URL.createObjectURL() to convert the downloaded Blob into a temporary local URL. You can then pass this local URL to the src array of your Howl instance.

Because blob URLs do not have file extensions, you must explicitly define the format property in your Howler configuration so the library knows how to decode the audio.

xhr.onload = function() {
    if (xhr.status === 200) {
        // Create a local URL representing the downloaded audio blob
        const blobUrl = URL.createObjectURL(xhr.response);

        // Initialize Howl with the blob URL
        const sound = new Howl({
            src: [blobUrl],
            format: ['mp3'], // Explicitly declare the file format
            onload: function() {
                console.log('Audio is fully loaded and ready to play!');
                sound.play();
            }
        });
    } else {
        console.error('Failed to download the audio file.');
    }
};

// Start the request
xhr.send();

Important Considerations