Web Autoplay 的限制
現在網頁上充斥著各式類型的資訊,有圖片、影音等等,今天要筆記一下在網頁上,關於影音自動播放的一些限制。
以日常大家最常使用的 facebook(?)作為舉例,你可能會注意到 facebook 的 Timeline 上有各式各樣的資訊,其中在影片的部分預設都是無聲音的,回想一下以前在無名小站,有些部落格一進去,馬上就有音樂播放,好聽的音樂大家會覺得很悅耳,但每個人的喜好不同,你播放的音樂不一定是別人喜歡的,某種程度上或許會給別人帶來一些困擾。
Autoplay Policy
那麼,影音在 Web 上,預設到底可不可以讓聲音自動播放呢?在早期瀏覽器是允許這個行為的,但現在是不允許的,但在一些條件下,還是可以自動播放的:
- 靜音允許自動播放(Muted autoplay is always allowed)
- 使用者與瀏覽器有所互動(例如:click, touch 事件)
- 頂部 frame 可以將自動播放權限委託給他們的 iframe,允許自動播放聲音
以影片播放來舉例:
<videoid="video"controls="controls"preload="none"poster="http://media.w3.org/2010/05/sintel/poster.png"><source src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4" /></video>
若是透過 JavaScript 來操控這個 Video 來讓他自動播放:
const [video] = document.getElementById('video');video.play();
會得到如下的錯誤:
DOMException: play() failed because the user didn't interact with the document first.
意思是,如果使用者和瀏覽器沒有互動的話,play()
會失敗;如果想要解決這個問題可以根據上面的方式,在 video
上加入 muted
的 tag,這樣 JavaScript 就可以成功執行 play()
方法。
<videoid="video"controls="controls"preload="none"poster="http://media.w3.org/2010/05/sintel/poster.png"muted><source src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4" /></video>
play() 方法是非同步的
當你呼叫 play()
方法時,可能會遇到以下的錯誤:
- Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
- Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.
這是因為 play()
方法是非同步的,當你呼叫 play()
方法後,隨著呼叫 pause()
方法,這時候 meida 還沒完全載入完全,所以會造成錯誤。
在 Chrome 50 版本後的 audio
和 video
都是回傳都是一個 Promise,確保 media 完全載入後,再執行其他的動作,推薦的方式如下:
// Show loading animation.const videoPromise = video.play();if (videoPromise !== undefined) {playPromise.then(() => {// Automatic playback started!// Show playing UI.}).catch(error => {// Auto-play was prevented// Show paused UI.});}