Cast SDK をウェブ センダー アプリに統合する

このデベロッパー ガイドでは、Cast SDK を使用して Web Sender アプリに Google Cast のサポートを追加する方法について説明します。

用語

モバイル デバイスまたはブラウザが送信側であり、これが再生を制御します。Google Cast デバイスが「受信側」であり、再生のために画面にコンテンツを表示します。

Web Sender SDK は、Framework API(cast.framework)と Base API(chrome.cast)の 2 つの部分で構成されています。通常は、よりシンプルで高レベルの Framework API で呼び出しを行います。呼び出しは下位レベルの Base API によって処理されます。

送信フレームワークとは、下位レベルの機能のラッパーを提供するフレームワーク API、モジュール、関連リソースを指します。送信側アプリまたは Google Cast Chrome アプリとは、送信側のデバイスの Chrome ブラウザ内で実行されるウェブ(HTML/JavaScript)アプリを指します。ウェブ レシーバー アプリとは、Chromecast または Google Cast デバイスで実行される HTML/JavaScript アプリのことです。

送信側フレームワークは非同期コールバック設計を使用して、送信側アプリにイベントを通知し、キャストアプリのライフサイクルのさまざまな状態間を遷移します。

ライブラリを読み込む

アプリに Google Cast の機能を実装するには、下記のように、Google Cast Web Sender SDK の場所をアプリが認識している必要があります。loadCastFramework URL クエリ パラメータを追加して、Web Sender Framework API も読み込みます。アプリのすべてのページで、次のようにライブラリを参照する必要があります。

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

フレームワーク

Web Sender SDK は cast.framework.* 名前空間を使用します。Namespace は以下を表します。

  • API に対するオペレーションを呼び出すメソッドまたは関数
  • API のリスナー関数のイベント リスナー

このフレームワークは、次の主要コンポーネントで構成されています。

  • CastContext は、現在のキャスト状態に関する情報を提供し、キャスト状態とキャスト セッション状態の変化のイベントをトリガーするシングルトン オブジェクトです。
  • CastSession オブジェクトはセッションを管理します。状態情報を提供し、デバイスの音量、ミュート状態、アプリのメタデータの変更など、イベントをトリガーします。
  • キャスト アイコン要素。HTML ボタンを拡張するシンプルな HTML カスタム要素です。提供されたキャスト ボタンでは不十分な場合は、キャスト状態を使用してキャスト アイコンを実装できます。
  • RemotePlayerController は、リモート プレーヤーの実装を簡素化するデータ バインディングを提供します。

名前空間の詳細な説明については、Google Cast Web Sender API リファレンスをご覧ください。

キャスト アイコン

アプリのキャスト アイコン コンポーネントは、すべてフレームワークによって処理されます。これには、公開設定の管理とクリック イベントの処理が含まれます。

<google-cast-launcher></google-cast-launcher>

または、プログラムでボタンを作成することもできます。

document.createElement("google-cast-launcher");

必要に応じて、サイズや位置などの追加のスタイル設定を要素に適用できます。--connected-color 属性を使用して、接続されている Web Receiver の状態の色を選択し、--disconnected-color を使用して切断された状態にします。

初期化

フレームワーク API を読み込むと、アプリはハンドラ window.__onGCastApiAvailable を呼び出します。送信者ライブラリを読み込む前に、アプリが window でこのハンドラが設定されていることを確認する必要があります。

このハンドラ内で、CastContextsetOptions(options) メソッドを呼び出してキャスト インタラクションを初期化します。

次に例を示します。

<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    initializeCastApi();
  }
};
</script>

次に、次のように API を初期化します。

initializeCastApi = function() {
  cast.framework.CastContext.getInstance().setOptions({
    receiverApplicationId: applicationId,
    autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
  });
};

まず、アプリはフレームワークから提供される CastContext オブジェクトのシングルトン インスタンスを取得します。次に、CastOptions オブジェクトを使用して setOptions(options) を使用し、applicationID を設定します。

登録が不要なデフォルトのメディア レシーバーを使用している場合は、applicationID の代わりに、次に示すように、Web Sender SDK によって事前に定義された定数を使用します。

cast.framework.CastContext.getInstance().setOptions({
  receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});

メディア コントロール

CastContext が初期化されると、アプリは getCurrentSession() を使用して、いつでも現在の CastSession を取得できます。

var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

CastSession を使用すると、loadMedia(loadRequest) で接続されたキャスト デバイスにメディアを読み込むことができます。まず、contentIdcontentType と、コンテンツに関連するその他の情報を使用して、MediaInfo を作成します。次に、そこから LoadRequest を作成し、リクエストに関連するすべての情報を設定します。最後に、CastSessionloadMedia(loadRequest) を呼び出します。

var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  function() { console.log('Load succeed'); },
  function(errorCode) { console.log('Error code: ' + errorCode); });

loadMedia メソッドは、正常な結果に必要なオペレーションの実行に使用できる Promise を返します。Promise が拒否された場合、関数の引数は chrome.cast.ErrorCode になります。

プレーヤーの状態変数には RemotePlayer でアクセスできます。メディア イベント コールバックやコマンドなど、RemotePlayer でのすべての操作は RemotePlayerController で処理されます。

var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);

RemotePlayerController は、読み込まれたメディアの再生、一時停止、停止、シークの完全なメディア コントロールをアプリに付与します。

  • 再生/一時停止: playerController.playOrPause();
  • 停止: playerController.stop();
  • シーク: playerController.seek();

RemotePlayerRemotePlayerController を Polymer や Angular などのデータ バインディング フレームワークとともに使用して、リモート プレーヤーを実装できます。

Angular のコード スニペットは次のとおりです。

<button id="playPauseButton" class="playerButton"
  ng-disabled="!player.canPause"
  ng-click="controller.playOrPause()">
    {{player.isPaused ? 'Play' : 'Pause'}}
</button>
<script>
var player = new cast.framework.RemotePlayer();
var controller = new cast.framework.RemotePlayerController(player);
// Listen to any player update, and trigger angular data binding
update.controller.addEventListener(
  cast.framework.RemotePlayerEventType.ANY_CHANGE,
  function(event) {
    if (!$scope.$$phase) $scope.$apply();
  });
</script>

メディア ステータス

メディアの再生中にさまざまなイベントが発生します。これらのイベントは、RemotePlayerController オブジェクトでさまざまな cast.framework.RemotePlayerEventType イベントのリスナーを設定することでキャプチャできます。

メディア ステータス情報を取得するには、再生が変更されたときと CastSession.getMediaSession().media が変更されたときにトリガーされる cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED イベントを使用します。

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    // Use the current session to get an up to date media status.
    let session = cast.framework.CastContext.getInstance().getCurrentSession();

    if (!session) {
        return;
    }

    // Contains information about the playing media including currentTime.
    let mediaStatus = session.getMediaSession();
    if (!mediaStatus) {
        return;
    }

    // mediaStatus also contains the mediaInfo containing metadata and other
    // information about the in progress content.
    let mediaInfo = mediaStatus.media;
  });

一時停止、再生、再開、シークなどのイベントが発生したとき、アプリはそれらのイベントを処理して、キャスト デバイス上のウェブ レシーバー アプリと同期する必要があります。詳細については、ステータスの更新をご覧ください。

セッション管理の仕組み

Cast SDK にはキャスト セッションのコンセプトが導入されています。このセッションは、デバイスへの接続、ウェブ レシーバー アプリの起動(または参加)、そのアプリへの接続、メディア コントロール チャンネルの初期化の手順を組み合わせたものです。Cast セッションと Web Receiver のライフサイクルについて詳しくは、Web Receiver のアプリケーション ライフサイクル ガイドをご覧ください。

セッションは、アプリで cast.framework.CastContext.getInstance() を介して取得できるクラス CastContext によって管理されます。個々のセッションは、Session クラスのサブクラスで表されます。たとえば、CastSession はキャスト デバイスとのセッションを表します。アプリは CastContext.getCurrentSession() を介して、現在アクティブなキャスト セッションにアクセスできます。

セッション状態をモニタリングするには、CastContextEventType.SESSION_STATE_CHANGED イベントタイプの CastContext にリスナーを追加します。

var context = cast.framework.CastContext.getInstance();
context.addEventListener(
  cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
  function(event) {
    switch (event.sessionState) {
      case cast.framework.SessionState.SESSION_STARTED:
      case cast.framework.SessionState.SESSION_RESUMED:
        break;
      case cast.framework.SessionState.SESSION_ENDED:
        console.log('CastContext: CastSession disconnected');
        // Update locally as necessary
        break;
    }
  })

接続の解除(ユーザーがキャスト ダイアログで「キャストを停止」ボタンをクリックした場合)には、リスナーに RemotePlayerEventType.IS_CONNECTED_CHANGED イベントタイプのリスナーを追加できます。リスナーで、RemotePlayer が切断されているかどうかを確認します。その場合は、必要に応じてローカル プレーヤーの状態を更新します。次に例を示します。

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
    if (!player.isConnected) {
      console.log('RemotePlayerController: Player disconnected');
      // Update local player to disconnected state
    }
  });

ユーザーはフレームワークのキャストボタンを介してキャストの終了を直接制御できますが、送信側は現在の CastSession オブジェクトを使用してキャストを停止できます。

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that Web Receiver app should be stopped.
  castSession.endSession(true);
}

ストリーミング転送

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

ストリーム転送中に新しい宛先デバイスを取得するには、cast.framework.SessionState.SESSION_RESUMED イベントが呼び出されたときに CastSession#getCastDevice() を呼び出します。

詳しくは、ウェブ レシーバーでのストリーミング転送をご覧ください。