一. HLS简介

  • 视频的封装格式是TS.
  • 视频的编码格式为H264,音频编码格式为MP3,AAC或者AC-3
  • 除了TS视频文件本身,还顶一个了用来控制播放的m3u8(文本文件)
    为什么苹果要提出HLS这个协议,其实主要是为了解决RTMP协议存在的一些问题.比如RTMP协议不使用标准的HTTP接口传输数据,所以在一些特殊的网络环境下,可能被防火墙屏蔽掉.但是HLS由于使用的HTTP协议传输数据,不会遇到被防火请屏蔽的情况,除非你的防火墙做了特殊设置

另外对于负载,RTMP是一种有状态协议,很难对视频服务进行平滑扩展,因为需要为每一个播放视频流的客户维护状态.而HLS基于无状态协议HTTP,客户端知识按照顺序使用下载存储在服务器的普通TS文件,做负责均衡如普通的HTTP文件服务器的负载均衡一样简单

另外HLS协议本身实现了码率自适应,不用宽带的设备可以自动切换到最适合自己码率的视频播放,其实HLS最大的优势就是他的亲爹是苹果,苹果在自家的IOS设备上只提供对HLS的原生支持,并放弃的Flash.Android也迫于压迫原生支持了HLS.这样一来flv,rtmp这些Adobe的视频方案要想在移动设备上播放需要额外下点功夫.当然Flash对移动设备造成很大的性能压力确实也是自身问题

但HLS也有一些无法跨越的坑,比如采用HLS协议直播的视频延迟无法下到10秒以下,而RTMP协议的延迟最低可以到3,4秒左右,所以说直播对延迟比较敏感请慎用HLS

HLS工作原理

结合这张官网给的图,从左到右讲,左下方的inputs的视频流源是什么格式都无所谓,他与server之间的通信也可以任意(如RTMP),总之只要把数据推流到服务器上即可.这个视频在server服务器上被转换成HLS格式视频(即TS和m3u8)文件.岔开来看server里面的Media encoder的是一个转码模块负责将视频中的视频数据转码到目标编码格式(H264)的H264视频数据之后,在stream segmenter模块将视频切片,切片的结果就是index file(m3u8)和ts文件了.图中Distribution其实只是一个普通的HTTP文件服务器,然后客户端只需要访问以及index文件的路径就会自动播放HLS视频流了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vwy9SGT3-1617772473783)(https://i.loli.net/2021/04/07/FtEqDQLlHTgpn8s.png)]

HLS的index文件

所谓index文件就是之前说的m3u8文件

如图,客户端播放HLS视频流的逻辑其实非常简单,先下载一级index file,它里面记录了二级索引文件(Alternate-A、Alternate-B、Alternate-C)的地址,然后客户端再去下载二级索引文件,二级索引文件中又记录了TS文件的下载地址,这样客户端就可以按顺序下载TS视频文件并连续播放

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IpNt9LGt-1617772473786)(https://i.loli.net/2021/04/07/cZ5SNAo2K6mqr7B.png)]

所谓index文件就是之前说的m3u8文本文件.

二. 一级index文件

下面是一个index.m3u8文件,可以自己新建一个文件试试,会推荐你用视频播放器打开,但是无法播放

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1064000
1000kbps.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=564000
500kbps.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=282000
250kbps.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2128000
2000kbps.m3u8

bandwidth指定视频的比特率,PROGRAM-ID无用无需关注,每一个#EXT-X-STREAM-INF的下一行是二级index文件路径,可以用相对路径也可以用绝对路径,例子中的是相对路径.这个文件中记录了不同比特率视频流的二级index文件路径,客户端可以自己判断自己现行网络带宽,来决定播放哪一个视频流,也可以在网络带宽发生变化时候平滑切换和带宽匹配的视频流

三. 二级index文件

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXTINF:10,
2000kbps-00001.ts
#EXTINF:10,
2000kbps-00002.ts
#EXTINF:10,
2000kbps-00003.ts
#EXTINF:10,
2000kbps-00004.ts
#EXTINF:10,

... ...

#EXTINF:10,
2000kbps-00096.ts
#EXTINF:10,
2000kbps-00097.ts
#EXTINF:10,
2000kbps-00098.ts
#EXTINF:10,
2000kbps-00099.ts
#EXTINF:10,
2000kbps-00100.ts
#ZEN-TOTAL-DURATION:999.66667
#ZEN-AVERAGE-BANDWIDTH:2190954
#ZEN-MAXIMUM-BANDWIDTH:3536205
#EXT-X-ENDLIST

二级文件实际负责给出ts文件的下载地址,这里同样适用了相对路径

  • #EXTINF : 表示每个ts切片视频文件的时长.
  • #EXT-X-TARGETDURATION : 指定当前视频流中的切片文件的最大时长,也就是说这些切片的时长不能大于#EXT-X-TARGETDURATION的值.
  • #EXT-X-PLATLIST-TYPE:VOD : 的意思是当前的视频流平不是一个直播流,而是点播流,换句话说就是该视频的全部的ts文件已经被生成好了,#EXT-ENDLIST表示视频结束,有这个标志同时也说宁当前的流是一个非直播流.

播放模式

  • 点播VOD的特点可以获取到所有index文件和ts文件.二级index文件中流了所有ts文件的地址,这种模式允许客户端访问全部内容.上面的例子中就是一个点播模式下的m3u8的结构
  • Live模式就是实时生成m3u8和ts文件.他的索引文件一直处于动态变化的,播放的时候需要不断下载二级index文件,以获取最新生成的ts文件播放视频.如果一个二级的index文件的末尾没有#EXT-ENDLIST结束标志,说明他是一个Live视频流

客户端在播放VOD模式的视频其实只需要下载一侧index文件和二级index文件就可以得到所有ts文件的下载地址,除非客户端进行比特率切换,否则无需再下载任何index文件,只需顺序下载ts文件并播放就可以了,但是Live模式下略有不同,因为播放的同时,新ts文件也在被生成中,所以客户端实际上是下载一次二级index 文件,然后下载ts文件,再下载二级index文件,再下载新ts文件,如此反复进行播放