媒體和 Web Audio API 的自動播放指南

在頁面載入時立即自動開始播放音訊(或帶有音訊軌道的影片)可能會讓使用者感到意外。雖然媒體自動播放很有用,但應謹慎使用,僅在需要時使用。為了讓使用者控制這一點,瀏覽器通常提供各種形式的自動播放阻止。在本指南中,我們將介紹各種媒體和 Web Audio API 中的自動播放功能,包括如何使用自動播放以及如何與瀏覽器合作以優雅地處理自動播放阻止的簡要概述。

當源媒體沒有音訊軌,或者音訊軌被靜音時,自動播放阻止不會應用於<video>元素。帶有活動音訊軌道的媒體被認為是可聽見的,自動播放阻止適用於它們。不可聽見的媒體不受自動播放阻止的影響。

自動播放和自動播放阻止

術語自動播放指的是任何導致媒體開始播放而不需使用者明確請求播放開始的功能。這包括使用 HTML 屬性自動播放媒體,以及使用 JavaScript 程式碼在處理使用者輸入之外的上下文中開始播放。

這意味著以下兩種情況都被認為是自動播放行為,因此會受到瀏覽器自動播放阻止策略的影響

html
<audio src="/music.mp3" autoplay></audio>

js
audioElement.play();

以下 Web 功能和 API 可能會受到自動播放阻止的影響

從使用者的角度來看,一個網頁或應用程式在沒有警告的情況下突然開始發出噪音,可能會讓人感到刺耳、不方便或令人反感。因此,瀏覽器通常只允許在特定情況下成功自動播放。

自動播放可用性

一般來說,您可以假設只有在滿足以下至少一個條件的情況下,才允許媒體自動播放

  • 音訊被靜音或其音量設定為 0
  • 使用者與網站進行了互動(例如,點選、輕觸、按下按鍵等)
  • 如果網站已被列入允許列表;這可能是自動發生的,如果瀏覽器確定使用者經常與媒體互動,或者透過偏好設定或其他使用者介面功能手動進行
  • 如果使用自動播放許可權策略<iframe>及其文件授予自動播放支援。

否則,播放可能會被阻止。導致阻止的確切情況以及網站被列入允許列表的具體方式因瀏覽器而異,但以上是良好的參考指南。

有關詳細資訊,請參閱Google ChromeWebKit的自動播放策略。

注意:換句話說,如果在尚未進行任何使用者互動的選項卡中以程式設計方式啟動任何包含音訊的媒體的播放,則通常會阻止其播放。瀏覽器還可能選擇在其他情況下進行阻止。

媒體元素的自動播放

現在我們已經瞭解了自動播放是什麼以及什麼可以阻止自動播放,接下來我們將看看您的網站或應用程式如何在頁面載入時自動播放媒體,如何檢測自動播放失敗以及在瀏覽器拒絕自動播放時應對的技巧。

autoplay 屬性

自動播放內容最簡單的方法是向您的<audio><video>元素新增autoplay屬性,這會將元素上的autoplay屬性設定為true。當autoplaytrue時,媒體將在滿足以下條件後儘快自動開始播放

  • 頁面被允許使用自動播放功能
  • 元素在頁面載入期間已建立
  • 已經接收了足夠的媒體以開始播放並持續播放到媒體結束,假設網路效能或頻寬沒有發生戲劇性的變化。

示例:autoplay 屬性

使用autoplay屬性的<audio>元素可能看起來像這樣

html
<audio id="musicplayer" autoplay>
  <source src="/music/chapter1.mp3" />
</audio>

示例 2:檢測是否允許自動播放

如果自動播放對您的應用程式很重要,您可能需要根據是否允許自動播放、是否不允許自動播放或是否只支援不可聽見的內容來定製行為。例如,如果您的應用程式需要自動播放影片,並且您知道頁面只允許自動播放不可聽見的內容,您可以將其靜音或提供沒有音訊軌道的影片。類似地,如果您知道完全不允許自動播放,您可能需要為影片提供預設影像(使用poster屬性),或者選擇推遲載入影片直到請求它。

Navigator.getAutoplayPolicy()方法可用於檢查文件中某類媒體功能(即所有媒體元素或所有音訊上下文)的自動播放策略,或檢查特定媒體元素或音訊上下文是否可以自動播放。

下面的示例展示瞭如何傳遞mediaelement字串以獲取文件中所有媒體元素的自動播放策略(傳遞audiocontext以獲取音訊上下文的策略)。程式碼假設video是使用<video>標籤或HTMLVideoElementHTMLVideoElement媒體元素,並且它預設配置為帶音訊自動播放。如果自動播放只允許不可聽見的內容,我們將靜音音訊;如果自動播放被禁止,我們將確保顯示影片的佔位符影像。

js
if (navigator.getAutoplayPolicy("mediaelement") === "allowed") {
  // The video element will autoplay with audio.
} else if (navigator.getAutoplayPolicy("mediaelement") === "allowed-muted") {
  // Mute audio on video
  video.muted = true;
} else if (navigator.getAutoplayPolicy("mediaelement") === "disallowed") {
  // Set a default placeholder image.
  video.poster = "http://example.com/poster_image_url";
}

測試特定元素或音訊上下文的程式碼相同,只是您傳入要測試的元素或上下文,而不是型別字串。在這裡,我們將傳入我們要測試的video物件。

js
if (navigator.getAutoplayPolicy(video) === "allowed") {
  // The video element will autoplay with audio.
} else if (navigator.getAutoplayPolicy(video) === "allowed-muted") {
  // Mute audio on video
  video.muted = true;
} else if (navigator.getAutoplayPolicy(video) === "disallowed") {
  // Set a default placeholder image.
  video.poster = "http://example.com/poster_image_url";
}

某類媒體的自動播放策略可能會因使用者與網站、頁面或特定元素的互動而改變。類似地,在某些瀏覽器上,特定元素的策略可能會改變,即使型別的策略沒有改變(例如,在使用者觸控特定元素即可允許該元素自動播放的瀏覽器上)。

由於無法在自動播放策略改變時(無論是型別還是元素)收到通知,因此我們通常建議在頁面載入時使用型別檢查策略。

示例 3:檢測自動播放失敗作為回退

自動播放成功或失敗不會觸發任何特定事件(或其他通知),因此不支援Navigator.getAutoplayPolicy()的瀏覽器無法輕鬆確定是否支援自動播放,也無法在觸發或未觸發自動播放時做出反應。

一種方法是監聽play事件的首次例項,該事件在媒體元素被暫停恢復播放時以及自動播放時觸發。這意味著play事件第一次被觸發時,您就知道您的媒體在頁面開啟後第一次被啟動,

考慮以下用於媒體元素的 HTML 程式碼

html
<video src="myvideo.mp4" id="video" autoplay></video>

在這裡,我們有一個<video>元素,它的autoplay屬性被設定,並且設定了play事件處理程式;該事件由名為handleFirstPlay()的函式處理,該函式接收play事件作為輸入。

handleFirstPlay()看起來像這樣

js
const video = document.getElementById("video");
video.addEventListener("play", handleFirstPlay, false);

let hasPlayed = false;
function handleFirstPlay(event) {
  if (!hasPlayed) {
    hasPlayed = true;

    // Remove listener so this only gets called once.
    const vid = event.target;
    vid.removeEventListener("play", handleFirstPlay);

    // Start whatever you need to do after first playback has started
  }
}

Event物件的target中獲取影片元素的引用後,我們使用它來移除事件監聽器。這將阻止任何未來的play事件傳遞到處理程式。這可能會發生在影片被使用者暫停和恢復,或者當文件處於後臺選項卡時由瀏覽器自動暫停和恢復時。

此時,您的網站或應用可以開始執行任何依賴於影片啟動的操作。

play() 方法

"自動播放" 一詞也指指令碼嘗試在處理使用者輸入事件之外的上下文中觸發包含音訊的媒體播放的情況。這是透過呼叫媒體元素的 play() 方法來實現的。

注意: 強烈建議您儘可能使用autoplay屬性,因為對自動播放首選項的支援在autoplay屬性上比其他自動播放媒體的方式更為廣泛。它還允許瀏覽器負責啟動播放,使其能夠最佳化播放的時機。

示例:播放影片

這個簡單的示例播放文件中找到的第一個 <video> 元素。play() 不會讓播放開始,除非文件有權自動播放媒體。

js
document.querySelector("video").play();

示例:處理 play() 失敗

當您使用 play() 方法啟動媒體時,檢測自動播放媒體失敗要容易得多。play() 返回一個 Promise,當媒體成功開始播放時,該 Promise 會被解決,當播放無法開始時(例如,如果自動播放被拒絕)會被拒絕。當自動播放失敗時,您可能需要提供一種方式讓使用者手動告訴瀏覽器詢問使用者是否允許播放媒體。

您可以使用類似以下程式碼來完成工作

js
let startPlayPromise = videoElem.play();

if (startPlayPromise !== undefined) {
  startPlayPromise
    .then(() => {
      // Start whatever you need to do only after playback
      // has begun.
    })
    .catch((error) => {
      if (error.name === "NotAllowedError") {
        showPlayButton(videoElem);
      } else {
        // Handle a load or playback error
      }
    });
}

我們首先對play()結果進行操作,確保它不是undefined。我們檢查這一點,因為在早期版本的 HTML 規範中,play()沒有返回值。最近添加了返回 Promise 以允許您確定操作的成功或失敗。檢查undefined可以防止此程式碼在舊版本的 Web 瀏覽器上出現錯誤。

如果play()返回的 Promise 在沒有錯誤的情況下被解決,則執行then()子句,並且可以在自動播放開始時開始執行任何需要執行的操作。

然後,我們向 Promise 新增一個 catch() 處理程式。這會檢視錯誤的 name,以檢視它是否為NotAllowedError。這表示播放由於許可權問題而失敗,例如自動播放被拒絕。如果是這種情況,我們應該提供一個使用者介面,讓使用者手動啟動播放;這裡由函式showPlayButton()處理。

任何其他錯誤都將根據需要處理。

如果您想在第一次與頁面互動後開始播放影片,可以使用 setInterval() 來實現這一點

js
let playAttempt = setInterval(() => {
  videoElem
    .play()
    .then(() => {
      clearInterval(playAttempt);
    })
    .catch((error) => {
      console.log("Unable to play the video, User has not interacted yet.");
    });
}, 3000);

使用 Web Audio API 自動播放

Web Audio API 中,網站或應用可以使用連線到 AudioContext 的源節點上的start()方法開始播放音訊。在處理使用者輸入事件之外的上下文中執行此操作受自動播放規則的約束。

自動播放許可權策略

除了上面描述的瀏覽器端對自動播放功能的管理和控制之外,Web 伺服器還可以表達其允許自動播放功能的意願。 HTTP Permissions-Policy 標頭的 autoplay 指令用於控制哪些域(如果有)可以用來自動播放媒體。預設情況下,autoplay Permissions Policy 設定為self,表示允許自動播放,因為它們與文件託管在同一個域上。

您還可以指定一個空的允許列表(())來完全停用自動播放,*來允許所有域的自動播放,或者一個或多個可以自動播放媒體的特定來源。這些來源之間用空格隔開。

注意: 指定的 Permissions Policy 適用於文件及其內部巢狀的每個 <iframe>,除非這些框架包含一個 allow,它為該框架及其內部巢狀的框架設定一個新的 Permissions Policy。

當在<iframe>上使用 allow 屬性為該框架及其巢狀的框架指定 Permissions Policy 時,您還可以指定值'src' 來僅允許從與框架的 src 屬性指定的域相同的域自動播放媒體。

示例:僅允許從文件域自動播放

要使用 Permissions-Policy 標頭僅允許從文件的 來源 自動播放媒體

http
Permissions-Policy: autoplay=(self)

要對 <iframe> 做同樣的事情

html
<iframe src="mediaplayer.html" allow="autoplay"> </iframe>

示例:允許自動播放和全屏模式

如果無論域如何都允許全屏訪問,則將 Fullscreen API 許可權新增到前面的示例會導致以下類似的Permissions-Policy 標頭;也可以根據需要新增域限制。

http
Permissions-Policy: autoplay=(self), fullscreen=(self)

使用<iframe>元素的allow屬性授予的相同許可權如下所示

html
<iframe src="mediaplayer.html" allow="autoplay; fullscreen"> </iframe>

示例:允許來自特定來源的自動播放

Permissions-Policy 標頭允許從文件(或<iframe>)自己的域和https://example.media播放媒體,如下所示

http
Permissions-Policy: autoplay=(self "https://example.media")

可以編寫一個 <iframe> 來指定應該將此自動播放策略應用於自身,以及任何子框架的編寫方式

html
<iframe
  width="300"
  height="200"
  src="mediaplayer.html"
  allow="autoplay 'src' https://example.media">
</iframe>

示例:停用自動播放

autoplay Permissions Policy 設定為()/none將完全停用文件或<iframe>及其所有巢狀框架的自動播放。HTTP 標頭為

http
Permissions-Policy: autoplay=()

使用<iframe>allow屬性

html
<iframe src="mediaplayer.html" allow="autoplay 'none'"> </iframe>

最佳實踐

這裡提供了一些技巧和推薦的最佳實踐,幫助您充分利用自動播放功能。

使用媒體控制元件處理自動播放失敗

自動播放的一個常見用例是自動開始播放與文章、廣告或頁面主要功能的預覽相關的影片片段。要自動播放這樣的影片,您有兩個選擇:不要有音訊軌道,或者有音訊軌道,但配置 <video> 元素預設情況下靜音,如下所示

html
<video
  src="/videos/awesomevid.webm"
  controls
  autoplay
  playsinline
  muted></video>

此影片元素被配置為包含使用者控制元件(通常是播放/暫停、在影片時間線上拖動、音量控制和靜音);此外,由於包含了 muted 屬性,以及 Safari 中自動播放所需的 playsinline 屬性,因此影片將自動播放,但音訊靜音。但是,使用者可以選擇透過單擊控制元件中的取消靜音按鈕重新啟用音訊。

瀏覽器配置選項

瀏覽器可能具有控制自動播放工作方式或處理自動播放阻止方式的首選項。這裡列出了任何可能對您作為 Web 開發人員特別重要或意義重大的首選項。這些包括可能有助於測試或除錯的任何首選項,以及您需要做好準備處理的任何可能以您需要的方式設定的首選項。

Firefox

media.allowed-to-play.enabled

一個布林值首選項,指定是否將非標準HTMLMediaElement.allowedToPlay屬性公開給網路。目前預設情況下為false(除了在 nightly 版本中,預設情況下為true)。如果為false,則allowedToPlay屬性將缺失於HTMLMediaElement介面中,因此不會出現在 <audio><video> 元素中。

media.autoplay.allow-extension-background-pages

這個布林值首選項,如果為true,允許瀏覽器擴充套件的後臺指令碼自動播放音訊媒體。將此值設定為false將停用此功能。預設值為true

media.autoplay.allow-muted

一個布林值首選項,如果為true(預設值),允許當前靜音的音訊媒體自動播放。如果將其更改為false,即使靜音,也不能播放帶有音訊軌道的媒體。

media.autoplay.block-webaudio

一個布林值首選項,指示是否將自動播放阻止應用於 Web Audio API。如果為false,則 Web 音訊始終允許自動播放。如果為true,則音訊上下文只能在頁面被 Sticky 啟用 後播放。預設設定為true

media.autoplay.default

一個整型首選項,指定預設情況下是否允許(0)、阻止(1)或提示使用(2)每個域的自動播放支援配置。預設值為0

media.autoplay.enabled.user-gestures-needed(僅限 nightly 版本)

一個布林值首選項,控制是否允許檢測使用者手勢來覆蓋media.autoplay.default的設定。如果media.autoplay.default設定為0(預設情況下允許自動播放),則此首選項為true,如果頁面已被使用者手勢啟用,則無論如何都允許自動播放帶有音訊軌道的媒體,並且不可聽的媒體不受任何限制。

media.block-autoplay-until-in-foreground

一個布林值首選項,指示是否在後臺選項卡上啟動時阻止媒體播放。預設值true表示,即使在其他情況下可用,自動播放也不會在選項卡被帶到前臺之前進行。這可以防止選項卡開始播放聲音,而使用者無法在所有選項卡和視窗中找到該選項卡的令人分心的情況。

另請參閱