最近几年,实时音视频领域越来越热,今年的疫情更是“火上浇油”了一把。网易智企旗下产品网易云信在实时音视频领域深耕多年,积累了不少实践经验。在本文里,笔者将以烹饪为比喻,深入浅出地将网易云信如何从0到1构建实时音视频引擎的过程分享给读者。
跟业界很多引擎的实现方案一样,网易云信也是基于 WebRTC 构建的实时音视频引擎。本文会从介绍 WebRTC 提供了什么开始,一步步引入工程化/产品化/优化实践等内容,完整呈现引擎的整个构建过程。
WebRTC 是什么
首先,WebRTC 是什么?
WebRTC 全称 Web Real-Time Communication。原本是用于支持网页浏览器开发实时音视频用的一套 API,它提供了统一的交互协议:SDP,同时提供了视频会议的核心技术,包括音频引擎、视频引擎、传输控制三大块,并且还支持跨平台:Windows / Mac / Linux / Android / iOS。
WebRTC 本来就是给浏览器用的,没有 native 代码可以参考。但是,在 2011 年它被 Google 开源了,源码被应用于各种 native 开发,并被业内广泛借鉴,大有一统天下的趋势。
WebRTC 提供了什么?
有了 WebRTC,是不是就等于有了实时音视频引擎呢?并不是,以烹饪来做比喻的话,有了 WebRTC 就好比是有了厨具/原材料,而实时音视频引擎是给客户的那顿大餐。
有了厨具/原材料,第一步是什么呢?“学会厨具使用方法”— WebRTC 的源码工程化。
WebRTC 官网和其他第三方渠道已有不少资料介绍如何使用 Google 提供的工具编译出 WebRTC 的生成物,本文不再详细赘述。
会用厨具之后,是不是就能做出一顿好吃的饭菜了呢?
现实往往是这样的:用着很牛的厨具和材料,做着难以下咽的料理…
所以要以合理的步骤来做一顿饭菜,这饭菜才适合下咽。
基于 WebRTC 网易云信如何构建音视频能力
在网易云信的实践中,我们选择了怎样的步骤呢?因为基于 WebRTC 建立通话的基础是通过设置 SDP 来完成的,所以我们选择了通过信令传递 SDP 信息,然后设置 SDP 信息给 PeerConnection 来完成建联。整个多人音视频能力中核心的是发布、订阅、响应订阅等媒体功能,其他的功能都是围绕着这些核心功能来做的。而核心功能是采用如下流程来完成的:
举例:
发布音视频:把自己的 SDP 信息给媒体服务器(上图中的媒体服务器是 SFU 服务器),媒体服务器把自己对应的 SDP 信息返回来。这样就具备了 Local SDP 和 Remote SDP,就可以完成一次设置并建联了。
订阅和被订阅也是类似的过程,通过发送自己的 SDP 给服务器,拿到远端的 SDP 信息,然后建立/更新联接。
以上是一个基本的建联过程。拿烹饪来说,是不是饭菜做熟了就很好吃了呢?其实还有很多需要提升的:把饭菜做得更好吃/根据不同人的口味做不同的饭菜。这个提升的过程,就是各种优化。
网易云信优化实践
网易云信的优化实践有很多,下面介绍其中的几种优化。
优化一:Simulcast
所谓 Simulcast,就是在一路视频里提供多个分辨率的视频流,订阅方灵活根据需要订阅想要的视频流。典型的就是在会议场景的应用,如下图:
如果没有 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 的硬件编解码功能不够完整,为了能用起来,我们在整条路径中做了不少事情。如下图:
Android 端主要是硬件的碎片化引起,iOS 端主要是偶发的崩溃引起。碎片化靠下发白名单来解决(只对认证过的硬件启用),偶发崩溃靠收集线上信息来限制特定版本/特定机型来解决。两个移动端都有偶发失败的问题,所以设计了一个失败时的回退机制,以免视频卡住的现象发生。最后再补完 simulcast 逻辑,就完成了这个硬件编解码的支持。
以上的优化,基本上是大部分场景都可以适用的,但也有些优化要看具体场景确定。这就好比不同的人口味不一样,有人喜欢辣,有人喜欢原味,做不到一套方法搞定所有的食客,于是我们做了定制化的优化来进行适应。
优化三:Audio profile
Audio 的优化做了很多,这其中挑了一个 Audio profile 的优化来讲。语音场景里,需要的编码码率不太高,而娱乐场景里(比如播放伴音歌曲的),对码率要求就高很多了,不然会丢失音质。码率要求高了对网络要求也会高,所以为了应对不同的场景,audio 的采样数/声道数都是不一样的。音频硬件又是五花八门,能力不统一,如果采集上来的数据不合适,就需要做重采样支持。同时 codec 的倾向也做了 speech 和 music 的区分,以适应不同的需要。WebRTC 原先的设计里,基本只考虑了语音,跟娱乐场景相关的部分都需要优化支持。同时,为了能够兼容更多的音频处理/更差性能的机器,我们在优化过程中,将播放/采集线程进行了分离,相当于硬件要求降低了一半。
优化四:传输策略优化
传输策略要照顾实时性/清晰度/流畅度三个维度,理想中的优化当然是三个都做得更好,可惜这三个维度是互为掣肘的。如下图所示:
这三个点里,一个点加强了,其他点会被影响。举个例子:实时性要求很高,那缓存时间就得降低,这时候如果出现网络抖动,很可能会卡顿,流畅性就受影响。所以想要同一个策略满足不同的需求不太现实。在项目实践中,我们根据不同的场景,设置不同的策略,来满足不同倾向的需求。
通信场景一般对实时性要求高。举个例子,你跟别人语音聊天,隔了一秒钟才听见对面的声音,那么两个人的聊天很容易“打架”,互相抢着发言。如果是多人语音聊天,那这个现象就更加严重了。娱乐直播场景对清晰度要求很高,但却可以接受较高的延时。所以我们在实践过程中给予了不同的策略支持,就好比做不同口味的饭菜来满足不同人的口味。
以上就是网易云信在构建音视频引擎过程中的一些实践经验,在此分享给大家,希望能给有兴趣的同学参考。
更多内容关注 网易智企技术+ 公众号。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。