Audio API to calculate the duration of multiple songs

Asked

Viewed 1,080 times

3

I’m working on a player audio and need to know how to calculate the duration of various MP3’s that are selected on the user’s machine by a input of the kind file?

EDIT:

Follows my current code and does not return the correct value...

var audioElement2 = document.createElement('audio');
var fill;
var tamanho = 0;
$("#file666").change(function() {
    fill = this.files.length;


    for (var i = 0; i < fill; i++) {
    file3[i] = this.files[i];

    fileB = URL.createObjectURL(file3[i]);
    audioElement2.setAttribute('src', fileB);

    $(audioElement2).on("loadedmetadata", function () {
    tamanho = tamanho + parseInt(audioElement2.duration);
    });

    }


    $("#musicas").html("Músicas Carregadas: " + fill + " (Tempo Total: " + tamanho + ")");
});

I’m trying to use a loop for with a variable summing all mp3 but it doesn’t work, it returns "0" as a result...

Jsfiddle

  • 1

    Apparently it is only possible to read the duration afterward that the audio was injected into src tag <audio>. I tested some libraries to read the ID3 that allow to read the properties of each this.files[i], but often the information Length does not appear in the MP3 file.

  • I had thought about answering, but since Tony already killed the riddle, I leave the links to my research: 1, 2, 3, 4, 5

3 answers

2


The loademetadata It’s an event, so you almost got it: it will be called and you need to increment a variable to store the Total Time and update the user interface each time the event occurs.

Perhaps the best way is to connect this variable to HTML, using Angularjs.

Jsfiddle with code on http://jsfiddle.net/7f6dxt5s/18/

HTML:

<input type="file" id="fileInputSelector" size="60" name="fileInputSelector" multiple>
<div id="musicas">Músicas Carregadas: 0 (Tempo Total: 0 segundos)</div>

Code

var tempoTotal = 0;

$("#fileInputSelector").change(function () {
    var quantidadeDeArquivos = this.files.length;
    for (var i = 0; i < quantidadeDeArquivos; i++) {
        var esteArquivo = this.files[i];
        fileB = URL.createObjectURL(esteArquivo);

        var audioElement2 = new Audio(fileB);
        audioElement2.setAttribute('src', fileB);
        audioElement2.onloadedmetadata = function (e) {
            tempoTotal = tempoTotal + parseInt(this.duration);
            $("#musicas").html("Músicas Carregadas: " + quantidadeDeArquivos + " (Tempo Total: " + tempoTotal + " segundos)");
            //alert("loadedmetadata" + tempoTotal);
        }
    }
    tempoTotal = 0;
});
  • strange, it adds up only the duration of the last song...

  • I renamed the variables for better reading. I updated the answer. It’s now working correctly.

1

In Html5 there is the property duration

In your case it would look something like:

duracao = audioElement.duration

Remembering that the return will be in seconds!

To convert seconds to minutes/hours I use the module Moment.

follows code:

var seconds = audioElement.duration;
var duration = moment.duration(seconds, "seconds");

var time = "";
var hours = duration.hours();
if (hours > 0) { time = hours + ":" ; }

time = time + duration.minutes() + ":" + duration.seconds();
  • actually it is to calculate the duration of several mp3 at the same time!!! I’m trying to use a loop for with a variable summing all mp3 but it doesn’t work...

  • "does not work out" is too vague, a loop would work perfectly, in reality there are not many alternatives, you will need to walk within a loop catching the Duration of each mp3, in the end you will have a total sum of all selected files in seconds, then just convert to hours/minutes

  • 1

    Eder, the problem is that the duration is only available afterward that an audio element was set with a src, the loop new Audio + setAttribute in Tony’s response.

  • Good @brasofilo actually I had not noticed that was missing the new Audio in the @aps code ...

1

To analyze the duration of the MP3 file, the easiest (and perhaps even efficient) mode is to iterate on all selected files, read its contents and interpret the file header.

Data Reading

Be it file of the kind File, you can read data as follows:

var reader = new FileReader();
reader.onloadend = function(evt) {
    if (evt.target.readyState == FileReader.DONE) { // DONE == 2
        // evt.target.result; <-- contém os bytes lidos.
  }
};

var blob = file.slice(start, stop + 1); // start = 0, stop deve ser grande o suficiente.
reader.readAsBinaryString(blob);

Interpretation of the Header

Now either you build a parser or use one that already exists. I recommend the mp3-parser. After referencing the downloaded JS, use:

var tags = mp3Parser.readTags(new DataView(/* bytes do mp3 */));

Now, just examine the variable tags to get all the information you want.

Joining together...

The code to interpret a single file will then look similar to:

var reader = new FileReader();
reader.onloadend = function(evt) {
    if (evt.target.readyState == FileReader.DONE) {
        var tags = mp3Parser.readTags(new DataView(evt.target.result));
        // basta analisar a variável tags.
  }
};

var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);

The analysis of the variable tags and the integration of the proposed code with the issue code is a ;D exercise

Browser other questions tagged

You are not signed in. Login or sign up in order to post.