直播协议hls介绍

hls 是什么?

我觉得以直播来说,hls 是一个相当好懂的协定,其实就是透过一个 .m3u8 的播放列表,然后里面有多个 .ts 的档案
你只要照着播放列表里面给你的档案顺序播放就好了,听起来很容易吧!

为了让大家更明白,直接附上摘取自某处的播放列表:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-MEDIA-SEQUENCE:4454
#EXT-X-TARGETDURATION:4
#EXTINF:3.998, no desc
25133_src/4460.ts
#EXTINF:3.992, no desc
25133_src/4461.ts
#EXTINF:3.985, no desc
25133_src/4462.ts
#EXTINF:3.979, no desc
25133_src/4463.ts
#EXTINF:3.996, no desc
25133_src/4464.ts</pre>

就算你没看过这个格式,你大概看一下也可以猜出来它在做什么每一个 ts 就是一个片段,然后 #EXTINF:3.996 代表这个片段的时间长度#EXT-X-TARGETDURATION:4,这边的数字必须比播放清单中的任何一个影片的时间都大代表播放器应该每隔几秒去抓一次新的播放清单

例如说,下一次抓到的可能会长这样:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-MEDIA-SEQUENCE:4455
#EXT-X-TARGETDURATION:4
#EXTINF:3.992, no desc
25133_src/4461.ts
#EXTINF:3.985, no desc
25133_src/4462.ts
#EXTINF:3.979, no desc
25133_src/4463.ts
#EXTINF:3.996, no desc
25133_src/4464.ts
#EXTINF:3.998, no desc
25133_src/4465.ts

就是最后面多了一个片段。所以只要一直维持这个规则,就能够不断取到新的片段。那如果很不巧的,server 没有及时产生出播放列表怎么办呢?

例如说在第 4 秒的时候去拿,发现没更新,server 在第 4.5 秒才把新的播放片段产生出来。如果发生这种「拿了播放清单,但长的一样」的情形,就会把抓取的时间减一半,直到抓到为止。像以上情形,第 4 秒没拿到新的,就会隔 2 秒之后再去抓。

这个规则可以参考:HTTP Live Streaming draft-pantos-http-live-streaming-20

When a client loads a Playlist file for the first time or reloads a Playlist file and finds that it has changed since the last time it was loaded, the client MUST wait for at least the target duration before attempting to reload the Playlist file again, measured from the last time the client began loading the Playlist file.
If the client reloads a Playlist file and finds that it has not changed then it MUST wait for a period of one-half the target duration before retrying.

至于做直播最关心的延迟问题,也可以直接从这个播放列表直接推测出来。以上面的例子来说,一共有 5 个片段,每一个片段 4 秒,延迟就是 20 秒。Apple 官方建议的是 3 个片段,每个片段 10 秒。

What duration should media files be? A duration of 10 seconds of media per file seems to strike a reasonable balance for most broadcast content.

How many files should be listed in the index file during a continuous, ongoing session? The normal recommendation is 3, but the optimum number may be larger.

可参考:Apple: HTTP Live Streaming Overview

不过依照官方的建议,就会有 30 秒的延迟,当然延迟越久直播的状况会越好,可是体验也会比较差一点。因此,我们可以来看看几个直播网站都是怎么设定的。

先来看看直播大头:Twitch

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:5
#ID3-EQUIV-TDTG:2016-11-26T02:40:23
#EXT-X-MEDIA-SEQUENCE:376
#EXT-X-TWITCH-ELAPSED-SYSTEM-SECS:1511.137
#EXT-X-TWITCH-ELAPSED-SECS:1508.980
#EXT-X-TWITCH-TOTAL-SECS:1535.137
#EXTINF:4.000,
index-0000000377-6zCW.ts
#EXTINF:4.000,
index-0000000378-vHZS.ts
#EXTINF:4.000,
index-0000000379-Gkgv.ts
#EXTINF:4.000,
index-0000000380-PNoG.ts
#EXTINF:4.000,
index-0000000381-h58g.ts
#EXTINF:4.000,
index-0000000382-W88t.ts

6 个片段 * 4 秒 = 24 秒。可是如果你仔细观察(开 chrome devtool 就可以了),实际上 twtich 的播放器在拿到列表以后会直接尝试从「倒数第三个」片段开始载入,所以延迟就缩短为 3*4 = 12 秒了。

再来看看台湾的 livehouse.in

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:2291
#EXT-X-TARGETDURATION:6

#EXTINF:5.2090001106262207,
1480116261segment_v02291.ts
#EXTINF:5.2080001831054688,
1480116261segment_v02292.ts
#EXTINF:5.2080001831054688,
1480116261segment_v02293.ts

5*3 = 15 秒

所以一般用 hls 的直播网站,延迟大概都会在 10~20 秒这个区间以内。我猜比这个短的话对 server 压力可能很大,而且网速慢的话,看起来会很卡。比这个长的话虽然很顺,但是使用者体验不太好,延迟太高,所以能找到最好的延迟就是在这个区间内了。

最后,我们来看看如果要在网页上播放的话,有哪些选择。因为现在已经是个 flash 快死掉的年代了,所以如果可以的话,首选当然是 html5,浏览器支援度不够高的话再 fallback 回去 flash。

先来介绍一下现成的商业授权播放器,例如说 jwplayer 或是 flowplayer,都是很不错的选项。尤其是当 open source 的方案出现问题你又修不好的时候,就会很希望公司花钱买一个商业播放器,一切问题都搞定。

open source 的方案大概就是 videojs 一支独秀了,有没有其他的后起之秀我是不知道啦,有的话麻烦推荐一下。

然后因为 hls 这个格式浏览器本身是没办法播放的,所以要搭配一些 plugin。videojs 官方有一个 videojs-contrib-hls,加上去之后就可以播放了,但我自己用过以后感觉不是很好。

最后选择了知名的影音网站 dailymotion 提供的开源解决方案 hls.js

回复

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据