M3U8 是一种常见的流媒体格式,主要以文件列表的形式存在,既支持直播又支持点播,尤其在 Android、iOS 等平台最为常用,下面就来看一下 M3U8 的最简单的例子:
从这个例子中可以看到如下几个字段,其含义具体如下。
M3U8 文件必须包含的标签,并且必须在文件的第一行,所有的 M3U8 文件中必须包含这个标签。
M3U8 文件的版本,常见的是 3,其实版本已经发展了很多了,直至截稿时,已经发布到了版本 7,经历了这么多版本,期间也对不少标记进行了增删。
例如在版本 2 以后支持了 EXT- X-KEY 标签,在版本 3 以后支持了浮点 EXTINF
duration 值,在版本 4 以后支持了 EXT-X-BYTERAGE 标签与 EXT-X-I-FRAMES-ONLY 标签,在版本 5 以后支持了 EXT-X-KEY 的格式说明 KEYFORMAT 与 KEYFORMATVERSION 标签以及 EXT-X-MAP 标签,在版本 6 以后支持了 EXT-X-MAP 标签里面不包含 EXT-X-I-FRAMES-ONLY 标签。当然,也在一些版本中删除了一些标签,例如版本 6 中删掉了 EXT-X-STREAM-INF 标签与 EXT-X-I-FRAME-STREAM-INF 标签,从版本 7 中删除掉了 EXT-X-ALLOW-CACHE 标签等信息。
每一个分片都会有一个分片自己的 duration,这个标签是最大的那个分片的浮点数四舍五入后的整数值,例如 1.02 四舍五入后的整数为 1,2.568 四舍五入后的整数为 3,如果在 M3U8 分片列表中的最大的 duration 的数值为 5.001,那么这个 EXT-X-TARGETDURATION 值为 5。
M3U8 直播时的直播切片序列,当播放打开 M3U8 时,以这个标签的值为参考,播放对应的序列号的切片。当然关于客户端播放 M3U8 的标准还有更多的讲究,下面就来逐项进行介绍。
分片必须是动态改变的,序列不能相同,并且序列必须是增序的。
当 M3U8 列表中没有出现 EXT-X-ENDLIST 标签时,无论这个 M3U8 中有多少
分片,播放分片都是从倒数第三片开始播放,如果不满三片则不应该播放。当然,如果有些播放器特别定制了的话,则可以不遵照这个原则。
如果前一片分片与后一片分片有不连续的时候播放可能会出错,那么需要使用 EXT-X-DISCONTINUITY 标签来解决这个错误。
以播放当前分片的 duration 时间刷新 M3U8 列表,然后做对应的加载动作。
如果播放列表在刷新之后与之前的列表相同,那么在播放当前分片 duration 一半的时间内再刷新一次。
EXTINF 为 M3U8 列表中每一个分片的 duration ,如上面例子输出信息中的第 一个分片的 duration 4.120000 秒;在 EXTINF 标签中除了 duration 值,还可以包含可选的描述信息,主要为标注切片信息,使用逗号分隔开。
EXTINF 下面的信息为具体的分片信息,分片存储路径可以为相对路径,也可以为绝对路径,也可以为互联网的 URL 链接地址。
除了以上的这些标签之外,还有一些标签同样是常用的标签,具体如下。
若出现 EXT-X-ENDLIST 标签,则表明该 M3U8 文件不会再产生更多的切片,可以理解为该 M3U8 已停止更新,并且播放分片到这个标签后结束。M3U8 不仅仅是可以作为直播,也可以作为点播存在 ,在 M3U8 文件中保留所有切片信息最后使用 EXT-X-ENDLIST 结尾,这个 M3U8 即为点播 M3U8。
EXT-X-STREAM-INF 标签出现在 M3U8 中时,主要是出现在多级 M3U8 文件中时,例如 M3U8 中包含子 M3U8 列表,或者主 M3U8 中包含多码率 M3U8 时;该标签后需要跟一些属性,下面就来逐一说明这些属性。
BANDWIDTH 的值为最高码率值,当播放 EXT-X-STREAM-INF 下对应的 M3U8 时占用的最大码率,这个参数是 EXT-X-STREAM-INF 标签中必须要包含的
属性。
AVERAGE-BANDWIDTH 的值为平均码率值,当播放 EXT-X-STREAM-INF 下对应的 M3U8 时占用的平均码率,这个参数是一个可选参数。
CODECS 的值用于声明 EXT-X-STREAM-INF 下面对应 M3U8 里面的音
频编码、 视频编码的信息,例如,若 AAC-LC 的音频与视频为 H.264 Main Profile、Level3.0 的话,则 CODECS 值为“mp4a.40.2,avc 1.4d401e”,这个属性应该出现在 EXT-X-STREAM-INF 标签里,但是并不是所有的 M3U8 中都可以看到,仅供参考。
M3U8 中视频的宽高信息描述,这个属性是一个可选属性。
子 M3U8 中的视频帧率,这个属性依然是一个可选属性。
下面针对 EXT-X-STREAM-INF 举一个实际的例子:
在这个 M3U8 文件中,使用了 4 个 EXT-X-STREAM-INF 标签来标注子 M3U8 的属性:
FFmpeg 中自带 HLS 的封装参数,使用 HLS 格式即可进行 HLS 的封装,但是生成 HLS 的时候有各种参数可以进行参考,例如设置 HLS 列表中切片的前置路径、生成 HLS 的 TS 切片时设置 TS 的分片参数、生成 HLS 时设置 M3U8 列表中保存的 TS 个数等,详细参数请参考表 3-29。
常规的从文件转换 HLS 直播时,使用的参数如下:
./ffmpeg -re -i input.mp4 copy -f hls -bsf:v h264_mp4toannexb output.m3u8
输出内容如下:
可参考:ffmpeg转HLS参数介绍(ffmpeg转m3u8参数)
-bsf:v h264_mp4toannexb
将 MP4 中的 H.264 数据转换为 H.264 AnnexB 标准的编码
start number
start number 参数用于设置 M3U8 列表中的第一片的序列数
hls_time
hls_time 参数用于设置 M3U8 列表中切片的 duration
hls_list_size
hls_list_size 参数用于设置 M3U8 列表中 TS 切片的个数
hls_wrap
hls_wrap 参数用于为 M3U8 列表中 TS 设置刷新回滚参数
hls_base_url
his_ base url 参数用于为 M3U8 列表中的文件路径设置前置基本路径参数
hls_segment_filename
为 M3U8 列表设置切片文件名的规则模板参数
hls_flags
delete_segments
使用 delete_segments 参数用于删除已经不存在 M3U8 列表中的旧文件
round durations
实现切片信息的 duration 为整型
discont start
在生成 M3U8 的时候在切片信息的前边插入 discontinuity 标签,在切片不连续时作特别声明用
omit endlist
在生成 M3U8 结束的时候若不在文件末尾则不追加 endlist 标签
split_by_time
生成 M3U8 时是根据 his_time 参数设定的数值作为秒数参考对 TS 进行切片的,并不一定要遇到关键帧(这个参数设置一开始有可能会花屏,非特殊不设置)
use_localtime
以本地系统时间为切片文件名
method
用于设置 HLS 将 M3U8 以及 TS 文件上传至 HTTP 服务器
(这个比较重要,原来推流是这样完成的,就是让ffmpeg将m3u8文件生成到http代理目录下)