关于webrtc:实践解析-如何通过-WebAssembly-在-Web-进行实时视频人像分割

25次阅读

共计 4523 个字符,预计需要花费 12 分钟才能阅读完成。

5 月 15 日,声网 Agora 高级架构师高纯加入了 WebAssambly 社区举办的第一场线下流动“WebAssembly Meetup”,并围绕声网 Agora 在 Web 实时视频人像宰割技术的利用落地,分享了实践经验。以下为演讲分享整顿。

RTC 行业在近几年的倒退突飞猛进,在线教育、视频会议等场景凋敝蓬勃。场景的倒退也给技术提出了更高的要求。于是,机器学习越来越多地利用到了实时音视频场景中,比方超分辨率、美颜、实时美声等。这些利用在 Web 端也存在同样的需要,同时也是所有音视频开发者面对的挑战。所幸 WebAssembly 技术为 Web 高性能计算提供了可能。咱们首先围绕 Web 端的人像宰割利用进行了摸索实际。

视频人像宰割都用在什么场景?

提到人像宰割,咱们首先想到的利用场景,就是在影视制作中的绿幕抠图。在绿幕环境下拍摄视频后,通过后期制作,将背景替换成电脑合成的电影场景。

另一种利用场景大家应该都见过。在 B 站上,你会发现有些视频的弹幕不会遮挡画面上的人物,文字会从人像的前面穿过。这也是基于人像宰割技术。

以上列举的人像宰割技术都是在服务端实现的,而且不是实时音视频场景。

而咱们声网做的人像宰割技术实用于视频会议、在线教学等实时音视频场景。咱们能够通过人像宰割技术,能够对视频的背景进行含糊解决,或替换视频背景。

[⏸️点击查看视频]

为什么这些实时场景须要这项技术呢?

最近的一项钻研发现,在均匀 38 分钟的电话会议中,有整整 13 分钟的工夫被节约在解决烦扰和中断上。从在线面试、演讲和员工培训课程到集思广益、销售推介、IT 帮助、客户反对和 网络研讨会,所有这些状况都面临同样的问题。因而,应用背景含糊或从自定义和预设的许多虚构背景选项中抉择一个,能够大大减少烦扰。

还有一项考察显示,有 23% 的美国员工示意视频会议让他们感到不难受;75% 的人示意他们依然更喜爱语音会议,而不是视频会议。这是因为人们不心愿将本人的寓居环境、隐衷裸露在公众视线中。那么通过替换视频背景,就能够解决这个问题。

目前,实时音视频场景下的人像宰割、虚构背景,大多是运行在原生客户端上的。只有 Google Meet 利用 WebAssembly 实现过在 Web 实时视频中的人像宰割。声网的实现是联合机器学习、WebAssembly、WebGL 等技术实现的。

Web 实时视频虚构背景的实现

人像宰割的技术组件和实时处理流程

在做 Web 的人像宰割时,咱们还会须要用到这些组件:

  • WebRTC:做音视频的采集和传输。
  • TensorFlow:作为人像宰割模型的框架。
  • WebAssembly:做人像宰割算法的实现。
  • WebGL:GLSL 实现图像处理算法,来解决人像宰割后的图像。
  • Canvas: 最终渲染视频和图像后果。
  • Agora Web SDK:进行实时的音视频传输。

人像宰割的实时处理流程是这样的。首先会利用 W3C 的 MediaStream 的 API 进行采集。而后数据会交给 WebAssembly 的引擎去进行预测。因为机器学习的运算开销较大,这就要求输出的数据不能太大,所以须要在输出到机器学习框架前对视频图像做一些缩放的解决或归一化。运算后果从 WebAssembly 输入后还要进行一些后处理,而后再传递给 WebGL。WebGL 会通过这些信息与原始视频信息来做滤波、叠加等解决,最初生成出的后果。这些后果会到 Canvas 上,而后通过 Agora Web SDK 来进行实时传输。

机器学习框架的抉择

咱们在做这样的人像宰割之前,必定会思考是不是有现成的机器学习框架。目前可用的包含 ONNX.js、TensorFlow.js、Keras.js、MIL WebDNN 等。它们都会采纳 WebGL 或 WebAssembly 作为运算后端。然而在尝试这些框架的时候,都发现了一些问题:

1. 短少对模型文件的必要爱护。个别在运行的时候会让浏览器从服务端把模型加载过去。那么模型会间接裸露在浏览器客户端上。这不利于知识产权爱护。

2. 通用 JS 框架 IO 设计未思考理论场景。比方 TensorFlow.js 的输出是通用数组,在运算的时候会将内容包装成 InputTensor,而后交给 WebAssembly 或上传为 WebGL 纹理来解决。这个过程绝对简单,在解决对实时性要求很高的视频数据时性能得不到保障。

3. 算子反对不欠缺。通用框架或多或少会短少能够解决视频数据的算子。

对于这些问题,咱们的解决策略是这样的:

1. 实现原生机器学习框架的 Wasm 移植。

2. 对于没有实现的算子,咱们通过定制来补齐。

3. 性能方面,咱们用 SIMD(单指令多数据流的指令集)和多线程来进行优化。

视频数据预处理

数据的预处理须要对图像进行缩放。在前端个别有两种形式来做:一种是用 Canvas2D,另一种是应用 WebGL。

通过 Canvas2D.drawImage() 把 Video 元素里的内容画到 Canvas 上,而后用 Canvas2D.getImageData() 来获取你须要缩放的图像尺寸。

WebGL 自身能够将 Video 元素自身作为一个参数上传成为纹理。WebGL 也提供了从 FrameBuffer 里读取 Video 数据的能力。

咱们也对这两种办法的性能进行了测试,如下图所示,在 x86_64 window10 的环境下,在两种浏览器上,别离测试了三种分辨率的视频在 Canvas2D 和 WebGL 上的预处理工夫开销。你能够从中判断出在针对不同分辨率的视频进行预处理时,应该选用的办法。

Web Workers 及多线程问题

因为 Wasm 计算开销过大,会导致 JS 主线程阻塞。而且当遇到一些比拟非凡的状况,比方进入一家咖啡馆,左近没有电源,那么设施就会处于低能耗模式,这时候 CPU 会降频,从而可能引起的视频解决丢帧。
所以,咱们要晋升性能。在这里,咱们用到的是 Web Workers。咱们将机器学习推理运算运行在 Web Worker 上,能无效缩小 JS 主线程的阻塞。

应用办法也比较简单。主线程来创立 Web Worker,它会在另一个线程上运行。主线程通过 worker.postMessage 给它发消息,让 worker 来拜访。(如下述代码示例)

但这也可能会引入一些新的问题:

  • postMessage 数据传输带来的结构化拷贝开销
  • 共享内存带来的资源竞争及 Web 引擎兼容性

针对这两个问题,咱们也做了一些剖析。

当传输数据的时候,你的数据是 JS 原始数据类型、ArrayBuffer、ArrayBufferView、lImageData,或 File /
FileList / Blob,或 Boolean / String / Object / Map / Set 类型的时候,那么 postMessage 会应用结构化克隆算法进行深拷贝。

咱们在 JS 主线程和 WebWorkers 之间或不同 page 之间进行数据传输的性能测试。如下图所示,测试环境是 x86_64 window10 的电脑。测试后果如下:

咱们预处理后的数据大略在 200KB 以下,所以能够从上图比照看出,工夫开销会在 1.68ms 以下。这种性能开销简直能够忽略不计。

如果你想要防止结构化拷贝,那么能够采纳 SharedArrayBuffer。顾名思义,SharedArrayBuffer 原理是让主线程与 Worker 共享一块内存区域,做到同时存取数据。

然而与所有的共享内存办法一样(包含原生的),SharedArrayBuffer 也会呈现资源竞争的问题。那么这时候就须要 JS 引入额定的机制来解决竞争。JavaScript 中的 Atomics 就是为解决这个问题而诞生的。

咱们声网在做人像宰割的时候也尝试过 SharedArrayBuffer,也发现了它还会引发一些问题。首先一点就是兼容性问题。目前只有 Chrome 67 版本以上能应用 SharedArrayBuffer。

要晓得,在 2018 之前,Chrome、Firefox 两个平台都反对 SharedArrayBuffer,然而 18 年所有 CPU 都被爆出了两个重大破绽,Meltdown 和 Spectre,它们会导致过程之间的数据隔离被突破,于是两个浏览器就禁用了 SharedArrayBuffer。直到 Chrome 67 做了站点上的过程隔离之后,才又开始容许应用 SharedarrayBuffer。

另一个问题就是开发难度比拟高。为解决资源竞争引入的 Atomics 对象使前端开发难度不亚于原生语言的多线程编程。

WebAssembly 模块的性能与实现策略

WebAssembly 次要负责人像宰割。咱们要实现的次要性能以及实现策略如下:

其中,机器学习模型会有不同的向量、矩阵的运算框架。以 TensorFlow 为例,它有三套运算框架:XNNPACK、Eigen、ruy。实际上它们在不同平台上的性能都有差别。咱们对此也进行了测试。在 x86_64 window10 环境下的测试后果如下。能够显著看到在咱们的解决场景下 XNNPACK 的体现是最好的,因为它是专门针对浮点运算进行了优化的运算框架。

这里咱们只是展现了 x86 下的运算测试后果,并不能代表所有平台上的最终后果。因为 ruy 这个框架是 TensorFlow 在挪动平台上的默认运算框架,它对 ARM 架构优化更好。所以咱们也在别的不同平台上进行了测试。这里就不做一一分享了。

WASM 多线程

开启 WASM 多线程可将 pthread 映射到 Web Workers,将 pthread mutex 办法映射到 Atomics 办法。在开启多线程之后,人像宰割场景在 4 线程时性能晋升达到最大值,晋升幅度达到了 26%。线程的应用不是越多越好,因为自身会有调度开销。

最初,咱们在通过人像宰割解决后,会通过 WebGL 来实现图像的滤波、抖动打消与画面合成,最初会失去下图的成果。

总结

目前在应用 WebAssembly 的过程中还存在一些痛点。

首先在上文提到过,咱们会通过 SIMD 指令来优化计算效率。目前 WebAssembly 的 SIMD 指令优化仅反对 128-bit 数据宽度。所以目前社区中也有很多人提出,如果能够实现对 256-bit AVX2 及 512-bit AVX512 指令的反对能进一步改善并行运算性能。

第二,目前 WebAssambly 是无奈间接拜访 GPU 的。如果它可能提供较间接的 OpenGL ES 调用能力,则可防止 OpenGL ES 到 WebGL 的 JSBridge 性能开销。

第三,目前 WebAssambly 还无奈间接拜访音视频数据。从 Camera 和 Mic 采集的数据须要通过较多的解决步骤能力达到 wasm。

最初,针对 Web 端人像宰割,咱们总结了几点:

  • WebAssembly 是 Web 平台应用机器学习的正确办法之一。
  • 特定状况下启用 SIMD、多线程带来性能晋升有显著意义。
  • 当根本运算性能和算法设计较差时,SIMD、多线程带来的性能晋升意义不大。
  • 应用 WebGL 进行视频解决和渲染时,WebAssembly 输入数据需放弃 WebGL 纹理采样的格局兼容。
  • 使用 WebAssembly 进行实时视频解决时需思考整个 Web 解决流程中的要害开销,并做适合优化晋升整体性能。

如果想理解更多对于 Web 端人像宰割的相干实践经验,欢送拜访 rtcdeveloper.com 发帖与咱们交换。浏览更多技术实际干货,请拜访 agora.io/cn/community。

正文完
 0