📌 前言
为什么是 restart 呢,因为我遇到的问题是点击播放后无论如何再次点击播放,它就报错
(index):41 Uncaught DOMException: Failed to execute ‘start’ on ‘AudioBufferSourceNode’: cannot call start more than once. at HTMLButtonElement.
📌 问题复现
我在页面上定义了两个按钮(一个播放按钮,一个暂停按钮)和一个选择文件的 input ,我想要实现的功能是点击播放就能播放,点击暂停就能暂停,所以呢我会定义了两个点击事件(播放和暂停)
接下来使用 audioContext
来实现音乐播放,为了兼容各个浏览器,我首先写了各个浏览器获取 audioContext
的方法
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
然后创建 createBufferSource()
对象对音频播放这个功能来说是必须的,于是就有了下面的错误代码,我紧接着就在 audioCtx
变量后面新建了 createBufferSource
变量
var AudioBufferSourceNode = audioCtx.createBufferSource()
var play = document.getElementById("play")
var pause = document.getElementById("pause")
var bufferData = null
注意:上面的 AudioBufferSourceNode 是这篇文章所述的问题所在
然后是监听 input
上的 change
事件,当用户选择音频文件后执行回调函数中的代码
document.getElementById("loadfile").addEventListener("change", function () {
var file = this.files[0] // 获取音频文件对象
// ... 其他代码
}
然后在拿到音频文件对象后创建 FileReader
对象来异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,然后监听其 load
事件,当音频文件加载完毕后使用 decodeAudioData
对其进行解码操作,decodeAudioData 中有两个参数,第一个是 audioData音频数据;第二个是一个回调函数,它返回一个 buffer
缓存,当拿到成功 buffer
后就说明音频加载完毕了,现在就可以点击播放和暂停了
document.getElementById("loadfile").addEventListener("change", function () {
var file = this.files[0]
var fr = new FileReader()
fr.addEventListener("load", function(e) {
audioCtx.decodeAudioData(e.target.result, function(buffer){
// playFun(buffer); // 解码后返回的AudioBuffer对象作为播放函数的参数传入
console.log("音乐载入完毕");
bufferData = buffer
/* 写到 decodeAudioData 事件内部,当音乐加载完毕后才能执行播放和暂停 */
// 播放
play.addEventListener("click", function () {
console.log("播放");
AudioBufferSourceNode.buffer = bufferData // AudioBuffer数据赋值给buffer属性
AudioBufferSourceNode.connect(audioCtx.destination); // 如果只是播放音频,这边就直接将AudioBufferSourceNode连接到AudioDestinationNode
AudioBufferSourceNode.start(0); // 开始播放音频
console.log("音乐状态:", audioCtx.state);
})
// 暂停
pause.addEventListener("click", function () {
console.log("暂停");
AudioBufferSourceNode.stop(0) // 停止播放音乐
console.log("音乐状态:", audioCtx.state);
})
},function(err){
console.log(err);
})
})
fr.readAsArrayBuffer(file);
})
注意:以上代码是bug代码,请谨慎复制进行使用
📌 问题解决
在我查阅大部分资料之后,同样是没有找到合适的答案,但是在寻找答案的同时也给我带来了灵感,那就是如果重复点击播放的话,而当前的 AudioBufferSourceNode 还是用的旧的(没有更新或重新赋值),则会出现本文提到的那个错误,或找不到 buffer 之类的红色错误,所以说,我应该在点击播放时为 AudioBufferSourceNode
重新赋值
一起来实现吧~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<button id="play">播放</button>
<button id="pause">暂停</button>
<input type="file" id="loadfile">
</div>
<script> var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); var AudioBufferSourceNode = null var play = document.getElementById("play") var pause = document.getElementById("pause") var bufferData = null document.getElementById("loadfile").addEventListener("change", function () { var file = this.files[0] var fr = new FileReader() fr.addEventListener("load", function(e) { audioCtx.decodeAudioData(e.target.result, function(buffer){ // playFun(buffer); // 解码后返回的AudioBuffer对象作为播放函数的参数传入 console.log("音乐载入完毕"); bufferData = buffer /* 写到 decodeAudioData 事件内部,当音乐加载完毕后才能执行播放和暂停 */ // 播放 play.addEventListener("click", function () { console.log("播放"); AudioBufferSourceNode = audioCtx.createBufferSource() // 必须在播放时重新创建 AudioBufferSourceNode 对象,否则会出现不能再次播放的问题 AudioBufferSourceNode.buffer = bufferData // AudioBuffer数据赋值给buffer属性 AudioBufferSourceNode.connect(audioCtx.destination); // 如果只是播放音频,这边就直接将AudioBufferSourceNode连接到AudioDestinationNode AudioBufferSourceNode.start(0); // 开始播放音频 console.log("音乐状态:", audioCtx.state); }) // 暂停 pause.addEventListener("click", function () { console.log("暂停"); AudioBufferSourceNode.stop(0) // 停止播放音乐 console.log("音乐状态:", audioCtx.state); }) },function(err){ console.log(err); }) }) fr.readAsArrayBuffer(file); }) </script>
</body>
</html>
📌 效果图
今天的文章使用 AudioContext restart 音频分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16059.html