我正在尝试使用HTML5 Web Audio API创建均衡器类型的图形,但是由于某些原因,数据从未带入MediaElementSource中。

$('.table').on('click', 'tr', function() {
    if ($(this) != $('.table tr:first-child')) {
        var src = $(this).children().first().attr('data-src');
        var audio = new Audio();
        audio.src = src;
        audio.controls = true;
        $('.file-playlist').append(audio);
        console.log(audio);
        audio.load();
        audio.play();
        context = new webkitAudioContext();
        console.log(context);
        analyser = context.createAnalyser();
        console.log(analyser);
        source = context.createMediaElementSource(audio);
        console.log(source);
        source.connect(analyser);
        console.log(source);
        analyser.connect(context.destination);
        console.log(analyser);
        rafCallback();
    }
});

在上面的函数中,我创建了一个audio元素并将其用作上下文的MediaElementSource的源,但是我找不到一些问题,因为在控制台中,AudioContext的activeSourceCount属性始终为0,这意味着它从未收到我给它作为参数的音频元素。

编辑:

我根据idbehold所说的修改了我的代码;但是,现在我有2个错误,InvalidStateError: DOM Exception 11行上的source = context.createMediaElementSource(audio);TypeError: Cannot read property 'frequencyBinCount' of undefined行上的var freqByteData = new Uint8Array(analyser.frequencyBinCount);。此外,MediaElementSource仍然具有0 activeSourceCounts。
$(document).ready(function() {
    var context = new webkitAudioContext();
    console.log(context);
    var audio;
    var source;
    $('.table').on('click', 'tr', function() {
        if ($(this) != $('.table tr:first-child')) {
            var src = $(this).children().first().attr('data-src');
            if (audio) {
                audio.remove();
                audio = new Audio();
                audio.src = src;
                audio.controls = true;
                $('.file-playlist').append(audio);
                console.log(audio);
                audio.addEventListener("canplay", function(e) {
                    analyser = context.createAnalyser();
                    console.log(analyser);
                    source.disconnect();
                    source = context.createMediaElementSource(audio);
                    console.log(source);
                    source.connect(analyser);
                    console.log(source);
                    analyser.connect(context.destination);
                    console.log(analyser);
                    audio.load();
                    audio.play();
                }, false);
            }
            else {
                audio = new Audio();
                audio.src = src;
                audio.controls = true;
                $('.file-playlist').append(audio);
                console.log(audio);
                audio.addEventListener("canplay", function(e) {
                    analyser = (analyser || context.createAnalyser());
                    console.log(analyser);
                    source = context.createMediaElementSource(audio);
                    console.log(source);
                    source.connect(analyser);
                    console.log(source);
                    analyser.connect(context.destination);
                    console.log(analyser);
                    audio.load();
                    audio.play();
               }, false);
            }
        }
        rafCallback();
    });
});

编辑2:

在我的rafCallback()函数中,我注意到从未处理过Uint8Array的数据,因此我添加了getByteFrequencyData(analyser.frequencyBinCount);来修复所有问题。

最佳答案

您只能在每个窗口中创建一个AudioContext,并且应该等到音频的canplay事件触发后再设置MediaElementSource。使用完后,还应该断开MediaElementSource的连接。

这是我用来回答类似问题的示例:http://jsbin.com/acolet/1/

07-24 09:44