从0到1 构建实时音视频引擎

最近几年,实时音视频领域越来越热,今年的疫情更是“火上浇油”了一把。网易智企旗下产品网易云信在实时音视频领域深耕多年,积累了不少实践经验。在本文里,笔者将以烹饪为比喻,深入浅出地将网易云信如何从0到1构建实时音视频引擎的过程分享给读者。

跟业界很多引擎的实现方案一样,网易云信也是基于WebRTC构建的实时音视频引擎。本文会从介绍WebRTC提供了什么开始,一步步引入工程化/产品化/优化实践等内容,完整呈现引擎的整个构建过程。

首先,WebRTC是什么?

WebRTC全称Web Real-Time Communication。原本是用于支持网页浏览器开发实时音视频用的一套API,它提供了统一的交互协议:SDP,同时提供了视频会议的核心技术,包括音频引擎、视频引擎、传输控制三大块,并且还支持跨平台:Windows / Mac / Linux / Android / iOS。

WebRTC本来就是给浏览器用的,没有native代码可以参考。但是,在2011年它被Google开源了,源码被应用于各种native开发,并被业内广泛借鉴,大有一统天下的趋势。

有了WebRTC,是不是就等于有了实时音视频引擎呢?并不是,以烹饪来做比喻的话,有了WebRTC就好比是有了厨具/原材料,而实时音视频引擎是给客户的那顿大餐。

从0到1 构建实时音视频引擎_第1张图片

有了厨具/原材料,第一步是什么呢?“学会厨具使用方法”—WebRTC的源码工程化。

WebRTC官网和其他第三方渠道已有不少资料介绍如何使用Google提供的工具编译出WebRTC的生成物,本文不再详细赘述。

会用厨具之后,是不是就能做出一顿好吃的饭菜了呢?

现实往往是这样的:用着很牛的厨具和材料,做着难以下咽的料理…

从0到1 构建实时音视频引擎_第2张图片

所以要以合理的步骤来做一顿饭菜,这饭菜才适合下咽。在网易云信的实践中,我们选择了怎样的步骤呢?因为基于WebRTC建立通话的基础是通过设置SDP来完成的,所以我们选择了通过信令传递SDP信息,然后设置SDP信息给PeerConnection来完成建联。整个多人音视频能力中核心的是发布、订阅、响应订阅等媒体功能,其他的功能都是围绕着这些核心功能来做的。而核心功能是采用如下流程来完成的:

从0到1 构建实时音视频引擎_第3张图片

举例:

发布音视频:把自己的SDP信息给媒体服务器(上图中的媒体服务器是SFU服务器),媒体服务器把自己对应的SDP信息返回来。这样就具备了Local SDP 和 Remote SDP,就可以完成一次设置并建联了。

订阅和被订阅也是类似的过程,通过发送自己的SDP给服务器,拿到远端的SDP信息,然后建立/更新联接。

以上是一个基本的建联过程。拿烹饪来说,是不是饭菜做熟了就很好吃了呢?其实还有很多需要提升的:把饭菜做得更好吃/根据不同人的口味做不同的饭菜。这个提升的过程,就是各种优化。

网易云信的优化实践有很多,下面介绍其中的几种优化。

优化一:Simulcast

所谓Simulcast,就是在一路视频里提供多个分辨率的视频流,订阅方灵活根据需要订阅想要的视频流。典型的就是在会议场景的应用,如下图:

从0到1 构建实时音视频引擎_第4张图片

如果没有Simulcast功能,假定需要720P的视频,在这个场景里,发送方需要发送/压码一路720P视频,接收/解码4路720P视频,带宽和性能压力非常大。如果增加了Simulcast能力,同时能够发送720P/180P的视频。在这个场景里,发送方通常只要发送/压码180P视频,接收/解码1路720P视频,接收/解码3路180P视频。带宽要求和性能要求降到了原先的1/4左右,而效果是完全一样的。

WebRTC的Simulcast功能,并不是由WebRTC团队完成的,而是一个第三方开发团队开发,并merge到WebRTC里去的。要开启它,需要开启一个实验室接口,然后在Video quality control里更改相应的源码才能正常运行。配合上层的信令,就能做到灵活订阅了。

优化二:__视频硬件编解码

通常,视频硬件编解码会比软件编解码性能开销更低。无论在日常使用还是上高清分辨率(比如1080P)都有很重要的作用。WebRTC的硬件编解码功能不够完整,为了能用起来,我们在整条路径中做了不少事情。如下图:

从0到1 构建实时音视频引擎_第5张图片

Android端主要是硬件的碎片化引起,iOS端主要是偶发的崩溃引起。碎片化靠下发白名单来解决(只对认证过的硬件启用),偶发崩溃靠收集线上信息来限制特定版本/特定机型来解决。两个移动端都有偶发失败的问题,所以设计了一个失败时的回退机制,以免视频卡住的现象发生。最后再补完simulcast逻辑,就完成了这个硬件编解码的支持。

以上的优化,基本上是大部分场景都可以适用的,但也有些优化要看具体场景确定。这就好比不同的人口味不一样,有人喜欢辣,有人喜欢原味,做不到一套方法搞定所有的食客,于是我们做了定制化的优化来进行适应。

优化三:__Audio profile

Audio的优化做了很多,这其中挑了一个Audio profile的优化来讲。语音场景里,需要的编码码率不太高,而娱乐场景里(比如播放伴音歌曲的),对码率要求就高很多了,不然会丢失音质。码率要求高了对网络要求也会高,所以为了应对不同的场景,audio的采样数/声道数都是不一样的。音频硬件又是五花八门,能力不统一,如果采集上来的数据不合适,就需要做重采样支持。同时codec的倾向也做了speech和music的区分,以适应不同的需要。WebRTC原先的设计里,基本只考虑了语音,跟娱乐场景相关的部分都需要优化支持。同时,为了能够兼容更多的音频处理/更差性能的机器,我们在优化过程中,将播放/采集线程进行了分离,相当于硬件要求降低了一半。

优化四:__传输策略优化

传输策略要照顾实时性/清晰度/流畅度三个维度,理想中的优化当然是三个都做得更好,可惜这三个维度是互为掣肘的。如下图所示:

从0到1 构建实时音视频引擎_第6张图片

这三个点里,一个点加强了,其他点会被影响。举个例子:实时性要求很高,那缓存时间就得降低,这时候如果出现网络抖动,很可能会卡顿,流畅性就受影响。所以想要同一个策略满足不同的需求不太现实。在项目实践中,我们根据不同的场景,设置不同的策略,来满足不同倾向的需求。

通信场景一般对实时性要求高。举个例子,你跟别人语音聊天,隔了一秒钟才听见对面的声音,那么两个人的聊天很容易“打架”,互相抢着发言。如果是多人语音聊天,那这个现象就更加严重了。娱乐直播场景对清晰度要求很高,但却可以接受较高的延时。所以我们在实践过程中给予了不同的策略支持,就好比做不同口味的饭菜来满足不同人的口味。

以上就是网易云信在构建音视频引擎过程中的一些实践经验,在此分享给大家,希望能给有兴趣的同学参考。

你可能感兴趣的