javascript - 什么情况下会静音
问题描述
我意识到标题可能有点令人困惑,所以让我提供一些背景信息。
我正在编写一个扩展程序来使用 Google Meet 进行一些音频操作,并且在研究了它的行为之后,我发现了一个我似乎无法解决的奇怪问题。
Google Meet 似乎使用三个<audio>
元素来播放音频,每个元素都有自己的 MediaStreams。通过一些测试,似乎:
- 静音该
<audio>
元素会停止 Google Meet 关于谁在说话的音频可视化。 - 交换
.srcObject
两个音频元素的属性然后调用.play()
它们不会影响 Google Meet 的音频可视化。
这些似乎指向 Google Meet 将源 MediaStream 连接到其音频处理图以创建可视化而不是捕获<audio>
元素,因为我可以在不影响可视化的情况下交换 MediaStream。
但是,考虑到过去的信息,我注意到的另一件事似乎没有意义:
MediaStreamAudioSourceNode
从元素的.srcObject
中添加一个新的<audio>
并将其连接到一个AnalyserNode
表明,即使我将<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>
元素。
解决方案
这有点令人困惑,但 的行为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
每个音频元素来处理音频。
推荐阅读
- hazelcast-jet - 使用 Hazelcast Jet 可以下沉到 java 列表?
- python - 使用 optirun 在虚拟环境中运行 python 脚本
- html - CSS 弹出菜单
- javascript - 是否可以访问 d3-shape 的 curveMonotoneX 算法?
- oracle - 如何在 PLSQL 中创建内存数据结构列表
- scala - 如何在scala中将几个Dataframes组合在一起?
- django - SummernoteInplaceWidget 无法正常工作 - summernote-lite
- c# - 访问冲突异常保存位图
- angular - 在 Observable 上调用observer.next()
在 RxJS 中 - r - 如何在 Jupyter Notebook 中使用与 tidyverse 兼容的代码格式化包?