如何获取JavaZoom AdvancedPlayer的已播放音频帧数
如何获取JavaZoom AdvancedPlayer的已播放音频帧数
我太懂你现在的困扰了——用JavaZoom AdvancedPlayer做带进度滑块的音频播放器时,总帧数能正常获取,但已播放帧数总是不准,而且你还想用skippedFrames变量来处理滑块点击后的跳转逻辑对吧?
其实AdvancedPlayer本身并没有直接提供获取已播放帧数的API,我们得自己做个小包装来统计读取的音频帧,下面是具体的解决方法:
自定义计数型AudioInputStream
我们可以写一个包装类,继承AudioInputStream,在读取音频数据的时候自动统计已读取的帧数,还能避免多线程播放时的计数混乱:import javax.sound.sampled.AudioInputStream; import java.io.IOException; import java.util.concurrent.atomic.AtomicLong; public class CountingAudioInputStream extends AudioInputStream { private final AtomicLong framesRead = new AtomicLong(0); private final AudioInputStream delegate; public CountingAudioInputStream(AudioInputStream delegate) { super(delegate, delegate.getFormat(), delegate.getFrameLength()); this.delegate = delegate; } @Override public int read(byte[] b, int off, int len) throws IOException { int bytesRead = delegate.read(b, off, len); if (bytesRead > 0) { // 按每帧字节数计算读取的帧数,用AtomicLong保证线程安全 framesRead.addAndGet(bytesRead / getFormat().getFrameSize()); } return bytesRead; } public long getFramesRead() { return framesRead.get(); } // 用于跳转后同步帧数 public void setFramesRead(long frames) { framesRead.set(frames); } }替换原输入流并初始化播放器
把原来的AudioInputStream替换成我们的计数版本,这样播放时就能自动统计帧数了:import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javazoom.jl.player.advanced.AdvancedPlayer; import java.io.File; // 初始化示例 File audioFile = new File("your-audio-file.mp3"); AudioInputStream originalStream = AudioSystem.getAudioInputStream(audioFile); CountingAudioInputStream countingStream = new CountingAudioInputStream(originalStream); AdvancedPlayer player = new AdvancedPlayer(countingStream);同步跳转后的帧数计数
当你通过滑块点击调用seekTo(targetTime)时,别忘了同步更新计数的帧数,不然之前的统计会和实际播放位置脱节:public void seekTo(long targetTimeMs) { float sampleRate = countingStream.getFormat().getSampleRate(); // 计算目标时间对应的帧数 long targetFrames = (long) (targetTimeMs * sampleRate / 1000); // 计算需要跳过的帧数 long framesToSkip = targetFrames - countingStream.getFramesRead(); // 执行跳转(这里假设你的skipFrames逻辑是正常的) skippedFrames = player.skip((int) framesToSkip); // 同步更新计数的帧数,确保后续统计准确 countingStream.setFramesRead(targetFrames); }实时获取已播放帧数
之后你就可以在需要更新滑块进度的地方,调用countingStream.getFramesRead()拿到准确的已播放帧数,和总帧数(countingStream.getFrameLength())对比就能算出当前播放进度了。
备注:内容来源于stack exchange,提问作者Artik
相关产品推荐
相关产品推荐

