網路音訊、自動播放政策和遊戲

Tom Greenaway
Hongchan Choi

我們在 2017 年 9 月宣布,Chrome 將根據自動播放行為政策調整音訊處理方式。這項政策異動已於 2018 年 5 月在 Chrome 66 穩定版中發布。

我們根據網路音訊開發社群的意見回饋後,延後發布自動播放政策的「網路音訊」部分,讓開發人員有更多時間可以更新網站。此外,我們也對網路音訊政策的執行方式做了一些調整,減少了需要調整程式碼 (尤其是網頁遊戲) 的網站數量,為使用者提供更優質的體驗。

這項政策異動現已預計在 2018 年 12 月的 Chrome 71 版推出。

政策異動究竟會有什麼改變?

「自動播放」是內容在網頁載入時立即播放的指定名稱。不過,這項變更預設會導致網站無法自動播放內容。在大多數情況下,系統會繼續播放,但在其他情況下則需要稍微調整程式碼。具體來說,開發人員必須加入程式碼,以便在使用者與網頁互動時恢復內容。

不過,如果使用者到達含有自動播放內容的網頁,而且從相同來源的網頁前往該網頁,那麼該內容絕不會遭到封鎖。參閱有關自動播放政策的網誌文章,查看詳細範例

此外,我們也加入經驗法則,讓使用者瞭解自動播放音訊的網站如何瞭解使用者過去的行為。我們會偵測使用者在大部分造訪網站期間,是否定期讓音訊播放超過 7 秒,並且為該網站啟用自動播放功能。

方法是將索引儲存在裝置上的每個 Chrome 設定檔本機上,而不會同步到所有裝置,只會做為匿名使用者統計資料的一部分分享。我們將這份索引稱為媒體參與指數 (MEI),您可以透過 chrome://media-engagement 查看。

MEI 會追蹤有多少次的造訪網站,包括播放超過 7 秒的音訊,根據使用者的 MEI,我們得以瞭解使用者預期音訊是否來自特定網站,並預測使用者的未來意圖。

如果使用者經常允許網站網域播放音訊超過 7 秒,我們日後會假設使用者希望這個網站有權自動播放音訊。因此,我們授權該網站可以自動播放音訊,而不需要使用者與該網域的分頁互動。

不過,我們不保證這項權利會無限期享有。如果使用者的行為切換 (例如在 7 秒內停止播放音訊或關閉分頁),我們就會移除網站自動播放的權利。

使用媒體 HTML 元素 (影片和音訊) 以及網路音訊 (JavaScript 例項化的 AudioContext 物件) 都會影響 MEI。在準備推出這項與網路音訊相關的政策使用者行為時,將從 Chrome 70 以上版本開始影響 MEI。這樣我們就能確定自動播放功能和經常造訪的網站時,能預測到使用者希望的意圖。

提醒你,如果嵌入 iframe 的上層網頁會將 iframe 延伸至指定 iframe, iframe 只能在使用者未互動的情況下直接自動播放。

延後變更來支持社群

當這項變更在 Chrome 穩定版發布時,網路音訊開發人員社群 (尤其是網路遊戲開發人員和 WebRTC 開發人員) 注意到了這項變動。

該社群的意見回饋表示,許多網路遊戲和網路音訊體驗將受到這項異動的影響,具體來說,許多未更新的網站將不再播放音訊。因此,我們的團隊認為應該延遲這項變更,讓網路音訊開發人員有更多時間更新網站。

此外,我們這次也加入了:

  • 請務必審慎思考這項政策異動是否是最佳措施。
  • 瞭解我們可以透過哪些方式減少含有音訊的網站數量。

我們最終認為,為了改善多數使用者的使用者體驗,政策修訂的確有其必要。如要進一步瞭解政策異動可解決的問題,請參閱本文下一節的說明。

至於後者,我們已調整網路音訊實作方式,減少原本受影響的網站數量。在我們已知的網站中,其中許多網站都是因為網路遊戲開發社群的例子而無法正常運作。經過調整後,有超過 80% 的網站會自動執行這類變更。如要查看我們對範例網站進行的分析和測試,請參閱這個網頁。以下將進一步說明這項新調整。

我們也做出了變更來支援 WebRTC 應用程式;只要有執行中的擷取工作階段,系統就會允許自動播放功能。

這項行為變更想要解決的問題為何?

瀏覽器一直以來都無法協助使用者管理音效。如果使用者在開啟網頁時收到不符預期或想要的聲音,會導致使用者體驗不佳。這表示我們想要解決的使用者體驗不佳。不必要的雜訊是使用者不希望瀏覽器自動播放內容的主要原因。

不過,有時使用者會希望內容自動播放,然後使用者之後又播放了有大量 Chrome 遭到封鎖的自動播放影片。

因此,我們相信,向使用者學習,並為每個網站預測使用者意圖,才能打造最佳的使用者體驗。如果使用者經常允許從網站上播放內容,日後我們就會自動播放該網站的內容。相反地,如果使用者經常停止特定網站的自動播放內容,系統預設會禁止自動播放該內容。

社群後續提出的提案之一,就是將分頁音訊設為靜音,而非暫停自動播放。不過,我們認為暫停自動播放體驗是更好的做法,讓網站知道自動播放已遭封鎖,並讓網站開發人員可以對此做出因應。舉例來說,雖然有些開發人員想直接靜音,但其他開發人員可能希望音訊內容暫停,直到使用者積極與內容互動為止,否則使用者可能會錯過音訊體驗。

協助網頁遊戲開發人員推出全新調整項目

開發人員最常使用 Web Audio API 的方式,就是建立兩種播放音訊的物件類型:

網路音訊開發人員會建立音訊內容來播放音訊。如要在自動播放政策自動暫停 AudioContext 後繼續音訊,必須在使用者與分頁互動後,在這個物件上呼叫 Resume() 函式:

    const context = new AudioContext();

    // Setup an audio graph with AudioNodes and schedule playback.
    ...

    // Resume AudioContext playback when user clicks a button on the page.
    document.querySelector('button').addEventListener('click', function() {
      context.resume().then(() => {
        console.log('AudioContext playback resumed successfully');
      });
    });

許多介面繼承自 AudioNode,其中一個是 AudioScheduledSourceNode 介面。實作 AudioScheduledSourceNode 介面的 AudioNode 通常稱為「來源節點」 (例如 AudioBufferSourceNode、ConstantSourceNode 和 OscillatorNode)。來源節點會實作 start() 方法。

來源節點通常代表遊戲播放的個別語音片段,例如玩家收集金幣或在目前階段播放的背景音樂時播放的音效。每當遊戲需要上述任何音效時,遊戲開發人員就可能在來源節點呼叫 start() 函式。

一旦發現網路遊戲的常見模式,我們決定依下列方式調整導入方式:

只要同時符合以下兩個條件,系統就會自動重新啟用 AudioContext:

  • 使用者與網頁互動。
  • 系統會呼叫來源節點的 start() 方法。

受到這項變更的影響,大多數網頁遊戲會在使用者開始玩遊戲時繼續播放音訊。

推動網路發展

為了推動網路平台發展,有時必須做出變更,以避免相容性問題。遺憾的是,音訊自動播放功能相當複雜,屬於這類變更。不過,確保網路不會停滯或失去創新優勢,這一點非常重要。

不過,我們也瞭解,短期內有時可能無法為網站套用修正措施,原因包括:

  • 網頁開發人員可能無法立即專注於新專案,而維護舊網站的維護工作並非一蹴可幾。
  • 網路遊戲入口網站可能無法掌控自家目錄中的遊戲實作方式,就算沒有數千款遊戲,也會耗費大量時間和成本。
  • 有些網站可能只是老舊,已基於某些原因或其他原因而停止維護,但仍會基於歷史目的代管。

以下這個簡單的 JavaScript 程式碼片段會攔截新的 AudioContext 物件,並在使用者進行各種使用者互動時,自動觸發這些物件的繼續功能。這段程式碼必須在在網頁上建立任何 AudioContext 物件之前執行。舉例來說,您可以將這段程式碼加進網頁的代碼中:

(function () {
  // An array of all contexts to resume on the page
  const audioContextList = [];

  // An array of various user interaction events we should listen for
  const userInputEventNames = [
    'click',
    'contextmenu',
    'auxclick',
    'dblclick',
    'mousedown',
    'mouseup',
    'pointerup',
    'touchend',
    'keydown',
    'keyup',
  ];

  // A proxy object to intercept AudioContexts and
  // add them to the array for tracking and resuming later
  self.AudioContext = new Proxy(self.AudioContext, {
    construct(target, args) {
      const result = new target(...args);
      audioContextList.push(result);
      return result;
    },
  });

  // To resume all AudioContexts being tracked
  function resumeAllContexts(event) {
    let count = 0;

    audioContextList.forEach(context => {
      if (context.state !== 'running') {
        context.resume();
      } else {
        count++;
      }
    });

    // If all the AudioContexts have now resumed then we
    // unbind all the event listeners from the page to prevent
    // unnecessary resume attempts
    if (count == audioContextList.length) {
      userInputEventNames.forEach(eventName => {
        document.removeEventListener(eventName, resumeAllContexts);
      });
    }
  }

  // We bind the resume function for each user interaction
  // event on the page
  userInputEventNames.forEach(eventName => {
    document.addEventListener(eventName, resumeAllContexts);
  });
})();

但請注意,這個程式碼片段無法協助繼續在 iframe 內例項化的 AudioContexts,除非這段程式碼片段加入 iframe 本身的內容範圍內。

為使用者提供更好的服務

為了因應政策異動,我們也推出了一項機制,讓使用者可以停用自動播放政策,並因應自動學習功能無法正常運作或因異動而無法使用的網站。這項異動將隨著 Chrome 71 版推出,您可以在「音效設定」中找到這項異動;可以將要允許使用者允許自動播放的網站加入允許清單。

如何針對新使用者建立 MEI?

如前所述,我們持續根據使用者行為自動建構 MEI,預測使用者對含有自動播放內容的網站所希望的意圖。在這份索引中,每個網站都有一個介於 0 至 1 的分數。分數越高,代表使用者預期會在該網站播放內容。

不過,對於新的使用者設定檔,或是使用者清除瀏覽資料 (而非一律封鎖所有自動播放功能),系統會使用彙整前的 MEI 分數預先種子名單,決定要讓哪些網站自動播放。這項資料僅決定建立使用者設定檔時 MEI 的初始狀態。使用者瀏覽網路並與自動播放內容的網站互動時,他們的個人 MEI 會覆寫預設設定。

預先種子網站清單是透過演算法產生,而非手動收錄,且任何網站皆可加入。如果網站有一定的造訪使用者允許自動播放,那麼網站就會加入清單中。這個門檻是以百分比為依據,因此為了避免偏重大型網站。

尋找平衡

我們發布了新說明文件,協助您進一步瞭解決策程序及相關政策的設計原理。同時參閱新說明文件,瞭解預先種子網站清單的運作方式

我們始終優先考量使用者的需求,但不希望網路開發社群成為成員。有時候,瀏覽器必須審慎平衡這兩個目標。我們相信,為了配合政策執行方式有所調整,也為網頁音訊開發人員提供額外時間來更新程式碼,如此一來,即使使用 Chrome 71,也能夠達到最佳平衡。

意見回饋