实时音视频通话作为高效便捷的沟通手段在许多场景下得到应用。随着5G商用元年的真正到来,实时音视频通话将会得到更加蓬勃的发展。本次LiveVideoStackCon 2020线上峰会我们邀请到了网易云信资深音视频服务端开发工程师鲁林俊,他将结合网易云信流媒体服务搭建的实战经验,进行一些深入的分享。
文 / 鲁林俊
整理 / LiveVideoStack
大家好,我叫鲁林俊,很高兴参加LiveVideoStackCon 2020线上峰会,本次我分享的主题是网易云信流媒体服务端架构设计与实现。
本次内容主要分为三个部分:一是实时音视频为基础的流媒体服务端设计;二是录制服务方案设计;三是视频会议传输质量控制。
1.1 分发架构
在设计以实时音视频为基础的流媒体服务器之前需要解决的一个问题是:转发方案的选取。讨论比较多的方案有三种:
一是Mesh方案,即通话各端两两进行媒体通道的建立,并交换数据,实现媒体通话。从服务器角度看,这种方案比较简单,服务器只要实现一些信令和打洞相关的能力等就可以实现通话,但这种方案的缺陷是通话能否成功建立依赖于打洞的成功率。
二是SFU弹性转发方案,下行转发的单位是每个用户的单个流。
三是MCU方案,媒体服务器会进行媒体处理,将混合好的音频和视频进行重新编码并转发给下行用户。
网易云信搭建音视频服务器时选取的是一个混合转发方案,它是基于SFU为主的媒体转发方案,辅助MCU进行特定场景转发。特定场景比如用户为观众端,可以以一条MCU的流转播给观众端。
这种方案的优势在于:一是基于SFU的设计,服务器逻辑轻、性能好。二是SFU弹性转发设计,可以配合发布订阅的逻辑,做到可选的下行转发。三是可以配合MCU,做到下行宽带的节省以及跨通话系统间的互通简化。
1.2 传输通道和协议
协议通道的设计中有两个协议通道:非可靠的UDP通道和可靠的KCP通道。
非可靠的UDP通道主要用于传输媒体,可靠的KCP通道主要用于登入、登出、网络状态同步、传输控制等。
1.3 小程序网关和WebRTC网关
除此之外,传输层是基于我们自己的私有协议。
做PaaS服务仅仅覆盖三端是不够的,要尽可能覆盖更多的平台,比如基于web的开发、基于小程序的开发。由于基于私有协议比较困难,我们搭建了WebRTC网关和小程序网关。
WebRTC网关基于WebRTC标准的实现,接收RTP/RTCP的流,进行协议的转封装,并推送到中转分发服务器的骨干节点上面,最终推送到私有用户上,这就实现了私有端和web端的互通,小程序的网关同理。这两个网关的搭建足够满足纯粹的实时音视频场景,但要做纯粹的实时音视频,PaaS服务是无法满足用户的需求的。
1.4 流媒体处理辅助系统
当一个拥有几十万粉丝的用户进行一个简单的聊天时,想要获得聊天内容又想将聊天内容直播给粉丝看,此外,也想和粉丝聊天并将聊天内容给其他粉丝看。这就是在基于纯粹的实时音视频的基础上去获得录制、直播、互动直播的功能。
为了满足用户的场景需求,在基于实时音视频为主要核心系统的基础上,搭建了两个辅助的媒体处理系统:直播系统和录制点播系统。
图中左边展示的是实时通话系统,实时通话内容把媒体数据推给互动直播服务器进行媒体数据协议封装,封装成私有协议或者RTMP协议,并推送到CDN和我们自建的直播源站,这样用户就可以基于标准协议从CDN或者直播源站上进行拉流,这也正是图中右侧所展示的直播系统。
直播系统中还有一个单项的直播功能,主播支持RTMP协议或者私有协议并推送到直播源站,用户从直播源站拉流观看即可。另外,录制功能同样是将媒体内容推送到录制服务器,录制服务器进行相应的录制后上传到NOS存储上,最后到达点播源站,用户通过CDN回源到点播源站,并进行录制内容的点播。以上就是在实现纯粹的实时音视频通话基础上,我们相应扩展了其他媒体处理能力,使用户使用场景最大化。
1.5 中心控制系统
因为会面临会话如何发起、节点如何就近接入、通话过程中如何对通话进行管理等问题,所以我们搭建了三个中心控制服务器。
第一个是会议接入控制中心,它的主要职能是提供IM通道,用户基于IM消息通知服务器发起通话。
第二个是会话调度中心,它的职能是为用户创建房间、加入房间调度一个最佳节点。
第三个是房间管理中心,它负责整个房间信息生命周期的管理,并提供RESTful Api,为用户提供房间管理,比如查询目前通话的房间内容等,都可以通过房间管理中心进行相应的处理。
举个例子,当用户发起一通通话,用户A可以基于IM消息发一个创建会议的消息,会议接入控制中心会将此消息推送给用户B。同时会议接入控制中心,从房间管理中心、会议调度中心获取相应的信息后,通过IM通道将结果反馈给用户A,用户A再将这些信息反馈给用户B。用户A或者用户B获取信息后推送给中转分发服务器集群,实现整个会议接入点流程。
以上的内容主要介绍了网易云信如何基于用户的需求打造音视频的PaaS服务。
以下部分我将介绍了录制服务的搭建,很多人认为云端录制比较容易,但是由于2B业务的用户场景的多样化,使得录制服务会面临很多挑战。
首先是录制服务方案如何选取。如果采用实时录制,全量通话进行MCU处理,性能无法满足。
如果采用离线处理,会遇到一些用户需求问题,比如用户要马上看到文件,但录制还未开始。
另外,有些用户想要有录制的功能,但是媒体数据他们自己加密了,我们的服务器没法进行解密,所以也无法进行录制。以上都是一些客观存在的问题,为了应对各种用户场景,我们设计了一套融合录制方案。
2.1 融合录制方案
这张图向大家展示了融合录制方案的内容。对于即时点播需求很高的用户,我们提供了实时MCU服务器,实时通话时会把通话内容转给MCU服务器进行数据的混合编码,以H264单帧的方式投递到MP4/FLV协议封装服务器上,并将封装后的MP4/FLV数据上传到云存储,这样用户就可以进行相应的点播。
另外,对于录制功能有要求但对即时点播要求不高的客户,需要选择离线处理的方案,网络码流Dump服务器实时地将需要录制的会话Dump下来,并转成私有Dump文件,离线MCU处理器将私有Dump文件进行调度处理,最终上传到MP4/FLV协议封装服务器上,用户就可以进行相应的点播操作。以上就是实时录制方案和离线录制方案。
针对于用户想要将媒体数据加密并且保留录制功能的需求,我们开发了录制SDK。用户可以基于录制SDK开发用户自建录制服务器,这套录制方案可以解决大多数用户的录制场景。
2.2 离线录制实现
这部分细致介绍一下离线录制方案,用户基于RESTful Api向房间管理中心发送录制请求,房间管理中心基于调度中心就近调度到一个实时网络码流Dump服务器,同时将录制请求和录制参数(用户录制如何布局、是否进行音频能量的选取等)下发到选中的网络码流Dump服务器。网络码流Dump服务器收到请求通知后会和中转分发服务器建立拉流链路并获取媒体数据,之后进行私有协议文件的封装,这相当于进行一个离线处理,将实时数据封装到离线文件里,然后经过离线MCU服务器进行离线文件处理并录制,再将录制好的码流投递到文件封装上传服务再到存储点播服务器,这样从录制的发起到上传、存储的离线录制就完成了。
其中私有协议文件格式设计非常重要,离线处理要处理好音频和视频的同步以及画面中所有人的音频和视频的同步,就需要建立一个合适的同步机制以适配私有协议文件。
2.3 实时音视频录制与白板录制同步回放机制
教育场景下,如何进行实时音视频录制和白板录制同步回放?
由于白板通讯基于TCP,实时音视频基于UDP,两者相互独立。用户基于白板SDK进行白板数据的传输,基于音视频SDK进行音视频通话,这就要解决如何进行跨系统之间的录制文件的同步回放问题。
首先,白板服务器集群和音视频服务器集群要基于NTP同步服务器进行时间同步操作,即做到离散服务器之间的系统时间一致。
其次,需要制定一个合理的同步方案,即在白板录制文件和MP4文件里增加同步字段(NTP时间)。每一个白板数据和视频帧都增加NTP时间,也就是基于NTP时间进行相应的同步。但要解决NTP存放的问题,对于白板录制而言,因为白板录制文件是私有录制文件,只需要在TAG-HEADER字段里每个隔一个字段存放NTP这个时间的字段即可。
对于实时音视频录制而言,MP4或者FLV要基于H246一帧插入一个NAL-SEI,NAL-SEI的payload type要设置为5,在用户自定义数据里同样插入一个NTP字段。MP4播放时间是基于MP4player的,无法控制其播放进度,所以整体的同步方案是基于白板播放时,实时的用位于同步时间轴上下的两个NTP进行校准,进行白板的加速播放或者慢播放,这样就可以做到音视频录制文件和白板录制文件同步回放的效果。
对于视频会议传输质量控制要从三个模块分析:一是第一公里接入;二是多流发布订阅机制;三是传输层上下行QoS策略。
3.1 第一公里接入
第一公里接入主要采取两种方法:一是边缘加速代理和传输层路由策略结合。二是进行网络探测和智能选路。
3.1.1 边缘加速代理和传输层路由策略结合
第一公里接入模块的具体操作是,首先在基于现有的中转分发服务器集群覆盖的场景下,无法做到覆盖所有的地域、运营商,一些偏远地域或者运营商还是依赖于其他的云服务器厂商,并利用他们的节点进行就近接入。
就近接入就是在云厂商的云主机上部署我们的代理服务器,代理服务器监管传输层的数据和PaaS传输层的协议,并获取下一跳地址,也就是用户就近把数据发送到第一跳加速节点上,加速节点进程接管传输层,由传输层的头部获取下一跳地址,再把数据抛给下一跳加速节点上,然后推送到中转分发服务器集群,并最终推送到实际的接收端。
3.1.2 网络探测和智能选路
网络探测和智能选路方法的具体操作是:当用户发起接入时,会调度给它一组就近接入的节点。节点的选取是在会话开始前和开始过程中都进行网络探测,并按一定频率的机制去发送探测数据包。当节点接收探测数据包时会进行接收信息反馈,基于这些信息反馈将这次探测结果的丢包率、RTT、jitter、BW指标计算出来,基于这些指标进行评分,最终从调度基础的就近接入节点选取最佳的接入节点。
3.2 多流发布订阅机制
多流发布订阅机制可以解决两个问题:一是用户可以根据自己的意愿或者能力进行下行接收;二是媒体处理服务器在进行下行QoS控制时会基于探测到的网络真实的带宽,帮助用户智能的选取可以接受的码流。所以基于发布订阅机制可以做到两件事情:一是满足用户需求;二是做好传输质量。
具体实现是在媒体服务器上有两个模块:一是媒体处理模块,二是Pub/Sub管理器。用户发布流时会基于可靠信道,发布一条想要Pub流的信令给发布订阅管理器,发布订阅管理器会将所有用户的Pub列表广播到所有接收端,由所有的接收端根据需要通知发布订阅管理器订阅哪一条流,然后发布订阅管理器会将所有消息同步到媒体线程并进行下行转发的管理,这样就实现了发布订阅功能。
发布订阅机制发布的内容是:以stream为发布单位,以编码能力为基本内容。其中编码能力包括:codec、分辨率、帧率、码率。
订阅分为两个部分:客户端订阅和服务器订阅。客户端订阅以stream为订阅单位,并携带订阅优先级,也就是流在下行接收中的重要性会反馈在订阅优先级上。另外,当所有的客户发布订阅消息后是交由服务器订阅,它汇聚所有端的订阅消息,向发布源端发送订阅消息,同时将订阅码率反馈给源端。
右图显示的是多流的发布机制是弹性码率大小流机制,上行发布的大小流并不是固定的分辨率,而是一个可伸展的码率空间,小流的码率范围和大流的码率范围都是很大的,这样的设计是以弹性的码率针对上行的带宽,并动态的调整码率,以进行最佳的上行发布,针对下行所有的接收端来调整码率,做到最大程度提高用户体验。
3.3 传输层上下行QoS策略
3.3.1 传输层上行QoS策略
对于上行QoS服务器策略主要设计了四种:一是FEC/RED;二是NACK重传请求;三是PLI/FIR;四是接受信息反馈。
在这里我区分了FEC/RED,因为使用RED是为了增强音频的保障性。对于视频,使用矩阵运算的方式生成额外的冗余包去对抗丢包。NACK重传请求是服务器作为接收端在上行传授过程中,如果数据有丢失的话会主动作为接收端发送重传请求进行对抗丢包。
PLI/FIR主要是首帧问题,在偏大量的丢包场景下,也会进行关键帧请求去替代NACK请求。
接受信息反馈是记录上行接受信息,并反馈给源端,源端基于接收信息计算带宽、网络指标等进行一个上行的把控。
FEC/RED和NACK重传请求这两种设计都是比较普通的对抗丢包的手段。
FEC/RED机制是基于预测丢包,提前产生冗余,对抗丢包。它的优势是低时延;劣势是抗丢包效果依赖于丢包预测准确性。NACK/RTX机制是如果丢包已经发生,则基于测量的RTT做重传请求的控制。它的优势是不用预测,低时延恢复率高,产生额外流量小;劣势是产生时延,高时延场景恢复效果差,设计不好容易产生NACK风暴。
针对前两个设计对抗丢包的特点,网易云信分三个步骤来进行传输质量控制:一是建立网络状态的观测器,评估网络相关指标。二是ARQ手段先行,FEC手段做兜底,也就是尽量利用ARQ对抗丢包,再利用FEC兜底,这样可以减少带宽的浪费,做到较好的抗丢包效果,图中的式子是FEC需要做兜底的丢包率。三是基于接受端反馈以及模块自检的策略调整,这一模块会统计NACK成功率、NACK响应时长和FEC恢复率。
具体做法是:ARQ和FEC并不是割裂的两个模块,它们的统筹由抗丢包综合控制器进行管控,抗丢包综合控制器最核心的地方是FEC兜底的丢包率的计算公式,它的计算来源于网络观测器基于对它的观测,计算出来的网络的指标,去生成公式。而且基于服务器端FEC模块数据统计反馈、服务器端ARQ请求响应模块数据统计反馈和拥塞控制模块数据反馈统筹的告知抗丢包综合控制器。
此外,ARQ模块和FEC模块产生的,流量也会统筹的告知抗丢包综合控制器,最终由抗丢包综合控制器进行公式的参数调整,最终做到在不影响网络质量的场景下做到最大的丢包场景。
3.3.2 传输层下行QoS策略
下行QoS服务器策略在复用了上行QoS服务器策略的基础上增加了一些其他的QoS手段,主要有四个模块:一是设计出下行接收端可弹性接收流组合的方案;二是准确的探测出用户真实的下行宽带;三是制定合理的宽带分配方案;四是进行流量的平滑发送以及拥塞控制。
这张图展示了四个模块相互作用的关系。用户在上行发布了两天流,要做到下行的最佳体验,实际接收到的流要匹配用户的真实带宽。如果上行发布的都是大流,而用户的带宽不足,无法支撑所有大流的支撑,可能就会将某些大流切成小流。
智能订阅
总体就是首先是发布订阅管理模块,基于多流的发布订阅管理,进行下行的一个可智能选取的方案。其次是带宽分配模块,探测出用户真实的带宽之后告知带宽分配器,再结合用户实际订阅以及上行流的码率等数据后,帮助用户选取最佳的接受组合。最后是总体把控拥塞控制模块,它的工作是进行下行流量的平滑,另外,它基于其他的设计能够避免让网络产生拥塞,最终让下行产生最佳的效果。
下行带宽探测
接下来我将介绍以上四个模块是如何具体操作的。第一个模块是发布订阅模块。第二个模块是带宽探测模块,它是基于google的BBR音视频场景下的优化,主要有六点:一是probe_RTT阶段的隐藏弱化;二是上行网络丢包带宽补偿;三是上行网络RTT突变以及高jitter场景优化;四是下行链路抖动自己丢包的优化;五是padding流量的优化;六是快速上探机制的实现。右图展示了我们优化后的BBR在弱网下的探测效果,基本做了探测准确度为95%以上。
带宽分配策略
探测出带宽后如何结合地域关系、上行的实际码率做下行带宽的分配。假如下行用户实际带宽有2M,订阅了A、B、C的大流,A、B、C的大流的最大码率和最小码率分别是2M、800k,1M、700k,1.6M、1M。那么下行用户实际带宽2M是不可以接收所有的大流的。
针对以上问题,带宽的分配策略为:首先基于现有大小流进行选择性接收;其次综合所有下行接收端的带宽以及预分配结果,反馈到发送端,进行上行流的码率的压制。
拥塞控制
拥塞控制模块主要有四个模块:一是平滑发送;二是基于流级别的优先级策略以及可选择性发送策略;三是拥塞避免;四是拥塞缓解。
基于流级别的优先级策略以及可选择性发送策略中优先级是在实际发送包后制定的包的优先级:重传包>音频包>视频包>被切掉的流>padding包。
可选性发送策略是在实际转发中基于上行流SVC的码流,我们制定了SVC时域分层选取:在实际下行转发时会实时评估各个层总体的码流,在实际分发过程中会基于当前近程发送队列的拥塞程度去实时选取应该分发的层。
拥塞缓解的具体工作为:首先下调SVC分层选取,如果拥塞严重就切小流,然后基于包级别的优先级发送。其次是如果实际网络发生拥塞,需要改造BBR的发送周期,即减少1.0倍发送周期。另外,如果数据超发,源端的码率波动比较大,需要代替网络主动丢包。
下图是具体的丢包策略:绿色条柱是应用程序发送队列的堆积情况,基于堆积的安全阈值和堆积的Trendline这两个去判断当前是否需要主动丢包。
上图是拥塞控制总图,首先是拥塞避免从BBR获取匹配的发送数据,当避免不了的时候就需要进行流优先级控制以及SVC分层选取控制,并进行拥塞缓解,最后数据真实发送给用户时要进行平滑发送。