背景
RTC(Real time communication)实时通信,是实时音视频的一个简称,我们常说的RTC技术一般指的是WebRTC技术。
WebRTC是一个由Google发起的实时通讯解决方案,其中包含视频音频采集,编解码,数据传输,音视频展示等功能,我们可以通过技术快速地构建出一个音视频通讯应用,在不借助中间媒介的情况下,建立点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。虽然其名为WebRTC,但不光支持Web,还可以通过编译C++代码达到全平台的互通。
在B站的直播业务中,有多个互动类型的业务,比如:视频连线、PK、语聊房、语音连麦等。这类业务都有实时性的要求,底层都采用了WebRTC技术。
质量保障规划
RTC相关业务的用户在使用过程中对质量的要求很高,任何卡顿、延迟、音画不同步、无声、杂音等问题,都很容易导致主播和观众体验差,影响直播连麦质量。为此,我们测试团队通过专项测试的方式提供RTC的质量保障。
在整个WebRTC接入和直播互动的业务实现过程中,涉及了多个服务端和客户端的不同模块,各模块可能涉及多个研发团队的协作,如下图。
区别于业务团队针对于业务功能的保障,专项测试团队主要致力于客户端的webRTC SDK,以及服务端的信令和媒体服务的质量保障。
测试对象
客户端SDK
客户端的sdk主要包括:
音视频处理模块:包括音频采集、编码、解码、播放和视频采集、编码、解码、渲染等功能
网络传输模块:包括数据封装、传输和解封装等功能,主要负责将音视频数据传输到远端
信令传输模块:包括建立连接、发送和接收信令等功能,主要负责协调和管理音视频传输
RTC服务端
服务端主要包括信令服务器、媒体服务器
信令服务器:主要负责协调和管理音视频传输,包括建立连接、发送和接收信令等功能,另外也充当了业务服务和媒体服务交互的桥梁。
媒体服务器:主要负责音视频数据的转发、混合、分发等功能。当媒体服务器充当媒体中继时,它通常被称为SFU(Selective Forwarding Unit选择性转发单位),主要目的是在客户端之间转发媒体流。
此外,实际的部署中,SFU不是单一的中心服务,而是采用了CDN边缘服务器,提升用户客户端推拉流质量。
测试设计
功能测试
功能测试一方面需要验证各个功能业务正常,另一方面梳理切合webRTC的测试用例和验证点。为此,我们设计了两种测试视角,从两个视角来指导我们的测试用例设计和测试执行。
两种视角分别对应了模块测试阶段和回归测试阶段。模块测试阶段,从能力模块视角切入测试,解耦业务模块,重点验证基于webRTC实现的各个模块能力,同时验证性能、弱网对抗等能力没有裂化;回归测试阶段,又从业务模块视角切入测试,回归webRTC实现的全部业务功能,验证本次webRTC SDK的迭代版本兼容了线上的全部功能。
媒体处理模块测试
包括音频采集、编码、解码、播放和视频采集、编码、解码、渲染等功能。采集环节往往需要访问设备硬件(相机、麦克风等)、处理环节需要调用系统的编解码、播放环节需要调用系统的渲染模块或者自研的渲染引擎等,在采集完成后还会增加一些像美声、美颜的预处理。
由于系统和厂商的迭代更新,部分SDK的API和功能在一些客户端会有差异甚至无法使用。兼容性是媒体处理模块测试的重点。系统类型(Android、 iOS、Windows)、厂商、系统版本等,测试机型分类多多益善。特别是一些底层API的调用和SDK版本升级,在一些较新和较旧的手机系统都容易出现问题。
信令模块测试
信令传输模块:包括建立连接、发送和接收信令等功能,主要负责协调和管理音视频传输。这部分一方面需要和功能测试深度结合,比如需要验证发起连麦、关闭连麦、连麦过程静音和取消静音、踢人、主动退出、再次PK等;另一方面也需要通过日志观察各个过程中的信令交互时序是否符合预期,信令的漏发、多发、乱序,都可能直接对应必现或者偶现的bug。
网络传输模块测试
一个直播连线的过程中,涉及多种网络协议,底层的TCP/IP、UDP,webRTC建立连接用到的ICE/STUN/TURN,流媒体的传输的RTMP/RTSP/RTP,业务或者信令层的HTTP/HTTPS、webSocket等。以上只是可能涉及的协议,具体需求和实现方式还会出现各种不同的定制。因此,相比于业务测试只需要简单的弱网,RTC的测试过程中需要更精细的网络模拟手段以及网络问题排查能力。
RTC需要的弱网测试
传统的app弱网测试(参考文档[3]),弱网测试主要就是对带宽、丢包、延时等进行模拟弱网环境。相比于业务接口,弱网对RTC的质量和用户体验有更直接的影响。
延时:延时是网络中的一项重要指标,可衡量数据从一个端点移动到另一个端点所需的时间。延时主要会影响用户体验。在严格的音频通话中,150毫秒的延时是非常明显的并且会影响用户。在严格的视频通话中,认为400毫秒是可辨识的。简单来说,在视频连麦业务中,远端收到自己传输过去的音视频数据所用的时间越短越好,一般认为超出400ms就会在连麦时明显感受到延迟。播放延时是数据包到达时和播放时间之间的延时。一个高延时的网络会极大的降低网络的效率,因为RTT(往返时延)可能会远远的超过接收端可等待的时间范围。为了确保音画同步,接收端只能最多等待音频缓冲区那么长的时间。音频通常不会被这种情况影响,因为音频并不依赖于关键帧。
丢包:指在一段时间内数据包在数据流中被丢弃或者丢失的数量或者百分比。大多数的媒体流都会或多或少地丢弃一些数据包,尤其是在WiFi网络的环境下。在一个实时媒体流中,宁愿让连接的设备主动丢弃掉一些数据/帧,也不愿意产生延时。如果丢包率很高而且恢复机制无法弥补的话,视频就会卡住,帧速率会下降,声音会因为经常断续而变得难以辨识。如果与高延迟网络相结合,丢包就会造成最严重的影响,会影响到基于NACK的重传机制的效率。
带宽:是指数据可以在两个端点之间传输的速率。你可以将你和远端之间的网络看成一个管道,而带宽就是这个管道最小的尺寸。你的网速可以特别的快,但是如果对方只有几KB/s的网速,你的网速再快也没有用。如果一个不受控制的发送端所发送数据的速率超过了接收端的可用带宽,那么它就会迅速压垮整个网络,导致数据流质量产生严重的恶化。一个过载的连接会出现以下几种问题:视频停止、视频帧速率降低、断断续续的音频、连接性能下降等。
抖动:抖动是一项用来描述网络流中时间稳定性的参数。换句话说,数据包实际到达的时间与应该到达的时间之间的间隔是多大。因为UDP并不能保证传输的有序性,抖动会发生在每个连接中。每次网络路径上的传递都可能会发生抖动,所以高延时网络或者跳跃次数多的网络更有可能出现高抖动值的问题。因为媒体解码器/播放模块必须按顺序处理数据包,所以如果在收到数据包之后立即就进行处理的话就会出现问题。一旦一个数据包被解码器进行处理时,任何“之前的”数据包就必须被丢弃掉。这很容易造成丢掉可以增加音频质量或者进行重传视频的重要数据。
网络测试方法
除了以上公有的弱网测试,RTC测试过程中,需要一些更自定义化网络规则,比如针对特定的ip、ip集进行网络配置,也可以只针对TCP或者UDP协议进行设置,又比如在特定时间内出现网络异常情况(比如连麦1分钟后,网络断了5秒后恢复)。
这些测试环境,最好的建立方法是使用专业版本的网损仪,搭建一套无线路由器AP方案,从操作系统的角度控制网络流转,以API的方式对外暴露,客户端可以连接AP的网络后再通过API调整网络环境,达到网络模拟的能力。
也可以通过网络模拟工具来模拟,比如iOS系统在开发者模式下也支持系统级网络模拟。而Mac/Linux系统本身拥有强大的网络设置能力,通过对这些能力的配置使用,可以帮助我们实现想好的网络。
在Mac OS X系统中,你可以使用pfctl和dnctl命令来设置UDP和TCP的丢包率创建一个名为pf.conf的文件dummynet in proto udp all pipe 1dummynet out proto udp all pipe 1dummynet in proto tcp all pipe 2dummynet out proto tcp all pipe 2创建一个名为pipe.sh的脚本#!/bin/shdnctl pipe 1 config plr 0.2dnctl pipe 2 config plr 0.1运行以下命令来启动pfctlsudo pfctl -f pf.conf运行pipe.sh脚本来设置网络条件sh pipe.sh以上的设置将设置UDP的丢包率为20%,TCP的丢包率为10%。可以根据需要调整这些参数。
Windows端我们主要采用clumsy这款工具来进行网络模拟,它支持Lag、Drop、Throttle、Duplicate、Out of order、Tamper、Set TCP RST、Bandwidth这些功能,除了可以对正常网络进行设置外,还支持自定义网络规则,比如针对特定的ip、ip集,也可以只针对TCP或者UDP进行设置,比如通过设置Filtering为tcp.DstPort == 端口 or tcp.SrcPort == 端口,然后设置Lag的Drop都为100%,就是系统只能访问UDP网络。
在测试移动端的时候,我们会用随身Wi-Fi等工具让移动端也可以连接这个网络,做到一端控制多端的网络模拟。
客户端性能
建连后的视频渲染,退出连麦后的UI关闭,都是比较容易出现内存泄漏的场景,此外音视频采集、传输、渲染本身在实现代码中都可能有性能问题,最终用户会感受到卡顿、发烫甚至APP崩溃等体验很差的问题,所以利用perfdog等客户端性能测试工具进行测试也是必要的,重点关注CPU、内存、GPU、渲染帧率、温度、功耗等指标。
下表是一次典型的性能问题,某次迭代中,因为改动到了帧率参数,导致PK过程中的GPU使用率过高,从历史版本的23.1%,上升到了45.5%。
测试版本GPU使用率
对比版本GPU使用率
服务端性能
在WebRTC中,用户之间的实时通信可以通过一个名为"房间(room)"或"频道(channel)"的概念来组织,房间或频道是指一个虚拟的空间,它可以容纳多个用户,并允许这些用户之间进行实时通信。当一个用户加入到房间或频道中后,它可以向房间或频道中的其他用户发送音频、视频、文本等实时数据,并接收来自其他用户的数据。在线会议就几乎是这个概念一个业务体现。然后在B站直播的连麦场景几乎都是一个用户发起连麦申请,对方收到一个申请点击同意之后才加入一个频道开始建连。发起连麦本身是一个RPC请求,向信令服务器发起请求,而接收申请连麦的用户是通过一个广播服务的长链与业务服务器交互。所以从业务的角度,需要对RPC的服务与广播服务的长链进行请求的功能验证,在有重大改动或者影响性能的改动时,可以对其进行压测,关注服务器的负载、请求耗时、请求错误数等压测指标。
媒体服务器主要负责音视频的编解码和媒体分发等功能,同样也很适合进行压测,只是不同于传统的HTTP压测,需要有发压端和接收端,当然也可以将发压和接收分离,然后以多角色加入多频道,发送&接收音视频流,探测媒体服务器的负载情况。
线上质量观测
大多数关于线上RTC质量讨论,主要围绕两个术语:QoS(Quality of Service,技术服务质量指标)和QoE(Quality of Experience,用户体验指标)。
QoS的数据是必须真实准确的,用于问题追踪或者性能优化时准确定位根因。B站RTC团队从客户端SDK到服务器,全链路建立了质量数据上报:发送端有音视频基本信息、发送包数、发送rtt时间、图像丢失关键帧请求次数、码率等数据,服务器端有编码时间首帧耗时、丢包数、接收字节数、jitter_buffer、渲染延迟等数据。这些数据使得端到端的连麦问题很容易定位。
QoE更偏向于用户体验数据,比如我们建立的进房成功率、首帧渲染、解码成功率、卡顿率、端到端平均时间等大盘数据。
部分QoE的用户体验差问题可能是QoS就有问题,这类情况可以很方便定位并解决。用户体验千人千面,B站在直播间有“反馈”功能,我们在收到用户反馈后,根据用户的描述和现象,并根据日志和一些QoS指标来定位这个是否是问题,如果有较多用户反馈同类问题,那基本就是需要靠优化QoS去提升QoE。