有使用 ffmpeg 生成 hls 视频文件经历的小伙伴肯定知道,尽管设置了 ts 切片的目标时长,但是实际场景中,总会出现 ts 切片时长或大于目标时长,或小于目标时长的情况。那么,我们就很有必要了解在 hls 中生成 ts 切片的内在逻辑,今天本文就来进行相关逻辑的解密。
参数 f 是用来指定目标文件的输出封装格式,比如 hls、flv、mp4 等。
参数 hls_time 在 ffmpeg 命令中就是用来控制 ts 切片目标时长的,单位是秒。
参数 split_by_time 用来控制生成 ts 切片时完全依赖时间戳进行切割。
为了更好的理解上面的参数,我们展示一个命令示例:
ffmpeg -f flv -i rtmp://input -c copy -f hls -hls_time 2 -hls_flags split_by_time out.m3u8
音频和视频切片的逻辑还是有所不同的,出现差异的根本原因是视频依赖关键帧进行切割,而音频没有关键帧的概念,音频更多的还是依赖时间戳进行切割。
源码中 pkt->flags & AV_PKT_FLAG_KEY 就是关键帧的判断,此时,如果媒体包的时间大于等于 hls_time,那么就可以进行 ts 切割了。为什么要在关键帧处进行切割呢?因为这样可以保证每个 ts 切片都可以单独解码,保证播放器播放正常。
源码中对应 hls->flags & HLS_SPLIT_BY_TIME 的条件,当指定 split_by_time 时,会让 ffmpeg 在生成 ts 切片过程中完全依赖媒体包的时间戳大于 hls_time 的值。
如果指定了 hls_init_time > 0,那么 ts 切片会动态调整为初始分段和常规分段的不同时长,生成前后时长不一致的 ts 切片。
影响 ts 切片时长的因素有很多,其中比较关键的影响因素有GOP的大小、max_seg_size 的限制、不准确的 pts 等。
视频 h264 媒体包写入 ts 切片的流程图:
音频 aac 媒体包写入 ts 切片的流程图:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。