为什么咱们要独立开发 WEBRTC 框架
- 当初市面上缺失好的基于 WEBRTC 的框架,咱们心愿做的框架可能充分利用原生平台的自在拓展能力、安全性、以及 WEB 的一些低劣开发个性及生态等等。像传统原生的音视频利用,个别在针对特定平台零碎的客户端,都会做非凡的技术优化,比方 window 平台会应用 MFC 或 WCF 等技术,能做到 16/32/64 路视频的高清解码等等。像一些内容分发型利用,就须要突出内容更新及布局拓展能力,比方咱们常常应用的桌面版微信,就是利用了后面提到的个性,除了内容渲染,为了保障传输的安全性,在实现方面将网络通信局部放在了原生平台去做。
- 将来 Web 利用是什么样的呢?2007 年谷歌 CEO 的对 web3.0 下定义的时候,他提到,心愿将来的利用十分小,能够快速访问,并且可能反对跨平台。明天,就像咱们当初常常应用的微信、支付宝外面的小程序,华为的快利用等,咱们通过扫二维码或者点击链接的形式,就间接能够跳转到指标平台的利用,这就是一些 WEB 利用的劣势,咱们前端要发挥这些短处!
基于 WebRTC 的 Web 利用面临的问题
目前,针对 WebRTC 来说,最大的问题就是应用体验不现实,常常卡顿,次要问题咱们能够简略从上面三点剖析:
- Web 平台碎片化重大。WebRTC 官网正式规范始终到最近两年才被确定下来,而且规范的迭代十分迅速,比方国外的 chrome、Firefox,国内的 360 浏览器、QQ 浏览器等等,都有基于本人想法上的可选性实现。
- WebRTC 实现细节不可控。对于很多 Web 的开发者而言,咱们往往比拟关注的是 Media、Vedio 这些 HTML5 标签自身,但比方我要想管制外面的一些网络传输 FEC、弱网反抗、带宽预计、优先级保障等算法、应用非凡的编码解码,依赖纯 Web 是做不到的,这不是浏览器的使命,如果想要做这种更底层的管制,就只能要想其余方法参加到外面去。
- 计算密集型算法可选项少。咱们很多时候须要对视频进行一些预处理的动作,比方美颜性能,当初通用的做法是首先须要获取到用户本地的一些原始的视频采集数据,而后绘制到 canvas 上,通过 canvas 接口获取到 imagedata,将 imagedata 传递到 Web Assembly,而后再对它进行进一步的算法运算,比方磨皮、提亮等等这些操作,而后从新绘制到 canvas 外面,这个过程链路自身比拟长。还有一点就是 Web Assembly 技术自身,也是始终在不停倒退,他自身有本人的限度,比方 Web Assembly 的实现是基于 chrome 自身的一个 render 主线程驱动。尽管后续呈现了 Web worker 的工作线程实现以及并行计算等,然而执行性能也不是特地好,如果咱们心愿可能充分利用的计算资源,在这种状况下就很难实现。
另外,对于 GPU 局部,WebGl 实现的细节上是有侧重点的,因为浏览器 WEB 自身是要面向整个标签页的渲染,而不仅是视频窗口这一小块,所以相比业余的视频渲染性能方面的体现并不太好。
声网的一些实际解决思路分享
- 对立渲染引擎。针对 Web 平台碎片化问题,咱们提供了统一的渲染引擎,让用户应用一个对立的运行渲染环境,以此来解决厂商、版本等差别引入的碎片化问题。
- 对于 WebRTC 的实现细节、算法这一块,属于利用可扩大局部,咱们会尽量想方法,将这些能力封装到原生平台外部去实现。
PC 端利用的框架选型
在最开始咱们做技术评估的时候,可选框架有几大类,Electron、CEF、Qt 等等,但很多的开发框架,像 CEF 和 Qt 根底技术栈比拟偏差 C、C++、Java 等等,开发习惯和生态上和咱们前端开发体验不统一,尤其是它的开发工具链是须要独立构建,所以最终咱们抉择了 Electorn,它是基于 Nodejs 的一个技术计划,前端在开发的时候,咱们能够应用相熟的开发环境,比如说 Npm、yarn,还有包含后续的测试打包等整个构建过程。
扩大能力混合注入时的一些问题
- 原生扩大能力问题
对于原生扩大能力的注入,咱们将一些要害的业务逻辑的实现,通过用 C ++ 代码放到 V8 引擎里与原生能力联合起来的,后续通过 bridge,将能力裸露给下层。这里最大的问题在于每一个 V8 引擎版本,底层 C ++ 的接口并不统一,并且,随着 nodejs 版本的降级,每个版本外面的接口实现也稍微不同的,这也是长期以来让社区比拟诟病问题。这里咱们的解决方案是,采纳 nodejs 提供的 node api 实现,它是向后兼容的,以此来放弃底层接口一致性,解决开发插件接口和 node 版本依赖的问题。
当咱们的 js 层调用通过 bridge 注入到 native 后,驱动咱们另外一个团队开发的 native SDK,蕴含了声网次要的性能和算法,比方咱们的 RTN 网络接入、AI 降噪算法、背景宰割、超分算法等等。另外从前端开发体验上,用户只须要改变大量的代码,就能够实现基于 agora sdk ng 开发的自有 APP 的适配,这也是咱们框架的初衷之一,放弃内部开发用户的体验的根底上,可能晋升它外面的利用能力。
- 异步事件驱动
音视频利用的特点就是它的数据体积比拟大,每一帧数据依据用户视频分辨率的不同,从几 K 到几十 M 都有可能,同时,咱们还必须对这些数据进行解码、编码等等操作,这就要求咱们可能去充沛应用用户本地的计算能力,这里就波及到子线程相干的调度操作,通过异步事件驱动,咱们能够设计异步事件的队列治理,原生平台生产、主线程生产的模式。另外因为单个数据体积比拟大,如果渲染线程和异步线程数据交互通过 copy 进行交互,内存开销可想而知,这里就必须应用到一些 node api 提供的 external-ArrayBuffer 技术,相似智能指针援用的解决方案,咱们只须要保障 Buffer 的生命周期即可,即在 js 层调用期间可用,指针销毁时同时销毁 buffer,防止内存透露。
- 动静分辨率问题
受限于网络风暴等等问题,咱们用户很多时候分辨率很难放弃 1080P 不变,这个时候咱们就须要一些均衡算法,在帧率和分辨率之间做均衡,这种状况下,视频宽窄就有可能发生变化,那咱们就须要针对这种状况做一些非凡解决,canvas 是能够通过更新 texture 的形式,适配视频数据帧的宽高、步长等,而后通过 CSS 款式管制整体页面渲染比例及布局即可,不须要再做重采样来保障宽高比,这个做法也是和传统原生视频利用渲染方面有显著差别的中央。
音频播放
本地音频采集完个别不须要本地回放,但在一些业务场景下,咱们的用户心愿可能依据本人的声音反馈做一些非凡解决,比方用户会心愿能够通过直观的听到本人的音量来调整麦克风的绝对地位等等。而且这也算是咱们为了可能保障与 agora sdk ng 这一致性性能。因为浏览器音频播放是异步执行的,即主线程将音频数据转发给音频线程,音频线程播放完结后告诉主线程,主线程再解决下一个音频数据段,这个过程自身是会有始终耗费的,所以在实时音频播放场景中的直观体验就是,随着工夫增长,时延累加显著,并且数据播放距离呈现有显著乐音。
咱们的解决方案比较简单间接,采纳 audio workletprocessor 接口,由咱们来管制音频传递给音频播放线程的频率,流式传递音频数据到异步线程,这样就防止线程间反馈造成的时延累加,听起来会很顺滑,加上每次数据段比拟短,约 10ms 左右,用户听起来就感觉本人的声音变大了,没有显著的回音感。
将来瞻望
将来咱们心愿可能把更多声网 nativeSDK 能力裸露到下层利用中,比方咱们的桌面共享、AI 降噪、美声、vp9 编码解码、背景宰割、美颜、超分等等,咱们声网外部曾经进入到测试环节,后续也心愿可能赋能给咱们的用户更加不便、弱小的 Web 利用开发能力。