Audio在移動端的實踐

好久沒寫blog了,有三點原因,一是懶,二是懶,三是懶。

因為最近項目里面有個需求,要在移動端用web的Audio實現音頻播放。本想說臣妾做不到啊~然而,還是開始挖坑了。在這里記錄下各種坑死人的問題。

準備

先看兼容性(下圖),可以看到在移動端上用是完全可行的(理論上):

compatibility.png

我們再分別看看audio提供的屬性,方法和事件

屬性

params.png

方法

way.png

事件

event.png

具體的可以戳這里

實踐

其實按照上面的方法,隨便怎么寫怎么玩都可以,但主要有以下幾個問題要解決的:

1.預加載的問題;
2.加載進度條問題;
3.多個音頻文件切換問題;
4.其他的兼容性問題。

1.預加載的問題

我們先來看預加載的流程(如下),先用load去加載音頻,當音頻可以播放就會觸發canplay事件,表示加載已經完成,可以播放,完美。

patten1.png

但是,理想和現實總是有區別的,在表現不一的手機上就有問題了。

問題一:load方法調用了沒效果,根本沒有加載音頻,要調用play方法才開始加載。

問題二:在三星note3 和錘子T1手機上,有50%的幾率預加載失敗。如果預加載失敗,要切換好幾次播放/暫停狀態才開始加載播放,或者一直沒反應。

問題三:一般觸發load加載音頻文件后,音頻文件緩沖好會觸發canplay事件的。

在安卓下,觸發canplay事件,會有下面問題:

  • 360瀏覽器audio.seekablefalse;
  • uc瀏覽器,魅族自帶瀏覽器,微信audio.buffered.length居然為0;

在iOS下,有以下問題:

  • canplay事件觸發后,微信的audio.seekablefalse
  • safariload了之后,canplay事件不觸發,點擊play后才觸發 (9.1版本是正常的);

看到這里是不是覺得坑大了,想逃?不要急,接著看。

解決方法

上面問題總的來說有倆個,一個是加載進度,另外一個就是播放Bug了。這里主要說下問題二的解決方法。

調用load事件后,對加載進度進行檢測,如果直到canplay觸發,加載進度一直為0,就判斷為預加載失敗。然后在點擊播放的,設置進度audio.currentTime = 1;,這樣就會再次觸發加載。這里還有個問題,如果是用zeptotap監聽點擊播放事件,可以再次加載,但一直不播放,要監聽touchend這些事件才行(這個問題糾結N久)。
這樣調整后,在三星note 3 和錘子T1這些有問題的手機上基本沒什么問題了。

2.加載進度條問題

加載進度,瀏覽器提供了progress事件,但這個事件會有一些小問題,所以采用setInterval的去實行。正常來說在canplay的時候顯示進度條:

onCanplay: function () {
    this.seekable = this.audio.seekable && this.audio.seekable.length > 0;

    if ( this.seekable ) {
        this.timer = setInterval(this.onProgress.bind(this), 500);
    }

    var name = this.list[this.index].name || '',
        time = this.list[this.index].time || '';

    this.trigger('canplay', time, name, this.list[this.index]);
},

onProgress: function () {
    if ( this.audio && this.audio.buffered !== null && this.audio.buffered.length ) {
        this.duration = this.audio.duration === Infinity ? null : this.audio.duration;
        this.load_percent = ((this.audio.buffered.end(this.audio.buffered.length - 1) / this.duration) * 100).toFixed(4);
        if (isNaN(this.load_percent)) {
            this.load_percent = 0;
        }

        if ( this.load_percent >= 100 ) {
            this.clearLoadProgress();
        }

        this.trigger('progress', this.load_percent);
    }
},

// 對于play觸發后才開始加載
play: function () {
    if (!this.seekable) {
        this.timer = setInterval(this.onProgress.bind(this), 500);
    }
    this.audio.play();
},

上面代碼的邏輯主要是檢測audio的buffered,因為不同瀏覽器對buffered的解析不同,如果跳躍播放,有的會產生多段buffered,所以獲取最新的緩存要這樣:this.audio.buffered.end(this.audio.buffered.length - 1)

3.多音頻切換問題

在播放列表里,有多個音頻文件,點擊可以切換。正常的做法是,用tap綁定點擊事件,事件內部這樣處理:

audio.pause();
audio.setAttribute('src', url);
audio.play();

在PC的chrome上是很正常的,完美。但是,在手機上就嗝屁了。問題為:偶發性的出現,切換音頻后,直接觸發音頻的ended事件,然后再怎么切換播放/點擊都是無效的了。
這個問題的解決方法很簡單,就是在canplay觸發的時候再觸發play就好,不要切換了音頻url馬上play

_t.audioHandler.on('canplay', function (totalTime, name) {
    _t.audioHandler.play();
});

因為沒有預加載的過程,每次都是點擊列表的音頻才播放,所以這樣理論上是可行的。但是如果點擊了播放,觸發了加載,馬上就點暫停,這時候canplay還沒觸發,會不會有問題?

4.其他的兼容性問題

  • 關于音頻的總時間,理論來說,正常加載的情況,在canplay的時候是可以讀取到的,但因為上面一堆load問題,所以音頻總時間要手動設置。
  • tab去綁定播放事件好像會有奇葩的問題,用touch系列又太靈敏了,都接受不了可以用fastclick

暫時還沒發生其他問題,下面就看看例子吧。例子分兩個,一個是單音頻預加載播放,另外一個是多音頻列表播放(UI直接用項目的了)。

例子1:單音頻預加載播放

audio1.gif

例子2:多音頻切換播放

audio2.gif

上面倆個例子的代碼在這里

最后

實踐都這里就算完了。不過這里有個更好玩的東西,有興趣可以看看,非常酷炫。

在開發的過程中,針對移動端,參考了Audio5js,整理出了個audio的庫。代碼在這里,有興趣可以關注下。

參考:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容