Java使用mp4parser生成.m4s片段输出为空,如何修复格式异常?
mp4parser生成DASH音频.m4s片段异常修复方案
根因定位
你对比发现的两个box结构差异就是问题的直接诱因:
TrackFragmentHeaderBox(tfhd)的durationIsEmpty为true:MPEG-DASH规范要求每个媒体片段的tfhd必须携带有效时长信息,你在构造tfhd时未显式设置片段总时长,也未配置默认采样时长,导致该标记被置为无效状态,播放器识别片段为空。TrackRunBox(trun)的参数异常:dataOffsetPresent为false、dataOffset为-1:该字段标识trun box结束位置到实际音频样本数据的字节偏移量,mp4parser不会自动计算填充该值,未显式设置的情况下播放器找不到音频数据的起始位置,最终表现为拼接后的文件为空。sampleDurationPresent为true、采样数不匹配:你开启了单样本携带时长的开关,但正常DASH音频片段使用tfhd的默认采样时长即可,无需每样本单独携带时长;采样数多2是因为统计时包含了aac编码产生的2个无效填充帧,实际有效音频帧只有468个。
代码调整方案
按以下步骤修改ChunkFragmentM4sBuilder类逻辑即可修复问题:
- 调整
TrackFragmentHeaderBox配置
统计当前片段所有有效aac样本的总时长,显式调用setDefaultSampleDuration()设置tfhd的默认采样时长,调用setDuration()设置当前片段总时长,强制将durationIsEmpty标记为false。 - 调整
TrackRunBox配置- 构造trun时显式传入
dataOffsetPresent=true参数,在所有box结构拼装完成后、写入输出流前,计算trun头部长度 + 所有样本属性字段的总长度,得到实际偏移值后调用setDataOffset()写入。 - 构造trun时显式设置
sampleDurationPresent=false,复用tfhd的默认采样时长即可,减少不必要的字段开销。 - 校准采样数统计逻辑:解析ffmpeg输出的aac文件的ADTS帧头,过滤末尾的空填充帧,确保trun的采样数和实际有效aac帧数量(468)对齐。
- 构造trun时显式传入
- 附加校验逻辑
确保初始化mp4文件中moov->trak->mdia->minf->stbl表的采样时长配置,和每个片段tfhd的默认采样时长完全一致,避免播放时出现时间戳断层。
验证方式
- 调整完成后用
MP4Box -info 生成的.m4s命令查看box结构,确认tfhd的durationIsEmpty为false,trun的dataOffset为正整数、dataOffsetPresent为true、sampleDurationPresent为false,采样数为468。 - 拼接初始化文件和m4s片段后,用
ffplay直接播放拼接后的文件,确认音频正常播放。
内容的提问来源于stack exchange,提问作者Nick Charney Kaye
相关产品推荐
相关产品推荐

