基本的なキャスト レシーバーを作成する

googlecastnew500.png

この Codelab では、キャスト対応のレシーバー アプリを作成して、Google Cast デバイスでコンテンツを再生できるようにする方法を説明します。

Google Cast とは

Google Cast は、モバイル デバイスのコンテンツをテレビにキャストできる機能です。モバイル デバイスやパソコンの Chrome ブラウザをリモコンとして使い、テレビでのメディア再生を操作できます。

Google Cast SDK を使用すると、Google Cast 対応デバイス(テレビやサウンド システムなど)の操作機能をアプリに組み込むことができます。Cast SDK では、Google Cast デザイン チェックリストに沿って、必要な UI コンポーネントを使用できます。

Google Cast デザイン チェックリストは、サポートされているすべてのプラットフォームで、キャストの操作をシンプルで予測可能なものにするために設けられています。詳しくはこちらをご覧ください。

達成目標

この Codelab を完了すると、キャスト対応デバイスに動画コンテンツを表示できる独自のカスタム レシーバーとして機能する HTML5 アプリを作成できるようになります。

演習内容

  • レシーバー開発のセットアップ方法。
  • Cast Application Framework に基づくキャスト対応レシーバーの基本。
  • キャスト動画の受信方法。
  • Debug Logger の統合方法。
  • スマートディスプレイ向けにレシーバーを最適化する方法。

必要なもの

  • 最新の Google Chrome ブラウザ。
  • node.js、npm、http-server および ngrok モジュール。
  • インターネットに接続できる ChromecastAndroid TV などの Google Cast デバイス。
  • HDMI 入力対応のテレビまたはモニター。

経験

  • ウェブ開発の知識が必要です。
  • 一般的なテレビの視聴経験も必要です。

このチュートリアルの利用方法をお選びください。

閲覧のみ 閲覧と演習を行う

ウェブアプリ作成のご経験についてお答えください。

初心者 中級者 上級者

テレビ視聴のご経験についてお答えください。

初心者 中級者 上級者

すべてのサンプルコードをパソコンにダウンロードできます。

ソースをダウンロード

ダウンロードした ZIP ファイルを解凍します。

キャスト デバイスでレシーバーを使用するには、キャスト デバイスからアクセスできる場所でレシーバーをホストする必要があります。HTTPS に対応しているサーバーを使用できる場合は、次の手順をスキップして、サーバーの URL をメモしておきます。この情報は次のセクションで必要になります。

使用できるサーバーがない場合は、node.jshttp-serverngrok ノード モジュールをインストールします。

npm install -g http-server
npm install -g ngrok

サーバーを実行する

http-server を使用している場合は、コンソールで次のコマンドを実行します。

cd app-start
http-server

次のように表示されます。

Starting up http-server, serving ./
Available on:
  http://127.0.0.1:8080
  http://172.19.17.192:8080
Hit CTRL-C to stop the server

使用されているローカルポートを確認し、新しいターミナルを開いて次のコマンドを実行し、ngrok を使用して HTTPS 経由でローカル レシーバーを公開します。

ngrok http 8080

これにより、ローカル HTTP サーバーに ngrok トンネルが設定され、グローバルに利用できる HTTPS で保護されたエンドポイント(https://1162ec943.eu.ngrok.io)が割り当てられて、次の手順で使用できるようになります。

ngrok by @inconshreveable                                                                                                                                                                                                                                     (Ctrl+C to quit)

Session Status         online
Version                2.2.4
Web Interface          http://127.0.0.1:8080
Forwarding             http://116ec943.eu.ngrok.io -> localhost:8080
Forwarding             https://116ec943.eu.ngrok.io -> localhost:8080

Codelab の演習中は、ngrokhttp-server の両方を実行しておく必要があります。ローカルで行った変更はすぐに反映されます。

この Codelab で作成するカスタム レシーバーを Chromecast デバイスで実行できるようにするには、アプリの登録が必要です。アプリを登録すると、アプリ ID が発行されます。センダーアプリでの API 呼び出し(レシーバー アプリを起動するなど)には、この ID を使用する必要があります。

d8b39f5d33d33db4.png

[Add new application(新しいアプリを追加)] をクリックします。

e8c19e57b85c7d.png

[Custom Receiver(カスタム レシーバー)] を選択します(これを今から作成します)。

bf364a7d382e3c58.png

新しいレシーバーの詳細を入力します。前のセクションでメモしておいた URL を

必ず指定してください。新しいレシーバーに割り当てられたアプリ ID をメモしておきます。

また、Google Cast デバイスを登録して、公開前のレシーバー アプリにアクセスできるようにしておく必要があります。レシーバー アプリを公開した後は、すべての Google Cast デバイスからアクセスできるようになります。この Codelab では、公開していないレシーバー アプリを使用することをおすすめします。

a446325da6ebd627.png

[Add new Device(新しいデバイスを追加)] をクリックします。

a21355793a3f4cd5.png

キャスト デバイスの背面に記載されているシリアル番号を入力し、わかりやすい名前を付けます。シリアル番号は、Google Cast SDK Developer Console へのアクセス時に Chrome で画面をキャストして確認することもできます。

レシーバーとデバイスをテストする準備ができるまでには 5~15 分かかります。5~15 分待ってから、キャスト デバイスを再起動します。

Google_Chrome_logo_icon.png

新しいレシーバー アプリをテストする準備ができるまで、完成したサンプルのレシーバー アプリがどのようなものになるか見てみましょう。これから作成するレシーバーでは、アダプティブ ビットレート ストリーミングを使用してメディアを再生できます(Dynamic Adaptive Streaming over HTTP(DASH)用にエンコードされたサンプル コンテンツを使用します)。

ブラウザで、コマンド アンド コントロール(CaC)ツールを開きます。

7dbd91a75140c46f.png

  1. CaC ツールが開きます。
  2. デフォルトのサンプル レシーバー ID「CC1AD845」を使用し、[Set App ID(アプリ ID を設定)] をクリックします。
  3. 左上のキャスト アイコンをクリックして、Google Cast デバイスを選択します。

a02db8244a963fd6.png

  1. 上部の [Load Media(メディアの読み込み)] タブを選択します。

acd63df355a0493.png

  1. [Load by Content(指定したコンテンツを読み込む)] をクリックして、サンプル動画を再生します。
  2. Google Cast デバイスで動画の再生が開始し、デフォルトのレシーバーの基本的なレシーバー機能を確認できます。

次に、ダウンロードした開始用アプリを Google Cast 対応にします。この Codelab では次のような Google Cast の用語を使用します。

  • センダーアプリはモバイル デバイスやノートパソコンで動作します。
  • レシーバー アプリは Google Cast デバイスで動作します。

お好きなテキスト エディタを使用して、開始用プロジェクトを基に作業する準備を行います。

  1. ダウンロードしたサンプルコードの android_studio_folder.pngapp-start ディレクトリを選択します。
  2. js/receiver.jsindex.html を開きます。

この Codelab の作業を進めていくと、http-server に変更が自動的に適用されます。変更が適用されない場合は、http-server を強制終了して再起動してみてください。

アプリの設計

レシーバー アプリは、キャスト セッションを初期化して、センダーから LOAD リクエスト(メディアの再生コマンド)を受け取るまで待機します。

アプリは、index.html で定義されるメインビューと、レシーバーを機能させるためのすべてのロジックを定義した js/receiver.js という JavaScript ファイルで構成されます。

index.html

レシーバー アプリの UI を定義する HTML ファイルです。今の時点では空ですが、この Codelab の演習を通じてコードを追加していきます。

receiver.js

レシーバー アプリのすべてのロジックを管理するスクリプトです。今の時点では空のファイルですが、次のセクションで、コードを数行だけ追加して、完全に機能するキャスト レシーバーを定義します。

基本的なキャスト レシーバーでは、起動時にキャスト セッションを初期化します。初期化は、接続されているすべてのセンダーアプリにレシーバーが正しく起動したことを通知するために必要となります。なお、新しい SDK は、DASH、HLS、スムーズ ストリーミングを使用したアダプティブ ビットレート ストリーミング メディアや通常の MP4 ファイルを処理できるよう最初から設定されています。それでは作業を始めましょう。

初期化

index.html のヘッダーに次のコードを追加します。

<head>
  ...

  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>

index.html<body> で、receiver.js, を読み込む <footer> の前に次のコードを追加します。これにより、上で追加したスクリプトで表示されるデフォルトのレシーバー UI のスペースが Receiver SDK で確保されます。

<cast-media-player></cast-media-player>

次に、以下の処理を行って、js/receiver.js で SDK を初期化する必要があります。

  • CastReceiverContext(Receiver SDK 全体へのメインのエントリ ポイント)への参照を取得する
  • PlayerManager(再生を処理し、独自のロジックのプラグインに必要なすべてのフックを提供するオブジェクト)への参照を格納する
  • CastReceiverContextstart() を呼び出して SDK を初期化する

js/receiver.js に次のコードを追加します。

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

context.start();

この Codelab では、CaC ツールを使用して新しいレシーバーをテストします。

ウェブブラウザで、コマンド アンド コントロール(CaC)ツールを開きます。

72039b93a476e35e.png

さきほど使用したアプリ ID のフィールドにご自身のアプリ ID を入力して、[Set App ID(アプリ ID を設定)] をクリックします。これにより、キャスト セッションを開始するときに、ご自身のレシーバーが使用されるようになります。

メディアをキャストする

大まかに説明すると、キャスト デバイスでメディアを再生するプロセスは、次のようになります。

  1. センダー: Cast SDK を使用して、メディア アイテムをモデル化する MediaInfo JSON オブジェクトを作成します。
  2. センダー: キャスト デバイスに接続して、レシーバー アプリを起動します。
  3. レシーバー: LOAD リクエストを介して MediaInfo オブジェクトを読み込み、コンテンツを再生します。
  4. レシーバー: メディアのステータスをモニタリングして追跡します。
  5. センダー: 再生コマンドをレシーバーに送信し、センダーアプリに対するユーザーの操作に基づいて再生を制御します。

ます、最初の基本的な作業として、再生可能なアセット URL(MediaInfo.contentUrl に格納)を MediaInfo に入力します。

実際のセンダーでは、MediaInfo.contentId のアプリ固有のメディア識別子が使用されます。レシーバーでは、contentId を識別子として使用して適切なバックエンド API 呼び出しを行い、実際のアセット URL を解決して MediaInfo.contentUrl. に設定します。また、レシーバーでは DRM ライセンスの取得や広告ブレークに関する情報の挿入といったタスクも処理します。

レシーバーを拡張して、そうした処理を実装する手順は次のセクションで行います。ここでは、キャスト アイコンをクリックし、デバイスを選択してレシーバーを開きます。

4954e949c3d3b232.png

[Load Media(メディアの読み込み)] タブに移動して [Load by Content(指定したコンテンツを読み込む)] をクリックします。レシーバーでサンプル コンテンツの再生が開始します。

ccd8cc258d0c1522.png

Receiver SDK は、次の処理を行えるよう最初から設定されています。

  • キャスト セッションを初期化する
  • センダーから受信した、再生可能なアセットを含む LOAD リクエストを処理する
  • 大画面での表示に対応した基本的なプレーヤー UI を提供する

次のセクションに進む前に、CaC ツールやそのコードを確認しておいてください。次のセクションでは、レシーバーを拡張して、センダーから受信した LOAD リクエストの実行をシンプルなサンプル API に指示します。

今回は、実際のアプリで一般的なキャスト レシーバーのユースケースに沿って、再生可能なアセット URL を送信する代わりに、API キーによって目的のメディア コンテンツを参照する LOAD リクエストを処理するようレシーバーを調整します。

この方法が一般的なのは、次の理由によります。

  • センダーがコンテンツの URL を知らない可能性がある。
  • レシーバー側で認証やその他のビジネス ロジック、API 呼び出しを直接処理するようキャストアプリが設計されている。

この機能は主に PlayerManagersetMessageInterceptor() メソッドで実装されています。これにより、受信したメッセージをタイプに応じてインターセプトし、SDK の内部メッセージ ハンドラに到達する前に変更を加えることができます。このセクションでは、LOAD リクエストに対して次の処理を行います。

  • 受信した LOAD リクエストとそのカスタム contentId を読み取る。
  • API に GET 呼び出しを行い、contentId が一致するストリーミング可能なアセットを検索する。
  • LOAD リクエストを変更して、ストリームの URL を指定する。
  • MediaInformation オブジェクトを変更して、ストリーム タイプ パラメータを設定する。
  • 再生のためリクエストを SDK に渡すか、リクエストされたメディアが見つからない場合はコマンドを拒否する。

以下のサンプル API では、一般的なレシーバーのタスクをカスタマイズするため、SDK のフックを使用していますが、大部分は最初の状態のままです。

サンプル API

ブラウザで https://storage.googleapis.com/cpe-sample-media/content.json にアクセスして、サンプル動画のカタログを表示します。カタログには、png 形式のポスター画像の URL と、DASH 形式および HLS 形式のストリームが含まれています。DASH 形式と HLS 形式のストリームは、断片化された mp4 コンテナに格納されている分離済みの動画ソースと音声ソースを参照しています。

{
  "bbb": {
    "author": "The Blender Project",
    "description": "Grumpy Bunny is grumpy",
    "poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
    "stream": {
      "dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
      "hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
    "title": "Big Buck Bunny"
  },
  "fbb_ad": {
    "author": "Google Inc.",
    "description": "Introducing Chromecast. The easiest way to enjoy [...]",
    "poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
    "stream": {
      "dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
      "hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
    "title": "For Bigger Blazes"
  },

  [...]

}

次の手順では、レシーバーが LOAD リクエストで呼び出された後に、各エントリのキー(bbb, fbb_ad など)をストリームの URL にマッピングします。

LOAD リクエストをインターセプトする

この手順では、ホストされている JSON ファイルに対して XHR リクエストを行う関数を使用して、読み込みのインターセプタを作成します。JSON ファイルを取得したら、コンテンツを解析してメタデータを設定します。MediaInformation パラメータをカスタマイズしてコンテンツ タイプを指定する作業は次のセクションで説明します。

js/receiver.js ファイルで、context.start() を呼び出す直前に次のコードを追加します。

function makeRequest (method, url) {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest();
    xhr.open(method, url);
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300) {
        resolve(JSON.parse(xhr.response));
      } else {
        reject({
          status: this.status,
          statusText: xhr.statusText
        });
      }
    };
    xhr.onerror = function () {
      reject({
        status: this.status,
        statusText: xhr.statusText
      });
    };
    xhr.send();
  });
}

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
        // Fetch content repository by requested contentId
        makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            reject();
          } else {
            // Add metadata
            let metadata = new
               cast.framework.messages.GenericMediaMetadata();
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
        });
      });
    });

次のセクションでは、読み込みリクエストの media プロパティを DASH コンテンツ向けに設定する方法について説明します。

サンプル API の DASH コンテンツを使用する

読み込みのインターセプタを作成したら、コンテンツ タイプをレシーバーに通知します。これにより、レシーバーはマスター再生リストの URL とストリームの MIME タイプを取得できます。js/receiver.js ファイルで、LOAD インターセプタの Promise() に次のコードを追加します。

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            ...
          }
        });
      });
    });

この手順を完了したら、「テストする」に進んで、DASH コンテンツの読み込みをテストできます。HLS コンテンツの読み込みをテストする場合は、次の手順に進んでください。

サンプル API の HLS コンテンツを使用する

サンプル API には、DASH 形式と HLS 形式のコンテンツが含まれています。サンプル API の HLS URL を使用するには、前の手順と同様の contentType の設定に加えて、いくつかのプロパティを読み込みリクエストに追加する必要があります。HLS ストリームを再生するようレシーバーを設定した場合、想定されるデフォルトのコンテナタイプはトランスポート ストリーム(TS)になります。そのため、contentUrl プロパティのみを変更した場合、レシーバーはサンプルの MP4 ストリームを TS 形式で開こうと試みます。これに対処するには、読み込みリクエストで MediaInformation オブジェクトを変更してプロパティを追加し、レシーバーでコンテンツ タイプが TS ではなく MP4 と認識されるようにします。js/receiver.js ファイルで、読み込みのインターセプタに次のコードを追加して、contentUrl プロパティと contentType プロパティを変更します。さらに、HlsSegmentFormat プロパティと HlsVideoSegmentFormat プロパティを追加します。

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.hls;
            request.media.contentType = 'application/x-mpegurl';
            request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
            request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
            ...
          }
        });
      });
    });

テストする

もう一度コマンド アンド コントロール(CaC)ツールを開き、アプリ ID としてご自身のレシーバーのアプリ ID を設定します。キャスト アイコンをクリックしてデバイスを選択します。

[Load Media(メディアの読み込み)] タブに移動します。ここでは、[Load by Content(指定したコンテンツを読み込む)] の近くにある [Content URL(コンテンツ URL)] 欄のテキストを削除します。これにより、メディアの contentId の参照のみを含む LOAD リクエストがアプリから送信されます。

3e830710c562189f.png

レシーバーに加えた変更に問題がなければ、インターセプタによって MediaInfo オブジェクトが処理され、SDK により画面上で再生可能なコンテンツに変換されます。

[Load by Content(指定したコンテンツを読み込む)] をクリックして、メディアが適切に再生されるか確認してください。Content ID を content.json ファイルの別の ID に変更してみることもおすすめします。

スマートディスプレイはタッチ操作が可能なデバイスです。レシーバー アプリをタッチ操作に対応させると、こうしたデバイスでも使用できるようになります。

このセクションでは、スマートディスプレイでの起動時にレシーバー アプリを最適化する方法と、プレーヤー コントロールをカスタマイズする方法について説明します。

UI コントロールにアクセスする

スマートディスプレイの UI コントロール オブジェクトにアクセスするには、cast.framework.ui.Controls.GetInstance() を使用します。js/receiver.js ファイルで、context.start() の前に次のコードを追加します。

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();

context.start();

<cast-media-player> 要素を使用しない場合は、CastReceiverOptionstouchScreenOptimizedApp を設定する必要があります。この Codelab では <cast-media-player> 要素を使用します。

context.start({ touchScreenOptimizedApp: true });

デフォルトのコントロール ボタンは、MetadataTypeMediaStatus.supportedMediaCommands に基づいて各スロットに割り当てられます。

動画のコントロール

MetadataType.MOVIEMetadataType.TV_SHOWMetadataType.GENERIC の場合、スマートディスプレイの UI コントロール オブジェクトは次の例のように表示されます。

5f5a3d567813cf10.png

  1. --playback-logo-image
  2. MediaMetadata.subtitle
  3. MediaMetadata.title
  4. MediaStatus.currentTime
  5. MediaInformation.duration
  6. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.QUEUE_PREV
  7. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.SEEK_BACKWARD_30
  8. PLAY/PAUSE
  9. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.SEEK_FORWARD_30
  10. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.QUEUE_NEXT

音声のコントロール

MetadataType.MUSIC_TRACK の場合、スマートディスプレイの UI コントロール オブジェクトは次のように表示されます。

e93d4557f324e8c0.png

  1. --playback-logo-image
  2. MusicTrackMediaMetadata.albumName
  3. MusicTrackMediaMetadata.title
  4. MusicTrackMediaMetadata.albumArtist
  5. MusicTrackMediaMetadata.images[0]
  6. MediaStatus.currentTime
  7. MediaInformation.duration
  8. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.NO_BUTTON
  9. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.QUEUE_PREV
  10. PLAY/PAUSE
  11. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.QUEUE_NEXT
  12. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.NO_BUTTON

サポートされるメディア コマンドを更新する

UI コントロール オブジェクトでは、MediaStatus.supportedMediaCommands に基づいて ControlsButton を表示するかどうかも制御します。

supportedMediaCommands の値が ALL_BASIC_MEDIA の場合、デフォルトのコントロール レイアウトは次のようになります。

5b97ada8d239239c.png

supportedMediaCommands の値が ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT の場合、デフォルトのコントロール レイアウトは次のようになります。

2d8267d4d8b68e87.png

supportedMediaCommands の値が PAUSE | QUEUE_PREV | QUEUE_NEXT の場合、デフォルトのコントロール レイアウトは次のようになります。

39c9afe44c4fa8dc.png

テキスト トラックを使用できる場合は、字幕ボタンが常に SLOT_1 に表示されます。

771952ab29e2eb21.png

レシーバー関連要素の開始後に supportedMediaCommands の値を動的に変更する場合は、PlayerManager.setSupportedMediaCommands を呼び出して値をオーバーライドできます。また、addSupportedMediaCommands を使用して新しいコマンドを追加したり、removeSupportedMediaCommands を使用して既存のコマンドを削除したりすることも可能です。

コントロール ボタンをカスタマイズする

コントロールをカスタマイズするには、PlayerDataBinder を使用します。js/receiver.js ファイルで、touchControls の後に次のコードを追加して、コントロールの最初のスロットを設定します。

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    // Clear default buttons and re-assign
    touchControls.clearDefaultSlotAssignments();
    touchControls.assignButton(
      cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
      cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
    );
  });

context.start();

メディア ブラウズは、タッチデバイスで追加のコンテンツを使用できるようにする CAF Receiver の機能です。実装するには、PlayerDataBinder を使用して BrowseContent UI を設定します。そして、表示するコンテンツに応じて BrowseItems を入力します。

BrowseContent

次に BrowseContent UI とそのプロパティの例を示します。

e40623e1907d983a.png

  1. BrowseContent.title
  2. BrowseContent.items

アスペクト比

画像アセットに最適なアスペクト比を選択するには、targetAspectRatio property を使用します。CAF Receiver SDK では SQUARE_1_TO_1PORTRAIT_2_TO_3LANDSCAPE_16_TO_9 の 3 つのアスペクト比がサポートされています。

BrowseItem

各アイテムのタイトル、サブタイトル、再生時間、画像を表示するには、BrowseItem を使用します。

838a0db6c9224710.png

  1. BrowseItem.image
  2. BrowseItem.duration
  3. BrowseItem.title
  4. BrowseItem.subtitle

メディア ブラウズデータを設定する

ブラウジングするメディア コンテンツのリストを取得するには、setBrowseContent を呼び出します。js/receiver.js ファイルで、playerDataBinder の後の MEDIA_CHANGED イベント リスナー内に次のコードを追加して、ブラウズ アイテムのタイトルを「Up Next」に設定します。

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

...

let browseItems = getBrowseItems();

function getBrowseItems() {
  let browseItems = [];
  makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
  .then(function (data) {
    for (let key in data) {
      let item = new cast.framework.ui.BrowseItem();
      item.entity = key;
      item.title = data[key].title;
      item.subtitle = data[key].description;
      item.image = new cast.framework.messages.Image(data[key].poster);
      item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
      browseItems.push(item);
    }
  });
  return browseItems;
}

let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    ....

    // Media browse
    touchControls.setBrowseContent(browseContent);
  });

メディア ブラウズ アイテムがクリックされると、LOAD インターセプタがトリガーされます。LOAD インターセプタに次のコードを追加して、request.media.contentId をメディア ブラウズ アイテムの request.media.entity にマッピングします。

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

      // Map contentId to entity
      if (request.media && request.media.entity) {
        request.media.contentId = request.media.entity;
      }

      return new Promise((resolve, reject) => {
            ...
        });
    });

BrowseContent オブジェクトを null に設定して、メディア ブラウズ UI を削除することもできます。

Cast Receiver SDK では、CastDebugLogger APIコマンド アンド コントロール(CaC)ツールを使用してログを取得することで、レシーバー アプリを簡単にデバッグできます。

初期化

API を組み込むには、index.html ファイルに CastDebugLogger ソース スクリプトを追加します。このソースは、<head> タグ内の Cast Receiver SDK の宣言の後で宣言する必要があります。

<head>
  ...
  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <!-- Cast Debug Logger -->
  <script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>

js/receiver.js ファイルの先頭の playerManager の後に次のコードを追加して、CastDebugLogger インスタンスを取得し、ロガーを有効にします。

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

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);

デバッグロガーが有効になっている場合は、DEBUG MODE というテキストのオーバーレイがレシーバーに表示されます。

d9cb99e7742fc240.png

プレーヤーのイベントをログに記録する

CastDebugLogger を使用すると、CAF Receiver SDK によって呼び出されるプレーヤーのイベントを簡単にログに保存して、さまざまなロガーレベルでイベントデータを記録できます。loggerLevelByEvents を設定する際に、cast.framework.events.EventTypecast.framework.events.category を使用してログに記録するイベントを指定します。

castDebugLogger の宣言の後に次のコードを追加して、プレーヤーの CORE イベントがトリガーされたときや mediaStatus の変更がブロードキャストされたときにログに記録するよう設定します。

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

ログ メッセージとカスタムタグ

CastDebugLogger API では、レシーバーのデバッグ オーバーレイに表示するログ メッセージをさまざまな色で作成できます。使用できるログメソッドを優先度の高い順に示します。

  • castDebugLogger.error(custom_tag, message);
  • castDebugLogger.warn(custom_tag, message);
  • castDebugLogger.info(custom_tag, message);
  • castDebugLogger.debug(custom_tag, message);

各ログメソッドの最初のパラメータはカスタムタグです。カスタムタグには、状況を示す任意の文字列を使用できます。CastDebugLogger ではタグを使用してログをフィルタします。タグの使用方法については、後で詳しく説明します。2 つ目のパラメータはログ メッセージです。

ログを実際に表示するには、LOAD インターセプタにログを追加します。

playerManager.setMessageInterceptor(
  cast.framework.messages.MessageType.LOAD,
  request => {
    castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');

    // Map contentId to entity
    if (request.media && request.media.entity) {
      request.media.contentId = request.media.entity;
    }

    return new Promise((resolve, reject) => {
      // Fetch content repository by requested contentId
      makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
        .then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            castDebugLogger.error(LOG_TAG, 'Content not found');
            reject();
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);

            // Add metadata
            let metadata = new cast.framework.messages.MovieMediaMetadata();
            metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
      });
    });
  });

デバッグ オーバーレイにどのメッセージを表示するかは、各カスタムタグの loggerLevelByTags でログレベルを設定して制御します。たとえば、カスタムタグでログレベル cast.framework.LoggerLevel.DEBUG を有効にした場合は、エラー、警告、情報、デバッグのすべてのログ メッセージが表示されます。カスタムタグでレベル WARNING を有効にした場合は、エラーと警告のログ メッセージのみが表示されます。

loggerLevelByTags の設定は省略できます。カスタムタグにロガーレベルを設定しない場合は、デバッグ オーバーレイにすべてのログ メッセージが表示されます。

CORE イベントロガーの後に次のコードを追加します。

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
    [LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};

デバッグ オーバーレイ

Cast Debug Logger では、レシーバーにデバッグ オーバーレイを提供して、キャスト デバイスにカスタムのログ メッセージを表示します。デバッグ オーバーレイを切り替えるには、showDebugLogs を使用します。オーバーレイ上のログ メッセージを消去するには、clearDebugLogs を使用します。

レシーバーのデバッグ オーバーレイをプレビューするには、次のコードを追加します。

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);

// Show debug overlay
castDebugLogger.showDebugLogs(true);

// Clear log messages on debug overlay
// castDebugLogger.clearDebugLogs();

356c6ac94318539c.png

最新の Cast Receiver SDK を使用してカスタムのレシーバー アプリを作成する方法は以上です。他のサンプルアプリについては、GitHub(github.com/googlecast)をご覧ください。