HTML5音频API - “音频资源不可用于AudioContext构建” [英] HTML5 Audio API - "audio resources unavailable for AudioContext construction"

查看:127
本文介绍了HTML5音频API - “音频资源不可用于AudioContext构建”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为HTML5音频创建图形均衡器类型可视化 - 此时仅使用webkitAudioContext创建Chrome。

I'm trying to create a graphic equalizer type visualization for HTML5 audio - Chrome only at this point, using webkitAudioContext.

我发现了异常且不可预测的行为当我试图改变音频的来源,即播放不同的歌曲。我读到某个地方,我应该等到音频上的canplay事件被触发,然后再连接到上下文/分析器:

I'm finding unusual and unpredictable behaviour when I try to change the source of the audio i.e. to play a different song. I read somewhere I should wait until the "canplay" event on the audio is triggered before connecting it to the context / analyser:

var context, sourceNode, analyser, javascriptNode, audio;

var ctx = $("#songcanvas").get()[0].getContext("2d");    


function loadSong(url) { 
    if (audio!=undefined) { audio.pause(); }
    audio = new Audio();
    audio.src = url;
    audio.addEventListener("canplay", function(e) {
         setupAudioNodes();
    }, false);
}

function setupAudioNodes() {
        context = new webkitAudioContext();
        javascriptNode = context.createJavaScriptNode(2048, 1, 1);
        javascriptNode.connect(context.destination);

        analyser = context.createAnalyser();
        analyser.smoothingTimeConstant = 0.3;
        analyser.fftSize = 512;

        sourceNode = context.createMediaElementSource(audio);
        sourceNode.connect(analyser);
        analyser.connect(javascriptNode);

        sourceNode.connect(context.destination);

        javascriptNode.onaudioprocess = function() {
            var array =  new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteFrequencyData(array);
            ctx.clearRect(0, 0, 1000, 325);
            ctx.fillStyle="rgba(32, 45, 21,1)";
            drawSpectrum(array);
        }
        audio.play();
}

function drawSpectrum(array) {
    for ( var i = 0; i < (array.length); i++ ){
        var value = array[i];
        ctx.fillRect(i*5,325-value,3,325);
    }
};

前三次或四次我更改源,它可以工作,然后最终失败并出现Uncaught SyntaxError :音频资源无法用于AudioContext构建

The first three or four times I change the source, it works, then eventually fails with "Uncaught SyntaxError: audio resources unavailable for AudioContext construction"

此处完整演示 http: //jsfiddle.net/eAgQN/

推荐答案

我建议不要创建 JavaScriptNode 如果您只是想绘制频谱。而是尝试使用 requestAnimationFrame 方法,因为它将节省CPU周期并使您更接近常量60fps(如果您的窗口/选项卡在后台作为任何函数,则特别有用包含在 requestAnimationFrame 中将等待窗口再次聚焦,然后才开始拍摄。)

I'd recommend staying away from creating a JavaScriptNode if you're simply going to be drawing the spectrum. Instead try utilizing the requestAnimationFrame method as it will save CPU cycles and will get you closer to a constant 60fps (is especially useful if your window/tab is in the background as any function wrapped in a requestAnimationFrame will wait until the window is in focus again before firing).

你原因是什么可能是因为A)你只能在每个窗口创建一个 AudioContext ,B)你应该断开 MediaElementSource 当你使用完毕后,C)你也应该删除实际的音频元素。

The reason you're probably getting that error is because A) you can only create a single AudioContext per window, B) you should be disconnecting the MediaElementSource when you're finished using it, and C) you should also be removing the actual Audio element too.

以下是我在上面概述的更改的演示: http://jsbin.com/acolet/1/

Here's a your demo with the changes I outlined above: http://jsbin.com/acolet/1/

window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext(),
    audioAnimation, sourceNode, analyser, audio,
    songs  = document.getElementById('songs'),
    canvas = document.getElementById('songcanvas'),
    WIDTH  = canvas.width,
    HEIGHT = canvas.height,
    // get the context from the canvas to draw on
    ctx = canvas.getContext('2d'),
    gradient = ctx.createLinearGradient(0, 0, 0, HEIGHT),
    bar = { width: 2, gap: 2, ratio: HEIGHT / 256 };

gradient.addColorStop(1.00,'#000000');
gradient.addColorStop(0.75,'#ff0000');
gradient.addColorStop(0.25,'#ffff00');
gradient.addColorStop(0.00,'#ffff00');
ctx.fillStyle = gradient;

songs.addEventListener('click', loadSong, false);

function loadSong(e) {
  e.preventDefault();
  var url = e.target.href;
  if (!url) return false;
  if (audio) audio.remove();
  if (sourceNode) sourceNode.disconnect();
  cancelAnimationFrame(audioAnimation);
  audio = new Audio();
  audio.src = url;
  audio.addEventListener('canplay', setupAudioNodes, false);
}

function setupAudioNodes() {
  analyser = (analyser || context.createAnalyser());
  analyser.smoothingTimeConstant = 0.8;
  analyser.fftSize = 512;

  sourceNode = context.createMediaElementSource(audio);
  sourceNode.connect(analyser);
  sourceNode.connect(context.destination);
  
  audio.play();
  drawSpectrum();
}

function drawSpectrum() {
  var freq = new Uint8Array(analyser.frequencyBinCount);
  analyser.getByteFrequencyData(freq);
  ctx.clearRect(0, 0, WIDTH, HEIGHT);
  audioAnimation = requestAnimationFrame(drawSpectrum);
  for ( var i = freq.length - 1; i >= 0 ; i-- ){
    var x = i * (bar.width + bar.gap);
    var y = HEIGHT - (freq[i] * bar.ratio);
    ctx.fillRect(x, y, bar.width, HEIGHT);
  }
}

body { font-family: sans-serif; background-color: #000; }
a { color: #fff; text-decoration: none; }
ul { padding: 20px 0; width: 100px; }
ul, canvas { float: left; }

<ul id="songs">
  <li><a class="song" href="http://upload.wikimedia.org/wikipedia/en/4/45/ACDC_-_Back_In_Black-sample.ogg">ACDC</a></li>
  <li><a class="song" href="http://upload.wikimedia.org/wikipedia/en/9/9f/Sample_of_%22Another_Day_in_Paradise%22.ogg">Phil Collins</a></li>
  <li><a class="song" href="http://upload.wikimedia.org/wikipedia/en/1/1f/%22Layla%22%2C_Derek_and_the_Dominos_song_%28sample%29.ogg">Clapton</a></li>
</ul>
<canvas id="songcanvas" width="400" height="128"></canvas>

这篇关于HTML5音频API - “音频资源不可用于AudioContext构建”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆