导读
本文介绍了B站流媒体技术在春晚直播中的一些应用,包括用户体验提升和玩法创新。
背景概述
2024年底,B站的研发团队悄悄开启了一个代号CNY的神秘项目,原来是B站会在除夕当天转播央视春晚。因为是一项非常大的直播活动,且预期会有大量的新用户进来,产品和研发都想在这个项目上大展拳脚,希望给到新老用户一些新奇的直播玩法和更好的直播体验。结合B站已有的直播基础能力,以及产品的需求功能, 其中涉及流媒体技术的部分主要分为以下两大类。
首先是体验提升:分为画质提升和降低延时及卡顿两个部分,其中画质提升包括提供HDR清晰度和更高的视频观看质量。
然后是玩法创新:今年春晚涉及到流媒体技术核心玩法是结合B站的弹幕特色,“送弹幕上春晚”。
以下会详细介绍我们是如何实现这些功能,遇到了哪些问题,都是如何解决的。
系统介绍
一般的直播系统链路如下,用户推流到直播的源站,然后经过直播转码系统,再通过下行CDN分发给用户。这种情况下源流的卡顿会在链路中持续放大,如果直播间观看人数很多,下游大量用户观看卡顿时可能会刷新房间或者重试某些接口,导致房间页部分功能QPS直接激增,引发问题。
为了防止类似问题发生,B站引入了云导播台进行稳流,它通过多输入源+自动切流等操作,可以防止因为源流抖动/断流导致的链路问题放大,同时也在云导播台上进行更多的玩法。包括转码稳流,无缝切流,动态调整码率,动态分辨率,直播安全帧,自定义SEI,超分增强,外挂字幕等等。
云导播台的架构如下,感兴趣的后面可单独出一篇文章说明,这里不做展开。
体验提升
今年B站上线了HDR直播功能,相比于普通的SDR(Standard Dynamic Range,标准动态范围)HDR(High Dynamic Range,高动态范围)可以提供更多的动态范围和图像细节。给用户更好的观看体验。对于部分源是普通的SDR,我们在导播台上集成基于AI算法和GPU调色的SDR2HDR功能。而对于春晚这样一个面向更多用户的直播活动,我们希望给到用户最好的观看体验,所以也计划提供HDR清晰度支持,考虑到性能和效果,我们完成了基于GPU调色的SDR2HDR功能,并输出了demo通过业务方验收。不过在一月初我们得知央视会给到我们的源有两种规格:
使用SRT传输的4K50FPS的HDR(HLG);
使用RTMP传输的1080P25FPS的SDR。
这下好了,不用做SDR2HDR了, 但是新的问题来了,如何为无法播放4K50FPS HDR的用户提供替代方案?要给他们生产一个4K50FPS的SDR清晰度。一般的方法为用4K50FPS的HDR去做HDR2SDR的颜色变换,或者使用1080P25FPS的SDR超分插帧到4K50FPS的SDR。后者有较大的性能压力,很难实时,决策下选择HDR2SDR的方案。同时考虑到主备多活,我们最终的导播台转码链路图设计如下。使用2个导播台,分别拉央视的主备流,且将输出的清晰度拆成了两部分,包括1080P25及以下清晰度和1080P50HDR及以上清晰度,考虑到单机器性能负载,其中导播台只负责稳流和进行颜色转换输出用于转码输入的原画P清晰度,其他对用户开放的清晰度交给了直播转码系统来做(注意这里,要考的)。
在和央视联调时发现HDR2SDR出来的SDR画面效果和央视的原生SDR在色调上差距较大,考虑到效果体验,甚至一度决策不展示4KSDR清晰度。后续研发同学找到了基于LUT的HDR2SDR的颜色转换方案并集成到了导播台使用的自研二进制中,最终效果符合预期,验收通过。
到这里,我们好像解决了体验功能侧的需求?并没有,还有个大难题,带宽成本和延时。转码系统有个不可能三角,带宽(成本)、算力、画质。先说下大型活动的整体流程:一般是运营方确定活动日期、观看人数、对外展示的清晰度规格,多媒体根据对应的活动等级,申请对应的机器,在机器上配置相应的直播云导播台,导播台转出对应的清晰度规格, 然后转推到下游服务。大家都知道当用户去观看一个直播视频时,会消耗数据流量,这是因为用户的客户端会从云端下载了一份视频数据到本地播放器上进行播放,这是用户侧的观看成本。相应的直播平台也需要传一份数据到云端供用户下载观看,这是一个平台一对多的情况,上传和下载都是会产生带宽成本的,而且当用户规模增大时,上传成本也会逐渐增大。当然平台可能会通过P2P,CDN等方式减少这方面的带宽成本。
这次活动因为可预期的观看人数很多,需要用到很多第三方的CDN资源,而第三方的资源也是有配额限制的,需要提前申请,且都是要按量计费的。如何在一开始就给出一个较为合理的带宽预估也是需要考虑的事情。这个复杂计算系统的源头就是直播转码系统的转出质量和转出码率,当转出码率增加,对应的带宽成本会成倍放大。而针对春晚这场盛大的活动,业务方的诉求是达到很好的画质的同时又希望带宽不会超出预期。这其中可能会存在多轮的拉扯,这就需要转码系统具有较强的基建能力,能够根据业务方的需求和资源情况进行灵活调整,并输出相关数据辅助决策。
首先是转码质量评估方面:一般会使用PSNR,SSIM,VMAF来评估转码质量,在直播场景下,VMAF这种需要较高算力的指标无法实时输出,所以我们使用PSNR来作为转码中的质量指标,且会实时输出每一秒的PSNR和码率数据。对于转码系统,一般是定一个画质的目标(比如PSNR=44),按照这个目标,通过调节编码器的转码参数,使得转码产物的质量数据趋近或者超过这个画质目标。调节的方式一般为ABR或者CRF,我们采用了CRF的方式,即通过调整CRF的方式来达到相应的画质指标,对应的会有一个转码产物的码率指标,我们称这个过程为质量标定。
然后是转码的性能评估方面:直播转码有一个很关键的要求是实时性,即编码器的性能需要达到实时,比如60FPS,否则用户看到的画面就会丢帧或者卡顿。 而编码器在不同的机器(主要是cpu型号)或者编码参数下, 能达到的性能也有差别。保险起见,我们可以无脑给最大的资源,但是这样有点浪费。我们的做法是用最复杂的视频作为输入,然后固定跟线上一致的编码参数,给指定的机器发批量的任务,统计所有任务的avg_fps和min_fps,要求avg_fps和min_fps都满足我们的最低标准(目标FPS多10%, 目标60FPS的档位需要达到稳定66FPS),而对于不同的CPU型号,我们采用单核归一化算力的方法, 将不同CPU型号的算力进行归一化, 之后按照系数归档。我们称这个过程为性能标定。
最后是转码延时评估方面:首先直播转码会需要一定的时间,如果转码耗时很长,会导致用户在很久之后才能看到主播当前的画面,这个过程增加的时间我们称之为链路延迟。那么如何知道整个系统的链路延时是多久呢?最简单的方法是打点,即在链路开始的时候,我们打上一个时间戳,在链路的结束,我们再打上一个时间戳,这样两个时间戳相减就可以得到整个链路的耗时。而在链路的中间节点上,我们也会加上打点,最后上报的地方放在客户端,这样每个用户在播放端进行播放的时候,就能统计到从源头到用户侧的全链路延时数据,用户在自己的播放器上也可以看到相关统计信息。这其中也涉及到转码系统的延时部分,我们会在进转码系统前打一个点,出转码系统后,打一个点,两个点相减就是转码系统的链路耗时。这其中还会统计解码耗时,编码耗时等。针对每一个编码器和对应的参数,我们在上线前都会进行这样一次统计,我们称这个过程为延时标定。延时这部分的时间戳数据是跟着视频流走的,我们放在了对应编码器的SEI信息中,对于AV1编码器,由于没有SEI的概念,我们放在了AV1的OBU_METADATA中,用于自定义SEI信息,这也符合SPEC的要求。
好了,有了这三个基建后,针对公司春晚业务方的各种需求,我们都可以给出明确的数据指导相关决策,实现快速迭代。且保证上线后的直播指标一切正常。
相关的决策包括但不限于:部分主力清晰度增加一定的画质(达到目标PSNR),带来的码率提升是否会超出预算;通过调整导播台的转码架构,降低整个转码系统的链路延迟,并实时检测转码延时是否达到预期。
重点说一下导播台降延时的方法,基于延时标定的方法和延时大盘,我们是知道目前线上的转码链路延时的。其实我们也可以算出转码链路延时,一般的:转码延时=解码延时+编码延时。其中解码延时和输入的分辨率帧率以及解码线程有关,但是解码耗时一般不高。编码延时主要和编码器缓存在其内部的用于编码的帧数量有关,假设编码器需要缓存30帧的内容,然后原片是15帧的,那理论的编码延时就是15/30=2s。而编码器内部到底需要缓存多少帧,和编码参数相关,一般的软件编码器涉及到的编码参数有threads=1,bframes=2(reorder=2),frame-threads=3,lookahead-threads=4, rc-lookahead=4(随机设置了些值),那么理论的延时帧数为4+1+3-1+(2+1)+2=12帧。而对于NVIDA硬编来说,理论延时帧数可以按照2*(bframes+1)+lookahead估算。这些也为我们降低编码延时提供了方向。当然每一个参数的调整都会对编码效率和编码质量有影响,所以这也是一个取舍的过程。
再结合刚刚提到的导播台转码链路图来看,这个方案有一个比较严重的问题:经过导播台是需要转码的,当一个流经过导播台再给到直播转码系统,那这个流相对于经过了2次解码,2次编码,且导播台自身使用了一定的buffer来稳流,整条链路延时会比一般的转码高。当系统有降延时需求的时候,我们采用了导播台直出的方案,申请了2台超多核CPU的机器来部署,让一个导播台输出全部1080P25及以下的清晰度。而1080P50HDR及以上清晰度,由于没有合适的机器,使用了导播台硬编加常规转转码的串联方式,这套方案下, 整个转码链路延时下降了1秒。最最终导播台转码链路图如下。
玩法创新
今年春晚涉及到流媒体技术的核心玩法是结合B站的弹幕特色的一个需求-->“送弹幕上春晚”。具体的产品需求是在一个指定的时间点(画面)出现后,需要所有用户的客户端触发一个特效动画,跟央视春晚现场画面的特效弹幕形成一个联动。这个功能的难点在于如何让这百万千万甚至上亿用户能同时触发这个特效,大家可以先设想一下如果让你来做这个需求,会如何去设计并实现这个功能。哦,还有个条件忘记说了,这个指定的时间点是动态的,你只能在指定节目A开始的时候才知道N秒后需要触发这个特效,也就是给你操作的时间窗口就是这N秒,之后你就要让可能上亿用户的客户端同时触发这个事件。一般的,我们可能会采用广播下发,或者配置下发的方式去触达用户,但是这样对触达服务的QPS压力会非常高,且大概率无法做到同时触发,同时端上的时间参照系也可能是错误的。
最终我们采用的方式是,在直播流里面加特定的SEI,SEI中规定了几个字段,一个是作为时间参照物的UTC时间戳T(采用当前机器的北京时间,多活的时候,多台机器之间提前通过网络校准对时),另外一些是需要触发指定事件的事件类型和相对时间参照物的时间戳。一开始SEI中只有作为时间参照物的UTC时间戳,当指定节目A开始的时候,由研发对SEI进行改写,通过+N秒的方式,刷新其他指定事件类型对应的时间戳。这样端上所有拉取直播内容的播放器,解析对应视频流里面的SEI信息,获取参照时间戳和对应事件的时间戳,就可以准时触发特效。
到这里好像方案设计的还行?也能满足业务方的需求了。但是如果说,让你来做最后的SEI写入操作,你会紧张嘛。下游那么多人开发了那么久的功能能不能生效,可就靠你这一拍了,万一?不,不能有万一,为了防止这个万一,我们做了非常多的保障措施。首先是关于SEI有没有写入成功的确认机制,我们在导播台的前端页面上增加了实时显示视频流SEI的能力,可以实时确认流里面的SEI信息是否符合预期,这需要SEI里面的信息是人和机器都可以快速理解的。然后是最关键的SEI改写的部分,考虑到我们云导播台异地多活的体系架构,这个命令需要快速触达全部的导播台,还要考虑到当晚可能出现的内外网故障风险等,一个人负责在导播台前端页面点击批量下发的按钮,一个人在公网通过脚本执行直接触达容器。而这些人的备份也需要进行同样的准备操作,只是备的同学的N可能是-10秒。还要考虑执行早了,执行晚了,执行太晚了,分别怎么办,SOP几乎考虑到了所有可能的异常情况。好在一切顺利,当晚没有发生意外情况,最后负责主执行的同学在执行完成后,发出了如下感叹。(小声说,已经成为了当晚最靓的表情包~
最后来看,给到我们决策的N只有几十秒,不过基于方案设计的比较好,该功能最终卡点大成功,客户端特效和春晚现场飘屏弹幕联动的效果非常好,实际效果如图:
结语
最终我们在这场春晚直播中给B站用户提供了4K超清画质,带来了可能全网唯一的春晚“HDR”直播清晰度,整体链路延时也做到了极低水平,同时上线了极速直转点功能增加了晚会结束后点播用户的观看体验(这个在另一篇文章中有详细介绍)。
-End-
作者丨青石、Jomy、猫先生、小辉辉、fengshi、Lighting
开发者问答
关于SEI信息在点直播场景中的应用, 大家还有什么优秀的方案和经验?
欢迎在留言区分享你的见解~
转发本文至朋友圈并留言,即可参与下方抽奖⬇️
小编将抽取1位幸运的小伙伴获取小电视鼠标垫键盘垫
抽奖截止时间:5月6日12:00
如果喜欢本期内容的话,欢迎点个“在看”吧!
往期精彩指路
Apache Kyuubi 在B站大数据场景下的应用实践
丨丨
丨丨
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...