使用AudioContext有下面几个好处vue
无需额外引入audio标签git
跟随系统的状态,即手机调成震动/静音模式了,这个声音也就不要出了github
能够音频解析,作特效,好比下面,一个是用canvas手写的,一个是echart作的ajax
Media实现对AudioContext的封装,使用以下canvas
<script src="media.js"></script>复制代码
souce:能够传出一个url或者一个ArrayBufferbash
options异步
loop:boolean类型,是否循环播放oop
volume:0~1,控制音量ui
analyser:是否开启音频分析,使用默认设置能够设为true;也能够是一个对象,size用于配置fftSize,默认1024this
let media = new Media(source, {
loop: true,
volume: 0.6,
analyser: {
size: 512
}
})复制代码
onload:音频加载完成,逻辑下载此事件中
onended:音频播放完触发
getData 获取分析的音频数据,类型Uint8Array,须要开启analyser选项
play 播放音频
suspend 暂停播放
start(offset) 设置音频开始播放的时刻,offset的范围为0~duration
setLoop(bool) 设置音频是否循环播放
setVolume(val) 设置音频音量,0 ~ 1.0
getCurrentTime 获取当前播放的时长
setOptions(options) 能够统一设置,如:{ loop: true, volume: 0.5 }
duration 获取音频总时长
state 获取当前音频的状态,running | suspend
volume 获取当前音量
loop 获取音频是否循环
下面说一下封装过程遇到的问题和解决办法
解决办法,声明一个delta用来保存这之间的差值,每次start需更新这个值,获取小心音频时刻时就相减,固然了,最大值不超过duration。
start(offset) {
this.delta = this.ctx.currentTime - offset
// ...}
getCurrentTime() {
return Math.min(this.ctx.currentTime - this.delta, this.duration)
}复制代码
AudioContext里面有个start(offset)方法可让音频从哪一个时刻后开始播放,可是这个方法只能使用一次,再次调用会报错,所以若是要实现用滑动条控制音频播放,必须处理start(offset)的问题。解决办法:只能从新生成source,在这以前要先调用stop,否则就会多首音频同时播放。
this.source.stop()
initBufferSource(decodedData) { this.source = this.ctx.createBufferSource() this.decodedData = decodedData this.source.buffer = this.decodedData}复制代码
本来想注册一个onended事件方便作别的操做,可是每次滑动滚动条,都会触发这个事件,而后音频并无播放完啊。找了很久发现是每次执行stop就会调用,所以在从新生成source前要解绑这个事件,而后从新绑定
this.source.onended = null
this.onended && (this.source.onended = this.onended)复制代码
里面有这样几个异步,若是开始传来的是url,会先调用request,也就是ajax请求音频资源。
还有一个是decodeAudioData,AudioContext把ArrayBuffer解码也是一个异步,好在新的API返回的是一个Promise对象。
问题是只有解码完成才能够操做音频,想了很久不知道怎么解决暂时注册一个onload事件,操做音频请在这个事件里处理,后续可能会改为返回一个Promise对象
大致是这样子的,特别小的细节就不说了,github有个vue的案例,你们能够看一下
若是您有什么建议、意见能够留言