Search code examples
.netaudiomp3

How to retrieve duration of MP3 in .NET?


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?


Solution

  • 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;
        }