如何将不确定数量的视频片段拼接为可实时输出的直播流
不确定数量实时视频片段拼接为直播流实现方案
前提约束
所有第三方返回的7秒视频片段需满足编码参数完全一致:分辨率、帧率、GOP长度、音视频编码格式、音频采样率/声道数完全匹配,否则拼接会出现花屏、音画不同步问题,参数不一致的场景需要先对每个片段做统一转码再进入拼接流程。
方案1:动态列表拼接(最稳定,落地片段可回溯)
核心原理
使用FFmpeg的concat解封装器的动态更新能力,不需要启动时指定所有输入文件,运行过程中可随时追加新片段。
操作步骤
- 初始化一个拼接配置文本文件
segments.txt,初始内容如下:
ffconcat version 1.0
- 启动常驻FFmpeg进程,命令如下:
# 输出碎片化MP4直接对接Web API流式响应的场景 ffmpeg -f concat -safe 0 -segment_time_metadata 1 -i segments.txt -c:v copy -c:a copy -f mp4 -movflags frag_keyframe+empty_moov pipe:1 # 输出HLS流直接给Web端播放器的场景 ffmpeg -f concat -safe 0 -segment_time_metadata 1 -i segments.txt -c:v copy -c:a copy -hls_time 2 -hls_list_size 10 -hls_flags delete_segments+append_list live.m3u8
参数说明:
-f concat -safe 0:启用concat解封装器,允许读取任意路径的片段文件-segment_time_metadata 1:自动对齐片段间时间戳,避免播放进度跳变-movflags frag_keyframe+empty_moov:生成无头部依赖的碎片化MP4,可直接流式传输-c:v copy -c:a copy:直接拷贝音视频流,无转码延迟,若片段参数不一致可替换为转码参数如-c:v libx264 -c:a aac
- 每次从第三方接口拿到新的7秒视频片段后,将片段落地存储到本地,再往
segments.txt末尾追加一行内容:
file '新片段的绝对路径'
FFmpeg会自动检测配置文件的更新,读取新片段拼接到输出流尾部,无需重启进程。
方案2:管道直推(无文件落地,延迟更低)
如果不需要留存片段、追求最低延迟,可以将所有片段转成MPEG-TS流式容器后按顺序写入FFmpeg标准输入:
- 启动FFmpeg进程,命令如下:
ffmpeg -f mpegts -i pipe:0 -c:v copy -c:a copy -f mp4 -movflags frag_keyframe+empty_moov pipe:1
- 每次拿到第三方返回的7秒MP4片段后,先调用轻量转码将片段转为MPEG-TS格式:
ffmpeg -i 新片段.mp4 -c copy -f mpegts pipe:1
- 将转码得到的TS流按顺序写入上一步启动的拼接FFmpeg进程的标准输入即可,FFmpeg会自动识别TS流的边界完成拼接。
ASP.NET Web API对接注意事项
- 可直接将拼接FFmpeg进程的标准输出绑定到HTTP响应流,响应头
Content-Type根据输出格式设置为video/mp4或application/vnd.apple.mpegurl - 监听客户端断开事件,收到断开信号后及时销毁FFmpeg进程,避免资源泄漏
- 多客户端并发场景建议先将FFmpeg输出推到本地SRS/NGINX-RTMP直播服务,所有客户端统一从直播服务拉流,避免每个客户端单独启动FFmpeg进程占用过多资源
内容的提问来源于stack exchange,提问作者Max Hay
相关产品推荐
相关产品推荐

