首页 > 解决方案 > 什么情况下会静音

问题描述

我意识到标题可能有点令人困惑,所以让我提供一些背景信息。

我正在编写一个扩展程序来使用 Google Meet 进行一些音频操作,并且在研究了它的行为之后,我发现了一个我似乎无法解决的奇怪问题。

Google Meet 似乎使用三个<audio>元素来播放音频,每个元素都有自己的 MediaStreams。通过一些测试,似乎:

这些似乎指向 Google Meet 将源 MediaStream 连接到其音频处理图以创建可视化而不是捕获<audio>元素,因为我可以在不影响可视化的情况下交换 MediaStream。

但是,考虑到过去的信息,我注意到的另一件事似乎没有意义:

以下是通过浏览器控制台完成的一些示例代码和输出:

ac = new AudioContext();
an = ac.createAnalyser()
sn = ac.createMediaStreamSource(document.querySelectorAll("audio")[0].srcObject)
sn.connect(an)
function analyse(aNode) {
  const ret = new Float32Array(aNode.frequencyBinCount);
  aNode.getFloatTimeDomainData(ret);
  return ret;
}

analyse(an)
// > Float32Array(1024) [ 0.342987060546875, 0.36688232421875, 0.37115478515625, 0.362457275390625, 0.35150146484375, 0.3402099609375, 0.321075439453125, 0.308746337890625, 0.29779052734375, 0.272552490234375, … ]

document.querySelectorAll("audio")[0].muted = true
analyse(an)
// > Float32Array(1024) [ -0.203582763671875, -0.258026123046875, -0.31134033203125, -0.34375, -0.372802734375, -0.396484375, -0.3919677734375, -0.36328125, -0.31689453125, -0.247650146484375, … ]

// Here, I mute the microphone on *my end* through Google Meet.

analyse(an)
// > Float32Array(1024) [ -0.000030517578125, 0, 0, -0.000030517578125, -0.000091552734375, -0.000091552734375, -0.000091552734375, -0.00006103515625, 0, 0.000030517578125, … ]
// The values here are much closer to zero.

如您所见,当音频元素静音时,AnalyserNode 仍然可以接收音频,但 Meet 的可视化会中断。那是我不明白的。这个怎么可能?

当元素被静音时,连接的 AnalyserNode 怎么能不中断<audio>,但不使用其他东西.captureStream()呢?

另一个奇怪的事情是它只发生在 Chrome 上。在 Firefox 上,即使音频元素被静音,Meet 的可视化效果也能正常工作。我认为这可能与已知的 Chrome 问题有关,其中 MediaStreams 需要播放<audio>元素才能将任何内容输出到音频图(https://stackoverflow.com/a/55644983),但我看不出这将如何影响静音 <audio>元素。

标签: javascriptaudiowebrtcweb-audio-apigoogle-meet

解决方案


这有点令人困惑,但 的行为AudioElement.captureStream()实际上与使用MediaElementAudioSourceNode.

new MediaStreamAudioSourceNode(audioContext, audioElement.captureStream());

// is not equal to

new MediaElementAudioSourceNode(audioContext, audioElement);

通过调用获得的流AudioElement.captureStream()不受音频元素上任何音量变化的影响。调用AudioElement.captureStream()也不会改变音频元素本身的音量。

但是,使用 aMediaElementAudioSourceNode会将音频元素的音频重新路由到AudioContext. 音频将受到对音频元素所做的任何音量更改的影响。这意味着静音音频元素将导致静音通过管道传输到AudioContext.

最重要的是,使用 aMediaElementAudioSourceNode将使音频元素本身静音。

我假设 Google Meet 使用MediaElementAudioSourceNode每个音频元素来处理音频。


推荐阅读