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

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

1. 概要

Google Cast ロゴ

この Codelab では、Cast 対応デバイスでコンテンツを再生するカスタムの Web レシーバー アプリを作成する方法について説明します。

Google Cast とは

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

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

Google Cast の設計チェックリストは、サポートされているすべてのプラットフォームでキャスト ユーザー エクスペリエンスをシンプルかつ予測可能なものにするために提供されています。詳細

達成目標

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

学習内容

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

必要なもの

  • 最新の Google Chrome ブラウザ。
  • node.js、npm、http-serverngrok モジュール。
  • Google Cast デバイス(ChromecastAndroid TV など)とインターネット アクセスの設定
  • HDMI 入力対応のテレビまたはモニター

経験

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

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

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

ウェブアプリの構築について、どの程度評価されていますか。

初心者 中級者 上級者

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

初級 中級 上級

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

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

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

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

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

使用可能なサーバーがない場合は、node.jshttp-server および ngrok ノード モジュール)をインストールできます。

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://116ec943.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 の両方を実行し続ける必要があります。ローカルで加えた変更はすぐに反映されます。

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

この Codelab で作成したカスタム レシーバーを Chromecast デバイスで実行できるようにするには、アプリを登録する必要があります。アプリケーションを登録すると、受信側のアプリケーションなど、送信者のアプリケーションが API 呼び出しの実行に必要なアプリケーション ID を受け取ります。

Google Cast SDK Developer Console の [新しいアプリを追加] ボタンがハイライト表示されている画像

[&Add a new application] をクリックします。

[新しいレシーバー アプリケーション] の画像と、[カスタム レシーバー] オプションがハイライト表示されている画面の画像

「カスタム レシーバー」を選択し、現在構築しているものを選択してください。

新しいカスタム レシーバーの画像&#39。誰かが受信側のアプリの URL を入力している画面の URL

新しいレシーバーの詳細を入力します。入力した URL を必ず使用してください

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

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

Google Cast SDK Developer Console の [新しいデバイスを追加] ボタンの画像

[新しいデバイスの追加] をクリックします。

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

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

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

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

Google Chrome のロゴ

新しいレシーバー アプリケーションがテストできる状態になるのを待つ間、完成したレシーバー アプリのサンプルをご覧ください。構築するレシーバーは、アダプティブ ビットレート ストリーミングを使用してメディアを再生できるようになります(HTTP の動的アダプティブ ストリーミング用にエンコードされたサンプル コンテンツを使用します)。

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

キャスト接続とロガー コントロールの画像とコントロール(CaC)ツールのタブ

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

キャスト接続とロガー コントロールの画像

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

コマンドとコントロール(CaC)ツールの ' 読み込みメディア' タブの画像

  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 で定義されたメインビューと、レシーバを動作させるためのロジックをすべて含む js/receiver.js という名前の JavaScript ファイルで構成されています。

index.html

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

レシーバー.js

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

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

基本的な Cast レシーバーが、起動時にキャスト セッションを初期化します。これは、接続されているすべての送信側に、受信者の起動が成功したことをアプリケーションに伝えるために必要です。また、新しい 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, を読み込む前に、<body> の前に 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)ツールのタブ

欄に先ほど入力した独自のアプリ ID を置き換えます。[App ID を設定] をクリックします。キャスト セッションの開始時にレシーバーを使用するようにツールに指示します。

メディアのキャスト

キャスト デバイスでメディアを再生するには、概要として以下のことが必要です。

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

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

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

次のセクションで、同じようにレシーバーを拡張します。現時点では、キャスト アイコンをクリックしてデバイスを選択し、レシーバーを開きます。

キャスト接続とロガー コントロールの画像

[メディアを読み込む] タブに移動し、[コンテンツで読み込み] をクリックします。レシーバーがサンプル コンテンツの再生を開始します。

コマンドとコントロール(CaC)ツールの &#39; 読み込みメディア&#39; タブの画像

そのため、Receiver SDK は設定不要ですぐに使用できます。

  • キャスト セッションを初期化する
  • 体験プレイ アセットを含む送信元からの LOAD の受信リクエストを処理する
  • 大きな画面に表示できる基本的なプレーヤー UI を用意します。

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

9. 外部 API との統合

実際のアプリケーションでキャスト レシーバを操作する場合とほとんど同じです。レシーバを変更し、体験プレイ アセットの URL で API リクエストを送信するのではなく、API キーで目的のメディア コンテンツを参照する LOAD リクエストを処理します。

通常、アプリケーションは次の理由でこれを行います。

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

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

  • 受信した LOAD リクエストとそのカスタム contentId を読み取ります。
  • API に対して GET 呼び出しを行い、contentId でストリーミング可能なアセットを検索します。
  • ストリームの URL を指定して LOAD リクエストを変更します。
  • 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 形式で開こうとします。読み込みリクエストで、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 に設定します。キャスト ボタンを使用してデバイスを選択します。

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

コマンドとコントロール(CaC)ツールの &#39; 読み込みメディア&#39; タブの画像

レシーバに対する変更がすべて問題なく機能することを前提として、インターセプタは SDK が画面上で再生できるものに MediaInfo オブジェクトを形成する必要があります。

「コンテンツ別の読み込み」ボタンをクリックして、メディアが適切に再生されるかどうかを確認します。content.json ファイル内の Content ID を別の ID に自由に変更してください。

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

スマートディスプレイは、タッチ機能を備えたデバイスであり、受信側のアプリはタップ対応のコントロールをサポートできます。

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

UI コントロールへのアクセス

スマートディスプレイの UI Controls オブジェクトには、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 Controls オブジェクトは次の例のように表示されます。

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 Controls オブジェクトは、MediaStatus.supportedMediaCommands に基づいて ControlsButton を表示するかどうかを決定します。

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

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

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

メディア プレーヤー コントロールの画像: 進行状況バー、再生ボタン、前へスキップボタン、後方にスキップ、ボタン、前へキューに入れる、ボタンを有効にする

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

メディア プレーヤー コントロールの画像: 進行状況バー、再生ボタン、前のキューへの接続、次のキューへの追加ボタンの有効化

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

メディア プレーヤー コントロールの画像: 進行状況バー、再生ボタン、前へスキップ&#39、前方にスキップ&#39、前へスキップ&#39、前へキューと連携、ボタン、クローズド キャプション、ボタンを有効にする

レシーバ コンテキストの開始後に 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();

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

メディア ブラウズは、ユーザーがタッチデバイスで追加のコンテンツを探索できるようにする CAF レシーバー機能です。これを実装するには、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 を呼び出します。以下のコードを playerDataBinderjs/receiver.js ファイルと MEDIA_CHANGED イベント リスナーに追加して、「Browse 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 とそれに付随するコマンド&コントロール(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 を表示するオーバーレイがレシーバに表示されます。

フレームの左上に赤い背景に表示される「デバッグモード」のメッセージが表示されている画像

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

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.
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 デベロッパー ガイドをご覧ください。