如何让GStreamer直接输出多文件分片fMP4支持直播场景
GStreamer实时输出拆分fMP4多文件方案
你之前用ismlmux输出单fMP4再靠mp4split事后拆分的方案确实无法适配直播场景,splitmuxsink默认输出独立可播放完整MP4、multifilesink无法识别MP4原子边界的问题,完全可以通过GStreamer原生组件组合解决,不需要后置拆分工具就能实时生成init.mp4加独立.m4s分片的标准fMP4结构,和你手动拆分得到的文件结构完全一致。
最简实现方案(推荐)
GStreamer 1.14及以上版本自带的封装组件原生支持fMP4分片独立输出,不需要额外写代码监听事件,直接配置管线参数即可:
如果是1.20及以上版本,直接用cmafenc组件,配置最简单:
gst-launch-1.0 filesrc location=../test.ts ! decodebin ! x264enc ! h264parse ! aacenc ! aacparse ! cmafenc fragment-duration=6000 header-output-location=init.mp4 fragment-output-location=segment-%04d.m4s write-playlist=false
核心参数说明:
fragment-duration=6000:和你之前ismlmux的配置一致,单分片时长6秒header-output-location=init.mp4:单独输出包含ftyp、moov、mvex原子的初始化文件,和mp4split生成的init.mp4结构完全匹配fragment-output-location=segment-%04d.m4s:每一组moof+mdat原子对单独存储为一个m4s分片,生成过程是实时的,不需要等整个文件录制完成write-playlist=false:关闭组件默认生成的DASH/HLS播放列表,只输出需要的初始化文件和分片文件
如果你的GStreamer版本低于1.20没有cmafenc,可以用dashsink实现同样效果,把多余的播放列表输出丢弃即可:
gst-launch-1.0 filesrc location=../test.ts ! decodebin ! x264enc ! h264parse ! dashsink fragment-duration=6000 header-name=init.mp4 segment-name=segment-%04d.m4s mpd-name=/dev/null
自定义需求实现方案
如果你需要自定义分片规则、不想用DASH/CMAF相关的封装逻辑,也可以基于mp4mux自己实现切分逻辑:
- 给
mp4mux配置fragment-mode=1开启fMP4输出模式,同时设置你需要的fragment-duration分片时长 - muxer每输出一个完整分片前会在总线抛出分片开始事件,输出完完整moof+mdat块后抛出分片结束事件
- 监听这两个事件切换文件写入句柄即可:第一块包含ftyp、moov、mvex的buffer写入init.mp4,后续每个完整分片块单独写入独立的m4s文件
这种方式灵活度最高,可以自定义分片命名规则、插入自定义MP4扩展原子,适合有二次开发需求的场景。
避坑提示
- 音视频流进入fMP4封装组件前,必须加上对应的解析组件:H.264流加
h264parse、AAC流加aacparse,否则封装组件无法正确计算分片偏移,生成的moof原子信息会出错 - 直播场景下不要开
faststart参数,这个参数会缓存完整文件后把moov原子移到文件头,会引入很高的延迟,fMP4格式本身不需要moov前置就可以正常启动播放 - 生成的文件可以直接用Bento4的
mp4dump验证原子结构,和事后拆分的文件完全一致,不需要二次处理。
内容的提问来源于stack exchange,提问作者Jan Pokorný
相关产品推荐
相关产品推荐

