使用FFAudioFileReader调用audio.reset()时时间戳更新失败问题求助
问题分析与解决方案
报错原因
你遇到的FFmpeg警告,本质是调用audio.mark(0)时标记的字节数为0,导致BufferedInputStream无法保留任何音频数据;同时底层FFAudioFileReader依赖的FFmpeg解码流,无法在reset时正确回溯到起始位置,进而引发时间戳同步失败。另外,原始FFAudioFileReader返回的AudioInputStream本身可能原生不支持mark/reset,仅靠简单包装BufferedInputStream无法彻底解决问题。
解决方案1:正确配置缓冲与标记
修改解码逻辑,确保BufferedInputStream有足够缓冲区,且提前标记足够的字节数:
public AudioInputStream DecodeFLAC_OGG_MP3() throws IOException, UnsupportedAudioFileException { FFAudioFileReader audioFileReader = new FFAudioFileReader(); AudioInputStream audio = audioFileReader.getAudioInputStream(this.file); AudioFormat baseFormat = audio.getFormat(); AudioFormat decodedFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false ); AudioInputStream decodedAudio = AudioSystem.getAudioInputStream(decodedFormat, audio); // 计算缓冲大小:优先用音频总帧字节数,未知则用1MB固定缓冲区 int bufferSize = (int) (decodedAudio.getFrameLength() * decodedFormat.getFrameSize()); if (bufferSize <= 0) { bufferSize = 1024 * 1024; } BufferedInputStream bufferedInputStream = new BufferedInputStream(decodedAudio, bufferSize); AudioInputStream wrappedAudio = new AudioInputStream(bufferedInputStream, decodedFormat, decodedAudio.getFrameLength()); // 提前标记起始位置,传入足够覆盖整个音频的字节数 wrappedAudio.mark(bufferSize); return wrappedAudio; }
重置时直接调用:
audio.reset();
解决方案2:重置时重建音频流
如果上述方法仍有警告,说明底层FFmpeg流的mark/reset支持存在缺陷,可通过重新解码实现重置:
// 重置操作:关闭旧流,重新解码获取新流 try { if (audio != null) { audio.close(); } audio = DecodeFLAC_OGG_MP3(); } catch (IOException | UnsupportedAudioFileException e) { e.printStackTrace(); }
额外注意事项
- 调用reset前必须确保已调用过mark,且标记的字节数足够覆盖需要回溯的范围,否则会抛出IOException。
- 若要彻底消除FFmpeg警告,可尝试升级
com.tagtraum.ffsampledsp库到最新版本,新版本可能修复了时间戳同步的底层问题。
内容的提问来源于stack exchange,提问作者Andy Glaros
相关产品推荐
相关产品推荐

