盡管 HTML5 音頻表現出色,但作為一個仍在開發的規范,它仍有很多局限。移動版 Safari 甚至引入了更多的限制。在本文中,您將了解 HTML5 在移動版 Safari 方面的局限性。一些工作示例提供了相應的解決方案和全面的變通方法。通過本文您將了解在移動版 Safari 中使用 audio sprite 的好處,並嘗試使用幾個獨到的解決方案來繞過 iOS 中的 HTML5 局限。
目錄[-]
- 常用的縮略語
- HTML5 音頻的局限性
- 格式支持
- 表 1. HTML5 視頻格式支持
- 清單 1. 音頻元素的 HTML 標記
- 處理和效果
- 單音頻層(多音的)
- iOS、移動版 Safari 和 HTML5 音頻的限制
- 單音頻流
- 清單 2. 單音頻流
- 清單 3. 可互換的音頻視頻流
- 自動播放
- 加載音頻
- 圖 1. 在移動版 Safari 中加載音頻的工作流
- 清單 4. 在頁面加載時播放音頻流在默認情況下會失敗
- 清單 5. 移動版 Safari 中不支持 preload 屬性
- 其他的怪癖
- 清單 6. 在切換音頻對象時的 HTML5 音頻延時
- 清單 7. 在一個尚未載入其元數據的音頻流上設置 currentTime
- 清單 8. iOS < 5 的音頻循環變通方案
- 解決方案
- 單個音頻流
- 清單 9. 置換一個音頻對象的源文件
- 自動播放
- 清單 10. iOS 4.2.1 之前,可以在一個 Ajax 調用的回調中加載一個音頻流
- 加載音頻
- 清單 11. 使用一個事件觸發事件來加載一個音頻流
- 圖 2. 割繩子游戲的 HTML5 啟動屏幕
- 不受支持的事件
- 表 2. 桌面和移動版 Safari 對媒體事件的支持
- 清單 12. 設置 currentTime 將會觸發 seeking 和 seeked 事件
- Audio sprite
- 圖 3. Audio sprite
- 清單 13. 簡單的 audio sprite 實現
- 清單 14. 添加當到達 sprite 的結尾時停止流的邏輯
- 功能全面的示例
- directCanvas 和 multiSound 如何加速 HTML5 游戲性能
- 圖 4. 使用 directCanvas 獲得的從移動版 Safari 到 MobiUs 應用程序的平均 HTML5 性能改進
- 結束語
簡介
過去幾年,開發人員一直都在制造完善的交互體驗,努力使其可以在瀏覽器中正確運行。這樣的站點通常需要使用瀏覽器插件 (Flash)。隨着智能手機和平板電腦的推出,交互體驗看似與新的小部件能夠完美匹配。但是,由於移動設備的處理能力有限,瀏覽器插件不再是一種可行的開發平台。
常用的縮略語
-
AAC:高級音頻編碼 (Advanced Audio Coding)
-
CSS:級聯樣式表 (Cascading Style Sheet)
-
HTML:超文本標記語言 (HyperText Markup Language)
-
MP3:MPEG-1 Audio Layer 3
-
OGG:一種開放容器格式 (open container format)
-
WAV:波形音頻格式 (Waveform Audio Format)
HTML5 已經添加了大量無需額外插件的使用的工具。W3C 的 HTML5 規范仍在開發之中,但是在規范開發過程中,瀏覽器已經開始提供支持。
HTML5 音頻是一個巨大的進步,它允許在瀏覽器中嵌入聲音,尤其是在移動設備中,比如 iOS 的移動版 Safari 瀏覽器上。盡管 HTML5 音頻是一個新特性,但已提供了 iOS 支持。根據流行的移動應用程序 Instapaper 的開發人員報導,2011 年 11 月,其 iOS 用戶中有 98.8% 都在使用 iOS 4 或更高版本(請參閱 參考資料)。由於 HTML5 音頻是在 iOS 3 中引入到移動版 Safari 中的,所以您可以放心,iOS 平台為 HTML5 音頻提供了廣泛的支持。
在文本中,您將了解 HTML5 在桌面上和移動版 Safari 內的局限性,並嘗試采用一些解決方案來創建交互的聲音效果。本文涵蓋的其他內容包括:不受支持的事件、audio sprite 以及如何使用 directCanvas 和 multiSound 加速 HTML5 游戲性能。
有一點非常值得關注:對於 iOS 6,Apple 已經添加了對 Web Audio API(討論如下)的支持,因此不再需要使用本文中所討論的許多變通方法。不過,iOS 6 剛剛面世不到幾周時間,所以 iOS 5 仍然是市場的主流。本文中所討論的問題以及所提供的變通方式仍有效,應該在為移動版 Safari 開發聲頻時考慮使用它們。
您可以 下載 本文中使用的示例的源代碼。
HTML5 音頻的局限性
在討論移動版 Safari 中的局限性之前,有必要理解 HTML 音頻在桌面上的局限性。HTML5 音頻雖然很健壯,但有其局限性,這主要取決於它的實現。對於音樂播放器(點唱機播放器)或簡單的聲音效果,它很有效,但是對於聲音密集的應用程序如游戲,它的表現不是很理想。
格式支持
不幸的是,並不是所有瀏覽器都支持相同的視頻文件格式。如表 1 所示,目前有四種主要格式:MP3、OGG、WAV 和 AAC。
表 1. HTML5 視頻格式支持
Ogg Vorbis | WAV | PCM | AAC | |
---|---|---|---|---|
Internet Explorer 9 | X | X | ||
Firefox | X | X | ||
Chrome/Safari/移動版 Safari | X | X | X |
為了涵蓋所有瀏覽器,最好是讓所有的視頻流都具有 Ogg Vorbis 和 AAC 兩種格式。
為什么沒有包括 MP3?MP3 在進行商業傳播時需要支付繁重的版稅。MP3 的授權要求對於所有超過 $100K 的數據收取 2% 的傳播費(請參閱參考資料)。出於這個原因,我更傾向於使用 AAC 而非 MP3。AAC 也並非完全免版稅的,但它對於免費傳播的許可沒有那么嚴格。AAC 還提供了更好的壓縮,文件可以更小,它是 Web 領域的福音(請參閱 參考資料)。
Ogg Vorbis 之所以壓倒性地獲得了我的喜愛是因為它是開源的、無專利費並且免版稅的。不過,只有 Firefox 支持它。
清單 1 顯示了跨瀏覽器兼容 HTML 標記。
清單 1. 音頻元素的 HTML 標記
<audio> // AAC file (Chrome/Safari/IE9) <source src="sound.m4a" type="audio/mpeg" /> // Ogg Vorbis (Firefox) <source src="sound.ogg" type="audio/ogg" /> </audio>
處理和效果
在處理音頻時,一個強大的特性是處理聲音的能力。無論動態合成聲音、處理聲音效果、應用環境效果,還是進行基本的立體聲平移,HTML5 音頻缺乏所有這些處理能力。您加載的視頻就是將要播放的視頻。
Web Audio API (Chrome) 和 Audio Data API (Firefox) 無需任何瀏覽器插件即可進行合成和動態處理音頻的能力幫助您解決了特性缺失的問題(請參閱 參考資料)。這兩種 API 均在開發當中,僅在 Chrome 14+ 和 Firefox 4+ 中受支持。不幸的是,在實現方面這二者差異很大。目前有一些表現不錯的庫可用來使支持正規化,比如 audiolibjs(請參閱 參考資料)。Chrome 的 Web Audio API 就是通過 W3C 推廣的標准。
單音頻層(多音的)
要重復播放聲音本身,必須實例化此聲音的一個單獨的音頻對象。在標記和能夠播放的音頻之間存在 1:1 的對應。對於當前狀態的 HTML5 音頻,是無法分層的。其他平台,比如 Flash,可以分出一個單獨的音頻對象,無需創建一個新的音頻對象。
iOS、移動版 Safari 和 HTML5 音頻的限制
HTML5 音頻本身多少存在一些限制,而移動版 Safari 則向 HTML5 音頻最基本的使用添加了其他的限制。
單音頻流
移動版 Safari 帶來的最大的局限之一是一次只能播放一個單音頻流。移動版 Safari 中的 HTML5 媒體元素都是單例的,所以一次只能播放一個 HTML5 音頻(和 HTML5 視頻)流。Apple 為這一局限做過解釋,但我們推斷這是為了減少數據費用(這也是大多數 iOS HTML5 其他局限的原因所在)。
iOS 為移動版 Safari 提供了單一 HTML5 媒體(音頻和視頻)容器。如果想要在播放一個音頻流的同時播放另一個音頻流,那么就會從容器中刪除前一個音頻流,新的音頻流將會在前一個音頻流的位置上被實例化。
清單 2 顯示了在一個流播放的同時調用 play()
如何會停止之前的流,在本例中該流為 audio1。
清單 2. 單音頻流
var audio1 = document.getElementById('audio1'); var audio2 = document.getElementById('audio2'); audio1.play(); // this stream will immediately stop when the next line is run audio2.play(); // this will stop audio1
查看並收聽 本例的效果。
有一點很重要,務必牢記,音頻和視頻是可以互換的。如果在視頻播放的同時要播放音頻文件,那么視頻就會停止。一次只能播放一個音頻或視頻流,如清單 3 所示。
清單 3. 可互換的音頻視頻流
var audio = document.getElementById('audio'); var video = document.getElementById('video'); video.play(); // at a later time audio.play(); // this will stop video
自動播放
在移動版 Safari 中加載的頁面上,不能自動播放音頻文件。音頻文件只能從用戶觸發的觸摸(單擊)事件加載。如果在 HTML 標記中使用了autoplay
屬性,那么移動版 Safari 將會忽略這個屬性,並且不會在加載頁面時播放此文件,如下所示:
<audio id="audio" src="audio_file.mp3" autoplay></audio>
Safari Developer Guide 上有有關於此的詳細信息(請參閱 參考資料)。
加載音頻
除非由用戶接觸事件,比如通過 onmousedown
、onmouseup
、onclick
或 ontouchstart
觸發事件,否則不能加載音頻流。圖 1 顯示了這樣的一個示例。
圖 1. 在移動版 Safari 中加載音頻的工作流
如果在加載頁面時運行清單 4 中的代碼,那么在移動版 Safari 中不會加載視頻流,甚至不會下載該視頻流。
清單 4. 在頁面加載時播放音頻流在默認情況下會失敗
var audio = document.getElementById('audio'); audio.play();
即便是 HTML markup 中使用了 preload
屬性,移動版 Safari 仍會忽視此屬性,並且不會加載此文件,除非由用戶觸摸事件,如清單 5 所示。
清單 5. 移動版 Safari 中不支持 preload
屬性
<audio id="audio" src="audio_file.mp3" preload="auto"></audio>
查看並收聽 本例的效果。
在桌面 Safari 上,在加載頁面時,清單 5 中的代碼會下載此音頻文件。但是,在移動版 Safari 上,此屬性會被忽視,並且不會下載此音頻文件。
其他的怪癖
在移動版 Safari 中使用 HTML5 音頻還有其他幾個怪癖需要考慮。
在初始化一個新的音頻流時會有幾秒的延時,這是因為 iOS 需要實例化一個新的音頻對象。清單 6 顯示了如何遭遇這種延時。
清單 6. 在切換音頻對象時的 HTML5 音頻延時
var audio1 = document.getElementById('audio1'); var audio2 = document.getElementById('audio2'); audio1.play(); // at a later time audio2.play(); // there will be a few-seconds delay as iOS is instantiating a new audio object. // at an even later time audio1.play(); // there will also be a few-seconds delay, as the audio object // for audio1 in iOS was destroyed when we played audio2.
查看並收聽 本例的效果。
重要的是確保您的邏輯不會假設音頻流是在加載頁面時載入的。調用 play()
在默認情況下會失敗,如果在將要加載但尚未載入其元數據的音頻流上嘗試設置 currentTime
,則會拋出一個致命錯誤,如清單 7 所示。
清單 7. 在一個尚未載入其元數據的音頻流上設置 currentTime
// run on page load var audio = document.getElementById('audio'); audio.play(); // This will silently fail audio.currentTime = 2; // This will throw a fatal error because the metadata // for the audio does not exist
查看並收聽 本例的效果。
音頻文件不能緩存在 iOS 上的移動版 manifest 中。只有在對某個離線應用程序使用清單 (manifest) 時,這才適用。如果一個音頻文件包含在此清單中,iOS 將會忽略它,並且不會緩存此文件。每當此 Web 應用程序需要訪問此音頻文件時,都需要從該網絡訪問此文件。
用 JavaScript 以編程方式進行相關設置時,移動版 Safari 並不會尊重此音量和 playbackRate
屬性。更改屬性也不會實際調整這些值。音量總是在用戶控制下,並且 playbackRate
在移動版 Safari 中仍然不受支持。音量總是保持設置為 1,playbackRate
則會設置為希望設置的新值,但是音頻流回放的實際速度不會發生改變。這會為 onratechange
事件帶來某些復雜性,我們將在 不受支持的事件 部分對此進行討論。
在 iOS 5 之前,循環屬性是不受支持的。為了解決缺乏支持的問題,可以向 onended
事件添加了一個事件偵聽程序,並在該函數中調用play()
。清單 8 顯示了一個例子。
清單 8. iOS < 5 的音頻循環變通方案
var audio = document.getElementById('audio'); audio.play(); var onEnded = function() { this.play(); }; audio.addEventListener('ended', onEnded, false);
查看並收聽 本例的效果。
解決方案
用來解決移動版 Safari 中 HTML5 音頻的缺陷的解決方案完全取決於具體用法。如果您只想播放一個單一音頻文件或音頻文件的播放列表,那么無需做太多更改。但是,如果需要獲得交互的聲音效果,那么事情就有些棘手了。
單個音頻流
單個音頻流局限的一種解決方案是用所需音頻置換出源文件,如清單 9 所示。這不是一種理想的解決方案,因為您需要等待加載新的音頻流后才能播放它。
清單 9. 置換一個音頻對象的源文件
var audio = document.getElementById('audio'); audio.play(); // at some later point in your script (does not need to be from a touch event) audio.src = 'newfile.m4a'; audio.play(); // there will be a slight delay while the new audio file loads
查看並收聽 本例的效果。
應對單個音頻流局限性的一種更好的解決方案是使用 audio sprite。簡言之,您要將所有的音頻綜合到一個單音頻流中,然后播放此流的各個部分。Audio sprite 部分提供了更詳細的信息。
自動播放
對於自動播放的局限性,沒有變通方案。正如前面所提及的,音頻流只能從用戶觸摸事件加載。當針對移動版 Safari 進行開發時,重要的一點是要在必要時調整您的工作流,以適應這個局限性。(以我的經驗來看,我知道如果在一開始沒有將這些考慮在內,那么將來會發生很多重構。)
在 iOS 4.2.1 之前,可以從一個同步 Ajax 調用的回調來加載音頻文件,如清單 10 內的示例所示。
清單 10. iOS 4.2.1 之前,可以在一個 Ajax 調用的回調中加載一個音頻流
// run on page load var audio = document.getElementById('audio'); jQuery.ajax({ url: 'ajax.js', async: false, success: function() { audio.play(); // audio will play in iOS before 4.2.1 } });
收聽 這個例子的效果。
清單 10 中的方法存在一個問題:因它是一個同步 Ajax 調用,所以瀏覽器是鎖定的,直到調用結束為止。在移動版 Safari 中,鎖定並不只是意味着頁面鎖定,整個應用程序都會鎖定。如果有錯誤發生,並且移動版 Safari 陷入鎖定狀態(可能性不是很大),那么退出瀏覽器的惟一方式是單擊 home 按鈕並強制關閉應用程序。
Apple 在 iOS 4.2.1 中修復了這種變通方式,所以這種變通方法在 iOS 4.2.1 和后續版本中是不起作用的。
加載音頻
音頻流只在用戶事件觸發時才能加載。如清單 11 所示,onmousedown
、onmouseup
、onclick
和 ontouchstart
都是一些可用的事件,當在一個回調中調用它們時,可成功加載一個音頻流。請注意,這種情況只適用於加載一個音頻文件時,在一個已經加載的文件上調用 play()
會按預期的那樣工作。
清單 11. 使用一個事件觸發事件來加載一個音頻流
// run on page load var button = document.getElementById('button'); var audio = document.getElementById('audio'); var onClick = function() { audio.play(); // audio will load and then play }; button.addEventListener('click', onClick, false);
查看並收聽 本例的效果。
乍一看,清單 11 更像是一個煩人的變通方案。但是,最好是為您的游戲或交互式體驗提供一個啟動屏幕,如圖 2 所示,要求用戶單擊一個按鈕來啟動。當用戶單擊 start 按鈕時,您可以使用該事件在您的項目中加載音頻。
圖 2. 割繩子游戲的 HTML5 啟動屏幕
不受支持的事件
雖然移動版 Safari 中的 HTML5 音頻支持來自桌面的所有媒體事件,但要注意的是,由於之前提到的幾個不受支持的屬性,某些事件永遠都不會觸發。還有幾個怪癖需要注意。
表 2 列出了此音頻元素的所有事件回調及其在桌面和移動版 Safari 上的兼容性。結果是以作者設置的 HTML5 音頻 事件調試程序 為基礎的,如果您願意,盡可以去嘗試。
表 2. 桌面和移動版 Safari 對媒體事件的支持
事件 | 描述 | 桌面 | 移動版 Safari |
---|---|---|---|
abort |
在媒體完全下載之前,瀏覽器停止獲取媒體。 | X | X |
canplay |
瀏覽器可恢復媒體數據的回放,但會做出評估:如果回放開啟,在不會停下來做進一步的內容緩沖的情況下,媒體資源在結束操作前不會以目前的回放速度呈現。 | X | X |
canplaythrough |
瀏覽器會做出評估:如果回放現在開始,那么在不停下來做進一步緩沖的情況下,媒體資源會以目前的回放速度呈現,一直到結束。 | X | X |
durationchange |
duration 屬性發生變化。 | X | X |
emptied |
媒體元素網絡狀態更改成 NETWORK_EMPTY 狀態。 | X | X |
ended |
回放在媒體資源的終點停止,且 ended 屬性被設置為 true。 | X | X |
error |
在獲取媒體數據前會發生錯誤。使用此 error 屬性來獲得當前的錯誤。 | X | X |
loadeddata |
瀏覽器可以初次在目前的回放位置呈現媒體數據。 | X | X |
loadedmetadata |
瀏覽器知道媒體資源的持續時間和大小。 | X | X |
loadstart |
瀏覽器開始加載媒體數據。 | X | X |
pause |
pause 方法返回后,回放暫停。 | X | X |
play |
play 方法返回后,回放開始。 | X | X |
playing |
回放開始。 | X | X |
progress |
瀏覽器在獲取媒體數據。 | X | X |
ratechange |
defaultPlaybackRate 或 playbackRate 屬性發生變化。 |
X | X (shouldn't) |
seeking |
seeking 屬性被設置為 true ,且有時間發送此事件。 |
X | X* |
seeked |
seeking 屬性被設置為 false 。 |
X | X* |
stalled |
瀏覽器獲取媒體數據,但媒體數據不再到達。 | X | X |
suspend |
瀏覽器暫停加載媒體數據,並且沒有下載完全部的媒體資源。 | X | X |
timeupdate |
currentTime 屬性作為正常回放的一部分或因為某些其他條件發生變化。 |
X | X |
volumechange |
volume 屬性或 muted 屬性發生變化。 | X | |
waiting |
瀏覽器停止回放,因為它在等待下一幀。 | X | X |
如下列表提供了有關幾個事件回放的一些注意事項。
-
ratechange
-
每當
playbackRate
發生更改,都會觸發ratechange
事件。正如之前提到的,移動版 Safari 不支持更改音頻流(以及視頻)的回放,所以playbackRate
不應觸發。但是,自 iOS 5.1.1 起,HTML5 音頻仍會觸發ratechange
事件,即便實際的回放速度並未發生改變。 -
volumechange
-
使用 JavaScript 不能更改音量,所以從不會觸發
volumechange
事件。即便在移動版 Safari 打開時用戶在其設備上更改了音量,也不會觸發這個事件。 -
seeking
/seeked
-
當這種尋找是通過 JavaScript 完成的時候,移動版 Safari 只支持
seeking
和seeked
事件,如清單 12 所示。如果顯示了內置控件,並且用戶使用了進度條進行尋找,那么不會按照預期的方式觸發seeking
和seeked
。清單 12. 設置
currentTime
將會觸發seeking
和seeked
事件var audio = document.getElementById('audio'); audio.currentTime = 60; // seeking and seeked will be fired
Audio sprite
使用 audio sprite 是滿足移動 Safari 中多音效需求的最佳解決方案。與 CSS image sprite 類似,audio sprite 可以將所有的音頻綜合到一個音頻流,如圖 3 所示。
圖 3. Audio sprite
原理很直觀。您需要存儲每個 sprite 的數據:開始點、結束點(或長度)和一個 ID。當您想要播放某個 sprite 時,需要將此音頻流的currentTime
設為開始位置並調用 play()
。清單 13 顯示了這樣的一個示例。
清單 13. 簡單的 audio sprite 實現
// audioSprite has already been loaded using a user touch event var audioSprite = document.getElementById('audio'); var spriteData = { meow1: { start: 0, length: 1.1 }, meow2: { start: 1.3, length: 1.1 }, whine: { start: 2.7, length: 0.8 }, purr: { start: 5, length: 5 } }; // play meow2 sprite audioSprite.currentTime = spriteData.meow2.start; audioSprite.play();
清單 13 將會播放 meow2 sprite,此外,因為沒有實現當 sprite 完成后即停止的邏輯,它還會播放一個發出嗚嗚聲的精靈。通過向清單 14 中的ontimeupdate
事件添加事件偵聽程序,還可以觀看 currentTime
,並在 sprite 到達其結尾時結束此音頻。
清單 14. 添加當到達 sprite 的結尾時停止流的邏輯
var handler = function() { if (this.currentTime >= spriteData.meow2.start + spriteData.meow2.length) { this.pause(); } }; audioSprite.addEventListener('timeupdate', handler, false);
查看並收聽 本例的效果。
使用 audio sprite 的一個巨大好處是在 sprite 間切換時沒有延時(類似於在音頻流間切換時,假設整個 audio sprite 已經加載)。讓所有的流位於一個文件中也優於削減 HTTP 請求。
清注意,更改 currentTime
並不是百分百正確的。將 currentTime
設為 6.5,而實際得到的卻是 6.7 或 6.2。每個 A sprite 之間需要少量的空間,以避免尋找到另一個 sprite 的尾部。添加這個空間會增加少許延時,如果流尋找到 6.4,而 sprite 開始於 6.8 秒。
在訪問任何 sprite 之前,務必確保整個音頻流均已加載。這很重要,因為如果音頻流沒有完全加載,那么在想要訪問已加載的流的任何一個部分時,那么這個流需要進行緩沖,而且還會在流加載過程中發生延時。
功能全面的示例
查看並收聽 一個 audio sprite 框架的示例。這個示例考慮到了本文所討論的這些主題。
directCanvas 和 multiSound 如何加速 HTML5 游戲性能
AppMobi 開發了一個有趣的解決方案,用 directCanvas 和 multiSound 克服移動設備上的各種 HTML5 局限性(請參閱 參考資料)。directCanvas 和 multiSound 在一個標准的 HTML5 瀏覽器中應用程序使用了設備的固有功能。緩慢的圖片性能以及本文所討論的這些局限性都不再是問題;您可以獲得一個原生應用程序的全部性能益處。
當一個用戶導航到使用了 directCanvas 的站點時,頁面會提醒該用戶從 App Store 下載 MobiUs 應用程序。如果用戶已經在其設備上安裝了此應用程序,那么頁面就會在 MobiUs 應用程序中打開。
AppMobi 的站點上有在 MobiUs 應用程序中運行游戲與在移動版 Safari 中運行游戲的並排對比視頻。結果很是驚人,性能獲得了 10 倍的提升,如圖 4 所示。
圖 4. 使用 directCanvas 獲得的從移動版 Safari 到 MobiUs 應用程序的平均 HTML5 性能改進
AppMobi 的 API 站點上有一些不錯的文檔,所以您可以立即查閱這些文檔。SDK 可免費下載獲得,而且還提供一個很順手的 Google Chrome 擴展,可方便您在自己的桌面瀏覽器中進行開發。
雖然要求用戶在其設備上安裝一個應用程序並不是很理想,但 AppMobi 有一個能夠博得認同的有趣解決方案。目前,App Store 還沒有提供 MobiUs 應用程序,但相信 MobiUs 很快就可以上線了。
結束語
盡管本文討論了 HTML5 音頻的一些局限性,但是 HTML5 音頻是對移動版 Safari 的一個很受歡迎的補充,您應該充分利用它。在本文中,我們了解了 HTML5 音頻在桌面和移動版 Safari 上的限制,遍歷了這些限制的解決方案,並探討了在移動版 Safari 中使用 audio sprite 的優勢。意識到移動版 Safari 的局限性可幫助提升它對您的可用性。
作為一個仍在制定中的規范,HTML5 音頻必然會不斷發展,但沒有理由等到規范在 2014 年(推測)最后完成后才使用它。HTML5 音頻提供了對所有 iOS 用戶的幾乎全局的兼容性,沒有理由不使用它。