WebAudio Analyzer不返回任何数据

时间:2017-11-19 18:19:53

标签: javascript html5-video web-audio web-audio-api

我想使用webAudio制作一个简单的VU Meter来指示<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;
}

2 个答案:

答案 0 :(得分:1)

首先获取要使用getByteTimeDomainData的VU表的值,而不是频率。

您的分析仪未提供读数的原因是因为音频未在任何地方路由。脚本处理器节点具有输入和输出数组,您必须将输入数组复制到输出数组以保持信号继续。 这些是onaudioprocess的事件对象的属性。 我建议删除脚本处理器节点,因为它会引入大量的音频延迟,在您的示例+脚本执行时间内至少有2048个样本。 您可以将onaudioprocess中的代码移动到请求动画帧循环中,这将不会导致音频延迟。唯一的缺点是你没有处理每一个样本,所以你可能会错过一个剪辑,你应该能够获得60 fps。 如果检测到剪辑对您的应用程序很重要,您可以在音频数据中查找它们(所有值> 1或<-1的解码音频数据) 基本上所有分析器节点都只给出了完整音频数据的一小部分,并将其从浮点数转换为字节格式。 使用bytetime域数据实际上需要比float更长的时间,因为它内部浮动并且必须转换它。 你可能想要考虑的是VU表主要使用峰值或Rms值,而不是平均值。

答案 1 :(得分:0)

@DavidSherman和@Kaiido - 感谢您的帮助。 @David,我已经将你的标记为正确的答案 - 即使我的剧本还没有实际工作 - 因为这里有一些非常有用的信息。要依次回答你的观点:

  1. 获取频域数据实际上是可行的,因为我只是得到整个频域的峰值平均值。我知道这并不像时域中的RMS那样好,它对我的​​应用程序来说已经足够好了。
  2. 感谢请求动画帧的提示 - 我现在正在使用它。
  3. 似乎我的问题是<video>元素,因为上面评论中链接的JS Fiddle有效。我需要回过头来看看我是如何生成<video>元素的。这很奇怪,因为这有效:
  4. var vid = document.getElementById('remotevideo'); vid.muted = !vid.muted;