将 AudioWorkletProcessor 与 MediaStream 源一起使用并在已经 运行 时连接蓝牙设备时会发生音频失真

Audio distortion occurs when using AudioWorkletProcessor with a MediaStream source and connecting a bluetooth device while it is already running

在我们的项目中,我们使用 AudioContext 将输入从麦克风连接到 AudioWorkletProcessor 并输出到 MediaStream。最终,这会在 WebRTC 调用中发送给其他对等方。

如果有人加载页面,音频总是听起来不错。但是,如果他们连接笔记本电脑麦克风或网络摄像头等有线麦克风,然后连接蓝牙设备(如 airpods 或耳机),则音频会失真并发出机器人声音。

如果我们撕掉所有其他代码并简化它,我们仍然有问题。

bypassProcessor.js

// Basic processor that wires input to output without transforming the data
// https://github.com/GoogleChromeLabs/web-audio-samples/blob/main/audio-worklet/basic/hello-audio-worklet/bypass-processor.js

class BypassProcessor extends AudioWorkletProcessor {
  process(inputs, outputs) {
    const input = inputs[0];
    const output = outputs[0];

    for (let channel = 0; channel < output.length; ++channel) {
      output[channel].set(input[channel]);
    }

    return true;
  }
}

registerProcessor('bypass-processor', BypassProcessor);

main.js

const microphoneStream = await navigator.mediaDevices.getUserMedia({
  audio: true, // have also tried { channelCount: 1 } and { channelCount: { exact: 1 } }
  video: false
})

const audioCtx = new AudioContext()

const inputNode = audioCtx.createMediaStreamSource(microphoneStream)

await audioCtx.audioWorklet.addModule('worklet/bypassProcessor.js')
const processorNode = new AudioWorkletNode(audioCtx, 'bypass-processor')

inputNode.connect(processorNode).connect(audioCtx.destination)

有趣的是,我发现如果您注释掉 2 条音频工作集线并创建一个简单的增益节点,那么它工作正常。

// await audioCtx.audioWorklet.addModule('worklet/bypassProcessor.js')
// const processorNode = new AudioWorkletNode(audioCtx, 'bypass-processor')
const gainNode = audioCtx.createGain()

此外,如果您只是创建 AudioWorkletNode,甚至不将其连接到其他节点,也会重现该问题。

我在这里创建了一个重现问题的小型 React 应用程序:https://github.com/JacobMuchow/audio_distortion_repro/tree/master

我已经尝试了一些选项,例如使用 'ondevicechange' 事件检测何时发生这种情况,关闭旧的 AudioContext 和节点并重新创建所有内容,但这只在某些时候有效。如果我等待一段时间然后再次重新创建它,它会起作用,所以我担心在尝试此操作时处理器会出现某种类型的垃圾收集问题,但这可能无关紧要。

我怀疑这与采样率有关...当正确重新创建 AudioContext 时,它会从 48 kHz 切换到 16 kHz,然后听起来会找到。但有时它仍然以 48 kHz 的频率重新创建,并且听起来继续像机器人一样。

互联网上与此相关的帖子非常稀少,我希望有人对这个问题或这个 API 有具体经验,并且可以指出我需要做的不同的事情。

对于 Chrome,问题很可能 https://crbug.com/1090441 最近已修复。我觉得 Firefox 没有这个问题,但我没有检查。