HLS直播协议在B站的实践
本期作者
李凯
哔哩哔哩资深开发工程师
2020年加入B站,负责HLS在B站落地实践, 从零到有构建HLS直播体系。
姜军
哔哩哔哩资深开发工程师
2015年加入B站直播团队,现负责B站直播音视频技术架构。
01 背景
在音视频直播领域,各种新技术与新标准层出不穷,直播场景也愈发复杂。为了更好的面对未来的挑战,我们需要亟需下一代直播协议来支持这些新标准的落地,B站在此方面进行了探索,率先在国内推行HLS(fmp4)协议在国内直播领域大规模落地。本期我们主要分享HLS在B站落地方面的工程实践经验。
02 现状与问题
传统直播技术使用的传输协议主要是RTMP/HTTP-FLV。其中RTMP是有Adobe公司开发的,虽然不是国际标准,但在当年Flash流行的年代影响下,成为了业界事实标准。
基于RTMP/FLV协议的直播,是国内比较成熟的直播架构体系,在行业中已经投入使用近10年。一个典型的直播架构图如下:
基于RTMP/FLV协议从技术上也比较成熟,整个生态支持度非常完善。但从长远考虑,RTMP也存在各种无法解决的问题,这让我们对未来兼容性有很大的担忧。
首先,RTMP/FLV标准已经超过10年没有更新,在兼容性层面已经面临着很大挑战,比如对h265的支持,当前业界是通过hack的方式进行追加,但如ffmpeg都需要打补丁之后才能支持,各种系统工具支持性较差。甚至也会出现各家hack的方式不同,导致系统无法对接。如果涉及到出海的业务,由于无法对齐国际标准,难以与海外公司展开技术合作。
其次,主流的浏览器原生不支持FLV,需要在web端进行一次额外的转封装操作,会有额外开销,在用户设备负载较高时,可能会影响观看体验。
最后,在直播场景中,非常适合p2p的应用,可以极大降低带宽成本,但在流式协议上构建P2P成本较高,通常也会牺牲标准的兼容性。
在对现有主流的直播协议做了充分调研后,HLS(fmp4)协议进入了我们的视野。相比较上述RTMP协议的一些缺点,HLS(fmp4)出现完美解决上述这些问题。
fmp4标准一直处于MPEG标准的维护中,对各种编码器和新技术, 如AV1,VVC支持度非常完善。主流浏览器也支持fmp4格式,省去了中间转封装的开销,可以减少网页端处理压力。
其次,CDN部署更容易,因为HLS是基于文件传输,传统的静态文件CDN只需要少量配置更改就可以支持相关业务,对传输内容不敏感。
另外,fmp4在DRM支持性上非常好,可以对版权内容做更好的保护。
最后,利用切片文件实现P2P较为方便,文件P2P方案在业界成熟, 也可以做到比较好的分享率,在直播场景中P2P可以有效节省带宽成本。
综合以上各方面,我们确定了要将HLS(fmp4)协议作为支撑未来新技术落地的主要方向。
03 HLS直播协议简介
HLS全称为 HTTP Live Streaming,是由苹果公司提出基于HTTP的流媒体网络传输协议。其基本原理是将直播的流式数据通过切割成一个个小文件,将这些小文件名记录成到一个索引文件中,播放器先请求索引文件,然后再取到对应的切片的文件,通过请求一个个小文件实现连续的播放。
流程如下图:
一个典型的索引文件(也称为M3U8播放列表)如下:
随着直播流的进行,播放列表中的切片文件会进行不停更新,播放器不停的请求索引文件和切片文件下载到媒体数据,进行解码播放,这样就实现了画面直播。
HLS协议主要有两种版本,mpegts版本和fmp4,顾名思义,他们主要的区别在于封装容器的不同,前者基于mpegts封装,mpegts因为有出色的纠错能力,常用于广播电视卫星传输。而后者在2017年8月正式进入ISO RFC8216标准,fMP4(分段式MP4)的封装格式正式被HLS支持。
fMP4不是一种新的封装格式,而是在传统MP4格式基础上增加若干新特性。传统的MP4因为文件结构所限,所有的索引和数据都是放在一起的,在播放时两者缺一不可,无法实现流式直播。fMP4主要是将MP4文件切割成更细的粒度,播放器可以加载一小部分数据之后就可以进行播放,这样就可以实现直播。
下图展示了MP4与fMP4的内部结构的区别:
04 直播架构设计
4.1 生产架构设计
在直播生产架构设计上,首先要保证稳定性和可靠性。我们重点做了以下几点:
在生产端使用了集群化进行切片的生产, 切片会在内存和文件对象存储进行双写
热备能力, 随时可以调整内部回源链路, 防止链路故障
从内存到持久化对象存储, 分级回源策略
可分布式部署, 利用HTTP302进行分布式调度
由于HLS协议问题,对磁盘IO要求非常高,我们使用Linux系统提供的内存映射盘去写文件,无论是写文件还是文件回源的读取速度都非常理想。但由于内存只能存有很少的切片,所以能保存的切片比较少,只用作实时直播回源,同时切片也会异步写入文件对象存储,用来做直播回放,在回源链路发生故障时,会自动进行降级,利用文件对象存储暂时对外提供回源服务。
4.2 回源架构设计
在回源架构方面,我们设计了一套动态回源方案。CDN在回源时需要根据我们的回源服务进行回源地址的查询,相比较固定的回源配置,我们可以实时上下线某些节点,也可以减少回源链路上面的延迟,在调度上比较灵活,同时容灾能力也极大提升。
除了提供动态回源查询服务之外,我们也充分利用了http302特性,允许使用http302进行回源跳转,在故障发生时可以做到自适应降级。
05 HLS启播优化
在HLS标准当中,每一个单独的切片文件都是一个GOP,但直播场景中用户推流的GOP大小都不固定,如果完全按照标准去实现的话就可能会导致切片长度过大,客户端下载时间过长,从而导致启播时间比较久。
在我们的实践中,首先采用了1s长度的切片,可以尽可能缩短因为产生切片所造成延迟,这样会出现一个问题,就是每一个切片可能不是一个GOP, 如果按照默认的客户端拉播放列表中最后三个切片进行播放,一旦倒数第三个的第一帧不是关键帧就会导致启播很慢或无法启播。在HLS标准中#EXT-X-START:TIME-OFFSET=0标签会告知客户端,从列表的第一个切片开始播放。
此时我们只需要保证列表的第一个切片的第一帧为关键帧,客户端就可以快速加载到关键帧。
此外,利用了fmp4和CMAF(一种基于mp4上的封装技术,与fmp4非常类似)的封装特性,在一个切片文件中可以进行了更小粒度的封装(chunk),使得客户端在下载几帧数据后就可以开始进行解码播放。如上图,对于第一个切片文件,客户端只需要下载第一个chunk拿到第一帧,就可以完成启播。这样就完成了不在破坏标准兼容性的基础上实现了启播的优化。
由于采用了1s一个切片的方式,相比较RTMP/FLV来讲,整体延迟只增加了1s,是一个可以接受的范围。相比较传统的HLS来讲,首帧提速2-3倍,配合客户端的追帧策略也可以使延迟得到很好的控制。
06 直播回放实现
由于HLS协议,是将流媒体进行切片,我们只需要将切片的保存时间延长,就可以让用户访问到之前的内容。具体的实现方法是,在直播生成索引文件的过程中,只需要同时生成对应的时间戳的索引文件,例如直播时索引文件叫index.m3u8,此时同时生成一份utc.m3u8,在用户选择回放时服务端会返回对应时间点的索引文件。这样就完成了直播回放的功能。除了需要文件保存更长的时间外,其他无需改动,实现比较容易。
除了用作直播回放之外,更可以用做录像进行长久保存,对审核相关业务也可以很好的支持,同时省却了专门维护录像业务的麻烦。
07 回源预热优化
HLS与RTMP/HTTP-FLV在回源上最大的不同在于,HLS是短链接, RTMP/HTTP-FLV是长链接。两种各有优缺,长链接只建立一次链接,开销较低,但在抗网络抖动性比较差, 遇到抖动时间短,且抖动强的状况,链接可能就直接断开,就会造成用户观看黑屏,但对于短链接,由于可以快速重试,时间短而剧烈抖动,可以比较快速进行恢复,某些情况下甚至用户端可能不会有感知到卡顿,但短链接需要频繁请求响应,对服务器CPU消耗较高。
HLS在回源链路上,全链路都支持了HTTP1.1,保证底层共享长链接,避免频繁TCP建联的开销。另一方面,我们利用了CMAF和HTTP Chunk传输特性,在服务端允许文件的边写边发,在切片还未完全落盘之前就可以允许CDN提前回源,存几帧数据就发几帧,直到指定切割点后,数据发送完成之后,断开请求,CDN已经保存了这份文件的缓存,这时切片服务再去更新M3U8播放列表。当客户端播到最新一个分片时,CDN由于提前进行过回源,已经缓存了对应文件。这种资源预热策略,尤其是针对频繁请求小分片的文件,可以有效提升回源质量。
08 展望总结
得益于底层fmp4提供的丰富的扩展性,我们正在技术和业务上做更多的尝试,如直播DRM的应用,自适应清晰度,数字水印,杜比世界/全景声直播等,后续也会有相关文章介绍,请持续关注我们。
出于对新技术和新业务的探索,B站前几年在业内率先引入SRT协议,如今我们在业内大规模落地HLS(fmp4),从直播上行到下行完成了技术探索,为我们后续技术演进做了深厚的积累,也标志我们可以尝试慢慢摆脱老旧的RTMP协议限制,真正的拥抱下一代直播技术!
参考资料:
https://datatracker.ietf.org/doc/html/rfc8216
https://developer.apple.com/documentation/http_live_streaming