从抖音到火山引擎——看流媒体技术演进和机会
【慧聪广电网】编者按: 8 月 5 日上午,LiveVideoStackCon 2022 音视频技术大会上海站邀请到了火山引擎 RTC 负责人宋慎义老师,为我们从实时性、沉浸式、跨地区和开发者等四个方向,来看从抖音到火山引擎,流媒体技术演进过程和机会。在宋慎义老师的演讲中,我们看到了火山引擎一路走来的历程,也了解到通过结合不同的场景,火山引擎对外来探索的坚持。
LiveVideoStack 是 2017 年开始创办的,我也恰好在那一年加入字节跳动,与字节跳动一同高速成长,从抖音到飞书,再到现在把这些成熟能力通过火山引擎对外输出,为更多的开发者与企业客户提供服务。
首先介绍一下过去几年,在流媒体技术上,我们遇到了哪些场景,解决了哪些难题以及从长远来看,未来几年我们需要持续关注的未来的方向和机会。
字节跳动大约是在 2016 年开始做流媒体相关的技术,之前只有点播。一开始我们是做单向的直播,后来有了实时互动。2020 年年初疫情爆发,更复杂的互动模式开始产生。我们在 2020 年推出了火山引擎,整个公司包括云基础、视频云以及大数据都开始向火山引擎上迁移。从那之后,字节跳动的技术能力开始慢慢成为火山引擎上的一些服务对外输出。之后,我们又利用火山引擎支撑游戏、沉浸式音视频等多种应用,火山引擎也帮助这些应用获得更好实现增长。
我们在做直播连麦业务的时候,遇到第一个问题是:如何在高清、实时和流畅这三个维度上做好平衡。想完全兼顾这三个维度是不可能的,虽然不能完全 100% 的实现高清、流畅和实时,但是可以 90% 实现,随着技术的演进,90% 可以提升到 99%,甚至更高。我们更多技术的发展也在不断地提高我们在高清、流畅和实时上的能力,不断提升用户体验。
疫情爆发以后,在线教育和视频会议也大爆发,诞生了很多非常复杂、有挑战的新场景,比如大班小组课、网络研讨会以及游戏的对战语音等,它需要一些新的突破,同时要解决全球化、多地区的问题,还要解决人和设备的问题。现在,除了人会加入互动,设备也会加入互动,所以通过架构的优化,我们提出多中心的分布式的信令的架构,能够支撑超大规模的互动。
近两年,沉浸式音视频忽然火爆起来,迎来音视频技术的新增长曲线,产生新的潮流,包括 VR 的视频、直播互动以及超低延时的直播和云端的渲染等,给技术方案提出了新的挑战。
今天,我从四个维度给大家介绍一下,我们在流媒体技术演进上重点关注的几个方向。第一个是实时性。实时性是流媒体技术发展最大的限制条件,如果没有实时性的限制,音视频技术复杂度至少能降低一半;第二个是沉浸式,这是现在需求比较大的一个演进的方向,近几年的技术进步也要开始沉浸式地、慢慢地走入千家万户,走入每个人的生活;第三个是全球化,目前是中国流量红利见顶的一个阶段,在这个前提下,不得不面临的一个问题是,我们既想继续发展技术,又想获得更多的用户,获得更多的增长,那就必须去面对全球化的问题;最后我讲一下我们在开发者生态上的思考,广义上的开发者不仅仅是开发者,还包括内容创作者。我们看看,通过技术进步能够提供给开发者,怎样的工具,怎样的服务。
1、实时性
提到实时互动,我发现同行们在信道传输上的讨论比较多,但怎样把信源跟信道结合起来,一起去做优化,是实时互动的一个关键的技术点。
实时性的核心理念就是信源分级与信道分级,用有限的信道去传输最重要的信息。展开来讲,我们可以把信源或者说要传输的信息,按照实时性和可靠性这两个维度进行拆分。有些信息非常重要,它对实时性和可靠性的要求非常高,比如说信令消息;有些信息它对实时性要求高,对可靠性的要求也许能低一些,例如音频;对于视频而言,可靠性要求就更低了;同时也有一些信息,它对可靠性要求很高,对实时性要求没有那么高,比如说文件的传输、直播等;也有一些信息对可靠性和实时性要求都不高,比如说日志。那么信源可以分级,信道其实也是可以分级的。信道看起来是一个单一的信道,但是毕竟这么多的信源是要在统一的一个信道里去传输的,所以我们要把信道划分成很多个不同的能力,要把一些重要的信道、传输方式、传输容量预留出来,给信源来使用。调节的方法就是通过调优先级、FEC 或者是调重传来实现这个信道的划分和信道的隔离。
前面的偏理论,现在讲一下如何落地。首先是信源分级的落地。实际场景中,音频跟视频这些信源会按照重要性继续进行拆分。常见的是低频的信号或低清的信号肯定更重要一些,高清的信号关键时刻是可以舍弃的。在视频的信源分级上相对是比较成熟的,我们常见的有 Simulcast 这样的技术,包括在直播上经常使用的 HLS、CMAF, 本质上都是做视频的信源分级。不同清晰度之间也可以互相参考,比如 SVC 的技术,它有时域跟空域上的机制的划分以及长期参考帧的技术,可以让我们在一定程度上降低一些带宽。高清的部分实在传不过去也没关系,现在也有很多超分辨率重建的技术,短时间内顶一下还是可以的。
我们在音频上的关注更多一些,因为在真正信道变化的时候,音频产生的问题对感官的影响更大。这里介绍一下我们使用的一个性价比比较高的技术是 MDC 多描述编码。简单来讲,就是可以把一个音频的序列拆成多个子序列,让它们「1、2、3,1、2、3」地报数,所有报 1 的站一队,所有报 2 的站一队,所有报 3 的站一队。这样的好处就是这三段编码、三段序列可以分开地去编码、传输,只要有任何一个序列能够到达对面,相当于音频的低频部分、低频信号就可以到达对面了。到达对面的分片越多,音频的清晰度就会越高。如果只到达一两个,它的清晰度会有一些影响,但是基本不会影响沟通,这是一种性价比比较高的方式,它是一种原生的抗丢包的 Codec。再把这种技术和 FEC、AI-Codec 结合起来,基本就可以实现:只要网是通的,只要有一点数据能够传到对面去,就能达到比较流畅的效果。实在传不过去,还有一些 NetEQ、PLC 的方式可以作补充。
经常有人问我,什么传输协议最好?
其实传输协议没有好与不好之分,只有合适与不合适的区别。
什么样的传输协议是合适的?
主要看应用场景、现实条件里有没有实时性的要求。如果没有实时性的要求,那一个能够有效利用信道与带宽的传输协议,就是最合适的。比如没有实时性要求,那 TCP 就是一个非常优秀的传输协议。如果有实时性要求,在传输协议的设计上就必须要实现三个目的:首先要能够调节重传实现可靠;有了一定可靠性之后,还要通过调节 FEC 让它实现一定的实时性;高优先级保证重要数据,丢弃 / 暂缓不重要数据。
一个很重要的传输协议的设计功能就是优先级。一个优秀的传输协议,实时传输协议一定要具备优先级的区别,这样能保证重要的数据优先传过去,不重要的数据就果断放弃。比如,一些非常重要的数据对实时性和可靠性的要求非常高,那就可以加很高倍的冗余,并且用很快速的重传方法,然后能高优先级地传输。虽然这样子的数据可能带宽浪费比较严重,没有办法传大量高码率的数据,但这样的数据用这样的传输协议就能实现很好的可靠性与实时性。对可靠性要求不是很高的数据,就可以进行低倍冗余,也可以进行有限重传,比如只重传关键帧,对于非关键帧不重传,这种情况下就可以实现信道的分级。这几个能力可以组合起来使用,但也可以是相对的,对于一些长肥网络可能最理智的方式就是关掉所有重传,让 FEC 去起作用。
信道分级以后一个重要的工作就是如何对信道进行建模。信道建模简单来讲就是要准确的表述网络状态。以前,信道建模的方式比较简单,都是用单一的变量,比如用丢包、带宽来描述一个信道,后来大家发现这些还是有一定的缺陷的,于是就有了相对组合的一些模型,比如延时带宽积。现在,随着算力的增加,信道建模的复杂度也相对越来越高,有的模型会有很多变量加进来参考。但是信道建模去描述网络状态是一方面,一个更重要的方式是,如何快速地感知网络的变化。有的模型其实是用统计类的指标,再加上滤波的方法来实现网络变化的感知。它可能会比较准,但是有一个很大的问题,它没有办法实现快速。有时候,我们的网络环境已经变了,但几秒钟之后它才感知出来。这样的话,对实时性的要求就会比较高,所以在实践中除了统计类的指标,比如丢包率、带宽这种需要好几秒才能统计出来指标,我们往往会加入一些瞬时指标去做修正,比如乱序、延时这些指标,就能够很快地去检测出来。
那么能够描述网络状态,感知网络的变化之后,剩下的就是如何快速地兼容弱网。大家很喜欢用这个弱网对抗这个词,但我不是很喜欢用弱网对抗,因为很多时候弱网是没有办法对抗的,只能去兼容。有些时候,动态变化是网络自身固有条件的、固有属性的动态变化。有些时候,是因为我们的信息传输发生了拥塞,那么这种时候需要改变的是信源自己。我们前面讲到信源分级,信源分级以后,通过快速地感知网络的变化,调整信源,然后果断舍弃不重要的数据,才能够实现更好的实时性。所以最终怎么去评价一个信道建模是否好,就看当网络快速变化的时候,我们缓冲区能不能快速地排空,快速地跟着变,然后把最重要的信息传到对面去。
2、沉浸式
可能会有人问,我们研究得那么细致到底有什么用?
随着我们现在需求越来越丰富、越来越膨胀,很多沉浸式的场景,它对实时性的要求也非常高。如果没有前面那么细致的信道分级、信源分级的技术,经常就会产生一些很大的拥塞,比如我们的实时性经常有几十兆甚至上百兆这样的码率,如果我们不去做很好的拥塞控制的话,可能一下就会拥塞几十秒。
我们在沉浸式音视频方面,也做了一些探索。下面给大家介绍一下,一个是自由视角,它整体的挑战还是很多的,比如实时视角的差值。我们在流媒体方面遇到了更多、更难的技术,就是如何快速的频道切换 、快速的视角切换。简单的方式是可以用一个低清的流进行预加载,但是这样依然无法解决快速视角切换时,应该怎样去进行预加载?有人提出全 I 帧的方案,也有人提出低 GOP 的方案,但是它对清晰度的损伤是非常大的。我们实践下来相对靠谱一点的方案,是用 Simulcast 加长期参考帧的方式。视角切换时,只需传一个 I 帧加一个长期参考帧和少量几个 P 帧,就可以实现快速的频道切换。这样的话 GOP 可以做得比较大,也可以实现在实时性和清晰度上达到相对不错的平衡。
另外一个广泛使用的是全景视频,这个方案大家也都研究过。全景视频的核心理念就是信源分级。首先会有一个低清的 540p 的全景图来进行兜底,这个我们就不细讲了。在高清部分,怎样把一个 8K 的视频传到对面去?我们的做法是分片去编码,这样可以实现一次编码,很多个人同时超低延时地观看。我们可以用一个六面体的投影,分成 640×640 的分片,这样就可以用高端显卡进行并行编码,一块 8K 的显卡大约能编出来 60 帧,需要编 120 帧的话,可以用两块显卡并行地编。在这个 demo 上,如果我们的头动视角是往右上方移动的话,就可以很快地把右上方的几个新的分片挪下来,然后把左边几个分片排除掉,实现快速的头动延时。当然还有一些合并编码和合并解码的问题,比如 264、265 都是有相关的能力的,264 有 Slice,265 有 Tile。编码标准的定义是比较完善的,但在实践上还是有很多工程问题需要解决,对码流格式的要求也是比较高。最终这个方案可以实现上行能压到大约 100 兆,下行能做到 10 兆以内,并且在这种场景下我们依然可以达到 400 毫秒的延时,也可以做到 150 毫秒的头动延时。如果想要更快的话,还可以用边缘云和私有云的方式去加速。
再讲一下点云传输,就是体积视频。点云传输相比于全景传输是一个体验性更好、更终极的方案,但目前大家的通用做法还是伪 3D 的方式,就是用 2D 的背景加前面的 3D 对象,其实也是在 2D 的环境下进行了投影,最后叠加上去了,然后重新贴到一个二维平面上,用二维技术把投影和深度数据进行重新编码,复用二维视频的编码和传输通道。我希望未来几年大家能够有真正的 3D 压缩能力,把它做出来。
前面讲的都是视频,接下来介绍音频。一个比较常用的音频沉浸式的方式就是双声道的空间音效,它可以基本复用现有的音频编码和传输链路,只在渲染端做一些模拟处理,但是这样的效果肯定不是最好的,更好的方式就是我们正在关注的这个方式 —— 多声道的采集。用多个麦克风去采集,然后经过变换抽离出多个音源,把多个音源分别进行编码然后传输。这里也用到了高精度采样技术,我们也可以把 16bit 的采样数据提升到 24bit,然后采样频率一并提升。
不过这样就带来一个问题,它的码率会膨胀,音频码率有时也能到好几百 K 甚至好几兆,那这种情况下如何实现实时性的全景声?一个是我们刚刚提到 MDC 多描述编码,另一个就是在音乐中经常用到的高低频段,分段编码的 SBR 技术以及参数立体声的技术,也可以跟现在的音频编码传输结合起来,保证重要的数据能够传过去,来保证实时性。
3、跨地区
另一个重点关注的问题就是全球化了,全球化的问题分为几块,一个比较重要的就是音视频的基础设施的能力,然后就是全球化的数据一致性的问题。
全球的节点是非常多的,面对成千上万的节点,难免会遇到节点与链路坏掉的情况,每天有几十次上百次的链路劣化。公网的路由检测往往只能检测通和断两种情况,它并不能检测质量下降的情况,而且缺少对路径综合能力的判断,毕竟检测的时效性较差,检测切换的速度也比较慢,还有一个缺点就是 DSCP 在广域网上是失效的,所以我们的做法就是把 SDN 技术搬到广域网上,建一层 overlay 的网络。在传输面就完全使用 SDN 的传输能力,在控制面上我们又重写了控制层,可以让广域网上实现 SDN 的能力。
这样有几点好处:一个是 DSCP 可以兼容,如果我们去改 DSCP,它在这个传输网络上还是可以生效的,能够实现包级别的 QS 控制,而且能够实现秒级的检测和切换,最终我们大概就能实现在公网上电信级的可能性。所以音视频已经慢慢地成为了基础设施,我们开发者就不用太关注体验、成本、稳定性这些东西,可以把精力放在自己的产品开发上。
另外讲一下,分布式场景下的数据一致性的问题。因为我们的实际用户是遍布在全球各地的,用中心的房间控制器和中心的信令是不合适的。如果你有一个中心信令的话,地球另一端的用户加入房间和推拉流的首帧延时就会非常长,有时候能到将近一秒。所以我们这里就不能做强一致性的保证,至少这个房间与用户的关系,这个是不能够做强一致性保证的,只能是做最终一致性的保证。
在真正人数多,也不能做强一致性保证的时候,如何保证大规模的互动呢?
我们最大的挑战,就是来自于大房间的架构上的挑战,比如说这个大班课、网络研讨会还有多人的游戏对战,需要非常多的人上台互动,并且有很多的用户来观看,有几十万甚至好几十万的用户要同时观看,有几百上千的用户在台上互动。这种情况下,信令跟传输层都需要做特定的优化。首先信令要做分布式信令,要去中心化,一定不能做单一的信令,因为它扛不住这么多用户的冲击。这种时候信令就要尽量地下沉,分散到全球的多个数据中心里,甚至是下沉到离用户最近的地方,我们只需要把活跃用户的状态一步步更新到其他的信令,而不需要把所有的用户状态分布出去。这样的话,理论上才能够实现无限的扩展,最终就可以实现一个 RTT 的进房,一个 RTT 的推拉流。
另外就是整个传输拓扑图的分发问题。在全球化的时候,传输拓扑图是并行去进行计算和更新的。因为串行的计算速度比较慢,会面临很多问题。这个传输拓扑需要一个大致平衡的分发树,它整体的树的高度应该是比较统一的,这样才能实现比较低的延时。并行计算的时候还要应对海量的用户快速进房、快速出房的问题,所以还需要进行节点的动态分裂与合并。有时候做一些容灾的和紧急修复的时候,它的 QPS 也非常高,同时在这种情况下就很容易引发回环的问题,所以还要做回环的检测与解除,这里面的限制也很多。
4、开发者
讲完全球化,我最后再讲一下开发者生态。整体上,我们随着全球化的业务越来越多,开发者生态的建设,包括全球的开发者一起参与进来,也是我们需要去探索的问题。我们以前觉得的流媒体技术商业化,最大的成本来自于资源、带宽,现在我渐渐发现流媒体技术商业化,最大的成本来自于开发者的开发成本,这里的开发者不仅仅包括代码的开发者,也包括内容的创作者。创作者实在是太难了,他们要想做出一个优秀的应用,想做出一些酷炫的内容,是需要非常高的学习成本的,如果我们能想办法一起能给他们提供一些非常方便的工具、非常方便的能力,这就是很大的价值,也是火山引擎持续关注的方向。
我们关注的开发者的工具,就是平民化的创作工具。现在,很多创作者是被很专业、复杂、昂贵的创作工具所限制想象力。一个新的机会,一个平民化的创作工具,一个好的技术要想走进千家万户,它的创作工具一定是非常简单的。比如说,我们最早的时候修图都用 Photoshop,但是真正把修图带进千家万户的其实是美图秀秀。我们最早去做视频、剪辑用 Premiere 和 Final Cut,但是真正把视频制作带进千家万户的其实是剪映。抖音这么火,推荐系统是肯定很重要的,但源源不断的内容供给也是最重要的因素之一,源源不断内容供给靠的是平民化、简单化的创作工具。我们现在有很多新技术,比如特效技术、流媒体技术,还有动作捕捉、数字人以及实时自由视角,但是真的要使用起来难度很大。如果我们大家一起去做出很多能让自己用手机就能做出来的工具、就能使用的一些场景,我相信将给整个行业带来更多的想象力。
过去几年,开发者的工具变化也很大。最早我们有 SaaS,SaaS 的应用形态相对比较单一,所以大家都觉得不够灵活。过了几年,出现了 PaaS。PaaS 是灵活了,但对开发者的使用门槛也越来越高。于是又出来了新的 aPaaS。我觉得很难讲,哪一个是未来的趋势,但是有这么多可能性,我们给开发者提供更多的选择,总归是更好的。
最后提一下,我们最近在重点思考和关注的一个事情就是多模块之间的协同。所有的方案都会涉及到多个模块的协同,大家往往喜欢做一个大而全的一个 APP,把所有的功能都装进去,安装包一下子就 100 多兆,直播、点播、RTC、网页、消息、小程序全都在里面,很多时候他们是一起工作的。所有的模块包括这个 APP 是共用带宽、共用所有的采集和播放的设备,并且也共用 CPU、GPU 的内存。但是很多模块在设计时不会去考虑,其他的模块是怎么去使用资源、带宽的。希望我们以后在设计这些模块时要考虑一下,如何去共享资源,甚至是出让资源而不是抢占资源。大家在设计的时候应该去思考如何去共享、协同,把更多的选择权留给开发者。
火山引擎在这方面也做了一些探索:一是我们所有模块都支持动态的性能的降级、动态的带宽降级。不但支持我们自己的降级,还支持自定义的降级。比如用我们的 SDK 的时候,可以把我们的 SDK 限制在最高的一个带宽使用量上,例如:500K 上,这样 SDK 就不会使用更高的带宽,也可以支持把目前你所能探索到的带宽预留出来 100K 给别的模块用。无论现在探测出来多少带宽,就只用现在的已有的带宽减 100K,剩下的预留给其他的模块,这样能够实现更好的协同。同时火山引擎也可以支持让不同的 SDK 之间设置优先级,让这个 SDK 比其他 SDK 更重要,这在很多场景下是有用的。比如在直播做互动的时候,虽然直播很重要,音视频很重要,但是消息更重要,有时用户送的特效礼物可能是一个点播文件,但有些时候这些东西甚至会比直播和 RTC 更重要。在教育、会议的场景下,这种现象就更多,比如我们的音视频共享,可能就比音频信号更重要,这种时候就要求我们的每个模块都能具备自定义的升降级以及自定义的优先级的能力,同样除了对带宽,对性能也可以做这样的上限和预留的操作。这个目的就是把更多的选择权留给开发者。
基于以上的设计理念,火山引擎推出了音视频云端一体解决方案 veVOS,这个方案有很多的优点,欢迎大家去火山引擎的官网上去看。这里专注讲一下协同,因为我觉得其他的优点大家之前能够关注到,但是协同这一点也是希望所有人、所有业内伙伴未来一起去关注的点。要做云和端的协同,要做模块与模块之间的协同,甚至要做我们自己的模块和宿主的 APP 应用之间的协同,防止这些模块之间的资源冲突,我们光把它们打成同一个包,打成一个 SDK 直接给客户和开发者是远远不够的,要提供更多的能力,让不同的模块之间、不同公司的 SDK 之间和应用之间,防止资源冲突,做到更好的协同。
流媒体行业已经发展几十年了,大家对互动性、沉浸式、全球化还有开发者生态方面的要求越来越高,所以我觉得未来还是有很多机会的。
从抖音到火山引擎,我们持续关注的流媒体行业中的几个重要的机会:一是沉浸式的实时音视频,希望不久之后能有真正的沉浸式实时音视频的产生,并且能够真正地融入到我们的生活。我们在科幻片里看到的那些实时互动,那种沉浸式的场景,我相信很快就会变成现实;另一个是平民化的创作工具,能够带给我们丰富的内容。我觉得平民化的创作工具其实是这个行业持续的发展、持续产生新动力的动力源泉;最后一个是音视频的基础设施,它让我们能够帮开发者做好很多事情,让开发者聚焦到做更多的、更好的产品,能促进这个行业更快的进步。所以希望在座的各位一起去关注这些机会,通过技术的进步和工具的建设,给流媒体行业带来更加丰富的可能性。
谢谢大家,谢谢 LiveVideoStack,欢迎大家持续关注火山引擎!