WebRTC 在今年 1 月被 W3C 和 IETF 发布为正式标准。从开源至今,十年的时间,倾注了众多开发者的贡献。本文由 Google WebRTC 产品经理 Huib Kleinhout 基于在由声网举办的 RTE 大会上的分享汇总整理,并增加了其近期对于 WebRTC 前景的看法。
2020 年,WebRTC 发生了很多变化。WebRTC 其实就是一个客户端库。大家都知道它是开源的。尽管 Google 大力地在支持 WebRTC,但社区的力量同样功不可没。
WebRTC 对于桌面平台、浏览器端实现音视频交互来讲十分重要。因为在你可以再浏览器上运行任何一种服务,并进行安全检查,无需安装任何应用。这是此前开发者使用该开源库的主要方式。
但 2020 年,浏览器的发展方向变了。首先讲讲 Microsoft,它将自研的浏览器引擎替换为基于 Chromium 的引擎,同时它们也成为了 WebRTC 的积极贡献者。Microsoft 贡献之一是 perfect negotiation,它使得两端以更稳妥的形式协商。而且,它们还改良了屏幕捕获,使其效率更高。
另一方面,还有 Safari。苹果的 Safari 还在继续改进他们 WebRTC API。激动人心的是,最新一版的 Safari Tech Preview 中已支持了 VP9,而且还支持硬件加速,大家可以在 Safari 的“开发者设置”中启用它。
火狐浏览器增加了重传以及 transport-cc,这有助于更好地估计可用带宽,从而改善媒体质量。
另一方面,Project Zero——Google 负责产品安全性的团队,通过寻找漏洞,帮助提高 WebRTC 的安全性。这意味着如果你的库不基于浏览器,及时更新 WebRTC 库、遵守说明就更加重要了。
另一件激动人心的事情就是,2020 年,云游戏已经上线了。它的实现有赖于 WebRTC。 Stadia(Google 的云游戏平台)已于 2019 年底推出,但 2020 年初才正式在浏览器得以支持。其云游戏搭载 VP9,提供 4k、HDR 图像和环绕声体验。这些都会通过 WebRTC 进行传输。
数月前,几个月前,NVIDIA 也发布了适用于 Chromebook 的 GeForce Now,同样使用了 WebRTC。最近,Microsoft 和亚马逊也宣布支持基于浏览器的云游戏开发。 这确实促使 WebRTC 从数百毫秒延迟降低到了数十毫秒延迟,同时开启了全新的应用场景。 但最重要的是, 2020 年,实时通讯(RTC)对于每个人来说都是必不可少的一部分。 因此,许多网络服务的使用率暴涨,涨幅从十倍到几百倍不等。 大家打语音电话的次数更多了,时间更久了,群组数量和成员人数也增加了, 线上交流越来越多。 所以我们需要更丰富的互动方式。
从 Google 的角度来看, 在疫情爆发的头 2、3 个月内,我们的最大需求容量增长了 30 倍。所以即使是 Google,要确保后端和所有系统功能都可以应对这么大的增长,我们也付出了很多努力。
在变化面前, WebRTC 和实时通信使用量激增。 大众的日常习惯也在变化。 现在不只在公司能工作, 自己的卧室、厨房里都是工作场所了。由于“社交距离”,面对面交流变得不再现实,我们需要其它与他人社交的方法。我们只能通过视频,依据别人的表情猜测他的意图,此时高清的视频质量就显得更加重要了。
每个人协作的方式不同,可能是因为我们用的设备不一样。 如果你在公司, 你用的可能是台式机,那你可能会用它在会议室里开会。 而下班之后,你可能会带你的笔记本电脑回家。 但现在人们都在用笔记本处理各种事宜,比如同时运行应用、视频会议和文字聊天。 这种场景下,电脑的使用率非常高。我们看到学校里的孩子们也在用笔记本电脑,比如 Chromebook, 但他们电脑的性能相对差一点。社交、学习线上化之后,电脑的任务处理量突然增大, 所以开展该 WebRTC 项目的意义在于我们需要帮助扩展 WebRTC,确保其运行良好。
其次,我们需要为 Web 开发者和实时通讯开发者提供更大的灵活度,让他们可以在当下开发出新的互动体验。当疫情爆发时,它阻碍我们了在 Chrome 中开展的所有实验,于是我们所做的一件事情就是专注于服务的扩展、维护。 但这远远不够,特别是在提高性能方面,我们需要做得更好。
大家可以猜一猜,如果你要在任何使用 WebRTC 的浏览器中开展实时服务, 最耗性能的部分会是什么呢?是视频编码?音频编码?网络适配?(因为你会考虑到可能会有丢包和网络变化)又或者是渲染?
当你想在屏幕显示摄像头采集的画面时,我们可以来看看浏览器中发生了什么。 我们假设你有一个通过 USB 驱动程序输入的摄像头, 驱动运行,开始处理,摄像头可能还会进行人脸检测、亮度调整等操作。 这要经过浏览器内的系统,Chrome 和其它浏览器都是多进程的。多进程有助于浏览器的稳定性和安全性,比如一个组件或一个页面崩溃,或存在安全漏洞,那么它就会与其他沙盒中的组件隔离。 但这也意味着进程间有大量的通信。 所以如果你有一帧视频数据从摄像头被采集,它可能是 MJPEG 格式。 当它开始渲染你定义媒体流的页面时, 格式可能为 I420。 当从渲染进程转到 GPU 进程(需要实际在屏幕上绘制)时,需要提供最高质量的数据,此时数据可能是 RGB 格式。 当它再次进入操作系统,在屏幕上进行合成时, 可能需要一个 alpha 层, 格式又要变。 这中间涉及到大量转换和复制步骤。 由此可见, 无论内容来自摄像头还是某一终端,仅仅把它放到屏幕上的视频帧中就要花费大量的处理时间。 所以这就是 WebRTC 服务中最复杂的部分——渲染。
这也是我们做了很多优化的地方。 渲染变得更加高效了,可以确保我们不会在每次更新视频帧时都重新绘制。 如果同时有多个视频,我们会把他们同步,再做其他操作。Chrome 团队优化了内存分配,确保每个视频帧都以最有效的方式得到分配。我们还改进了 Chrome OS 上的操作系统调度,以确保视频服务即使负载过重也能保证交互和响应。接下来的几个月里,我们将致力于从摄像头采集到视频帧渲染到屏幕这个过程的“零拷贝”。 我们希望不会出现一次拷贝或转换,但所有信息都会以最高效的方式保存在图片内存里的。
同时,我们也致力于使刷新率适应视频帧率。所以在没有任何变化的情况下,我们不需要 60Hz 的屏幕刷新率,但要适应视频的帧速率,例如 25 秒一次。 以下是我们觉得有用的建议:
1、避免耗时耗力的扩展操作,在 incongnito 模式下进行测试。
避免耗时耗力的扩展操作很难,它可以干扰你的服务进程,减缓你的服务速度。
2、避免安全程序干扰浏览器运行
杀毒软件若要做深度数据包检查或阻止数据包,会占用大量 CPU。
3、通过 Intel Power Gadgets 来测试
我们建议你用 Intel Power Gadgets 看看你的服务用了多少能耗。 它会比只看 CPU 百分比直观的多。
4、花哨的视频效果会占用更多性能
如果你用一些花哨的动画, 比如会动的圆点来装饰你的视频帧,就会占用更多性能。 尽管看起来不错,但它可能会导致视频帧卡顿一番才能渲染在屏幕上。
5、摄像头分辨率设置与传输分辨率一致
如果你使用摄像头采集,请确保打开摄像头时将其分辨率的设置,与你调用 getUserMedia 时的设置保持一致。 如果你打开摄像头,设置了高清画质,格式为 VGA,那么势必需要转换很多字节的信息都会被扔掉。
6、要留意 WebAudio 的使用
WebAudio 可能比预期需要更多 CPU 来处理。
关于视频编解码
视频编解码器可用于构建更高性能服务器。 因为不仅 CPU 资源很重要, 若你构建网络相关的服务,视频编解码器就显得重要起来了。 如果你要把业务拓展一百倍, Google 提供一款免费的编解码器,VP8、VP9、AV1,并且他在所有浏览器中都可用。
VP8 是目前为止浏览器内部使用最多的版本,所有浏览器都支持它。VP9 同样在市场中流通很多年了,也一直在改进。它具备 30%-50%的节约率,以及如支持 HDR 和 4K 的高质量功能。同时,它广泛应用于谷歌内部,支持 Stadia 及其他内部服务。 因为它有 VP8 中没有的功能,即能帮助你更好地适应高低带宽连接的转换。然后是 AV1。AV1 也即将在 WebRTC、一些开源实现和浏览器中使用。大多数浏览器已经可以使用它进行流式传输。 希望明年能正式启用它。 实际上,微软刚刚宣布他们的操作系统将支持硬件加速 AV1。 性能的提升给予了开发者更大空间。
WebRTC NV(Next Version)
发布 WebRTC 1.0 之后,我们就和社区一起研发下一个版本, 该版本叫“NV”。 该版本意在支持当前 WebRTC API 不可能或很难实现的新用例,比如虚拟现实。对于虚拟现实特效,就像前面提到过的笔记本电脑和机器学习的例子一样, 为了能够使用 WebRTC API 运行,我们需要更好地掌握媒体处理的技能, 比如更好控制传输和拥塞,使用编解码器进行更多自定义操作等等。
在以上这些目标上,WebRTC NV 的思路是不定义全新 API。 目前已经有两个 API 和 WebRTC,PeerConnetion 和 getUserMedia 了。 我们不会重新定义它们,从头开始研发。相反,我们正在做的是:允许我们使用称为“HTML 流”的接口访问端对 peer connection 内部,以及允许访问浏览器中的编解码器的接口。再加上诸如 Web Assembly 和 workers threads 的新技术,你可以在浏览器,以及集成的端对端连接中使用 Javascript 进行实时处理。
如果看一下现在的 WebRTC 的内部,你会发现媒体流就像是从网络传入时一样被拆包(depacketized)。这里会有一些丢失或延迟的适配。因此,我们对此进行了重构。
另一方面, 摄像头输入或麦克风输入已经经过编解码器如 Opus 或 VP8,去除了回声。比特率已经根据网络情况进行了适配,然后将其打包为 RTP 数据包并通过网络发送。我们想做到在 WebRTC NV 中拦截该管道,所以要从媒体框架开始。因此,我们希望能够在媒体帧从网络到达显示器,以及从摄像机麦克风到网络回到媒体帧时对其进行监听。我们希望能够更好地管理这些流。目前我们提出两个流方案,也正是我致力研究的两个 API。
第一个是可插入媒体流(Insertable Media Stream)。当前的 Chrome 浏览器 86 中已提供此功能。Google 服务和其他外部服务已使用了此功能。你可以使用它来实现端到端加密,或者可以使用它向框架中添加自定义元数据(meta-data)。你要做的是在 PeerConnection 中定义此编码的可插入媒体流,并且你也可以创建流。之后,当你从摄像头获取视频帧时,它首先被编码,比如 VP8 格式,之后你可以访问它并进行流式处理。你还可以对其进行加密或标记其中一些元数据。
另一个是原始媒体流 API(Raw Media Stream)。这是标准委员会正在讨论的标准工作。目前已经有一些确切的建议了。从 Google 的角度来说,我们正在尝试这种实现。该 API 允许我们访问原始帧。它意味着,当原始帧从摄像头采集后,在还未进行视频编码前,你就可以访问这些数据了。然后你可以对其进行处理,比如实现 AR 效果。你还可以运行多个滤镜来删除背景,然后应用一些效果。比如我想把我现在的视频背景设成一个热带岛屿。这还可以应用到自定义的编解码器中,比如你此前使用的一些编解码器与现在的浏览器不兼容,那么你可以利用这个接口将数据直接传给编解码器来处理。原始媒体流 API 可以提供一种非常有效的方式来访问此原始媒体。
总结一下。虽然 WebRTC 作为 W3C 正式标准已经发布,但仍在继续改进。新的视频编解码器 AV1 可节省多达 50%的带宽,正在 WebRTC 和网络浏览器中使用。开源代码的持续改进有望进一步减少延迟,提高视频流的质量。WebRTC NV 收集了创建补充 API 的倡议,以实现新的用例。这些 API 包括对现有 API 的扩展,以提供更多对现有功能的控制,例如可扩展视频编码,以及提供对 low-level 组件的访问的 API。后者通过集成高性能的定制 WebAssembly 组件,为网络开发者提供了更多的创新灵活性。随着新兴的 5G 网络和对更多交互式服务的需求,我们预计在未来一年内,持续增强在 WebRTC 的服务端建设。