7

I have build a WPF application where users can drag and drop MP3 files onto a listbox. I need a way to calculate the total duration of the playlist.

Any libraries I should use? Or is it possible using only the .NET framework?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sander Versluys
  • 72,737
  • 23
  • 84
  • 91
  • Answer from a later duplicate shows the easiest way in 2015: http://stackoverflow.com/a/34518350/1860652 – Alex Nov 08 '16 at 11:21

4 Answers4

18

After lots of theorizing, I found a way to correctly and indisputably calculate a duration of an mp3 file.

Let me first re-iterate why standard methods above won't work:

ID3 method: not all files have id3 tags, and if they have it, they might not have duration field set in it.

Estimating by reading one frame * file size: not gonna work for VBR files.

Xing header: not all files have it.

Decoding and determining it via PCM size: I have 3+ GB file, I'm not going to wait until it decodes.

I read everywhere and all things lead to NAudio. Mark, THANKS for the good effort and clean source! However, a method that is mostly suggested with NAudio is to read a file using Mp3FileReader and get all frames. Problem: Mp3FileReader creates a TOC at the start and that takes forever, even for small files of only ONE day :)

Mark suggested that I remove TOC creation, since source is available, and while doing it, I found much simpler method. Here it is; is speaks for itself:

    double GetMediaDuration(string MediaFilename)
    {
        double duration = 0.0;
        using (FileStream fs = File.OpenRead(MediaFilename))
        {
            Mp3Frame frame = Mp3Frame.LoadFromStream(fs);
            if (frame != null)
            {
                _sampleFrequency = (uint)frame.SampleRate;
            }
            while (frame != null)
            {
                if (frame.ChannelMode == ChannelMode.Mono)
                {
                    duration += (double)frame.SampleCount * 2.0 / (double)frame.SampleRate;
                }
                else
                {
                    duration += (double)frame.SampleCount * 4.0 / (double)frame.SampleRate;
                }
                frame = Mp3Frame.LoadFromStream(fs);
            }
        }
        return duration;
    }
Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
  • BTW, it calculated exact duration of file that was 9 days 18 hours long, in less than a minute (in fact it will do so as fast as disk can read the file, since it uses VERY LITTLE CPU). – Daniel Mošmondor Nov 07 '12 at 12:43
  • 2
    In my case, this calculated the duration to be four times the actual duration for all the files I was working with (they were all stereo files, btw). Maybe something has changed in NAudio since this answer, but I'm not sure the * 4.0 is necessary, at least in the case of the files I was testing with. Still, I appreciate the answer, it got me 99% of the way there. – Jared Phelps Mar 22 '13 at 19:02
  • @JaredPhelps you were few minutes of experimenting and one constant away :) – Daniel Mošmondor Mar 27 '13 at 19:12
  • 3
    I think @JaredPhelps is correct, multiplying the SampleCount by 2 or 4 is not necessary. At least for the file I tested, when I removed it, the duration came out correct. – Brian Apr 01 '13 at 21:33
  • @DanielMošmondor, could you elaborate a little on what you mean? What was I missing? – Jared Phelps Apr 05 '13 at 21:20
  • Any chance you have a similar function for WMA files? – Abe Miessler Apr 18 '13 at 23:48
  • @AbeMiessler that would be excellent new question, wouldn't it? – Daniel Mošmondor Apr 19 '13 at 06:33
  • @DanielMošmondor, yes it would! http://stackoverflow.com/questions/16107774/possible-to-get-the-length-of-a-wma-file-without-using-windows-media-player – Abe Miessler Apr 19 '13 at 15:09
  • 3
    hi @DanielMošmondor may i know the type of "_sampleFrequency " its giving an error for me. – Satish Singh Aug 29 '15 at 06:10
  • `_sampleFrequency` seems to be hanging out there doing nothing...? – Matthew Mar 31 '20 at 02:01
2

I wrapped mp3 decoder library and made it available for .net developers. You can find it here:

http://sourceforge.net/projects/mpg123net/

Included are the samples to convert mp3 file to PCM, and read ID3 tags.

I guess that it can be used to properly calculate mp3 file duration.

Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
1

I ended up writing my own for this purpose a few years back. You can write an effective one client-side using flash. The key points that I remember are:

  1. that you can't rely on the MP3 header to be accurate, so don't just read that to get the duration
  2. in flash, seek to the end of the MP3, and then read the current position. That will give you the duration.

Edit: I realize you wanted to do this with .Net, but it may actually be more useful to know client side before you upload the file to the server, as if you wish to impose limits on file length, you can do that much earlier in the process.

D'Arcy Rittich
  • 167,292
  • 40
  • 290
  • 283
  • The tip for flash will come in handy in the future as i have had to deal with it in the past and I indeed encountered wrong duration readings which would mess up the scrubber. Thanks! – Sander Versluys Dec 20 '08 at 13:30
1

[my own solution]

I've added a second mediaelement control which I use to open each mp3 file in the listbox and get it's NaturalDuration. Open and close each file in the list and make a sum of all the values.

As stated by others, the mp3 headers aren't accurate. The mediaelement provides the correct duration.

It's probably not the fastest method but in my case the simplest (it does not rely on other libraries).

Sander Versluys
  • 72,737
  • 23
  • 84
  • 91