Audio在移動(dòng)端的實(shí)踐

好久沒(méi)寫(xiě)blog了脸候,有三點(diǎn)原因,一是懶绑蔫,二是懶运沦,三是懶。

因?yàn)樽罱?xiàng)目里面有個(gè)需求配深,要在移動(dòng)端用web的Audio實(shí)現(xiàn)音頻播放携添。本想說(shuō)臣妾做不到啊~然而,還是開(kāi)始挖坑了凉馆。在這里記錄下各種坑死人的問(wèn)題薪寓。

準(zhǔn)備

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

compatibility.png

我們?cè)俜謩e看看audio提供的屬性澜共,方法和事件

屬性

params.png

方法

way.png

事件

event.png

具體的可以戳這里向叉。

實(shí)踐

其實(shí)按照上面的方法,隨便怎么寫(xiě)怎么玩都可以嗦董,但主要有以下幾個(gè)問(wèn)題要解決的:

1.預(yù)加載的問(wèn)題母谎;
2.加載進(jìn)度條問(wèn)題;
3.多個(gè)音頻文件切換問(wèn)題京革;
4.其他的兼容性問(wèn)題奇唤。

1.預(yù)加載的問(wèn)題

我們先來(lái)看預(yù)加載的流程(如下),先用load去加載音頻匹摇,當(dāng)音頻可以播放就會(huì)觸發(fā)canplay事件咬扇,表示加載已經(jīng)完成,可以播放廊勃,完美懈贺。

patten1.png

但是,理想和現(xiàn)實(shí)總是有區(qū)別的坡垫,在表現(xiàn)不一的手機(jī)上就有問(wèn)題了梭灿。

問(wèn)題一:load方法調(diào)用了沒(méi)效果,根本沒(méi)有加載音頻冰悠,要調(diào)用play方法才開(kāi)始加載堡妒。

問(wèn)題二:在三星note3 和錘子T1手機(jī)上,有50%的幾率預(yù)加載失敗溉卓。如果預(yù)加載失敗皮迟,要切換好幾次播放/暫停狀態(tài)才開(kāi)始加載播放搬泥,或者一直沒(méi)反應(yīng)。

問(wèn)題三:一般觸發(fā)load加載音頻文件后万栅,音頻文件緩沖好會(huì)觸發(fā)canplay事件的佑钾。

在安卓下西疤,觸發(fā)canplay事件烦粒,會(huì)有下面問(wèn)題:

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

在iOS下,有以下問(wèn)題:

  • canplay事件觸發(fā)后芭碍,微信的audio.seekablefalse徒役;
  • safariload了之后,canplay事件不觸發(fā)窖壕,點(diǎn)擊play后才觸發(fā) (9.1版本是正常的)忧勿;

看到這里是不是覺(jué)得坑大了,想逃瞻讽?不要急鸳吸,接著看。

解決方法

上面問(wèn)題總的來(lái)說(shuō)有倆個(gè)速勇,一個(gè)是加載進(jìn)度晌砾,另外一個(gè)就是播放Bug了。這里主要說(shuō)下問(wèn)題二的解決方法烦磁。

調(diào)用load事件后养匈,對(duì)加載進(jìn)度進(jìn)行檢測(cè),如果直到canplay觸發(fā)都伪,加載進(jìn)度一直為0呕乎,就判斷為預(yù)加載失敗。然后在點(diǎn)擊播放的陨晶,設(shè)置進(jìn)度audio.currentTime = 1;猬仁,這樣就會(huì)再次觸發(fā)加載。這里還有個(gè)問(wèn)題珍逸,如果是用zeptotap監(jiān)聽(tīng)點(diǎn)擊播放事件逐虚,可以再次加載,但一直不播放,要監(jiān)聽(tīng)touchend這些事件才行(這個(gè)問(wèn)題糾結(jié)N久)茵瀑。
這樣調(diào)整后愿吹,在三星note 3 和錘子T1這些有問(wèn)題的手機(jī)上基本沒(méi)什么問(wèn)題了。

2.加載進(jìn)度條問(wèn)題

加載進(jìn)度买雾,瀏覽器提供了progress事件把曼,但這個(gè)事件會(huì)有一些小問(wèn)題,所以采用setInterval的去實(shí)行漓穿。正常來(lái)說(shuō)在canplay的時(shí)候顯示進(jìn)度條:

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);
    }
},

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

上面代碼的邏輯主要是檢測(cè)audio的buffered嗤军,因?yàn)椴煌瑸g覽器對(duì)buffered的解析不同,如果跳躍播放晃危,有的會(huì)產(chǎn)生多段buffered叙赚,所以獲取最新的緩存要這樣:this.audio.buffered.end(this.audio.buffered.length - 1)

3.多音頻切換問(wèn)題

在播放列表里僚饭,有多個(gè)音頻文件震叮,點(diǎn)擊可以切換。正常的做法是鳍鸵,用tap綁定點(diǎn)擊事件苇瓣,事件內(nèi)部這樣處理:

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

在PC的chrome上是很正常的,完美偿乖。但是击罪,在手機(jī)上就嗝屁了。問(wèn)題為:偶發(fā)性的出現(xiàn)贪薪,切換音頻后媳禁,直接觸發(fā)音頻的ended事件,然后再怎么切換播放/點(diǎn)擊都是無(wú)效的了古掏。
這個(gè)問(wèn)題的解決方法很簡(jiǎn)單损话,就是在canplay觸發(fā)的時(shí)候再觸發(fā)play就好,不要切換了音頻url馬上play

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

因?yàn)闆](méi)有預(yù)加載的過(guò)程槽唾,每次都是點(diǎn)擊列表的音頻才播放丧枪,所以這樣理論上是可行的。但是如果點(diǎn)擊了播放庞萍,觸發(fā)了加載拧烦,馬上就點(diǎn)暫停,這時(shí)候canplay還沒(méi)觸發(fā)钝计,會(huì)不會(huì)有問(wèn)題恋博?

4.其他的兼容性問(wèn)題

  • 關(guān)于音頻的總時(shí)間,理論來(lái)說(shuō)私恬,正常加載的情況债沮,在canplay的時(shí)候是可以讀取到的,但因?yàn)樯厦嬉欢?code>load問(wèn)題本鸣,所以音頻總時(shí)間要手動(dòng)設(shè)置疫衩。
  • tab去綁定播放事件好像會(huì)有奇葩的問(wèn)題,用touch系列又太靈敏了荣德,都接受不了可以用fastclick闷煤。

暫時(shí)還沒(méi)發(fā)生其他問(wèn)題童芹,下面就看看例子吧。例子分兩個(gè)鲤拿,一個(gè)是單音頻預(yù)加載播放假褪,另外一個(gè)是多音頻列表播放(UI直接用項(xiàng)目的了)。

例子1:?jiǎn)我纛l預(yù)加載播放

audio1.gif

例子2:多音頻切換播放

audio2.gif

上面?zhèn)z個(gè)例子的代碼在這里近顷。

最后

實(shí)踐都這里就算完了生音。不過(guò)這里有個(gè)更好玩的東西,有興趣可以看看幕庐,非尘米叮酷炫。

在開(kāi)發(fā)的過(guò)程中异剥,針對(duì)移動(dòng)端,參考了Audio5js絮重,整理出了個(gè)audio的庫(kù)冤寿。代碼在這里,有興趣可以關(guān)注下青伤。

參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末督怜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子狠角,更是在濱河造成了極大的恐慌号杠,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丰歌,死亡現(xiàn)場(chǎng)離奇詭異姨蟋,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)立帖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)眼溶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人晓勇,你說(shuō)我怎么就攤上這事堂飞。” “怎么了绑咱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵绰筛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我描融,道長(zhǎng)铝噩,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任稼稿,我火速辦了婚禮薄榛,結(jié)果婚禮上讳窟,老公的妹妹穿的比我還像新娘。我一直安慰自己敞恋,他們只是感情好丽啡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著硬猫,像睡著了一般补箍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啸蜜,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天坑雅,我揣著相機(jī)與錄音,去河邊找鬼衬横。 笑死裹粤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜂林。 我是一名探鬼主播遥诉,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼噪叙!你這毒婦竟也來(lái)了矮锈?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤睁蕾,失蹤者是張志新(化名)和其女友劉穎苞笨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體子眶,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瀑凝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壹店。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猜丹。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖硅卢,靈堂內(nèi)的尸體忽然破棺而出射窒,到底是詐尸還是另有隱情,我是刑警寧澤将塑,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布脉顿,位于F島的核電站,受9級(jí)特大地震影響点寥,放射性物質(zhì)發(fā)生泄漏艾疟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔽莱。 院中可真熱鬧弟疆,春花似錦、人聲如沸盗冷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)仪糖。三九已至柑司,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锅劝,已是汗流浹背攒驰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留故爵,地道東北人玻粪。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像稠集,于是被迫代替她去往敵國(guó)和親奶段。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容