ウェブ オーディオ、自動再生ポリシー、ゲーム

Tom Greenaway 氏
Hongchan Choi

2017 年 9 月に、Chrome の自動再生動作ポリシーで音声を処理する方法に関する今後の変更を発表しました。このポリシーの変更は 2018 年 5 月に Chrome 66 Stable でリリースされました。

ウェブ オーディオ開発コミュニティからのフィードバックを受け、デベロッパーが十分に時間をおいてウェブサイトを更新できるように、自動再生ポリシーのウェブ オーディオ部分のリリースを延期しました。また、ウェブオーディオに関するポリシーの実装についても一部変更しました。これにより、ウェブゲームをはじめとする、コードの調整が必要なウェブサイトの数を減らし、ユーザー エクスペリエンスの向上を図りました。

このポリシーの変更は 2018 年 12 月に Chrome 71 でリリースされる予定です。

ポリシー変更によって、具体的にどのような影響がありますか?

自動再生とは、ウェブページを読み込んだときにすぐに再生するコンテンツに付けられる名前です。この変更により、コンテンツの自動再生が可能なウェブサイトでは、デフォルトで再生が行われなくなります。ほとんどの場合、再生は再開されますが、場合によってはコードを少し調整する必要があります。具体的には、ユーザーがウェブページを操作したときにコンテンツを再開するコードを追加する必要があります。

ただし、ユーザーが自動再生コンテンツを含むページにアクセスした際に、同じオリジンのページからそのページにアクセスした場合、そのコンテンツがブロックされることはありません。詳しい例については、自動再生に関するポリシーについての以前のブログ投稿をご覧ください。

また、音声を自動再生するウェブサイトに関するユーザーの行動から学習するヒューリスティックを追加しました。Google は、ウェブサイトへのアクセスの大部分で、音声が通常 7 秒以上再生されていることを検出し、そのウェブサイトに対して自動再生を有効にします。

そのために、デバイス上の Chrome プロファイルごとにローカルに保存されるインデックスを使用します。このインデックスは、デバイス間で同期されることはなく、匿名化されたユーザー統計情報の一部としてのみ共有されます。このインデックスは Media Engagement Index(MEI)と呼ばれ、chrome://media-engagement で表示できます。

MEI では、7 秒を超える音声が再生されたサイトへのアクセス数がトラッキングされます。ユーザーの MEI に基づいて、ユーザーが特定のウェブサイトの音声を期待しているかどうかを把握し、将来のユーザーの意図を予測できます。

ユーザーがウェブサイトのドメインで音声を 7 秒以上再生することが多い場合、ユーザーは今後、そのウェブサイトに音声を自動再生する権利があることを想定していると考えられます。そのため Google では、ユーザーがそのドメインのタブを操作することなく音声を自動再生する権利をそのウェブサイトに付与しています。

ただし、この権利は無期限に保証されるわけではありません。ユーザーの行動が切り替わった場合(複数回の訪問で音声の再生を停止する、タブを 7 秒以内に閉じるなど)、ウェブサイトの自動再生の権利を剥奪します。

メディアの HTML 要素(動画と音声)とウェブ オーディオ(JavaScript でインスタンス化された AudioContext オブジェクト)の両方の使用が MEI に反映されます。このポリシーのロールアウトに備えて、Chrome 70 以降では、ウェブオーディオに関するユーザーの行動が MEI に寄与します。これにより、自動再生やユーザーがよくアクセスするウェブサイトに関してユーザーが望む意図をすでに予測できるようになります。

iframe がユーザーの操作なしで自動再生する権利を獲得できるのは、iframe を埋め込んだ親ウェブページが、指定された iframe にその権利を拡張した場合のみです。

コミュニティをサポートするために変更を遅らせる

Chrome Stable チャンネルでこの変更が実装されると、ウェブ オーディオ デベロッパー コミュニティ(特にウェブゲーム デベロッパーと WebRTC デベロッパーの一部)は注意を払いました。

コミュニティからのフィードバックでは、多くのウェブゲームやウェブ オーディオ エクスペリエンスがこの変更によって悪影響を受けるというものでした。具体的には、更新されていない多くのサイトでは、音声が再生されなくなると思われます。そのため、Google のチームは、ウェブ オーディオのデベロッパーがウェブサイトを更新する時間を確保できるよう、この変更を延期することに値すると判断しました。

さらに、以下の取り組みを実施いたしました。

  • このポリシーの変更が最善の対応かどうかを慎重に検討してください。
  • 影響を受ける、音声を含むウェブサイトの数を減らす Google の取り組みをご確認ください。

前者に関しては、大多数のユーザーのユーザー エクスペリエンスを向上させるうえで、ポリシーの変更は実際に必要であると判断しました。ポリシー変更によって解決される問題について詳しくは、この記事の次のセクションをご覧ください。

後者については、ウェブ オーディオの実装に調整を加え、当初影響を受けたウェブサイトの数を減らすことになりました。この変更により機能しなくなるサイトの割合は高く、その多くはウェブゲーム開発コミュニティで例として挙げられています。この調整により、80% 以上が自動的に機能することがわかりました。サンプルサイトの分析とテストはこちらでご覧いただけます。この新しい調整について、以下で詳しく説明します。

また、WebRTC アプリケーションをサポートするための変更も行いました。アクティブなキャプチャ セッションの間は、自動再生が可能です。

この動作変更で解決しようとしている問題は何ですか。

ブラウザはこれまで、ユーザーの音声管理に役立ってきませんでした。ユーザーがウェブページを開いて、予想外の音声を受信した場合、ユーザー エクスペリエンスが低下します。Google では、このようなユーザー エクスペリエンスの低さを解決しようとしています。ユーザーがブラウザでコンテンツの自動再生を希望しない主な理由は、不要なノイズです。

しかし、ユーザーがコンテンツを自動再生させたいと望んでいる場合もあります。その場合、ユーザーは Chrome でブロックされた自動再生の相当数の再生がその後に続きます。

そのため Google は、ユーザーについて学び、ウェブサイトごとにユーザーの意図を予測することで、最適なユーザー エクスペリエンスを生み出すことができると考えています。ウェブサイトのコンテンツが再生される傾向にある場合は、今後そのサイトのコンテンツが自動再生されるようにします。逆に、ユーザーが特定のウェブサイトのコンテンツの自動再生を停止する傾向がある場合は、そのコンテンツの自動再生はデフォルトで無効になります。

コミュニティの皆さんから寄せられた提案の一つに、自動再生を一時停止するのではなく、タブの音声をミュートするというものがあります。ただし、自動再生がブロックされたことをウェブサイトが認識し、ウェブサイトのデベロッパーがこれに対応できるようにするには、自動再生を停止することをおすすめします。たとえば、単純に音声をミュートしたいデベロッパーもいれば、ユーザーが積極的にコンテンツを操作するまで音声コンテンツを一時停止させたい場合もあるでしょう。そうしないと、ユーザーが音声体験を損なう可能性があります。

ウェブゲーム デベロッパーを支援する新たな調整

Web Audio API を使用する最も一般的な方法は、オーディオを再生するための 2 種類のオブジェクトを作成することです。

ウェブ オーディオのデベロッパーは、オーディオを再生するための AudioContext を作成します。自動再生ポリシーによって AudioContext が自動的に一時停止された後に音声を再開するには、ユーザーがタブを操作した後で、このオブジェクトで restore() 関数を呼び出す必要があります。

    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 は、次の 2 つの条件が満たされると自動的に再開されます。

  • ユーザーがページで操作を行った。
  • ソースノードの 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 内でインスタンス化された AudioContext の再開には役立ちません。ただし、このコード スニペットが iframe 自体のコンテンツのスコープ内に含まれていない場合に限ります。

ユーザーにより良いサービスを提供

また、ポリシーの変更に伴い、自動学習が想定どおりに機能しない場合や、変更によって利用できなくなるウェブサイトに対応するために、ユーザーが自動再生ポリシーを無効にできる仕組みを導入します。この変更は Chrome 71 の新しいポリシーで展開され、[音声設定] で確認できます。ユーザーが自動再生を許可したいサイトは、許可リストに追加できます。

新規ユーザー向けの MEI はどのように構築されますか?

前述のように、Google はユーザーの行動に基づいて時間の経過とともに自動的に MEI を構築し、自動再生コンテンツがある特定のウェブサイトに対するユーザーの望ましい意向を予測します。各ウェブサイトのこのインデックスのスコアは 0 ~ 1 です。スコアが高いほど、ユーザーはそのウェブサイトからコンテンツを再生することを期待しています。

ただし、新しいユーザー プロフィールの場合、またはユーザーが閲覧データを削除した場合は、どこでも自動再生がブロックされるのではなく、匿名化されたユーザーの集計 MEI スコアに基づくプレシード リストを使用して、自動再生できるウェブサイトが決定されます。このデータによってのみ、ユーザー プロフィール作成時の MEI の初期状態が決まります。ユーザーがウェブをブラウジングして自動再生コンテンツのあるウェブサイトを操作すると、個人用 MEI がデフォルト設定よりも優先されます。

事前シード済みサイトのリストは、手動でキュレートされたものではなく、アルゴリズムによって生成されており、すべてのウェブサイトが対象となります。アクセスしたサイトで自動再生を許可しているユーザーの数が十分にある場合、そのサイトがリストに追加されます。このしきい値は、より大規模なサイトを優先しないよう、割合に基づいて設定されます。

バランスをとる

このポリシーの背後にある意思決定プロセスと設計の根拠についてさらに詳しく理解するための新しいドキュメントを投稿しました。加えて、プレシード サイトリストの仕組みに関する新しいドキュメントも追加しました。

Google は常にユーザーを第一に考えていますが、ウェブ開発コミュニティを失望させたくありません。ブラウザであるということは、この 2 つの目標を慎重にバランスを取る必要があることを意味します。ポリシーの実装方法を調整し、ウェブ オーディオのデベロッパーがコードを更新するために期間を延長することで、Chrome 71 でこのバランスを実現できると考えています。

フィードバック