18

The answers provided in How do I get a sound file’s total time in Java? work well for wav files, but not for mp3 files.

They are (given a file):

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
AudioFormat format = audioInputStream.getFormat();
long frames = audioInputStream.getFrameLength();
double durationInSeconds = (frames+0.0) / format.getFrameRate();  

and:

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
AudioFormat format = audioInputStream.getFormat();
long audioFileLength = file.length();
int frameSize = format.getFrameSize();
float frameRate = format.getFrameRate();
float durationInSeconds = (audioFileLength / (frameSize * frameRate));

They give the same correct result for wav files, but wrong and different results for mp3 files.

Any idea what do I have to do to get the mp3 file's duration?

Community
  • 1
  • 1
The Student
  • 27,520
  • 68
  • 161
  • 264

5 Answers5

15

Using MP3SPI:

private static void getDurationWithMp3Spi(File file) throws UnsupportedAudioFileException, IOException {

    AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);
    if (fileFormat instanceof TAudioFileFormat) {
        Map<?, ?> properties = ((TAudioFileFormat) fileFormat).properties();
        String key = "duration";
        Long microseconds = (Long) properties.get(key);
        int mili = (int) (microseconds / 1000);
        int sec = (mili / 1000) % 60;
        int min = (mili / 1000) / 60;
        System.out.println("time = " + min + ":" + sec);
    } else {
        throw new UnsupportedAudioFileException();
    }

}
The Student
  • 27,520
  • 68
  • 161
  • 264
  • 1
    This method is not working for this track: https://www.dropbox.com/s/735fdkp9roskapw/39007.mp3?dl=0 - The track has 3:52, but this code sais it has 22:17. – Daniel Cukier Dec 18 '14 at 14:41
  • Just tried this. The keys in the `properties` map are: `mp3.copyright, date, mp3.framesize.bytes, mp3.vbr, mp3.framerate.fps, mp3.id3tag.track, title, mp3.channels, mp3.id3tag.genre, mp3.bitrate.nominal.bps, mp3.padding, mp3.version.mpeg, mp3.crc, mp3.original, mp3.frequency.hz, album, author, mp3.id3tag.v2, mp3.vbr.scale, mp3.version.encoding, mp3.version.layer, mp3.id3tag.v2.version, mp3.header.pos, comment`. There is no `duration` key. – Jules Oct 30 '17 at 06:13
  • 1
    We are using this method and it provides the incorrect duration for 11KHz MP3 (reporting half the actual length). We will be looking for something else. – chrish Jan 05 '19 at 21:02
  • I tried to use this but I could not. I imported the jar and TAudioFileFormat was not found – Kwnstantinos Nikoloutsos Mar 22 '20 at 20:35
  • Doesn't work with any mp3 I have (thousands). – Adrian Dec 03 '21 at 11:20
  • MP3 SPI has now moved to a new location. Refer this https://mvnrepository.com/artifact/com.googlecode.soundlibs/mp3spi/1.9.5-1 to use it. – Divya Gupta Dec 23 '22 at 12:28
8

Here is the way I get the total time of a file .mp3, I'm using the library is Jlayer 1.0.1

Header h = null;
FileInputStream file = null;
try {
    file = new FileInputStream(filename);
} catch (FileNotFoundException ex) {
    Logger.getLogger(MP3.class.getName()).log(Level.SEVERE, null, ex);
}
bitstream = new Bitstream(file);
try {
    h = bitstream.readFrame();
} catch (BitstreamException ex) {
    Logger.getLogger(MP3.class.getName()).log(Level.SEVERE, null, ex);
}
int size = h.calculate_framesize();
float ms_per_frame = h.ms_per_frame();
int maxSize = h.max_number_of_frames(10000);
float t = h.total_ms(size);
long tn = 0;
try {
    tn = file.getChannel().size();
} catch (IOException ex) {
    Logger.getLogger(MP3.class.getName()).log(Level.SEVERE, null, ex);
}
//System.out.println("Chanel: " + file.getChannel().size());
int min = h.min_number_of_frames(500);
return h.total_ms((int) tn)/1000;
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Lăng Minh
  • 75
  • 1
  • 5
  • here is the way i get the total time of a file .mp3, I'm using the library is Jlayer 1.0.1 – Lăng Minh Jan 31 '17 at 11:22
  • this worked well for me, but the answer contains a lot of unneccesary stuff. long tn = new File(filename).length(); double duration = header.total_ms((int) tn)/1000; – feri Jun 20 '17 at 22:12
1

Here is a detailed explanation of the MP3 File structure

http://www.autohotkey.com/forum/topic29420.html

Kasturi
  • 3,335
  • 3
  • 28
  • 42
1

Use jave-1.0.1.jar library.

  • It passed my test on wave file formats such as: wav-pcm8/16, wav-alaw, wav-ulaw, wav-gsm, wav-adpcm;
  • It passed my test on some MP3 file formats: cbr vs vbr, stereo vs SingleChannel;
  • It can support video formats, which I haven't tested on.

Code sample:

File source = new File("C:\\22.mp3");
Encoder encoder = new Encoder();
try {
    MultimediaInfo mi = encoder.getInfo(source);
    long ls = mi.getDuration();
    System.out.println("duration(sec) = "+  ls/1000);
} catch (Exception e) {
    e.printStackTrace();
}

I've tried Jlayer 1.0.1, but it failed for some MP3 format. As for another libaray jaudiotagger-2.0.3.jar, it works fine for MP3 formats, but it can only support wav-pcm8/16.

davidu
  • 11
  • 1
-6

I'm old-fashioned in this, but I always simply get the specs for MP3, write a function that searches the right bits, and find it out.

If Winamp can determine this by reading the bitstream of an MP3 file, then so can I right?

And so can you, I believe in you mate!

Zorf
  • 6,334
  • 2
  • 29
  • 24
  • 16
    I think people came to SO looking for answers, not for words of faith, but thanks anyway... – The Student Jun 16 '10 at 13:33
  • By the way, I know nothing about handle mp3 files, do you have an example or article link about what you are saying? – The Student Jun 16 '10 at 13:34
  • Well, this is how built-in functions do it. MP3 is a specification, which means that at some index of an MP3 file in some format the length should be written. Say the length is at the 129th byte, you just load the file as a stream, go to that part and read it out. Below, some one posted a link of the MP3 file structure. – Zorf Jun 16 '10 at 13:53
  • In the TAGV2 part, it says that `Size of TAG is encoded into 4 Bytes. But not to be so easy, the most significant bit in each Byte is set to 0 and ignored. Only remaining 7 bits are used. The reason is to avoid mismatch with audio frame header which has the first synchro Byte FF).` That means when I find a FF is the end of TAGV2 and begin of audio frames? – The Student Jun 16 '10 at 17:48
  • 7
    The audio length isn't written explicitly in a field in the MP3 format. – indiv Jun 16 '10 at 18:50
  • 1
    "MP3 is a specification" .... this is true. But it's an unusually large and complicated one, containing 114 pages of specification that cost $200 US to purchase a copy of. Implementing the entire specification would likely take a single developer several months. Just understanding it would probably be weeks of work. As pointed out by the comment above, this isn't as simple as finding the field that contains the duration and extracting it. Yes, there are abbreviated summaries, but can you be sure they haven't missed out something that's critical and could make your results incorrect? – Jules Oct 30 '17 at 05:56