HLS概述
HLS(Http Live Streaming)是APPLE公司提出的基于HTTP的流媒体传输协议。
它的工作原理就是把整个ts流分成一个个ts小文件供播放器按顺序下载播放。
HLS作为当前媒体分发传输最为重要的几大协议之一,网络上已有大量深入分析文章,苹果官方文档也对协议应用做了完善的定义。故本篇文章仅简单介绍HLS的组成以及抓包对照分析。
另外,完整的HLS系统需由服务端切片和播放端下载切片两部分组成。本篇文章仅对后一部分进行介绍。
HLS优势
由于HLS只请求基本的HTTP报文,故它可以穿过任何允许HTTP数据通过的的防火墙或者代理服务器,因此对CDN加速分发有着天然的友好性。
与其他基于实时RTP族的协议需要为每一个连接维护状态的特点不同,HLS协议本身是无状态的,只需要按序进行简单HTTP下载即可。所以,HLS跟其它HTTP一样,通过普通的WEB服务器就能承载负载均衡等。
苹果在提出HLS时,自身就已考虑了码率自适应,实现了不同的带宽设备可以自动切换到最合适自己码率的视频播放。
另外不得不说的是,由于HLS由苹果提出,所以APPLE系列产品,iphone、ipad、Safari都不需要任何插件原生就支持HLS,加之后来Android也意外的原生支持了HLS,所以HLS就变得如此重要了。
HLS劣势
对于直播来说,HLS目前暂时还无法逾越的难题就是延时很难稳定的做到和RTMP一个级别,所以我们看到互动直播少有用HLS作为主协议的。
对于点播来说,就是TS切片文件太小,海量碎片文件在分发、一致性缓存、存储读写等方面小吃力。
HLS协议介绍
HLS协议由HTTP+M3U8+TS三部分组成,其中,HTTP是传输协议,M3U8是索引文件,TS是视音频的媒体信息。
不论是直播还是点播,播放器首先请求M3U8索引文件,然后根据M3U8里的TS列表,再请求真实的TS切片文件。
HLS协议规定:
-
视频的封装格式是TS;
-
视频的编码格式为H264,音频编码格式为MP3、AAC或者AC-3;
-
除了TS视频文件本身,还定义了用来控制播放的m3u8文件(文本文件)。
下面给出一个m3u8列表,结合实例简要介绍hls
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES ------> 指定客户端可以缓存下载下来的文件用于重播。
#EXT-X-MEDIA-SEQUENCE:0 ------> 指明出现在播放列表文件中的第一个URI的序列号
#EXT-X-TARGETDURATION:15 ------> ts列表里的最大时长(注意这里必须为整数,否则safari会播放失败)
#EXTINF:14.700, no desc ------> 14.700是stream-0.ts的时长
stream-0.ts
#EXTINF:11.600, no desc ------> 11.600 stream-1.ts的时长
stream-1.ts
#EXTINF:10.100, no desc
stream-2.ts
#EXTINF:11.600, no desc
stream-3.ts
#EXTINF:11.400, no desc
stream-4.ts
#EXTINF:11.400, no desc
stream-5.ts
对于直播来说,服务器会不断产生新的ts片,所以会不断的刷新m3u8和ts。播放器播放时,也不停的
请求m3u8和ts。
对于点播,所有的ts片都会写在m3u8里,m3u8不需要更新,所以点播的话只在开始时请求一次m3u8,然后
不停的请求ts。
播放器拿到该m3u8列表之后,会请求一片ts后,间隔一段时间请求下一片ts。 这个间隔的时间的长短,
一般是根据m3u8中的 #EXT-X-TARGETDURATION, 比如间隔1/2(或1/3)的EXT-X-TARGETDURATION
请求下一片ts。播放器不同,策略也不同。
播放器一般是根据EXT-X-MEDIA-SEQUENCE, 可能还会结合列表中ts片的数目,判断m3u8是否更新,然后决定
是否需要请求新的m3u8。
以上介绍的是最常见的hls。但是由于客户端每次请求ts或m3u8有可能都是一个新的连接请求,所以我们无法有效的标识客户端,一旦出现问题,基本无法有效的定位问题,所以一般工业级的服务器都会对传统的hls
做一些改进。
改进版的hls:
主要是网宿的variant hls 和 观止云的HLS plus(HLS+)
-
variant
这是从网宿的hls链接里面下载的m3u8文件,可以看出这是一个Variant Playlist file,是一个变种的m3u8文件也称作Master Playlist。该文件中有一层m3u8的嵌套,即一个m3u8文件中嵌套另一个m3u8:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1341000 // EXT-X-STREAM-INF, 指定一个包含多媒体信息的 media URI 作为PlayList,一般做M3U8的嵌套使用,它只对紧跟后面的URI有
http://ttpull.8686c.com/live/stream/playlist.m3u8?wsSession=ea62d7ecaff3ad0bc72fa4e3-147460862424110&wsIPSercert=b80d38c068c9e3634a7ebb2f2bbf9b89&wsMonitor=-1
再从这个m3u8文件中去得到真正的m3u8文件:
#EXTM3U
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:6
#EXTINF:3,
478294.ts?wsSession=ea62d7ecaff3ad0bc72fa4e3-147460862424110&wsIPSercert=b80d38c068c9e3634a7ebb2f2bbf9b89&wsMonitor=-1&wsApp=HLS
#EXTINF:3,
478298.ts?wsSession=ea62d7ecaff3ad0bc72fa4e3-147460862424110&wsIPSercert=b80d38c068c9e3634a7ebb2f2bbf9b89&wsMonitor=-1&wsApp=HLS
#EXTINF:3,
478302.ts?wsSession=ea62d7ecaff3ad0bc72fa4e3-147460862424110&wsIPSercert=b80d38c068c9e3634a7ebb2f2bbf9b89&wsMonitor=-1&wsApp=HLS
同时网宿采用wsSession来标识一条播放链接。
观止hls+采用的是302(也支持variant hls):
Redirect to http://58.222.18.3:8080/uplive.b0.upaiyun.com/live/loading.m3u8?shp_uuid=5afe6c2d614861f715206ef9e9da6040&shp_ts=1474619128984&shp_cid=890925&shp_pid=3049551&shp_sip0=127.0.0.1&shp_sip1=58.222.18.3&domain=uplive.b0.upaiyun.com
再次请求重定向后的链接得到真正播放的m3u8文件:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-MEDIA-SEQUENCE:15
#EXT-X-TARGETDURATION:3
#EXTINF:2.984, no desc
http://58.222.18.3:8080/uplive.b0.upaiyun.com/live/loading-15.ts?shp_uuid=5afe6c2d614861f715206ef9e9da6040&shp_ts=1474619128984&shp_cid=890925&shp_pid=3049551&shp_sip0=127.0.0.1&shp_sip1=58.222.18.3&domain=uplive.b0.upaiyun.com&shp_seqno=15
#EXTINF:2.980, no desc
http://58.222.18.3:8080/uplive.b0.upaiyun.com/live/loading-16.ts?shp_uuid=5afe6c2d614861f715206ef9e9da6040&shp_ts=1474619128984&shp_cid=890925&shp_pid=3049551&shp_sip0=127.0.0.1&shp_sip1=58.222.18.3&domain=uplive.b0.upaiyun.com&shp_seqno=16
#EXTINF:2.988, no desc
http://58.222.18.3:8080/uplive.b0.upaiyun.com/live/loading-17.ts?shp_uuid=5afe6c2d614861f715206ef9e9da6040&shp_ts=1474619128984&shp_cid=890925&shp_pid=3049551&shp_sip0=127.0.0.1&shp_sip1=58.222.18.3&domain=uplive.b0.upaiyun.com&shp_seqno=17
#EXTINF:2.995, no desc
http://58.222.18.3:8080/uplive.b0.upaiyun.com/live/loading-18.ts?shp_uuid=5afe6c2d614861f715206ef9e9da6040&shp_ts=1474619128984&shp_cid=890925&shp_pid=3049551&shp_sip0=127.0.0.1&shp_sip1=58.222.18.3&domain=uplive.b0.upaiyun.com&shp_seqno=18
#EXTINF:2.985, no desc
http://58.222.18.3:8080/uplive.b0.upaiyun.com/live/loading-19.ts?shp_uuid=5afe6c2d614861f715206ef9e9da6040&shp_ts=1474619128984&shp_cid=890925&shp_pid=3049551&shp_sip0=127.0.0.1&shp_sip1=58.222.18.3&domain=uplive.b0.upaiyun.com&shp_seqno=19
观止云采用的是uuid来标识一个播放连接。
两种方式都可以通过一组字符串(网宿的wsSession,观止的uuid)来唯一标识一个客户端的连接,这样可以有助于运维迅速的定位某个播放器播放hls失败的原因。
另外对于hls纯音频,必须开启相应的配置,否则很容易造成hls纯音频播放失败。
HLS延时分析
HLS理论上延时=1个切片的时长+ 0-1个td(td是EXT-X-TARGETDURATION,可简单理解为播放器取片的间隔时间) + 0-n个启动切片(苹果官方建议是请求到3个片之后才开始播放) + 播放器最开始请求的片的网络延时(网络连接耗时)。
从以上延时组成可以看出,理论上HLS延时很难做到和RTMP同一级别。为了追求低延时效果,可以将切片切的更小,取片间隔做的更小,播放器未取到3个片就启动播放。但是,这些优化方式都会增加HLS不稳定和出现错误的风险。