WebAudio Analyzer 不返回任何数据
WebAudio Analyser not returning any data
我想使用 webAudio 制作一个简单的 VU 表来指示 <video>
元素的音量,其中包含来自网络摄像头的实时流(使用 Janus 进行流式传输)。我从其他示例创建了以下函数。它在流初始化后调用,但 analyser.getByteFrequencyData(array);
方法生成的数组全为零。
function meterInit(){
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
videoElement = document.getElementById('remotevideo');
source = audioCtx.createMediaElementSource(videoElement);
analyser = audioCtx.createAnalyser();
analyser.smoothingTimeConstant = 0.2;
analyser.fftSize = 512;
analyser.minDecibels = -200;
source.connect(analyser);
analyser.connect(audioCtx.destination);
javascriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
javascriptNode.connect(audioCtx.destination);
analyser.connect(javascriptNode);
javascriptNode.onaudioprocess = function() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var average = getAverageVolume(array)
document.getElementById('vuMeter').value = average;
}
}
function getAverageVolume(array) {
var values = 0;
var average;
var length = array.length;
// get all the frequency amplitudes
for (var i = 0; i < length; i++) {
values += array[i];
}
average = values / length;
return average;
}
首先要使用 getByteTimeDomainData 而不是频率来获取 VU 表的值。
您的分析仪没有提供读数的原因是音频没有路由到任何地方。脚本处理器节点有一个输入和一个输出数组,您必须将输入数组复制到输出数组以保持信号继续。
这些是 onaudioprocess 的事件对象的属性。
我建议删除脚本处理器节点,因为它会引入大量音频延迟,示例中至少有 2048 个样本 + 脚本执行时间。
您可以将 onaudioprocess 中的代码移动到请求动画帧循环中,这将不会导致音频延迟。唯一的缺点是你没有处理每一个样本,所以你可能会错过一个剪辑,但你应该能够获得 60 fps。
如果检测剪辑对您的应用程序很重要,您可以在音频数据中查找它们(解码音频数据的所有值 > 1 或 < -1)
基本上,所有分析器节点都为您提供完整音频数据的一小部分,并将其从浮点格式转换为字节格式。
使用字节时间域数据实际上比浮点数需要更长的时间,因为它在内部是浮点数并且必须对其进行转换。
您可能需要考虑的一点是,VU 表主要使用峰值或 Rms 值,而不是平均值。
@DavidSherman 和@Kaiido - 感谢您的帮助。 @David,我已将你的答案标记为正确答案——尽管我的脚本实际上还没有运行——因为这里有一些非常有用的信息。依次回答你的观点:
- 获取频域数据实际上可行,因为我只是获取整个频域的峰值平均值。我知道这在时域中不如 RMS 好,但对我的应用来说已经足够了。
- 感谢关于请求动画帧的提示 - 我现在正在使用它。
- 我的问题似乎与
<video>
元素有关,因为上面评论中链接的 JS Fiddle 有效。我需要回头看看我是如何生成 <video>
元素的。这很奇怪,因为它有效:
var vid = document.getElementById('remotevideo');
vid.muted = !vid.muted;
我想使用 webAudio 制作一个简单的 VU 表来指示 <video>
元素的音量,其中包含来自网络摄像头的实时流(使用 Janus 进行流式传输)。我从其他示例创建了以下函数。它在流初始化后调用,但 analyser.getByteFrequencyData(array);
方法生成的数组全为零。
function meterInit(){
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
videoElement = document.getElementById('remotevideo');
source = audioCtx.createMediaElementSource(videoElement);
analyser = audioCtx.createAnalyser();
analyser.smoothingTimeConstant = 0.2;
analyser.fftSize = 512;
analyser.minDecibels = -200;
source.connect(analyser);
analyser.connect(audioCtx.destination);
javascriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
javascriptNode.connect(audioCtx.destination);
analyser.connect(javascriptNode);
javascriptNode.onaudioprocess = function() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var average = getAverageVolume(array)
document.getElementById('vuMeter').value = average;
}
}
function getAverageVolume(array) {
var values = 0;
var average;
var length = array.length;
// get all the frequency amplitudes
for (var i = 0; i < length; i++) {
values += array[i];
}
average = values / length;
return average;
}
首先要使用 getByteTimeDomainData 而不是频率来获取 VU 表的值。
您的分析仪没有提供读数的原因是音频没有路由到任何地方。脚本处理器节点有一个输入和一个输出数组,您必须将输入数组复制到输出数组以保持信号继续。 这些是 onaudioprocess 的事件对象的属性。 我建议删除脚本处理器节点,因为它会引入大量音频延迟,示例中至少有 2048 个样本 + 脚本执行时间。 您可以将 onaudioprocess 中的代码移动到请求动画帧循环中,这将不会导致音频延迟。唯一的缺点是你没有处理每一个样本,所以你可能会错过一个剪辑,但你应该能够获得 60 fps。 如果检测剪辑对您的应用程序很重要,您可以在音频数据中查找它们(解码音频数据的所有值 > 1 或 < -1) 基本上,所有分析器节点都为您提供完整音频数据的一小部分,并将其从浮点格式转换为字节格式。 使用字节时间域数据实际上比浮点数需要更长的时间,因为它在内部是浮点数并且必须对其进行转换。 您可能需要考虑的一点是,VU 表主要使用峰值或 Rms 值,而不是平均值。
@DavidSherman 和@Kaiido - 感谢您的帮助。 @David,我已将你的答案标记为正确答案——尽管我的脚本实际上还没有运行——因为这里有一些非常有用的信息。依次回答你的观点:
- 获取频域数据实际上可行,因为我只是获取整个频域的峰值平均值。我知道这在时域中不如 RMS 好,但对我的应用来说已经足够了。
- 感谢关于请求动画帧的提示 - 我现在正在使用它。
- 我的问题似乎与
<video>
元素有关,因为上面评论中链接的 JS Fiddle 有效。我需要回头看看我是如何生成<video>
元素的。这很奇怪,因为它有效:
var vid = document.getElementById('remotevideo');
vid.muted = !vid.muted;