1. 前言
HLS全称HTTP LIVE STREAMING 是苹果公司2009推出的一种流媒体协议, 从推出到现在得到了非常广泛的应用, 不管在点播还是直播中, 使用的公司非常多, 点播的情况下不必多说。我们都知道直播场景下, RTMP使用的显然比HLS更加广泛, 肯定是HLS存在某些缺陷才会导致在直播场景下应用不广泛。
显而易见, RTMP在传输时延方面确实有很大的优势, 这是目前直播用RTMP的主要原因。
2. HLS直播时延原因分析
HLS协议规定直播时,客户端不应该选择开始时间到最后一个segment结束时间间隔小于最后一个segment时长加两倍的目标时长的segment作为首个segment进行播放。也就是说,一般而言,客户端应该从m3u8文件中倒数第三个或倒数第四个segment开始播放。如下图所示,客户端应该选择标号为3的segment作为起始的segment播放。由此可见,HLS直播系统至少会产生3个segment时长之和的时延,假设每个segment时长6s,再加上客户端会有缓存(假设为1s)和传输时延,总体的时延可能会达到20s。
3. LL-HLS降低时延原理
LL-HLS的就是为了降低HLS的时延而提出的。它的原理是:LL-HLS是在上述带来时延的三个segment中,第一个封装完成,第二个正在封装,第三个还开始没封装的时候,就把三个的url都写入m3u8文件,如下图所示。这时候客户端发现m3u8文件里已经有三个segment的url了,就开始播放第一个segment了。这样,就减少了几乎是第二个和第三个segment时长之和(12s左右)的延时。
4. LL-HLS 做了什么改进
4.1 利用HTTP/1.1分块传输进行片段
分块就是把数据分成一块一块的再发送出去,浏览器收到后再组装起来,这种“化整为零”的思路在 HTTP 协议里就是“chunked”分块传输编码,在响应报文里用头字段“Transfer-Encoding: chunked”来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送。
每个分块包含两个部分,长度头和数据块,长度头是以 CRLF(回车换行,即rn)结尾的一行明文,用 16 进制数字表示长度,数据块紧跟在长度头后,最后也用 CRLF 结尾,但数据不包含 CRLF,最后用一个长度为 0 的块表示结束,即“0rnrn”。
4.2 在片段可用之前声明片段
尽管减少片段的大小是一个可行的方法,但是它有诸多限制。在一个最佳的场景中,每个片段起始于I帧,这让播放器可以迅速开始播放一个片段,而不用等待和下载一个更早的片段。因为I帧比P帧大很多,因此减少片段大小并增加I帧数目,将提升总体利用的带宽。
解决了大缓冲区的问题,因为该缓冲区的一部分预先声明了,但是不可用。因此,这实际上减少了实时点的强制退避,也减少了建立缓冲的能力。因此播放器需要迅速知道一个分块的位置。通过预期分块的创建和已经列出的未来分块的位置,一个播放器可以预测哪个文件需要被导入。尽早声明这些片段可以让不使用LHLS的播放器像正常的HLS流一样播放,并且改善延迟。
这个更新消除了通过分割视频流引入的延迟和播放列表引入的延迟。此外该方法可支持CDN,因为它们支持HTTP/1.1分块传输。
4.3 使用EXT-X-PRELOAD-HINT标签
借助此标签,发布低延迟HLS流的服务器可以宣布继续播放所需的下一个媒体数据的最可能位置。这允许播放器客户端执行请求,从而允许数据段的下一部分可用时立即流入。然后可以重复此过程,从而在加载新媒体数据时可以消除额外的往返时间(也是使用HTTP/2 push的主要原因)。
4.4 使用LL-HLS配置文件
它包含了LL-HLS初步规范中的大多数数据:不再需要阻止播放列表重新加载;可以为同一类型列出多个预加载提示;不再定义部分必须在播放列表中保留多长时间。
5. LL-HLS直播的实现
清楚HLS和LL-HLS的原理之后,认为支持HLS直播的客户端也是支持LL-HLS的。我们需要做的是,在服务器端,采集到一个segment的第一帧数据并把它封装到segment中之后,把这个segment的url写进m3u8文件(TS格式是支持数据一帧一帧的封装的)。这时候客户端就可以发起请求下载这个segment,但实际上这个segment还没有封装完成。
(1)采集视频数据并封装:
摄像头采集视频数据,并封装到TS文件中。第一帧数据封装完成时,将TS的url写入m3u8文件。
(2)发送动态大小文件:
我们想要实现的是客户端只发起一次请求,服务器端每有一帧数据封装到segment,就向客户端发送这一帧的数据。上述所说即服务器需要实现可以发送动态大小的文件。我们使用的服务器是nginx,世界上大部分web服务器都在使用nginx,它的性能是超过老牌服务器Apache的。我们通过查阅资料和阅读nginx服务器源码得到,nginx并没有发送动态大小文件的功能。
于是,在nginx源码基础上增加了发送动态大小文件功能。
(3)下载和播放LHLS直播流:
支持播放HLS直播流播放器都可以支持我们的LHLS直播。我们使用google的开源播放器ExoPlayer作为客户端,下载和播放LHLS直播流。
6. 小结
(1)LL-HLS在直播中的延时大大降低, 可以降低值3s内, 但是即使这样, 还是不如RTMP, 不过Apple还会努力的, LL-HLS还是可以优化的, 例如多服务器控制源。
(2)LL-HLS的控制粒度更细了, 对预加载/H2 push的利用效率更好, 核心原理还是要减少RTT和HLS的原有耗时点。
(3)国内使用LL-HLS并不多, 主要是目前RTMP并没有什么大的瓶颈, 而且RTC也在发展, 选择比较多, 不过LL-HLS很简单, 接入简单, 成本小, 需要维护的成本也小, 也不失为一种选择。
(4)Android 平台上ExoPlayer 2.13.0版本已经支持了LL-HLS, 可以体验实测。
作者:郭兆年 | 来源:公众号 —— 青榴实验室
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。