使用网络音频 api 播放简单的声音

Posted

技术标签:

【中文标题】使用网络音频 api 播放简单的声音【英文标题】:Playing a simple sound with web audio api 【发布时间】:2015-05-27 12:46:08 【问题描述】:

我一直在尝试按照一些教程中的步骤,使用按钮通过网络音频 API 播放简单的编码本地 wav 或 mp3 文件。我的代码如下(testAudioAPI.js):

window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var myBuffer;

clickme = document.getElementById('clickme');
clickme.addEventListener('click',clickHandler);

var request = new XMLHttpRequest();

request.open('GET', 'WoodeBlock_SMan_B.wav', true);

request.responseType = 'arraybuffer';

// Decode asynchronously
request.onload = function() 
  context.decodeAudioData(request.response, function(theBuffer) 
    myBuffer = theBuffer;
  , onError);

request.send();

function playSound(buffer) 
  var source = context.createBufferSource(), g = context.createGain();
  source.buffer = buffer;
  source.start(0);
  g.gain.value = 0.5;
  source.connect(g);
  g.connect(context.destination);


function clickHandler(e) 
    playSound(myBuffer);

html 文件如下所示:

    <!doctype html>
<html>
    <body>
        <button id="clickme">Play</button>
        <script src='testAudioAPI.js'></script>
    </body>
</html>

但是,没有任何声音。我已经尝试了几个sn-ps,但我仍然无法弄清楚。当我尝试通过创建振荡器节点来合成声音来生成声音时,我确实得到了声音,但没有来自本地文件的缓冲区。这里会有什么问题?谢谢你们。

【问题讨论】:

请参阅***.com/questions/26169678/… 以获得可能的解释 您是否在控制台中遇到任何错误? 另见***.com/questions/29708513/… 【参考方案1】:

现代 ES6 的简约方法。

    新的 AudioContext(); context.createBufferSource(); source.buffer = 音频缓冲区; audioBuffer通过fetch请求ArrayBuffer数据,然后decodeAudioData解码到AudioBuffer。 source.start()
<button id="start">playSound</button>
const audioPlay = async url => 
  const context = new AudioContext();
  const source = context.createBufferSource();
  const audioBuffer = await fetch(url)
    .then(res => res.arrayBuffer())
    .then(ArrayBuffer => context.decodeAudioData(ArrayBuffer));

  source.buffer = audioBuffer;
  source.connect(context.destination);
  source.start();
;

document.querySelector('#start').onclick = () => audioPlay('music/music.mp3');

停止播放:source.stop();

Web Audio API 不能自动播放,需要事件触发。

创建多个AudioContext 对象会导致错误,您应该注销然后创建它们。

Failed to construct 'AudioContext': number of hardware contexts reached maximum

const audioPlay = (() => 
  let context = null;
  return async url => 
    if (context) context.close();
    context = new AudioContext();
    const source = context.createBufferSource();
    source.buffer = await fetch(url)
      .then(res => res.arrayBuffer())
      .then(arrayBuffer => context.decodeAudioData(arrayBuffer));
    source.connect(context.destination);
    source.start();
  ;
)();

document.querySelector('#start').onclick = () => audioPlay('music/music.mp3');

【讨论】:

我最初使用的是 howler 库,它非常有问题,尤其是在 ios 上。切换到直接使用网络音频api,在ios、android或windows上没有问题。【参考方案2】:

本地文件,嗯?您只是从文件系统中获取它们(例如“file://”),还是运行了本地 Web 服务器?

据我回忆,在大多数(所有?)浏览器中,直接从文件系统提供服务违反了 CORS,这将阻止您的 AJAX 请求成功。

也许可以尝试使用python -m SimpleHTTPServer 或类似名称提供页面,然后通过http://localhost:8000 访问它。

据我所知,您的所有代码看起来都很好。

【讨论】:

嗨,是的,我正在从文件系统中获取它们。但我会尝试为该页面提供服务……那是我猜想生成 XMLHttpRequest 的唯一方法……谢谢!【参考方案3】:

您有一个未定义的onError 呼叫。

除此之外它应该可以工作,但不能与 Chrome 一起工作,因为 Chrome 会阻止所有 XMLHttpRequest 到本地文件。但以 Firefox 为例,一旦您定义(或摆脱)对onError 的调用,它就应该可以工作。

【讨论】:

Chrome 有一个不错的插件,它允许所有跨源调用:chrome.google.com/webstore/detail/allow-control-allow-origi/… 您好,感谢您提供有关使用 Chrome 进行本地文件的提示。您知道使用 javascript 代码加载本地文件的任何其他方式吗?我刚刚删除了对“onError”的调用,但恐怕它仍然无法在 Firefox 上运行...... 然后你必须检查你的控制台,你的代码看起来很好,除了 chrome 上的本地文件和 onerror 没有被定义。也就是说,除非您不需要高级功能,否则 html 中有一个音频元素,它比 AudioContext 更易于使用。这里:developer.mozilla.org/en-US/docs/Web/Guide/HTML/… 是的,@julien,我知道这一点。实际上,我的目标是用网络音频做更复杂的事情,而不仅仅是播放文件,这就是为什么我从简单的事情开始使用网络音频 API。再次感谢! 这并没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。

以上是关于使用网络音频 api 播放简单的声音的主要内容,如果未能解决你的问题,请参考以下文章

预计算的 Web 音频 API 时域和频谱图可视化

音频设备测试无法播放声音

网页音频API 第一章

从 UDP 接收到的消息播放音频,点击声音(Naudio API)

无法播放网络音频文件

Python编程实例-播放音频汇总(Linux环境)