使用ffmpeg/libav向MP4写入AVPacket边数据失败问题咨询
问题解决方案:AVPacket自定义边数据无法写入MP4文件
问题根因
- FFmpeg原生的MP4(MOV)封装器仅支持有限几种特定类型的AVPacket边数据做帧级写入,比如流ID、字幕标识等和特定场景绑定的边数据,不支持通用的
AV_PKT_DATA_STRINGS_METADATA类型边数据的帧级落盘逻辑。 - 你尝试的
use_metadata_tags参数仅支持将全局/流级元数据写入文件头,无法作用于帧级边数据;AVFMT_FLAG_KEEP_SIDE_DATA参数仅要求复用器处理过程中不主动丢弃边数据,但如果复用器本身没有实现对应边数据的写盘逻辑,添加该参数也不会生效。
可行解决方案
方案1:更换支持帧级元数据的封装格式
如果业务允许不强制使用MP4,直接切换为MKV封装即可,MKV的原生muxer完全支持AV_PKT_DATA_STRINGS_METADATA类型的帧级边数据写入,不需要修改现有业务逻辑,仅调整输出格式配置就能直接生效。
方案2:将自定义数据写入SEI帧(MP4场景最优方案)
这是MP4场景下最通用的实现方式,SEI(补充增强信息)是H.264/H.265编码标准定义的预留字段,会和视频帧绑定存入MP4,解码时可直接提取:
- 编码完成后将自定义元数据封装为标准的用户自定义SEI NALU
- 将SEI NALU和编码后的视频帧数据拼接后写入AVPacket的data字段
- 解码侧从帧数据中解析对应UUID的SEI即可拿到自定义元数据
该方案完全兼容标准MP4封装,不需要修改FFmpeg源码。
方案3:自定义MP4扩展Box
如果必须使用MP4且不能修改编码逻辑,可以自行扩展FFmpeg的mov封装器:
- 修改mov muxer源码,添加
AV_PKT_DATA_STRINGS_METADATA类型边数据的处理逻辑,将其写入每个sample的附属udta自定义Box中 - 同步修改mov demuxer源码,读取sample的自定义Box并还原为AVPacket边数据
该方案改造成本极高,非特殊需求不推荐使用。
额外排查注意事项
- 若使用FFmpeg 5.0及以上版本,确认API未过时:
av_init_packet已被标记废弃,建议改用av_packet_alloc/av_packet_free管理AVPacket生命周期,避免内存异常导致边数据意外丢失。 av_write_frame返回成功前不要主动释放边数据对应的内存,避免写入过程中数据失效。
内容的提问来源于stack exchange,提问作者mradul dubey
相关产品推荐
相关产品推荐

