カスタムのウェブ レシーバーを作成する

1. 概要

Google Cast ロゴ

この Codelab では、ウェブキャスト デバイス上でコンテンツを再生するためのカスタム ウェブ レシーバー アプリの作成方法について説明します。

Google Cast とは

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

Google Cast SDK を使用すると、Google Cast 対応デバイス(テレビやサウンド システムなど)をアプリから操作できるようになります。Cast SDK には、Google Cast デザイン チェックリストに基づいた UI コンポーネントが用意されています。

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

達成目標

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

学習内容

  • レシーバー開発のセットアップ方法
  • キャスト アプリケーション フレームワークに基づく Cast 対応レシーバーの基本
  • キャストされた動画を受け取る方法
  • Debug Logger を統合する方法
  • スマートディスプレイ向けにレシーバーを最適化する方法。

必要なもの

  • 最新の Google Chrome ブラウザ
  • HTTPS ホスティング サービス(Firebase Hostingngrok など)。
  • ChromecastAndroid TV など、インターネットにアクセスできる Google Cast デバイス。
  • HDMI 入力対応のテレビまたはモニター

テスト

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

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

通読するのみ 通読し、演習を行う

ウェブアプリの構築について評価してください。

初心者 中級者 上級者

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

初心者 中級 上級

2. サンプルコードを取得する

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

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

3. レシーバをローカルにデプロイする

ウェブデバイスでレシーバーをキャスト デバイスで使用するには、キャスト デバイスからアクセスできる場所にホストする必要があります。https 対応のサーバーをすでにお持ちの場合は、次のセクションで必要になるため、以下の手順をスキップして URL をメモしてください

使用できるサーバーがない場合は、Firebase Hosting または ngrok を使用できます。

サーバーを実行する

必要なサービスを設定したら、app-start に移動して、サーバーを起動します。

ホストされているレシーバーの URL をメモします。次のセクションでこれを使用します。

4. Cast Developer Console でアプリを登録する

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

[新しいアプリを追加] ボタンがハイライト表示されている Google Cast SDK デベロッパー コンソールの画像

[新しいアプリケーションを追加] をクリックします。

[Custom Receiver] オプションがハイライト表示されている [New Receiver Application] 画面の画像

[Custom Receiver] を選択します。これが構築されます。

[受信者のアプリケーションの URL] 欄に入力している URL が表示されている [新しいカスタム受信者] 画面の画像

新しいレシーバーの詳細を入力します。最終ページ URL を入力してください。

最後のセクション。新しいレシーバーに割り当てられたアプリケーション ID をメモします。

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

[新しいデバイスを追加] ボタンがハイライトされた Google Cast SDK デベロッパー コンソールの画像

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

[キャスト レシーバー デバイスの追加] ダイアログの画像

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

レシーバーとデバイスをテストする準備が整うまで 5 ~ 15 分かかります。5 ~ 15 分待ってから、キャスト デバイスを再起動する必要があります。

5. サンプルアプリを実行する

Google Chrome のロゴ

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

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

コマンド / コントロール(CaC)ツールの [Cast Connect & Logger Controls] タブの画像

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

コマンドとコントロール(CaC)ツールの [Cast Connect & Logger Controls] タブが表示され、レシーバー アプリに接続されていることを示す画像

  1. 上部にある [メディアの読み込み] タブに移動します。

Command and Control(CaC)ツールの [Load Media] タブの画像

  1. [コンテンツによる読み込み] ボタンをクリックして、サンプル動画を再生します。
  2. Google Cast デバイスで動画の再生が開始され、デフォルトのレシーバーを使用したレシーバーの基本機能が表示されます。

6. 開始プロジェクトを準備する

ダウンロードした開始用アプリに Google Cast のサポートを追加する必要があります。この Codelab では、以下の Google Cast の用語を使用します。

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

これで、お気に入りのテキスト エディタを使用してスターター プロジェクトを基盤にする準備が整いました。

  1. ダウンロードしたサンプルコードから フォルダ アイコンapp-start ディレクトリを選択します。
  2. js/receiver.jsindex.html を開く

この Codelab では、http-server が行った変更を取得するはずです。表示されない場合は、強制終了してから再起動してみてください。http-server

アプリの設計

レシーバー アプリは、キャスト セッションを初期化し、送信者からの LOAD リクエスト(つまり、メディアを再生するコマンド)が届くまでスタンバイ モードで待機します。

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

index.html

この HTML ファイルには、レシーバアプリの UI が含まれています。現時点では空ですが、Codelab 全体に追加していきます。

Receiver.js

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

7. 基本的なキャスト レシーバー

基本的なキャスト レシーバーは、起動時にキャスト セッションを初期化します。これは、接続されているすべての送信側に受信側が正常に表示されたことを示すために必要です。さらに、新しい SDK には、アダプティブ ビットレート ストリーミング メディア(DASH、HLS、スムーズ ストリーミング)とプレーン MP4 ファイル(すぐに使える)を処理するようにあらかじめ構成されています。試してみましょう。

初期化

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

<head>
  ...

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

receiver.js, を読み込む <footer> の前の index.html <body> に次のコードを追加して、追加したスクリプトで出荷されるデフォルトのレシーバー UI を表示するためのスペースをレシーバー SDK に提供します。

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

次に、js/receiver.js で SDK を初期化する必要があります。以下で構成されます。

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

js/receiver.js に以下を追加します。

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

context.start();

8. 「基本」の動画コンテンツのキャスト

この Codelab では、CaC ツールを使用して新しいレシーバーを試してみてください。

ウェブブラウザで コマンド コントロール(CaC)ツールにアクセスします。

コマンド / コントロール(CaC)ツールの [Cast Connect & Logger Controls] タブの画像

すでに入力されているとおり、ご自身のアプリ ID に置き換えてください。[アプリ ID を設定] をクリックします。これにより、キャスト セッションの開始時にレシーバーを使用するようにツールに指示します。

メディアのキャスト

キャスト デバイスでメディアを再生する大まかな流れは次のとおりです。

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

最初の基本的な試行では、再生可能なアセット URL(MediaInfo.contentUrl に格納される)を MediaInfo に組み込みます。

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

次のセクションでは、レシーバーを拡張して同様のことを行います。ここでは、キャスト アイコンをクリックしてデバイスを選択し、レシーバーを開きます。

コマンドとコントロール(CaC)ツールの [Cast Connect & Logger Controls] タブが表示され、レシーバー アプリに接続されていることを示す画像

[Load Media] タブに移動し、[Load by Content] ボタンをクリックします。レシーバーがサンプル コンテンツの再生を開始します。

Command and Control(CaC)ツールの [Load Media] タブの画像

そのため、Receiver SDK ではすぐに次の処理が行われます。

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

次のセクションに進む前に、CaC ツールとそのコードを自由に確認してください。次のセクションでは、レシーバーを拡張して、送信者からの受信 LOAD リクエストを処理する単純なサンプル API と通信します。

9. 外部 API との統合

ほとんどのデベロッパーが実際のアプリでキャスト レシーバを操作する方法に合わせて、レシーバを変更して、再生可能なアセットの URL ではなく API キーで目的のメディア コンテンツを参照するLOADリクエストを処理します。

通常、アプリケーションでは次の処理が行われます。

  • 送信者がコンテンツの URL を把握していない可能性があります。
  • キャストアプリは、レシーバーで直接、認証、その他のビジネス ロジック、または API 呼び出しを処理するように設計されています。

この機能は、主に PlayerManager setMessageInterceptor() メソッドに実装されています。こうすることで、受信メッセージをインターセプトして、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);
          }
        });
      });
    });

次のセクションでは、読み込みリクエストの DASH コンテンツ用の media プロパティを構成する方法の概要を説明します。

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

読み込みインターセプタの準備が完了したので、レシーバーにコンテンツ タイプを指定します。この情報は、レシーバーにマスター再生リストの URL とストリームの MIME タイプを提供します。次のコードを、LOAD インターセプターの Promise() の js/receiver.js ファイルに追加します。

...
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';
            ...
          }
        });
      });
    });

この手順を完了したら、Test It Out に進んで DASH コンテンツでの読み込みを試行します。HLS コンテンツの読み込みをテストする場合は、次の手順をご確認ください。

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

サンプル API には、HLS コンテンツと DASH が含まれています。サンプル API の HLS URL を使用するには、前のステップで行った contentType の設定に加えて、いくつかの追加プロパティが必要です。HLS ストリームを再生するようにレシーバーが構成されている場合、想定されるデフォルトのコンテナタイプはトランスポート ストリーム(TS)です。その結果、contentUrl プロパティのみが変更された場合、レシーバーはサンプル MP4 ストリームを TS 形式で開こうとします。読み込みリクエストでは、コンテンツが TS ではなく MP4 型であることを受信者が認識できるように、MediaInformation オブジェクトを追加のプロパティで変更する必要があります。次のコードを、読み込みインターセプタの 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;
            ...
          }
        });
      });
    });

試してみる

もう一度 Command and Control(CaC)ツールを開き、アプリ ID を受信側のアプリ ID に設定します。キャスト ボタンを使用してデバイスを選択

[Load Media] タブに移動します。今回は、[コンテンツ URL] フィールドの [コンテンツ別の読み込み] ボタンのテキストを削除します。これにより、アプリケーションはメディアの contentId 参照のみを含む LOAD リクエストを送信します。

Command and Control(CaC)ツールの [Load Media] タブの画像

レシーバの変更に問題がなかったとしても、インターセプタは、SDK が画面で再生できるものへと MediaInfo オブジェクトをシェーピングする必要があります。

[Load by Content] ボタンをクリックして、メディアが正常に再生されているかどうかを確認します。必要に応じて、Content ID を content.json ファイル内の別の ID に変更できます。

10. スマートディスプレイ向けに最適化する

スマート ディスプレイは、レシーバー アプリがタップ対応コントロールをサポートする、タップ機能を備えたデバイスです。

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

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 コントロール オブジェクトが表示されます。

UI コントロールが重ねて再生されている動画の画像

  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 コントロール オブジェクトは次のように表示されます。

UI コントロールが重ねて再生されている音楽の画像

  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 と等しい場合、デフォルトのコントロール レイアウトは次のようになります。

メディア プレーヤー コントロールの画像: 進行状況バー、[再生] ボタン、[スキップ] ボタン、[戻る] ボタンが有効

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

メディア プレーヤー コントロールの画像: 進行状況バー、[再生] ボタン、[スキップ] ボタン、[巻き戻し] ボタン、[前へキューを追加] ボタンが有効

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

メディア プレーヤー コントロールの画像: 進行状況バー、[再生] ボタン、[前へキューを追加] ボタン、[キューに追加] ボタンが有効

テキスト トラックが利用可能な場合、字幕ボタンは常に SLOT_1 に表示されます。

メディア プレーヤー コントロールの画像: 進行状況バー、[再生] ボタン、[スキップ] ボタン、[スキップ前] ボタン、[キューの次へ] ボタン、[字幕] ボタンが有効

レシーバー コンテキストの開始後に supportedMediaCommands の値を動的に変更するには、PlayerManager.setSupportedMediaCommands を呼び出して、値をオーバーライドします。addSupportedMediaCommands を使用して新しいコマンドを追加することも、removeSupportedMediaCommands を使用して既存のコマンドを削除することもできます。

コントロール ボタンのカスタマイズ

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

...

// 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();

11. スマートディスプレイでのメディア ブラウジングの実装

メディア ブラウズは、ユーザーがタッチデバイスでその他のコンテンツを探索できる CAF Receiver 機能です。これを実装するには、PlayerDataBinder を使用して BrowseContent UI を設定します。次に、表示するコンテンツに基づいて BrowseItems を設定できます。

閲覧コンテンツ

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

2 つの動画のサムネイル、3 分の 1 の一部を表示している BrowseContent UI の画像

  1. BrowseContent.title
  2. BrowseContent.items

アスペクト比

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

BrowseItem

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

2 つの動画のサムネイル、3 分の 1 の一部を表示している BrowseContent UI の画像

  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.contentIdrequest.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 を削除することもできます。

12. レシーバー アプリのデバッグ

Cast Receiver SDK には、デベロッパーが CastDebugLogger API とコンパニオン Command and Control(CaC)ツールを使用してログを取得することで、レシーバー アプリを簡単にデバッグするためのオプションが用意されています。

初期化

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

<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.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

デバッグロガーを有効にすると、DEBUG MODE を示すオーバーレイがレシーバに表示されます。

フレームの左上に赤い背景に「DEBUG MODE」メッセージが表示された動画の画像

プレーヤーのイベントを記録

CastDebugLogger を使用すると、CAF Receiver SDK によって発行されるプレーヤー イベントを簡単にロギングし、さまざまなロガーレベルを使用してイベントデータをロギングできます。loggerLevelByEvents 構成では、cast.framework.events.EventTypecast.framework.events.category を使用して、ログに記録するイベントを指定します。

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

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

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      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 を使用してオーバーレイのログメッセージを消去します。

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

context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      // 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();
  }
});

半透明の背景に動画フレームの上にデバッグログ メッセージのリストが表示されているデバッグ オーバーレイの画像

13. 完了

Cast Web Receiver SDK を使用してカスタム ウェブ レシーバー アプリケーションを作成する方法を学習しました。

詳細については、Web Receiver デベロッパー ガイドをご覧ください。