加载音频缓冲区并使用音频标签播放

14

我正在尝试从URL中加载音频缓冲区,然后播放它。我从这篇HTML5 Rocks教程中获取了大部分代码。

var request = new XMLHttpRequest();
request.open('GET', $(this).attr('data-url'), true);
request.responseType = 'arraybuffer';

request.onload = function() {
    console.log(request);
    context.decodeAudioData(request.response, function(buffer) {
        console.log(buffer);
        $('#play').click(function() {
              var source = context.createBufferSource();
              source.connect(context.destination);
              source.noteOn(0);
        }).removeAttr('disabled');
    }, function(err) { console.log(err); });
};
request.send();

然而,当我按下#play按钮时,没有任何反应。使用调试器检查后发现已经调用了source.noteOn(0)。所有对象都已正确加载和创建,但我听不到声音。

此外,似乎我需要重新构建一个完整的带有所有控件的播放器来使用这种方法。为了节省工作量并确保效果更好,我想把buffer放入一个<audio/>中,这样就可以在那里播放。

我知道有audio.src可以放置文件名,但我需要使用音频缓冲区。我尝试过:

audio.src = buffer;
audio.load()

但那并没有起作用。

那里有任何信息吗?

2个回答

20
为了回答真正的问题而不是只回答“不要使用音频元素”,我想提供另一种解决方案。我想展示用户音频控件,因此我需要一个解决所问问题的解决方案。
实际上,你只需要将ArrayBuffer转换为Blob,获取其URL并将其映射到<audio>元素的src属性就可以了。
const blob = new Blob([arrayBuffer], { type: "audio/wav" });
const url = window.URL.createObjectURL(blob);
audioElement.src = url;
请不要忘记相应地更改 MIME 类型,并且不要忘记调用。
window.URL.revokeObjectURL(url);

在将页面/组件卸载以进行垃圾回收时。


2
请注意,如果您需要解码arrayBuffer,则会分离缓冲区,因此您将无法创建blob。解决方案:获取arrayBuffer,创建blob,解码arrayBuffer。 - JohnDoe

2
如果您只是想播放音频文件,为了简单起见(而且不受限于webkit浏览器),您可能想使用<audio>标签。在您的示例中,您没有设置缓冲区源节点的缓冲区:
如果您想保持总体结构,您可以简单地添加一行source.buffer = buffer,如下所示:
context.decodeAudioData(request.response, function(buffer) {
    $('#play').click(function() {
          var source = context.createBufferSource();
          source.buffer = buffer;
          source.connect(context.destination);
          source.noteOn(0);
    }).removeAttr('disabled');
}, function(err) { console.log(err); })

通过将音频解码与事件处理分开,可以提高代码的可读性。

关于audio.src的另一个问题:
您应该将audio.src设置为音频文件的URL


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接