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,我已将你的答案标记为正确答案——尽管我的脚本实际上还没有运行——因为这里有一些非常有用的信息。依次回答你的观点:

  1. 获取频域数据实际上可行,因为我只是获取整个频域的峰值平均值。我知道这在时域中不如 RMS 好,但对我的应用来说已经足够了。
  2. 感谢关于请求动画帧的提示 - 我现在正在使用它。
  3. 我的问题似乎与 <video> 元素有关,因为上面评论中链接的 JS Fiddle 有效。我需要回头看看我是如何生成 <video> 元素的。这很奇怪,因为它有效:

var vid = document.getElementById('remotevideo'); vid.muted = !vid.muted;