如何使用Java编程获取mp3、wav等媒体文件的时长?
Java获取MP3/WAV音频时长的实现方案
以下提供两种可直接落地的实现路径,可根据项目依赖限制选择:
方案1:使用第三方库jaudiotagger实现(推荐)
该库专门用于处理音频元数据,对MP3、WAV格式兼容性极高,代码实现简单易维护。
- 第一步:引入Maven依赖
<dependency> <groupId>org</groupId> <artifactId>jaudiotagger</artifactId> <version>2.2.6</version> </dependency>
- 第二步:核心实现代码
import org.jaudiotagger.audio.AudioFile; import org.jaudiotagger.audio.AudioFileIO; import java.io.File; public class AudioDurationUtils { // 获取音频时长,返回单位:秒 public static int getAudioDuration(File audioFile) throws Exception { String fileName = audioFile.getName().toLowerCase(); if (!fileName.endsWith(".mp3") && !fileName.endsWith(".wav")) { throw new IllegalArgumentException("仅支持mp3和wav格式的音频文件"); } AudioFile audioFileObj = AudioFileIO.read(audioFile); return audioFileObj.getAudioHeader().getTrackLength(); } // 获取毫秒级精度的音频时长 public static long getAudioDurationMs(File audioFile) throws Exception { return (long) getAudioDuration(audioFile) * 1000; } }
优点:无需自行解析文件格式,兼容CBR/VBR编码的MP3、各类编码的WAV文件,误差极低
缺点:需要引入第三方依赖
方案2:纯JDK实现(无第三方依赖)
如果项目不允许引入外部依赖,可分别解析两种格式的文件头计算时长:
2.1 WAV格式时长计算
WAV属于RIFF封装格式,直接读取文件头参数即可计算时长:
import java.io.File; import java.io.FileInputStream; // 返回单位:毫秒 public static long getWavDurationMs(File wavFile) throws Exception { try (FileInputStream fis = new FileInputStream(wavFile)) { byte[] header = new byte[44]; fis.read(header); // 读取采样率(字节偏移24-27) int sampleRate = (header[27] & 0xff) << 24 | (header[26] & 0xff) << 16 | (header[25] & 0xff) << 8 | (header[24] & 0xff); // 读取声道数(字节偏移22-23) int channels = (header[23] & 0xff) << 8 | (header[22] & 0xff); // 读取位深(字节偏移34-35) int bitDepth = (header[35] & 0xff) << 8 | (header[34] & 0xff); // 读取音频数据块大小(字节偏移40-43) int dataSize = (header[43] & 0xff) << 24 | (header[42] & 0xff) << 16 | (header[41] & 0xff) << 8 | (header[40] & 0xff); // 公式计算时长 return (long) (dataSize * 1000.0 / (sampleRate * channels * bitDepth / 8.0)); } }
2.2 MP3格式时长计算
该实现仅支持CBR(恒定比特率)编码的MP3,VBR编码文件计算会存在误差:
import java.io.File; import java.io.FileInputStream; // 返回单位:毫秒 public static long getMp3DurationMs(File mp3File) throws Exception { try (FileInputStream fis = new FileInputStream(mp3File)) { byte[] id3Header = new byte[10]; fis.read(id3Header); int skipTagSize = 0; // 跳过ID3标签块 if (id3Header[0] == 'I' && id3Header[1] == 'D' && id3Header[2] == '3') { skipTagSize = (id3Header[6] & 0x7F) << 21 | (id3Header[7] & 0x7F) << 14 | (id3Header[8] & 0x7F) << 7 | (id3Header[9] & 0x7F) + 10; fis.skip(skipTagSize); } else { fis.reset(); } // 读取第一帧帧头 byte[] frameHeader = new byte[4]; fis.read(frameHeader); // 校验MP3帧同步位 if ((frameHeader[0] & 0xFF) != 0xFF || (frameHeader[1] & 0xE0) != 0xE0) { throw new IllegalArgumentException("无效的MP3格式文件"); } // 提取比特率 int bitRateIndex = (frameHeader[2] >> 4) & 0x0F; int[] bitRateTable = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}; int bitRate = bitRateTable[bitRateIndex] * 1000; // 提取采样率 int sampleRateIndex = (frameHeader[2] >> 2) & 0x03; int[] sampleRateTable = {44100, 48000, 32000, 0}; int sampleRate = sampleRateTable[sampleRateIndex]; // MP3每帧采样数固定为1152,计算单帧时长 double frameDuration = 1152.0 / sampleRate * 1000; // 计算总时长 long audioDataSize = mp3File.length() - skipTagSize; long totalFrames = (audioDataSize * 8) / bitRate / (long)(frameDuration / 1000); return (long) (totalFrames * frameDuration); } }
注意:如果需要兼容VBR编码的MP3,建议优先选择方案1
内容的提问来源于stack exchange,提问作者Raihanul Alam Hridoy
相关产品推荐
相关产品推荐

