我们一直在开发一个基于 JavaScript 的音频聊天客户端,它在浏览器中运行并通过 WebSocket 将音频样本发送到服务器。我们之前尝试使用 Web Audio API 的 ScriptProcessorNode 来获取样本值。这在我们的台式机和笔记本电脑上运行良好,但从我们必须支持的手持平台传输时,我们的音频质量很差。我们将此归因于记录在案的脚本处理器性能问题 ( https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API )。在手持设备上,脚本处理器缓冲区大小为 2048,音频始终存在中断。在下一个最大大小间隔 (4096) 处,音频很流畅(没有中断),但延迟太长(大约两秒)。
我们从 ScriptProcessorNode 得到的结果促使我们对 Audio Worklet 进行了实验。不幸的是,通过我们的工作集实现,音频质量更差:中断和延迟,即使在我们的笔记本电脑上也是如此。我想知道是否有办法调整我们的工作集实现以获得更好的性能,或者我们所经历的是否可以从音频工作集的当前状态(Chromium 问题796330、813825和836306似乎相关)。
以下是有关代码功能的更多详细信息:
- 使用从 getUserMedia 获得的 MediaStream 创建一个 MediaStreamStreamSourceNode。
- 将源节点连接到我们的工作节点实现(扩展 AudioWorkletNode)。
- 我们的worklet 处理器实现(扩展AudioWorkletProcessor)缓冲作为“输入”参数到达其处理方法的块。
- 当缓冲区已满时,使用 MessagePort 将缓冲区内容发送到工作集节点。
- Worklet 节点通过 WebSocket 连接传输缓冲区内容。
处理方法如下。var "samples" 是一个 Float32Array,它被初始化为缓冲区大小并被重用。我已经对缓冲区大小进行了一些试验,但似乎没有影响。该方法基于AudioWorklet 的第 4.1 节中的指导:Web 音频的未来以最小化内存分配。
if (micKeyed == true) {
if (inputs[0][0].length == framesPerBlock) {
samples.set(inputs[0][0], currentBlockIndex * framesPerBlock);
currentBlockIndex++;
if (currentBlockIndex == lastBlockIndex) {
// console.log('About to send buffer.');
this.port.postMessage(samples);
currentBlockIndex = 0;
}
} else {
console.error("Got a block of unexpected length!!!");
}
}
return true;
目前在 CentOS 7 上运行 Chrome 72.0.3626.109 的 PC 进行测试。我们的手持设备是 Panasonic FZ-N1,在 Android 6.0.1 上运行 Chrome 72.0.3626.105。
感谢您的阅读以及您可能提供的任何建议。