我正在尝试使用Web Audio API
在我的React
应用程序中播放声音。
当前在除Safari v12.1
以外的所有浏览器中播放声音。
我知道Safari在自动播放方面受到限制,并且需要用户互动才能播放声音,因此我有一个播放按钮,它会调用_play()
函数:
_play = (url, index) => {
this._getData(url);
this.source.start(index)
}
它正在调用_getData()
函数,如下所示:
_getData(url) {
this.source = this.audioContext.createBufferSource();
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = () => {
var audioData = request.response;
console.log(this.audioContext)
this.audioContext.decodeAudioData(audioData, buffer => {
this.source.buffer = buffer;
this.source.connect(this.audioContext.destination);
},
function(e){ console.log("Error with decoding audio data" + e.err); });
}
request.send();
}
this.audioContext
是使用以下命令在组件constructor
中创建的:
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
console.log(this.audioContext)
中的request.onload
在按下play之前先输出:
...然后按一下播放键:
但是没有声音在播放(在Safari中)。
我在做什么错了?
答案 0 :(得分:0)
我认为您遇到的问题是,一旦调用start(),Safari便不再允许您修改缓冲区。
例如,当您按下播放按钮时,以下页面确实在Safari中播放了一秒钟的噪音。
<!DOCTYPE html>
<html>
<body>
<button id="play-button">play</button>
<script>
document
.getElementById('play-button')
.addEventListener('click', () => {
const audioContext = new AudioContext();
const audioBufferSourceNode = audioContext.createBufferSource();
const sampleRate = audioContext.sampleRate;
const audioBuffer = audioContext.createBuffer(1, sampleRate, sampleRate);
const channelData = audioBuffer.getChannelData(0);
for (let i = 0; i < sampleRate; i += 1) {
channelData[i] = (Math.random() * 2) - 1;
}
audioBufferSourceNode.buffer = audioBuffer;
audioBufferSourceNode.connect(audioContext.destination);
audioBufferSourceNode.start(audioContext.currentTime);
});
</script>
</body>
</html>
但是如果您对其稍加修改,它将不再起作用。在分配缓冲区之前启动audioBufferSourceNode时,将不再有输出。
audioBufferSourceNode.connect(audioContext.destination);
audioBufferSourceNode.start(audioContext.currentTime);
audioBufferSourceNode.buffer = audioBuffer;
我想您可以通过在启动源之前等待HTTP响应和音频解码来使代码正常工作。在执行this.source.buffer = buffer
之前,请确保执行this.source.start(index)
。
我希望这会有所帮助。