(19.0205)本人在雙十一期間,作的一個移動端互動項目中,遇到一個在 App 、微信、h5頁面環境切換選擇音頻播放的功能,在測試的時候出了很多兼容性問題,這裏有不少值得探索的知識,今天咱們就來看一下這個 HTML5-Audio。html
Audio 標籤用於定義聲音,好比音樂或其餘音頻流,HTML5 的 Audio 標籤在很大程度上取代了 Flash 來播放音樂。html5
Audio 標籤在瀏覽器中的默認樣式以下圖所示,須要注意的一個地方:須要配置 controls 屬性(是否顯示默認控制條,是 Audio 標籤的控制屬性),不然不展現樣式效果。git
一、OGG:github
OGG 是一種新的音頻壓縮格式,相似於 MP3 等的音樂格式。OGG 是徹底免費、開放和沒有專利限制的。OGG 文件格式能夠不斷地進行大小和音質的改良,而不影響舊有的編碼器或播放器。web
二、MP3:chrome
MP3 是一種音頻壓縮技術,其全稱是 Moving_Picture_Experts_Group_Audio_Layer_III(動態影像專家壓縮標準音頻層面3),簡稱爲 MP3 。它被設計用來大幅度地下降音頻數據量。將音樂以 1:10 甚至 1:12 壓縮成容量較小的文件,而對於大多數用戶來講重放的音質與最初的不壓縮音頻相比沒有明顯的降低。瀏覽器
三、WAV:緩存
WAV 是微軟公司開發的一種聲音文件格式,它用於保存 Windows 平臺的音頻信息資源,被 Windows 平臺及其應用程序所普遍支持,標準格式化的 WAV 文件和 CD 格式同樣,所以在聲音文件質量和 CD 相差無幾。微信
咱們來從下面幾個角度看兼容性問題:markdown
一、音頻格式的兼容性
音頻格式 | Chrome | Firefox | IE9 | Opera | Safari |
---|---|---|---|---|---|
OGG | 支持 | 支持 | 支持 | 支持 | 不支持 |
MP3 | 支持 | 不支持 | 支持 | 不支持 | 支持 |
WAV | 不支持 | 支持 | 不支持 | 支持 | 不支持 |
說明:
Audio 標籤默認支持的主流的音頻文件格式有 MP三、WAV、OGG ,不一樣的瀏覽器對三種格式支持程度不同。其中 MP3 格式支持度最好。
WAV 格式音質最好,可是文件體積較大。MP3 壓縮率較高,普及率高,音質相比 WAV 要差。OGG 與 MP3 在相同位速率(Bit Rate)編碼的狀況下,OGG 體積更小,而且 OGG 是免費的不用交專利費(這點國人很中意)。
二、不一樣瀏覽器對於 HTML5 Audio 標籤的兼容性
說明:
在版本較新的瀏覽器中都是能夠支持 Audio 標籤的,在移動端上兼容性會更好一些。
咱們常常會使用到的屬性、方法、事件:
一、經常使用屬性:
屬性 | 屬性值 | 註釋 |
---|---|---|
src | url | 播放的音樂的 url 地址(火狐只支持 OGG 的音樂,而 IE9 只支持 MP3 格式的音樂。chrome 貌似全支持) |
preload | preload | 預加載(在頁面被加載時進行加載或者說緩衝音頻),若是使用了 autoplay 的話那麼該屬性失效。 |
loop | loop | 循環播放 |
controls | controls | 是否顯示默認控制條(控制按鈕) |
autoplay | autoplay | 自動播放 |
二、經常使用方法:
函數 | 做用 |
---|---|
load() | 加載音頻、視頻軟件 |
play() | 加載並播放音頻、視頻文件或從新播放暫停的的音頻、視頻 |
pause() | 暫停當前播放的音頻 |
三、經常使用事件:
事件名稱 | 事件做用 |
---|---|
play | play 和 autoplay 播放時 |
pause | pause 方法觸發時 |
ended | 當前播放結束 |
timeupdate | 當前播放時間發生改變的時候(播放中經常使用的時間處理) |
canplaythrough | 歌曲已經載入徹底完成 |
canplay | 緩衝至目前可播放狀態。 |
咱們能夠經過 JS 代碼來控制播放:
let audio = document.getElementById('audio');
audio.load();//加載
audio.play();//播放
audio.pause();//暫停
audio.loop = true;//循環播放
複製代碼
好的,咱們再來看具體看一下 Audio 標籤的兼容性問題:
現狀:preload 在 iOS 系統上的 safari 和微信是不支持的。
解決方法:**須要用戶主動觸發事件(Event)**才能進行播放。
示例代碼:
$("#btn").click(function() {
$("#audio").load();
})
複製代碼
現狀:當時項目中有切換不一樣音樂播放,若是採用更改 Audio 標籤的 src 的方式,iOS 下會出現不能播放音樂或者播放延遲過高問題。
解決方法:這種 bug 出現的緣由是音頻文件不能緩存在 iOS 系統上,每當頁面訪問其餘音頻文件時,都從網絡訪問音頻文件,解決方法:能夠在頁面中聲明多個 Audio 標籤,把須要引入的音頻文件預先引入,播放哪一個再調用相應文件,這個方案的缺點是在 iOS 系統下每個 Audio 佔一個線程,若是有多個的 Audio ,則很佔資源;或者把多個音頻文件合併成爲一個文件,播放其餘音頻的時候只須要調用合併以後的音頻文件的相應時段,雖然比較繁瑣,可是兼容性很好,能夠參考下該音頻合併工具(jsfiddle.net/aarongloege…
示例代碼:
<audio src="" id="audio1"></audio>
<audio src="" id="audio2"></audio>
var audio1 = document.getElementById('audio1');
var audio2 = document.getElementById('audio2');
audio1.play();
audio2.play();
複製代碼
現狀:iOS 端 safari 瀏覽器或者部分安卓手機的瀏覽器不支持 autoplay 屬性。
解決方法:仍是引導用戶手動觸發播放操做。 好比綁定 touchstart 事件進行 audio.play() 操做,所以在和產品、測試同窗溝通確認的時候就須要確認好這個點。若是在微信環境下能夠調用微信提供的插件( jweixin-1.0.0.js )。
示例代碼:
wx.ready(function() {
audio.play();
});
複製代碼
現狀:一個 Audio 標籤只能播放一個音頻。
解決方法:若是要同時播放多個音頻,只得使用多個 Audio 標籤,可是這個狀況下要注意,各瀏覽器是是支持在同一頁面播放多個音頻的,而項目場景基本只容許播放一個音頻,這個得注意控制播放當前音樂時要中止其餘音樂項的播放。
示例代碼:
<audio src="a.mp3" src="a.mp3"></audio>
<audio src="b.mp3" src="b.mp3"></audio>
<audio src="c.mp3" src="c.mp3"></audio>
複製代碼
現狀:在 iOS safari 下關閉瀏覽器窗口(切換至後臺)或者切換標籤時, Audio 仍然繼續循環播放音頻文件,若是關閉瀏覽器標籤纔會中止播放。
解決方法:使用循環存儲時間來檢查用戶是否在網頁上, timeupdate 事件是在音頻 Audio 的播放位置發生改變時觸發。
示例代碼:
var lastSeen;
var loop = function (){
lastSeen = Date.now();
setTimeout(loop, 50);
};
loop();
var music = document.getElementById('music');
music.addEventListener('timeupdate', function (){
if(Date.now() - lastSeen > 100){
this.pause();
}
}, false);
複製代碼
現狀:在 JDApp 端頁面音頻播放時,切換至後臺或者其餘應用,音樂暫停播放以後,再切換至音樂播放的原頁面,音樂沒有繼續播放。
解決方法:判斷是不是在 JDApp 下,若是在 JDApp 使用 JDAppUnite 調用原生方法 callRouterModuleWithParams 控制音頻繼續播放。
示例代碼:
function toOriginalChk(wvt, soundRouter) {
// 判斷環境
if (wvt == 'notJdApp') {
return;
} else if (wvt == 'wk') {
// 通知原生播放狀態
window.webkit.messageHandlers.JDAppUnite.postMessage({
'method': 'callRouterModuleWithParams',
'params': JSON.stringify(soundRouter)
});
} else if (wvt == 'ui') {
window.JDAppUnite && window.JDAppUnite.callRouterModuleWithParams(JSON.stringify(soundRouter));
}
}
複製代碼
現狀:在 iOS safari 瀏覽器初始化一個新的音頻流時會有幾秒的延時。
解決方法:出現這 bug 的緣由是由於 iOS 須要實例化一個新的音頻對象,再經過網絡請求音頻資源,音頻資源加載完畢以後才能進行播放,解決方案:在頁面 ready 以後把每一個文件都 load 一下,而後再調用 play 方法,這麼作可使音頻資源作預加載,提早請求網絡,能夠具體業務場景來優化使用。
(3) 示例代碼:
$(function() {
$("#audio1").load();
$("#audio2").load();
})
複製代碼
現狀:理想狀況下用戶能夠在相關頁面經過觸發事件實現音頻的靜音操做
解決方法:能夠經過設置 muted 屬性來設置 Audio 靜音,可是在 iOS 8及其如下 或者 IE9 及其如下版本不支持 muted 屬性。
示例代碼:
$("#audio").muted = true
複製代碼
現狀:若是在頁面未加載完成時調用 play 方法會失敗,在這種狀況下設置 currentTime 會拋出異常錯誤Failed to load resource: the server responded with a status of 404 ()。
解決方法:遇到此類問題,能夠先檢查網絡及音頻大小以排除。
現狀:在 iOS 系統在 5 以前不支持循環屬性。
解決方法:能夠經過向 onEnded 事件添加了一個事件偵聽程序,並在該函數中調用 play 方法解決。
示例代碼:
var audio = document.getElementById('audio');
audio.play();
var onEnded = function() {
this.play();
};
audio.addEventListener('ended', onEnded, false);
複製代碼
小tip:HTML5 Audio 標籤給咱們提供了一些額外的信息來指定播放哪一時間段,方法是在媒體文件後面跟隨(「#」)格式
<audio src="audio.mp3#t=10,20"></audio>
// src="audio.mp3#t=10,20" (從10s播放到20s)
// src="audio.mp3#t=10" (從10s播放到完)
// src="audio.mp3#t=,10" (從開頭播放到10s)
複製代碼
HTML5 提供的 Audio 標籤雖然有很多的兼容性問題, 可是在移動端使用音頻播放, Audio 仍然是 HTML5 發展的大勢所趨,值得咱們使用。本文介紹了 Audio 標籤的使用方法以及音頻文件的兼容版本和 Audio 在不一樣環境下的兼容性問題並相應給出瞭解決方案。最後附上本身開發的插件( github.com/jdf2e/audio… ),掃二維碼可訪問:
以上提到的解決方案能夠幫助你們解決大多數問題,若是須要更完善的規避這些 Audio 的坑能夠參考使用這個 JS 插件,使用方法以下:
jdMusic.create([{
src: 'https://jdch5.jd.com/yayoi/res/raw-assets/Sound/A.mp3',
isloop: false,
id: 'demo1',
class: 'demo1',
autoplay: false
}, {
src: 'https://jdch5.jd.com/yayoi/res/raw-assets/Sound/B.mp3',
isloop: false,
id: 'demo2',
class: 'demo2',
autoplay: true
}]);
jdMusic.play(0)
jdMusic.pause()
複製代碼
[1] HTML 5 audio 標籤
www.w3school.com.cn/html5/html5…
[2] HTML DOM Audio 對象
www.w3school.com.cn/jsref/dom_o…
[3] HTML5 Audio (音頻)
[4] audio sprite 工具
[5] audioCreate.js