カスタム ウェブ レシーバーにコア機能を追加する

このページでは、カスタム ウェブレシーバー アプリで使用できるコード スニペットと機能について説明します。

  1. ウェブ レシーバーに付属の組み込みプレーヤー UI を表す cast-media-player 要素。
  2. cast-media-player 要素のカスタム CSS のようなスタイル設定により、background-imagesplash-imagefont-family などのさまざまな UI 要素のスタイルを設定します。
  3. Web Receiver フレームワークを読み込むスクリプト要素。
  4. メッセージをインターセプトしてイベントを処理する JavaScript コード。
  5. 自動再生のキュー。
  6. 再生を設定するオプション。
  7. Web Receiver コンテキストを設定するオプション。
  8. Web Receiver アプリでサポートされているコマンドを設定するオプション。
  9. Web Receiver アプリケーションを起動する JavaScript 呼び出し。

アプリケーションの構成とオプション

CastReceiverContext は、デベロッパーに公開される最も外側のクラスであり、基盤となるライブラリの読み込みを管理し、Web Receiver SDK の初期化を処理します。

Web Receiver API で送信者の接続が解除されると、SENDER_DISCONNECTED イベントが発生します。maxInactivity 秒の間、ウェブ レシーバが送信者と通信できなかった場合は、SENDER_DISCONNECTED イベントが発生します。開発時には、maxInactivity を大きな値に設定して、Chrome リモート デバッガでアプリをデバッグするときにウェブ レシーバー アプリが閉じないようにすることをおすすめします。

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; //Development only
context.start(options);

ただし、公開済みの Web Receiver アプリケーションでは、maxInactivity を設定せず、代わりにデフォルト値を使用することをおすすめします。Web Receiver オプションは、アプリケーションで 1 回だけ設定されます。

もう 1 つの構成は cast.framework.PlaybackConfig です。これは次のように設定できます。

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

この設定は各コンテンツの再生に適用され、基本的にオーバーライド動作を提供します。デベロッパーがオーバーライドできる動作のリストについては、cast.framework.PlaybackConfig の定義をご覧ください。コンテンツ間の構成を変更するには、次のように PlayerManager を使用して現在の playbackConfig を取得し、オーバーライドを変更または追加して playbackConfig をリセットします。

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

PlaybackConfig がオーバーライドされていない場合、getPlaybackConfig() は null オブジェクトを返します。PlaybackConfig that のプロパティはすべて undefined であり、デフォルト値を使用します。

イベント リスナー

Web Receiver SDK を使用すると、Web Receiver アプリでプレーヤー イベントを処理できます。イベント リスナーは、リスナーをトリガーするイベントを指定する cast.framework.events.EventType パラメータ(またはこれらのパラメータの配列)を受け取ります。デバッグに役立つ事前構成された cast.framework.events.EventType の配列は、cast.framework.events.category にあります。event パラメータは、イベントに関する追加情報を提供します。

たとえば、mediaStatus の変更がブロードキャストされているタイミングを把握したい場合は、次のロジックを使用してイベントを処理します。

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

メッセージ インターセプト

Web Receiver SDK を使用すると、Web Receiver アプリでメッセージをインターセプトし、それらのメッセージでカスタムコードを実行できます。メッセージ インターセプタは、インターセプトされるメッセージの種類を指定する cast.framework.messages.MessageType パラメータを受け取ります。

インターセプトは、変更されたリクエストまたは変更されたリクエスト値で解決される Promise を返す必要があります。null を返すと、デフォルトのメッセージ ハンドラが呼び出されなくなります。詳しくは、メディアの読み込みをご覧ください。

たとえば、読み込みリクエストデータを変更する場合は、次のロジックを使用してデータをインターセプトして変更できます。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

エラー処理

メッセージ インターセプタでエラーが発生した場合、Web Receiver アプリは適切な cast.framework.messages.ErrorTypecast.framework.messages.ErrorReason を返す必要があります。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

メッセージ インターセプトとイベント リスナー

メッセージ インターセプトとイベント リスナーの主な違いは次のとおりです。

  • イベント リスナーでリクエスト データを変更することはできません
  • イベント リスナーは、分析やカスタム関数のトリガーに最適です。
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • メッセージ インターセプトを使用すると、メッセージのリッスン、メッセージのインターセプト、リクエスト データ自体の変更を行うことができます。
  • メッセージ インターセプトは、リクエスト データに関連するカスタム ロジックを処理する場合に最適です。

メディアの読み込み

MediaInformation には、cast.framework.messages.MessageType.LOAD メッセージ(entitycontentUrlcontentId など)でメディアを読み込むためのさまざまなプロパティが用意されています。

entity は、送信者アプリと受信者アプリの両方について実装で使用することが推奨されるプロパティです。このプロパティはディープリンクの URL で、プレイリストでも特定のメディア コンテンツでも指定できます。

contentUrl は再生可能な URL 用に設計されており、利用可能になった時点で使用できます。

値がメディアの URL、実際の ID、カスタム ルックアップのキー パラメータのあいまいさから、contentId のサポートは終了しました。

実際の ID またはキーパラメータを格納するのに entity を使用し、メディアの URL に contentUrl を使用することをおすすめします。次のスニペットは、LOAD リクエストに entity が存在し、再生可能な contentUrl を取得する場合の例を示しています。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

デバイスの機能

getDeviceCapabilities メソッドは、接続されたキャスト デバイスと、それに接続されている動画またはオーディオ デバイスのデバイス情報を提供します。getDeviceCapabilities メソッドは、Google アシスタント、Bluetooth、接続されたディスプレイ、オーディオ デバイスのサポート情報を提供します。

このメソッドは、指定された列挙型のいずれかを渡してその列挙型のデバイス機能を取得し、クエリを実行できるオブジェクトを返します。列挙型は cast.framework.system.DeviceCapabilities で定義されています。

この例では、Web Receiver デバイスが IS_HDR_SUPPORTED キー、IS_DV_SUPPORTED キーでそれぞれ HDR と DolbyVision(DV)を再生できるかどうかを確認します。

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

ユーザー操作の処理

ユーザーは、送信者アプリ(ウェブ、Android、iOS)、アシスタント搭載デバイスの音声コマンド、スマートディスプレイのタップ操作、Android TV デバイスのリモコンを介して、Web Receiver アプリを操作できます。Cast SDK には、Web Receiver アプリがこのようなインタラクションを処理し、ユーザー アクションの状態を通じてアプリケーション UI を更新できるさまざまな API が用意されています。また、必要に応じてバックエンド サービスを更新するために変更を送信することもできます。

サポートされているメディア コマンド

UI コントロールの状態は、iOS / Android 送信者拡張コントローラの MediaStatus.supportedMediaCommands、タッチデバイスで実行されるレシーバー アプリとリモート コントロール アプリ、Android TV デバイスのレシーバー アプリによって駆動されます。特定のビット単位の Command がプロパティで有効になっていると、そのアクションに関連するボタンが有効になります。値が設定されていない場合、ボタンは無効になります。これらの値は、次の方法で Web Receiver で変更できます。

  1. PlayerManager.setSupportedMediaCommands を使用して特定の Commands を設定する
  2. addSupportedMediaCommands を使用して新しいコマンドを追加する
  3. removeSupportedMediaCommands を使用して既存のコマンドを削除する。
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

レシーバが MediaStatus の更新を準備すると、supportedMediaCommands プロパティの変更が含まれます。ステータスがブロードキャストされると、接続された送信者アプリはそれに応じて UI のボタンを更新します。

サポートされているメディア コマンドとタッチデバイスの詳細については、Accessing UI controls ガイドをご覧ください。

ユーザー アクションの状態の管理

ユーザーが UI を操作する、または音声コマンドを送信するときに、再生中のアイテムに関連するコンテンツやプロパティの再生を制御できます。再生を制御するリクエストは、SDK によって自動的に処理されます。LIKE コマンドなど、再生中のアイテムのプロパティを変更するリクエストでは、受信側アプリがそれを処理する必要があります。SDK には、このようなリクエストを処理するための一連の API が用意されています。これらのリクエストをサポートするには、次のことを行う必要があります。

  • USER_ACTION メッセージをインターセプトして、リクエストされたアクションを決定します。
  • MediaInformation UserActionState を更新して UI を更新します。

以下のスニペットは、USER_ACTION メッセージをインターセプトし、リクエストされた変更でバックエンドの呼び出しを処理します。次に、レシーバーの UserActionState を更新する呼び出しを行います。

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

以下のスニペットは、バックエンド サービスの呼び出しをシミュレートします。この関数は UserActionRequestData をチェックして、ユーザーがリクエストした変更のタイプを確認し、アクションがバックエンドでサポートされている場合にのみネットワーク呼び出しを行います。

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

以下のスニペットは、UserActionRequestData を受け取り、MediaInformation に対して UserActionState を追加または削除します。MediaInformationUserActionState を更新すると、リクエストされたアクションに関連付けられたボタンの状態が変わります。この変更は、スマートディスプレイ ディスプレイ UI、リモコンアプリ、Android TV UI に反映されます。また、送信 MediaStatus メッセージを通じてブロードキャストされ、iOS と Android の送信者向けに拡張されたコントローラの UI を更新します。

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

音声コマンド

現在、以下のメディア コマンドは、アシスタント搭載デバイスの Web Receiver SDK でサポートされています。これらのコマンドのデフォルト実装は cast.framework.PlayerManager にあります。

コマンド 説明
Play 一時停止状態で再生または再開する。
一時停止 現在再生中のコンテンツを一時停止します。
前へ メディアキュー内の前のメディア アイテムにスキップします。
次へ メディアキューの次のメディア アイテムにスキップします。
停止 現在再生中のメディアを停止します。
リピートなし キューの最後のアイテムの再生が終了したら、キュー内のメディア アイテムの繰り返しを無効にします。
繰り返し 1 回 現在再生中のメディアを無期限に繰り返します。
すべて繰り返す キューの最後のアイテムが再生されたら、キュー内のすべてのアイテムを繰り返します。
全曲リピートとシャッフル キューの最後のアイテムの再生が完了したら、キューをシャッフルして、キュー内のすべてのアイテムを繰り返します。
シャッフル メディアキュー内のメディア アイテムをシャッフルします。
字幕のオン / オフ メディアの字幕を有効または無効にする。有効化 / 無効化は言語ごとに行うこともできます。
絶対時間までシーク 指定した絶対時間にジャンプします。
現在の時間に対して相対時間をシーク 現在の再生時間を基準にして、指定された時間だけ早送りまたは巻き戻しを行います。
もう一度プレイ 現在再生中のメディアを再開します。または、まだ何も再生していない場合は、最後に再生したメディア アイテムを再生します。
再生速度を設定する さまざまなメディアの再生速度これはデフォルトで処理されます。SET_PLAYBACK_RATE メッセージ インターセプトを使用して、受信レートのリクエストをオーバーライドできます。

音声によるサポートされているメディア コマンド

アシスタント搭載デバイスで音声コマンドでメディア コマンドがトリガーされないようにするには、まずサポートするサポート対象のメディア コマンドを設定する必要があります。これらのコマンドを強制するには、CastReceiverOptions.enforceSupportedCommands プロパティを有効にする必要があります。Cast SDK 送信者とタップ対応デバイスの UI は、これらの設定を反映するように変更されます。このフラグが有効になっていない場合は、受信した音声コマンドが実行されます。

たとえば、送信側アプリとタップ対応デバイスから PAUSE を許可する場合、それらの設定を反映するようにレシーバを構成する必要があります。構成済みのコマンドがサポートされているコマンドのリストに含まれていない場合、そのコマンドは破棄されます。

以下の例では、CastReceiverContext の開始時に CastReceiverOptions を指定しています。PAUSE コマンドのサポートを追加し、プレーヤーがそのコマンドのみをサポートするようにしました。音声コマンドが SEEK などの別のオペレーションをリクエストすると、拒否されます。このコマンドはまだサポートされていないことがユーザーに通知されます。

const context = cast.framework.CastReceiverContext.getInstance();

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

制限するコマンドごとに個別のロジックを適用できます。enforceSupportedCommands フラグを削除し、制限するコマンドごとに、受信メッセージをインターセプトできます。ここでは、SDK から提供されるリクエストをインターセプトし、アシスタント搭載デバイスに発行された SEEK コマンドによって Web Receiver アプリケーションでシークがトリガーされないようにしています。

アプリがサポートしていないメディア コマンドの場合は、適切なエラーの理由(NOT_SUPPORTED など)を返します。

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

音声アクティビティの背景

ユーザーの音声の聞き取りや読み上げなど、アシスタントのアクティビティによってキャスト プラットフォームでアプリのサウンドがバックグラウンド化されると、アクティビティの開始時に NOT_IN_FOCUSFocusState メッセージが Web Receiver アプリケーションに送信されます。アクティビティが終了すると、IN_FOCUS を含む別のメッセージが送信されます。 アプリと再生中のメディアによっては、メッセージ タイプ FOCUS_STATE をインターセプトして、FocusStateNOT_IN_FOCUS のときにメディアを一時停止できます。

たとえば、アシスタントがユーザーのクエリに応答している場合は、オーディオブックの再生を一時停止することをおすすめします。

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

音声指定の字幕言語

字幕の言語が明示的に指定されていない場合、字幕の言語はコマンドが話された言語になります。このような場合、受信メッセージの isSuggestedLanguage パラメータは、関連付けられた言語がユーザーによって提案されたか、明示的にリクエストされたかを示します。

たとえば、「OK Google, 字幕をオン」というコマンドの isSuggestedLanguagetrue に設定されています。これは、コマンドが話されている言語によって言語が推定されているためです。「OK Google, 英語の字幕をつける」のように、言語を明示的にリクエストした場合、isSuggestedLanguagefalse に設定されます。

メタデータと音声のキャスト

音声コマンドはデフォルトでウェブ レシーバによって処理されますが、コンテンツのメタデータは完全で正確である必要があります。これにより、アシスタントで音声コマンドが正しく処理され、Google Home アプリやスマートディスプレイなどの新しいインターフェース(Google Home Hub など)でメタデータが適切に表示されるようになります。

ストリーミング転送

セッション状態の保持はストリーム転送の基礎であり、ユーザーは音声コマンド、Google Home アプリ、スマートディスプレイを使用して既存の音声ストリームや動画ストリームをデバイス間で移動できます。メディアは、あるデバイス(ソース)で再生を停止し、別のデバイス(宛先)で再生を続けます。最新のファームウェアを搭載したキャスト デバイスは、ストリーミング転送のソースまたは宛先として機能します。

ストリーム転送のイベントフローは次のとおりです。

  1. ソースデバイスの場合:
    1. メディアの再生が停止します。
    2. Web Receiver アプリケーションは、現在のメディアの状態を保存するコマンドを受信します。
    3. Web Receiver アプリケーションがシャットダウンされます。
  2. 移行先のデバイスで次の操作を行います。
    1. Web Receiver アプリケーションが読み込まれます。
    2. ウェブ レシーバ アプリケーションは、保存されたメディアの状態を復元するコマンドを受信します。
    3. メディアの再生が再開されます。

メディア状態には次のような要素があります。

  • 曲、動画、メディア アイテムの特定の位置またはタイムスタンプ。
  • 幅広いキュー(プレイリストやアーティスト ラジオなど)に配置される
  • 認証されたユーザー。
  • 再生状態(再生、一時停止など)。

ストリーム転送を有効にする

Web Receiver にストリーム転送を実装するには:

  1. supportedMediaCommandsSTREAM_TRANSFER コマンドを使用して更新します。
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. 必要に応じて、セッション状態を保持するで説明されているように、SESSION_STATERESUME_SESSION のメッセージ インターセプタをオーバーライドします。これらをオーバーライドするのは、カスタム データをセッション スナップショットの一部として保存する必要がある場合のみです。それ以外の場合、セッション状態を保持するためのデフォルトの実装ではストリーム転送がサポートされます。

セッション状態を保持する

Web Receiver SDK には、現在のメディア ステータスのスナップショットを取り、ステータスを読み込みリクエストに変換し、読み込みリクエストでセッションを再開することで、セッション ステータスを保持するようにデフォルトで実装されています。

Web Receiver によって生成された読み込みリクエストは、必要に応じて SESSION_STATE メッセージ インターセプタでオーバーライドできます。カスタム データを読み込みリクエストに追加する場合は、loadRequestData.customData に配置することをおすすめします。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

カスタムデータは、RESUME_SESSION メッセージ インターセプタの loadRequestData.customData から取得できます。

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

コンテンツのプリロード

ウェブ レシーバは、キュー内の現在の再生アイテムの後でメディア アイテムをプリロードできます。

プリロード オペレーションは、今後のアイテムのセグメントをいくつか事前にダウンロードします。この指定は、QueueItem オブジェクトの preloadTime 値に対して行われます(指定されていない場合のデフォルトは 20 秒です)。この時間は、現在再生中のアイテムの終了時間を基準とした秒数です。有効な値は正の値のみです。たとえば、値が 10 秒の場合、前のアイテムが完了する 10 秒前にこのアイテムがプリロードされます。プリロードする時間が現行のアイテムに残っている時間よりも長い場合、プリロードはできるだけ早く行われます。queueItem で非常に大きなプリロードが指定されている場合、現在のアイテムを再生しているときにすでに次のアイテムをプリロードしているという効果が得られます。ただし、この値は現在の再生アイテムの帯域幅とストリーミング パフォーマンスに影響する可能性があるため、この設定はデベロッパーに任せます。

プリロードは、デフォルトで HLS、DASH、スムーズ ストリーミング コンテンツに対して機能します。

キャスト デバイスは 1 つのメディア要素のみをサポートし、既存のコンテンツ アイテムの再生中はプリロードに使用できないため、通常の MP4 動画ファイルや MP3 などの音声ファイルはプリロードされません。

カスタム メッセージ

メッセージ レシーバは、Web Receiver アプリケーションで使用される重要な操作方法です。

送信者は、送信者が動作しているプラットフォーム(Android、iOS、ウェブ)の送信者 API を使用して、ウェブ受信者にメッセージを送信します。イベント リスナーに渡されるイベント オブジェクト(メッセージのマニフェスト)には、特定のイベントタイプのプロパティを取るデータ要素(event.data)があります。

ウェブ レシーバ アプリケーションは、指定された名前空間でメッセージをリッスンすることを選択できます。それにより、Web Receiver アプリケーションはその名前空間プロトコルをサポートすると言われます。その後、適切なプロトコルを使用してその名前空間と通信する接続済み送信者は、任意に決定します。

すべての名前空間は文字列で定義され、「urn:x-cast:」で始まり、その後に任意の文字列が続きます。例: 「urn:x-cast:com.example.cast.mynamespace」。

接続された送信者からのカスタム メッセージをリッスンするウェブ レシーバーのコード スニペットを次に示します。

const context = cast.framework.CastReceiverContext.getInstance();

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

同様に、Web Receiver アプリケーションは、接続された送信者にメッセージを送信することで、送信者に Web Receiver の状態を常に通知できます。ウェブ レシーバ アプリケーションは、CastReceiverContextsendCustomMessage(namespace, senderId, message) を使用してメッセージを送信できます。ウェブ レシーバは、受信したメッセージに応じて、またはアプリケーションの状態の変化に応じて、個々の送信者にメッセージを送信できます。ウェブ レシーバは、ポイントツーポイント メッセージング(64 KB の上限)以外にも、接続されたすべての送信者にメッセージをブロードキャストできます。

オーディオ機器のキャスト

音声のみの再生のサポートについては、オーディオ デバイス向け Google Cast ガイドをご覧ください。

Android TV

このセクションでは、Google Web Receiver で入力を再生として使用し、Android TV の互換性について説明します。

アプリケーションとリモコンの統合

Android TV デバイスで実行されている Google ウェブレシーバーは、メディア再生メッセージで説明しているように、デバイスのコントロール入力(ハンドヘルド リモコン)からの入力を、urn:x-cast:com.google.cast.media 名前空間で定義されたメディア再生メッセージとして変換します。Android TV のコントロール入力から基本的な再生コントロールを行えるようにするには、アプリがこれらのメッセージをサポートしてアプリ メディアの再生を制御できる必要があります。

Android TV の互換性に関するガイドライン

アプリが Android TV に対応していることを確認するための、回避すべき推奨事項と一般的な注意点について説明します。

  • User-Agent 文字列には「Android」と「CrKey」の両方が含まれます。「Android」ラベルを検出するため、サイトによってはモバイル専用サイトにリダイレクトされる場合があります。ユーザー エージェント文字列の「Android」が常にモバイル ユーザーを示しているとは限りません。
  • Android のメディア スタックは、データの取得に透過的な GZIP を使用することがあります。メディアデータが Accept-Encoding: gzip に応答できることを確認します。
  • Android TV の HTML5 メディア イベントは、Chromecast とは異なるタイミングでトリガーされる場合があります。Chromecast に隠された問題が表示されることがあります。
  • メディアを更新するときは、<audio>/<video> 要素(timeupdatepausewaiting など)によって配信されるメディア関連のイベントを使用します。ネットワーク関連のイベント(progresssuspendstalled など)はプラットフォームに依存する傾向があるため、使用しないでください。レシーバでのメディア イベントの処理方法については、メディア イベントをご覧ください。
  • 受信側のサイトの HTTPS 証明書を構成する場合は、中間 CA 証明書を必ず含めてください。確認するには、Qualsys SSL テストページをご覧ください。サイトに対する信頼できる認証パスに「追加ダウンロード」というラベルの付いた CA 証明書が含まれている場合、Android ベースのプラットフォームでは読み込まれないことがあります。
  • Chromecast ではレシーバー ページを 720p グラフィック プレーンで表示しますが、Android TV などの他のキャスト プラットフォームでは 1080p までページを表示できます。レシーバページがさまざまな解像度でスムーズにスケーリングされるようにします。