在与同行交流过程当中,发现不少同行对 WebRTC 改动太多,致使没法升级 WebRTC 版本。而 WebRTC 开源社区的快速迭代,让他们感到欣喜又焦虑:开源社区的迭代效果,是否是超过了他们对 WebRTC 的优化效果?咱们针对特定场景优化 WebRTC 时,怎么紧跟 WebRTC 开源社区通用的优化?git
做者:阿里云智能技术专家 熊金水github
简言之,把 WebRTC 做为 Framework 使用,而不是 Library,即:WebRTC 仓库轻量化,核心模块插件化。web
详细的,WebRTC 做为 Framework 串联核心模块;核心模块既能够以插件形式使用咱们的实现,也能够 Fallback 到 WebRTC 的默认实现。目的是减小 WebRTC 冲突的可能性,提升升级 WebRTC 的敏捷性。算法
目标:一年升级一次 WebRTC,一次花费一我的月。架构
WebRTC 的核心模块,包括:ide
WebRTC 在长期的演进中,API 已经具有了做为 Framework 的大部分能力。红色的核心模块,已经基本能够插件化,以下面的 API:函数
light-rtc 做为 WebRTC 仓库,咱们须要保留两个 Remote,一个是 Alibaba,一个是 Google。升级 WebRTC 时,咱们从 Google 上 Pull 最新代码, 解决冲突,而后 Push 到 Alibaba。性能
对插件化的模块,咱们须要放到单独的仓库 lrtc-plugin 里,这样有两个好处:优化
对 lrtc-plugin 依赖的第三方库,也应该以单独的仓库存在,并保留两个 Remote,好比 Opus,这样,即便修改了 Opus 源码,仍然能够像升级 light-rtc 同样,方便的单独升级 Opus 版本。阿里云
音频编解码器、视频编解码器,是咱们最常优化的部分之一:
这部分插件化是相对简单的,只须要实现本身的[Video|Audio][Encoder|Decoder]Factory
便可。以 Simulcast为例,在本身实现的 VideoEncoderFactory 里,先用 WebRTC 原始的 VideoEncoderFactory,建立多个 Encoder 对象,而后封装到一个 Simulcast Encoder 里。
很惋惜,ADM(Audio Device Module)没有提供检测设备插拔的功能,须要增长 Callback 接口。
另外,虽然 WebRTC 支持样本数量的监控,可是当前只用于打印日志,若是想在此基础上作更多事情(如:发现采集样本为 0 时,重启采集),则单独作一个 AudioSampleMoniter 的类,比较有利于扩展。
ADM 是一个适配难点,相信是困扰 RTC 同行的共同难题。不一样操做系统、不一样机型,均可能有不同的问题。例如:
这些修改大部分属于 Bugfix,参考“Bugfix”章节。
APM(Audio Processing Module)多是 light-rtc 相对难处理的部分。
APM 与 NetEQ 一块儿,多是 WebRTC 核心模块中,开源价值最大的部分。在我对 APM 有限的认知里,对 APM 常见的优化可能有:
下图是 WebRTC APM 内部模块的数据流程图:
从图中能够看出,APM 其实也为插件化作了准备,可是只在近端信号的尾部、远端信号的头部。从 APM 构造函数上也能够看出来:
滤波/均衡,能够方便的实现一个 CustomProcessing 的 render_pre_processor。
其余的优化,遵循轻量化/插件化的理念,没有现成的插件接口,咱们能够创造新的插件接口,如啸叫抑制,以及 AECM 优化的部分算法。
但 APM 仍然会有不少没办法插件化的,只能修改 light-rtc 仓库,如 AECM Double Talk 优化等。
AM(Audio Mixer)的插件化,能够在不修改 light-rtc 的基础上,玩出不少花样:
FEC(Forward Error Correction),常见的修改:
CC(Congestion Control),包含两个方面,一个是 CC 算法自己,一个是 CC 关联模块。
算法自己,能够用不一样的算法实现,如 WebRTC 默认的 goog_cc,也能够是 BBR,甚至是知足 WebRTC::NetworkControllerFactoryInterface 接口的外部插件。
关联模块:
Android、iOS、Mac,WebRTC 都提供了默认的实现,虽然有少许 Bug,可是基本知足需求。
Windows 平台,早期 WebRTC 提供了 D3D 的实现,最新版已经剔除,咱们能够在 lrtc-plugin 仓库实现本身的 D3D,或者其余的渲染,如 QT OpenGL。
WebRTC 并无提供视频前处理(如:美颜)、后处理(如:超分辨率)的接口,可是咱们彻底能够像 rtc::BitrateAllocationStrategy 同样,创造 VideoProcessInterface 接口, 并在 lrtc-plugin 仓库里实现。
让 VideoProcessInterface 同时继承 Sink 和 Source 接口,能够方便的把多个对象串联起来。
其余核心模块,如 JitterBuffer、ICE 等,目前接触的主要是 Bugfix,尚未发现本身定制重写的必要。
Bugfix,每每只能修改 light-rtc 仓库。一方面,是尽可能把 Bugfix 内聚成函数,减小对已有代码的修改;另外一方面,尽可能把 Bugfix 贡献到开源社区(Issue Tracker),既为开源社区作了贡献,也完全避免了升级的冲突。
贡献到开源社区,每每比想象的要复杂,但也更能锻炼人。在特定场景,每每只用了 WebRTC 一部分能力,如视频 JitterBuffer,一个 Bugfix 可能只考虑到了 H264,贡献到开源社区时,则须要同时兼顾 VP8/VP9,甚至是未来的 AV1。在这个过程当中,Google 工程师会在 Code Review 中与你亲密切磋,实际上是很是好的锻炼机会,进一步提升对 WebRTC 的认识。
WebRTC m74 源码
RSFEC:
CC
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。