Krisp 的音频 SDK 包括了音频去噪、行为检测、背景音消除的功能。目前 Krisp 的 SDK 已经可以在各种设备和平台上进行部署,但目前还存在的挑战是在网页端还不可用。
在网页端部署的挑战主要在于不能直接运行 C++ 实现的应用,不能使用较大的模型权重文件,以及视频中每一帧的音频 Sample 数量都是固定的 128 的问题。
网页端部署存在的挑战
对于在网页端使用由 C++ 编写的程序,一个成熟的解决方案是使用 WebAssembly(WASM) 来实现,如下图所示。WASM 是一种二进制指令格式,可以将 C++ 或其他代码编译成 WASM,并实现在浏览器中运行。而将 C++ 编译成 WASM 则是通过使用 Emscripten 来实现。Emscripten 是一个完整的 WebAssembly 的编译器工具链,专注于速度、大小和并适配于的网络平台。
由于考虑到在网页端和移动设备的使用需求,网页端不能使用较大的模型权重文件。因此在 Krisp SDK 中,其桌面端版本使用正常的模型,大小在 30~40MB 左右,而网页端则使用小模型,其大小在 2~6MB 左右。
另一方面,由于在于 web 端的音频每帧有 128 个 sample。在 web 中,音频输入和输出是以帧为单位的,每一帧由 128 个音频 sample 组成。而音频的采样率决定了在每秒会收到多少个样本,这个数值取决于所用的设备。根据采样率和采样数计算持续时间很简单,假设当前的采样率是 44100,则可以得到每一帧音频的时间为 128/44100=2.902ms。
而在浏览器与 128 个音频 sample 通信时,需要至少 10 ms 长度的音频来处理。Krisp SDK 采用的解决方案为使用两个 buffer 来进行处理,如下图所示。首先由第一个 buffer 收集从浏览器提供的每帧的 128 个 sample,并直到这些音频数据达到能够播放 10 ms 的长度后,送入到 Krisp SDK 中进行处理。随后处理完成的 10 ms 的音频输入到第二个 buffer 中,并将其分割成 128 块,构成浏览器播放所需要的 128 个 sample,最后在输入到浏览器中进行播放。
网页端 Krisp SDK 架构
在 Java script 版本的 Krisp SDK 中,其关键模块主要包括了 C++ 部分与 JS 部分其架构图如下所示。
- C++处理模块
- XNNPACK:为 WebAssembly 平台优化的 BLAS(基本线性代数子程序)库
- Emscripten 编译器(编译 WASM 模块)
- C++ 端的缓冲系统(处理浏览器的 128 个样本数)
- JS 模块
- 网络音频 Api,与 WASM 模块一起工作
该架构中仍然存在一定的缺陷。使用 WASM 的缓冲系统增加了额外的中间件,存在丢失音频数据块的风险。并且该架构中可能存在多个内存泄漏问题,如终止 AudioWorkletNode 时,以及处理采样率变化(设备变化)时。并且只能通过在客户端提供静态 URL 的方式分别提供权重文件。
因此,在后续的改进版本中尝试解决这些问题,改进后的架构图如下所示。新的架构中将所有的缓冲区移到了 JS 端,这样 SDK 就能以预期的形式接收数据,以及将所有的音频处理转移到一个新的 web worker 线程中。对 C++ 端,则使用 1tol 方法绑定以赋予 JS 端更多的灵活性。另外,修改了加载权重的方式,使用 emscripten.data 文件;增加了会话 Ids,与 web worker 一起可以同时运行多个噪声处理器。最后,为了方便起见,也将 git 子模块移至 conan 包中。
改进后的架构将所有的缓冲过程放入到了一个 JS 实现的 web worker 线程中,关闭 worker 时可以关闭其中的所有运行内容。这也解决了最初版本无法完全关闭存在内存泄漏的问题。新的架构可以针对不同的设备进行处理,并能够同时并行运行多个实例。
在后续的改进空间方面,主要集中减少 POST 信息的数量。这可以通过使用 SharedArrayBuffer 来实现,但它有一些安全问题,而且需要用户设置一些特定的头文件来工作。演讲者表示目前正试图通过缓冲系统来减少 POST 信息的数量。
来源:Kranky Geek WebRTC 2022
主讲人:Arman Jivanyan
内容整理:张一炜
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。