一场突如其来的疫情,让数以亿计的白领只能居家办公,云视频会议系统突然成为最重要的办公软件。腾讯会议在2019年12月25日正式上线后,短短两个月时间内积累千万日活。除了时机,腾讯会议产品又为什么能脱颖而出呢?产品力是个不得不提的因素,腾讯多媒体实验室高级研究员王晓海在【腾讯技术开放日·云视频会议专场】中,对腾讯会议在复杂网络情况下如何保证高清音质进行了分享。
VoIP和PSTN的前世今生
PSTN(Public Switch Telephone Network公共交换电话网)从贝尔发明电话起就已经存在了,通过这张网连接全世界所有的电话机,发展到今天的PSTN骨干网基本上都已经数字化了,但是在一些集团电话或者偏远地区,PBX(Private Branch Exchange用户交换机)接入的可能还是一些模拟电信号接入的传统电话。PSTN可以通俗理解成传统电话和者蜂窝电话(Public Land Mobile Network公共路基移动网)的总和。
VoIP是基于IP(Internet Protocol)的语音传输,可以理解为经过互联网传输的通话,也有部分通过电信运营商的传统电话网络进行传输。VoIP网络通话是电脑或者移动终端之间的互通,比较典型的QQ或者微信,以及苹果设备之间的FaceTime。VoIP比较便宜,这是因为VoIP不过是一种互联网应用,那么这个流量用户来看视频,还是用来做语音视频通话,实际上资费是一样的。
那么为什么VoIP服务有些要收钱,有些却免费?这是因为VoIP服务不仅能够沟通VoIP用户,还可以和电话用户通话,比如使用传统固话PSTN,以及无线手机蜂窝网络(PLMN)2,3,4,5G的用户,对于这部分通话,VoIP服务商必须要给固话网络运营商以及无线通讯运营商支付通话费用,这部分的收回就会转到VoIP用户头上,而网络VoIP用户之间的通话可以是免费的。
有好多PSTN网络或者集团电话网络,它本身是有质量保证的。但是VoIP电话,一般是走公网的,它发出去或者接到的最后一公里电路是没有保障的,同时因为各种原因会丢包或者抖动,会让端到端通话质量受损。我们所关注的工作重点,就是图一右侧密密麻麻的这些内容,实际集中在QoS,也就是Quality of Service(服务质量),包含网络传输的一系列服务需求,比如带宽、延时、抖动、丢包等。
VoIP的发展进化史
Webex1995年诞生,是业界最早的一款VoIP产品。到了1999年GIPS诞生,它为业界提供了广泛的引擎,对整个VoIP影响巨大,在2003、2004年,GIPS向Skype和Webex,以及QQ提供了它的GIPS音频引擎,2011年GIPS被谷歌收购,该项目开始开源,即为大家所熟知的WebRtc开源项目。
2011年这个时间点很重要,因为WebRtc的开源,促使业界诸多音视频通讯领域的头部玩家开始躁动,同年Skype被微软收购,ZOOM创立,它的创始人就是Webex出来的。2011年腾讯也开始自研音频引擎,腾讯在国内召集了一批音频及通信领域的从业者开发了第一代引擎TRAE(Tencent Realtime Audio Engine),并且同年腾讯把自研的TRAE引擎上线换掉GIPS,TRAE音频引擎正式作为QQ音频引擎为几亿QQ用户服务。
2014年腾讯“新一代语音视频通信引擎Sharp系统”获得公司技术突破金奖,Skype在国际长途通话市场市占率达到40%,总通话量达到2000多亿分钟。2015年腾讯“音视频融合通讯项目”获得公司技术突破金奖,腾讯从2016年开始的向外界提供了OpenSDK能力,对内对外服务了众多音视频通话类的产品,其中2017年获得腾讯内部产品最高奖---名品堂的“全民K歌”也是使用OpenSDK的基础音视频处理及通讯能力,这种互联互通的能力为后来的发展奠定了坚实基础。
其实腾讯的音视频引擎又可以分为三个小代际。第一代就是QQ用的,2011年TRAE引擎,第二代是2016年开始向外界开放的OpenSDK引擎,到2017年腾讯开发了XCast引擎,这算作第三代,在最新的XCast引擎之上,诞生出今天的“腾讯会议”。
2019年12月25号腾讯会议上线,2020年3月6日腾讯会议已经登顶App Store免费软件NO.1,到今天不过两个多月,3月份日活达一千万,成绩还是比较难得的。ZOOM人数日活突破一千万是2014年6月份,当时的ZOOM是用了3年时间。
VoIP音频系统的主要构成
VoIP从发送端到接收端大概有哪些模块呢?我今天着重讲网络的流量控制、拥塞控制,包括丢包、抗网络抖动的一些逻辑,以及他们怎么样融合才能更好提升服务质量。核心是QoS的概念。
QoS(Quality of Services)概念当时在IETF(The Internet Engineering Task Force国际互联网工程任务组)提出的时候,只专注于纯网络范畴的指标,比如丢包、延迟、抖动、带宽等。进入新世纪以后,行业对VoIP或者融合通信的理解有变化,进入宽带时代以后对指标会有更高期许和更高要求,比如说音频采集,本来采集信源不好,再经过压缩、传输、解码,可能最终效果不好。如果从QoE(Quality of Experience)环节来看,端到端不限于采集模拟接口出来的声音,甚至包括人的讲话环境和听音环境影响,用户感受到的音频质量,是整个体系反馈出来的诊断。
QoS没有太多秘密,无非就是抗丢包,抗抖动,网络拥塞控制等等,ARC(Adaptive Rate Control)可以看做一个中央指挥官,它只能去指挥整合这些方式、手段,最终保证音频质量是良好的改动。所以说到这块,QoS一般套路就类似于一个全家桶,无非这六种模块的合理有机组合,接下来会对这几块深入讲一下。
腾讯会议是如何保证服务质量的?
1、腾讯会议的“流控”:ARC
先看ARC,ARC在腾讯会议的概念就是“流控”,流控能干什么?
是三个大的层面,首先它是一个配置系统,无论双人或多人通话,系统所需要的基础配置参数,还有在什么场景下需要什么样的参数。通过这个云端的参数配置及开关配置,系统拥有了基本的云端可控手段。
然后动态控制是中间的这块,流控是把源端到目标端的传输行为,发出来数据想让对方解码,会存在动态的能力交换的要求。此外,系统如果发生了抖动,或者丢包的情况,我们会动态的去控制相应的模块去处理这些情况。所以能力交换,或者动态下发的能力,实际上是动态控制的第二层次水平。
最高层的能力,是聪明灵活自适应的能力,就是对ARC的指挥能力的更进一步的要求,丢包的时候怎样去抗丢包,抖动的时候怎么样去抗抖动,去动态控制,但是这些抗丢包、抗抖动的方法有可能会占用过多的网络带宽、或者以牺牲端到端延时为代价的、于是当网络发现了比如带宽不足,或者网络用户本身终端连接路由器质量有问题,甚至出现网络趋于拥塞的情况,这种情况怎么去把它及时挽救回来,这个配置是对ARC更高层次的要求,涉及到网络拥塞控制(Congestion Control)这个核心命题上来了。
2、“流控”在腾讯内部的演进过程
一开始是都写死的参数,比如解码器参数、音频前处理3A开关等、抗丢包和抗抖动参数也基本是固定的,效果肯定不好。后来我们在系统增加了流控策略,根据客户端动态上报,动态去算QoS的参数下发。进化到多人通话以后,特别带宽预测是比较大的挑战,比如上行应该怎么算,下行是接收多交流又该怎么算,因为发送行为不一样,原来那种用一个算法对不同流进行预测,肯定不能用。
后来,我们还做了服务器混音。首先可以减少下行用户的流量,其次多路混音成一路,也可以对融合通信发挥基础作用。在对外提供OpenSDK的时代,因为对外用户的需求很不一样,因为应用场景的差别,有的用户需要不通类型Codec,有的用户需要关掉3A处理,有的用户不需要那么大流量,有的用户更加在乎质量而不在乎流量,所以云端的Spear可配置参数的流控策略可以满足我们企业内部应用,包括外部用户的差异化需求。
腾讯会议对于拥塞控制的做法
接下来我们看比较核心的拥塞控制(Congestion Control)。其实拥塞控制在实时RTC(Real Time Communication)音视频通讯领域应用中是必不可少的模块,WebRtc在开源以后分别向社区贡献了GCC1和GCC2版本,当然这块不是说Linux系统下编译器的那个GCC。
GCC1(Google Congestion Control ver.1)是一个基于接收端的算法,根据每家系统的软件架构的不同,它部署的位置也不一样。GCC1核心算法是通过实时监控端到端延时的变化量(Jitter),从而判断当前这个网络是否趋于达到网络拥塞的情况。
我们首先看端到端延时这个基础概念,端到端延时由三部分组成:一个是传输延时,跟数据包大小及链路宽有关;第二个是队列延时,即数据包在路由器的队列中通过的时长;第三个传播延时,一般传播延时跟传输介质有关。
实际上在GCC1或者GCC2里面,它真正进入系统、进入计算的这个变量不是端到端延时,而是其变化量即Jitter;Jitter=(TR(i)- TR(i-1))- (TS(i)- TS(i-1))包括前后两个数据包的接收时间戳之差再减去前后两个包发送时间戳之差,算法输入的是一个Jitter,GCC1通过Kalman自适应滤波器去除噪点,通过网络传输也好,通过整个链路传输过程也好,实际上这种延时的变化值Jitter是一种符合高斯分布的特征,当我们把噪点去掉以后就可以得出它的Jitter趋势。GCC1算法将滤波后的Jitter值与动态阈值进行相应的状态判断,从而得出当前的网络是否趋于拥塞或者处于正常,与此同时还通过实时接收到的流量和预测算法给出当前一个合理的带宽预测值。
后来GCC2又更新了,是基于发端的,它的数据处理源还是Jitter,就刚才说那个Jitter,它是一个什么概念呢?自变量就是Jitter,应变量是什么呢?应变量是它的历史平均值。所以它对自变量和应变量做了一个最小二乘法的一元线性回归,相当于去观察当前的Jitter值相比较历史平均值有怎样的发展趋势,被称作TrendLine算法。GCC算法它在发送端也好还是在接收端也好,带来了工作上的灵活性,而GCC1中绝对值的阈值比较变成了GCC2中趋势线的判断,算法的准确性上有提高。而从及时性上来说,我们在QQ时代使用GCC1算法是,SDK的架构还是有私有协议的,比如说反馈机制都是基于两秒的机制,在最新重构的第三代xCast SDK上上,完全兼容了标准协议,RTP算法核心有准确度的提升,反馈上RTCP时机和及时性也有提升,所以“腾讯会议”相关的算法控制会远远老一代的SDK产品更加及时和准确。
FEC如何把丢失的数据包恢复?
FEC(Forward Error Correction)实际上没有太多新意,这块无非就是利用其基本的特性。比如分组划分,接收端恢复不受数据包顺序影响等特征。举个例子:如果是分组是4,那么在网络传输过程中任意丢掉一个,在接收端任意收到任何顺序的4个属于本分组的数据包,那就可以把丢失的包恢复。
那么它到底是怎么工作的呢?FEC目前一般采用了Reed Solomon算法,Reed Solomon算法的核心思想包含三个部分:
1. 利用范德蒙德(Vandermonde)矩阵F,通过FEC控制参数生成冗余矩阵。冗余矩阵的上半部分是一个单位矩阵,分组数据矩阵和这部分计算完以后还是原来的数据,接下来这部分数据则是实际用来产生冗余数据的矩阵。图示相当于4+2的原始数据生成2个冗余数据,ENCODING就是这样范德蒙德矩阵与原始数据相乘,分组的原始数据相当于数据源,根据FEC编码参数额外生成的数据包就是冗余数据。
2. 利用高斯消元法(Gaussian elimination)恢复损坏的数据,即算冗余矩阵的逆矩阵。使用逆矩阵与接收端凑齐分组的数据矩阵进行行列式乘法计算,从而恢复丢失的数据包。
3.