Jonas
Jonas

Reputation: 588

How to calculate the total duration of a set of tracks using the HTML5 audio?

I am building a custom audio player (planning phase for now :) ), and I am stuck with this. I wanna calculate the total duration of all my songs in the beginning. I know that I need to load each song in order to know its duration. If I set the src attribute for instance for the first song I get the duration of it with the loadedmetadata event handler. But how to get the sum of them all? Do I need to load each one individually? Do I need to set the src attr of the audio element for each song I have in the list? Any hints would be much appreciated!

Upvotes: 3

Views: 1620

Answers (1)

Brian Peacock
Brian Peacock

Reputation: 1849

I was here yesterday because I needed to solve this exact same problem and, of course, StackOverflow was top of the search results - even for this four year-old unanswered questions. Alas my searches for a native JS solution proved fruitless, though I tried several different suggestions from here and there, so here's what I eventually came up with myself...

function tracksTotalLength(Tracklist) {
    var tempAudio = document.createElement('audio'),
        L = Tracklist.length,
        i = 0, // iterator
        TTL = 0, // TotalTrackLength
        flag = true;

    // set media-type and mute (belt and braces)
    tempAudio.type = 'audio/mpeg';
    tempAudio.muted = true;

    tempAudio.addEventListener(
        'durationchange',
        function(e) {
            TTL += e.target.duration;
            /* DEBUG ONLY */ console.log('TTL:',TTL);
            recursiveUpdater(i++);
        },
        false
    );

    function recursiveUpdater(ii) {
        if (!isNaN(TTL) && ii < L) {
            tempAudio.src = Tracklist[ii];
            // fires recursiveUpdater()
            // via 'durationchange' event
        } else {
            // sometimes not all values are caught
            // and TTL = NaN, so
            // reset and have another run at it
            if (isNaN(TTL) && flag) {
                i = 0;
                flag = false;
                recursiveUpdater(i);
            } else (
                // but you can't recurse all day so
                // remove tempAudio
                tempAudio = null;
                // if it hasn't caught return false
                return (!isNaN(TTL) : TTL : false);
            }
        }
    }
    return recursiveUpdater(i);
}

var tracks = [
    'path/to/track01.mp3',
    'path/to/track02.mp3',
    'path/to/track03.mp3',
    /*...etc... */ 
];
var totalLength = tracksTotalLength(tracks);
//=> totalLength = seconds (float) or false

The function tracksTotalLength() returns the total time of the list in seconds which can then be rounded into hh:mm:ss as per this classic StackOverflow answer.

The 'durationchange' is fired when the metadata is loaded or changed. More on this at Media Events (MDN)

Tested in latest Firefox and Chromium browsers on Lubuntu 14.04 with tracklists of 5-50 items.

Hope this helps someone, or at least encourages a true JS guru to come up with a better routine.

Upvotes: 1

Related Questions