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

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

用語

モバイル デバイスまたはブラウザは再生を制御する送信側、Google Cast デバイスはコンテンツを画面に表示して再生する受信側です。

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

「送信側フレームワーク」とは、下位レベルの機能のラッパーを提供する Framework 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 は、現在の Cast の状態に関する情報を提供し、Cast の状態と Cast セッションの状態の変化に関するイベントをトリガーするシングルトン オブジェクトです。
  • 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) を使用して接続された Cast デバイスにメディアを読み込むことができます。まず、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();
  • STOP: playerController.stop();
  • SEEK: 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 イベントにリスナーを設定することでキャプチャできます。

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

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 デバイス上の Web レシーバー アプリの間で同期する必要があります。詳しくは、ステータスの更新をご覧ください。

セッション管理の仕組み

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

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

セッション状態をモニタリングするには、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 アプリ、スマート ディスプレイを使用して、既存の音声ストリームと動画ストリームをデバイス間で移動できます。メディアの再生が 1 つのデバイス(ソース)で停止し、別のデバイス(宛先)で続行されます。最新のファームウェアを搭載した Cast デバイスは、ストリーム転送の転送元または転送先として機能します。

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

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