使用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的案例,你們能夠看一下
若是您有什麼建議、意見能夠留言