このページには、カスタム ウェブ レシーバー アプリで使用できる機能のコード スニペットと説明が記載されています。
- Web レシーバーで提供される組み込みプレーヤー UI を表す
cast-media-player要素。 cast-media-player要素のカスタム CSS 風のスタイル設定。background-image、splash-image、font-familyなどのさまざまな UI 要素のスタイルを設定します。- ウェブレシーバー フレームワークを読み込むためのスクリプト要素。
- メッセージをインターセプトしてイベントを処理する JavaScript コード。
- 自動再生のキュー。
- 再生を構成するオプション。
- Web Receiver コンテキストを設定するオプション。
- Web レシーバー アプリでサポートされているコマンドを設定するオプション。
- ウェブ レシーバー アプリケーションを開始する JavaScript 呼び出し。
アプリケーションの構成とオプション
アプリケーションを構成する
CastReceiverContext はデベロッパーに公開される最も外側のクラスで、基盤となるライブラリの読み込みを管理し、ウェブ レシーバー SDK の初期化を処理します。SDK は、アプリ デベロッパーが CastReceiverOptions を介して SDK を構成できる API を提供します。これらの構成は、アプリの起動ごとに 1 回評価され、start の呼び出しでオプションのパラメータを設定するときに SDK に渡されます。
次の例は、送信側接続がまだアクティブに接続されているかどうかを検出するデフォルトの動作をオーバーライドする方法を示しています。Web レシーバが maxInactivity 秒間送信側と通信できなかった場合、SENDER_DISCONNECTED イベントがディスパッチされます。次の構成では、このタイムアウトがオーバーライドされます。これは、IDLE 状態の接続済み送信者がゼロの場合に、ウェブ レシーバ アプリが Chrome リモート デバッガ セッションを閉じないようにするため、問題のデバッグに役立ちます。
const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);
プレーヤーを構成する
コンテンツを読み込む際、Web Receiver SDK は cast.framework.PlaybackConfig を使用して、DRM 情報、再試行構成、リクエスト ハンドラなどの再生変数を構成する方法を提供します。この情報は PlayerManager によって処理され、プレーヤーの作成時に評価されます。新しい読み込みが Web Receiver SDK に渡されるたびに、プレーヤーが作成されます。プレーヤーの作成後に PlaybackConfig に変更を加えた場合、その変更は次のコンテンツ読み込み時に評価されます。SDK には、PlaybackConfig を変更するための次のメソッドが用意されています。
CastReceiverOptions.playbackConfig(CastReceiverContextの初期化時にデフォルトの構成オプションをオーバーライドします)。PlayerManager.getPlaybackConfig(): 現在の構成を取得します。PlayerManager.setPlaybackConfig(): 現在の構成をオーバーライドします。この設定は、後続のすべての読み込みに適用されるか、再度オーバーライドされるまで適用されます。PlayerManager.setMediaPlaybackInfoHandler(): 現在の構成に加えて、読み込まれるメディア アイテムにのみ追加の構成を適用します。ハンドラは、プレーヤーの作成直前に呼び出されます。ここで行った変更は永続的ではなく、getPlaybackConfig()へのクエリには含まれません。次のメディア アイテムが読み込まれると、このハンドラが再び呼び出されます。
次の例は、CastReceiverContext を初期化するときに PlaybackConfig を設定する方法を示しています。この構成は、マニフェストを取得するための送信リクエストをオーバーライドします。ハンドラは、CORS Access-Control リクエストを Cookie や Authorization ヘッダーなどの認証情報を使用して行う必要があることを指定します。
const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});
次の例は、PlayerManager で提供されるゲッターとセッターを使用して PlaybackConfig をオーバーライドする方法を示しています。この設定では、1 つのセグメントが読み込まれた後にコンテンツの再生を再開するようにプレーヤーが構成されます。
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);
次の例は、メディア再生情報ハンドラを使用して、特定の読み込みリクエストの PlaybackConfig をオーバーライドする方法を示しています。ハンドラは、アプリケーション実装メソッド getLicenseUrlForMedia を呼び出して、現在のアイテムの contentId から licenseUrl を取得します。
playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
const mediaInformation = loadRequestData.media;
playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);
return playbackConfig;
});
イベント リスナー
Web Receiver SDK を使用すると、Web Receiver アプリでプレーヤー イベントを処理できます。イベント リスナーは、リスナーをトリガーするイベントを指定する cast.framework.events.EventType パラメータ(またはこれらのパラメータの配列)を受け取ります。デバッグに役立つ cast.framework.events.EventType の事前構成済み配列は、cast.framework.events.category にあります。イベント パラメータは、イベントに関する追加情報を提供します。
たとえば、mediaStatus の変更がブロードキャストされたタイミングを知りたい場合は、次のロジックを使用してイベントを処理できます。
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
cast.framework.events.EventType.MEDIA_STATUS, (event) => {
// Write your own event handling code, for example
// using the event.mediaStatus value
});
メッセージの傍受
ウェブ レシーバー SDK を使用すると、ウェブ レシーバー アプリでメッセージをインターセプトし、それらのメッセージに対してカスタムコードを実行できます。メッセージ インターセプタは、インターセプトするメッセージのタイプを指定する cast.framework.messages.MessageType パラメータを受け取ります。
インターセプタは、変更されたリクエストまたは変更されたリクエスト値で解決される Promise を返す必要があります。null を返すと、デフォルトのメッセージ ハンドラが呼び出されなくなります。詳しくは、メディアの読み込みをご覧ください。
たとえば、読み込みリクエストのデータを変更する場合は、次のロジックを使用してインターセプトし、変更できます。
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_FAILED);
if (!loadRequestData.media) {
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
if (!loadRequestData.media.entity) {
return loadRequestData;
}
return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
if (!asset) {
throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
}
loadRequestData.media.contentUrl = asset.url;
loadRequestData.media.metadata = asset.metadata;
loadRequestData.media.tracks = asset.tracks;
return loadRequestData;
}).catch(reason => {
error.reason = reason; // cast.framework.messages.ErrorReason
return error;
});
});
context.start();
エラー処理
メッセージ インターセプタでエラーが発生した場合、ウェブ レシーバー アプリは適切な cast.framework.messages.ErrorType と cast.framework.messages.ErrorReason を返す必要があります。
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_CANCELLED);
if (!loadRequestData.media) {
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
...
return fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
...
return loadRequestData;
}).catch(reason => {
error.reason = reason; // cast.framework.messages.ErrorReason
return error;
});
});
メッセージのインターセプトとイベント リスナー
メッセージのインターセプトとイベント リスナーの主な違いは次のとおりです。
- イベント リスナーではリクエスト データを変更できません。
- イベント リスナーは、分析やカスタム関数をトリガーするのに最適です。
playerManager.addEventListener(cast.framework.events.category.CORE,
event => {
console.log(event);
});
- メッセージのインターセプトを使用すると、メッセージをリッスンし、インターセプトして、リクエスト データ自体を変更できます。
- メッセージのインターセプトは、リクエスト データに関するカスタム ロジックを処理する場合に最適です。
メディアの読み込み
MediaInformation は、cast.framework.messages.MessageType.LOAD メッセージでメディアを読み込むための多数のプロパティ(entity、contentUrl、contentId など)を提供します。
entityは、送信側アプリと受信側アプリの両方の実装で使用することが推奨されるプロパティです。このプロパティは、再生リストまたはメディア コンテンツのいずれかであるディープリンク URL です。アプリケーションはこの URL を解析し、他の 2 つのフィールドのうち少なくとも 1 つに値を入力する必要があります。contentUrlは、プレーヤーがコンテンツの読み込みに使用する再生可能な URL に対応します。たとえば、この URL は DASH マニフェストを指す可能性があります。contentIdには、再生可能なコンテンツの URL(contentUrlプロパティの URL と同様)または読み込まれるコンテンツや再生リストの一意の識別子を指定できます。このプロパティを識別子として使用する場合は、アプリケーションでcontentUrlに再生可能な URL を入力する必要があります。
entity を使用して実際の ID またはキー パラメータを保存し、contentUrl を使用してメディアの URL を保存することをおすすめします。次のスニペットは、entity が LOAD リクエストに存在し、再生可能な contentUrl が取得される例を示しています。
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
...
if (!loadRequestData.media.entity) {
// Copy the value from contentId for legacy reasons if needed
loadRequestData.media.entity = loadRequestData.media.contentId;
}
return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
loadRequestData.media.contentUrl = asset.url;
...
return loadRequestData;
});
});
デバイスの機能
getDeviceCapabilities メソッドは、接続されているキャスト デバイスと、それに接続されている動画デバイスまたはオーディオ機器に関するデバイス情報を提供します。getDeviceCapabilities メソッドは、Google アシスタント、Bluetooth、接続ディスプレイ、オーディオ機器のサポート情報を提供します。
このメソッドは、指定された列挙型のいずれかを渡してクエリを実行し、その列挙型のデバイス機能を取得できるオブジェクトを返します。列挙型は cast.framework.system.DeviceCapabilities で定義されています。
この例では、それぞれ IS_HDR_SUPPORTED キーと IS_DV_SUPPORTED キーを使用して、Web Receiver デバイスが HDR と DolbyVision(DV)を再生できるかどうかを確認します。
const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
const deviceCapabilities = context.getDeviceCapabilities();
if (deviceCapabilities &&
deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
// Write your own event handling code, for example
// using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
}
if (deviceCapabilities &&
deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
// Write your own event handling code, for example
// using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
}
});
context.start();
ユーザー インタラクションの処理
ユーザーは、送信側アプリ(ウェブ、Android、iOS)、アシスタント搭載デバイスの音声コマンド、スマートディスプレイのタッチ操作、Android TV デバイスのリモコンを使用して、ウェブ レシーバー アプリケーションを操作できます。Cast SDK には、ウェブ レシーバー アプリがこれらの操作を処理し、ユーザー アクションの状態を通じてアプリケーション UI を更新し、必要に応じて変更を送信してバックエンド サービスを更新できるようにするさまざまな API が用意されています。
サポートされているメディア コマンド
UI コントロールの状態は、iOS と Android の送信側拡張コントローラ、タッチデバイスで実行されるレシーバー アプリとリモコン アプリ、Android TV デバイスのレシーバー アプリの MediaStatus.supportedMediaCommands によって制御されます。プロパティで特定のビット単位の Command が有効になっている場合、そのアクションに関連するボタンが有効になります。値が設定されていない場合、ボタンは無効になります。これらの値は、ウェブ レシーバで次のように変更できます。
PlayerManager.setSupportedMediaCommandsを使用して特定のCommandsを設定するaddSupportedMediaCommandsを使用して新しいコマンドを追加するremoveSupportedMediaCommandsを使用して既存のコマンドを削除します。
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
cast.framework.messages.Command.PAUSE);
受信側が更新された MediaStatus を準備するとき、supportedMediaCommands プロパティに変更を含めます。ステータスがブロードキャストされると、接続されている送信側アプリは UI のボタンを適宜更新します。
サポートされているメディア コマンドとタッチ デバイスの詳細については、Accessing UI controls ガイドをご覧ください。
ユーザー アクションの状態を管理する
ユーザーが UI を操作したり、音声コマンドを送信したりすると、コンテンツの再生と、再生中のアイテムに関連するプロパティを制御できます。再生を制御するリクエストは、SDK によって自動的に処理されます。LIKE コマンドなど、現在再生中のアイテムのプロパティを変更するリクエストは、レシーバー アプリケーションで処理する必要があります。SDK には、これらのタイプのリクエストを処理するための API が用意されています。これらのリクエストをサポートするには、次の操作を行う必要があります。
- メディア アイテムを読み込むときに、ユーザーの設定で
MediaInformationuserActionStatesを設定します。 USER_ACTIONメッセージをインターセプトし、リクエストされたアクションを特定します。MediaInformationUserActionStateを更新して UI を更新します。
次のスニペットは、LOAD リクエストをインターセプトし、LoadRequestData の MediaInformation を入力します。この場合、ユーザーは読み込まれているコンテンツを気に入っています。
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
const userActionLike = new cast.framework.messages.UserActionState(
cast.framework.messages.UserAction.LIKE);
loadRequestData.media.userActionStates = [userActionLike];
return loadRequestData;
});
次のスニペットは、USER_ACTION メッセージをインターセプトし、リクエストされた変更でバックエンドを呼び出す処理を行います。次に、受信側の UserActionState を更新する呼び出しを行います。
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
(userActionRequestData) => {
// Obtain the media information of the current content to associate the action to.
let mediaInfo = playerManager.getMediaInformation();
// If there is no media info return an error and ignore the request.
if (!mediaInfo) {
console.error('Not playing media, user action is not supported');
return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
}
// Reach out to backend services to store user action modifications. See sample below.
return sendUserAction(userActionRequestData, mediaInfo)
// Upon response from the backend, update the client's UserActionState.
.then(backendResponse => updateUserActionStates(backendResponse))
// If any errors occurred in the backend return them to the cast receiver.
.catch((error) => {
console.error(error);
return error;
});
});
次のスニペットは、バックエンド サービスへの呼び出しをシミュレートします。この関数は UserActionRequestData をチェックして、ユーザーがリクエストした変更のタイプを確認し、アクションがバックエンドでサポートされている場合にのみネットワーク呼び出しを行います。
function sendUserAction(userActionRequestData, mediaInfo) {
return new Promise((resolve, reject) => {
switch (userActionRequestData.userAction) {
// Handle user action changes supported by the backend.
case cast.framework.messages.UserAction.LIKE:
case cast.framework.messages.UserAction.DISLIKE:
case cast.framework.messages.UserAction.FOLLOW:
case cast.framework.messages.UserAction.UNFOLLOW:
case cast.framework.messages.UserAction.FLAG:
case cast.framework.messages.UserAction.SKIP_AD:
let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
setTimeout(() => {resolve(backendResponse)}, 1000);
break;
// Reject all other user action changes.
default:
reject(
new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
}
});
}
次のスニペットは UserActionRequestData を取得し、MediaInformation から UserActionState を追加または削除します。MediaInformation の UserActionState を更新すると、リクエストされたアクションに関連付けられているボタンの状態が変更されます。この変更は、スマート ディスプレイのコントロール UI、リモコン アプリ、Android TV UI に反映されます。また、送信 MediaStatus メッセージを介してブロードキャストされ、iOS と Android の送信者の展開されたコントローラの UI を更新します。
function updateUserActionStates(backendResponse) {
// Unwrap the backend response.
let mediaInfo = backendResponse.mediaInfo;
let userActionRequestData = backendResponse.userActionRequestData;
// If the current item playing has changed, don't update the UserActionState for the current item.
if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
return;
}
// Check for existing userActionStates in the MediaInformation.
// If none, initialize a new array to populate states with.
let userActionStates = mediaInfo.userActionStates || [];
// Locate the index of the UserActionState that will be updated in the userActionStates array.
let index = userActionStates.findIndex((currUserActionState) => {
return currUserActionState.userAction == userActionRequestData.userAction;
});
if (userActionRequestData.clear) {
// Remove the user action state from the array if cleared.
if (index >= 0) {
userActionStates.splice(index, 1);
}
else {
console.warn("Could not find UserActionState to remove in MediaInformation");
}
} else {
// Add the UserActionState to the array if enabled.
userActionStates.push(
new cast.framework.messages.UserActionState(userActionRequestData.userAction));
}
// Update the UserActionState array and set the new MediaInformation
mediaInfo.userActionStates = userActionStates;
playerManager.setMediaInformation(mediaInfo, true);
return;
}
音声コマンド
現在、アシスタント搭載デバイスの Web Receiver SDK でサポートされているメディア コマンドは次のとおりです。これらのコマンドのデフォルト実装は cast.framework.PlayerManager にあります。
| コマンド | 説明 |
|---|---|
| Play | 一時停止状態から再生を開始または再開します。 |
| 一時停止 | 現在再生中のコンテンツを一時停止します。 |
| 前へ | メディアキュー内の前のメディア アイテムにスキップします。 |
| 次へ | メディア キューの次のメディア アイテムにスキップします。 |
| 停止 | 現在再生中のメディアを停止します。 |
| Repeat None | キュー内の最後のアイテムの再生が完了したら、キュー内のメディア アイテムの繰り返しを無効にします。 |
| 1 曲をリピート | 現在再生中のメディアを無期限に繰り返します。 |
| 全曲リピート | キュー内の最後のアイテムが再生されたら、キュー内のすべてのアイテムを 1 回繰り返します。 |
| すべてリピートとシャッフル | キュー内の最後のアイテムの再生が完了したら、キューをシャッフルして、キュー内のすべてのアイテムを繰り返します。 |
| シャッフル | メディアキュー内のメディア アイテムをシャッフルします。 |
| 字幕のオン / オフ | メディアの字幕を有効 / 無効にします。言語ごとに有効 / 無効にすることもできます。 |
| 絶対時間にシークする | 指定された絶対時間にジャンプします。 |
| 現在時刻を基準とした相対時刻にシークする | 現在の再生時間から指定した期間だけ前後に移動します。 |
| もう一度プレイ | 現在再生中のメディアを再開するか、現在再生中のメディアがない場合は最後に再生したメディア アイテムを再生します。 |
| 再生速度を設定する | メディアの再生速度を変更します。これはデフォルトで処理されるはずです。SET_PLAYBACK_RATE メッセージ インターセプタを使用すると、受信レート リクエストをオーバーライドできます。 |
音声でサポートされているメディア コマンド
音声コマンドによってアシスタント対応デバイスでメディア コマンドがトリガーされないようにするには、まずサポートする予定のサポート対象のメディア コマンドを設定する必要があります。次に、CastReceiverOptions.enforceSupportedCommands プロパティを有効にして、これらのコマンドを適用する必要があります。これらの設定を反映して、Cast SDK の送信側とタッチ対応デバイスの UI が変更されます。このフラグが有効になっていない場合、受信した音声コマンドが実行されます。
たとえば、送信側アプリとタッチ対応デバイスからの PAUSE を許可する場合は、それらの設定を反映するように受信側も構成する必要があります。構成すると、サポートされているコマンドのリストに含まれていない音声コマンドはすべて破棄されます。
次の例では、CastReceiverContext の開始時に CastReceiverOptions を指定しています。PAUSE コマンドのサポートを追加し、プレーヤーがそのコマンドのみをサポートするように強制しました。これで、音声コマンドが SEEK などの別のオペレーションをリクエストした場合、拒否されます。このコマンドはまだサポートされていないことをユーザーに通知します。
const context = cast.framework.CastReceiverContext.getInstance();
context.start({
enforceSupportedCommands: true,
supportedCommands: cast.framework.messages.Command.PAUSE
});
制限するコマンドごとに個別のロジックを適用できます。enforceSupportedCommands フラグを削除し、制限するコマンドごとに、着信したメッセージをインターセプトできます。ここでは、SDK によって提供されたリクエストをインターセプトし、アシスタント搭載デバイスに発行された SEEK コマンドが Web Receiver アプリケーションでのシークをトリガーしないようにします。
アプリがサポートしていないメディア コマンドについては、NOT_SUPPORTED などの適切なエラー理由を返します。
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
seekData => {
// Block seeking if the SEEK supported media command is disabled
if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
.INVALID_REQUEST);
e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
return e;
}
return seekData;
});
音声アクティビティからのバックグラウンド化
ユーザーの発言を聴取したり、応答したりするなどのアシスタント アクティビティにより、Cast プラットフォームがアプリの音声をバックグラウンドにすると、アクティビティの開始時に NOT_IN_FOCUS の FocusState メッセージがウェブ レシーバ アプリケーションに送信されます。アクティビティが終了すると、IN_FOCUS を含む別のメッセージが送信されます。アプリケーションと再生中のメディアによっては、メッセージ タイプ FOCUS_STATE をインターセプトして、FocusState が NOT_IN_FOCUS のときにメディアを一時停止することが望ましい場合があります。
たとえば、Google アシスタントがユーザーのクエリに応答しているときにオーディオブックの再生を一時停止すると、ユーザー エクスペリエンスが向上します。
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
focusStateRequestData => {
// Pause content when the app is out of focus. Resume when focus is restored.
if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
playerManager.pause();
} else {
playerManager.play();
}
return focusStateRequestData;
});
音声指定の字幕言語
ユーザーが字幕の言語を明示的に指定しない場合、字幕に使用される言語は、コマンドが発話された言語と同じになります。このようなシナリオでは、着信したメッセージの isSuggestedLanguage パラメータは、関連付けられた言語がユーザーによって提案されたか、明示的にリクエストされたかを示します。
たとえば、「OK Google, 字幕をオンにして」というコマンドの場合、コマンドが発せられた言語から言語が推測されるため、isSuggestedLanguage は true に設定されます。「OK Google, 英語の字幕をオンにして」のように言語が明示的にリクエストされた場合、isSuggestedLanguage は false に設定されます。
メタデータと音声キャスティング
音声コマンドはデフォルトで Web レシーバによって処理されますが、コンテンツのメタデータが完全かつ正確であることを確認する必要があります。これにより、音声コマンドがアシスタントによって適切に処理され、Google Home アプリや Google Home Hub などのスマート ディスプレイといった新しいタイプのインターフェースでメタデータが適切に表示されるようになります。
ストリーミング転送
セッションの状態を保持することは、ストリーム転送の基本です。ストリーム転送では、音声コマンド、Google Home アプリ、スマートディスプレイを使用して、既存の音声ストリームと動画ストリームをデバイス間で移動できます。メディアの再生が 1 つのデバイス(ソース)で停止し、別のデバイス(宛先)で続行されます。最新のファームウェアを搭載した Cast デバイスは、ストリーム転送の転送元または転送先として機能します。
ストリーム転送のイベント フローは次のとおりです。
- ソースデバイスで、次の操作を行います。
- メディアの再生が停止します。
- ウェブ レシーバー アプリケーションは、現在のメディアの状態を保存するコマンドを受信します。
- ウェブ レシーバー アプリケーションがシャットダウンされます。
- 移行先のデバイスで、以下の操作を行います。
- ウェブ レシーバー アプリケーションが読み込まれます。
- Web Receiver アプリケーションは、保存されたメディアの状態を復元するコマンドを受信します。
- メディアの再生が再開されます。
メディアの状態の要素は次のとおりです。
- 曲、動画、メディア アイテムの特定の位置またはタイムスタンプ。
- より大きなキュー(プレイリストやアーティスト ラジオなど)での位置。
- 認証済みのユーザー。
- 再生状態(再生中、一時停止など)。
ストリーム転送を有効にする
ウェブ レシーバのストリーム転送を実装するには:
STREAM_TRANSFERコマンドを使用してsupportedMediaCommandsを更新します。playerManager.addSupportedMediaCommands( cast.framework.messages.Command.STREAM_TRANSFER, true);
- 必要に応じて、セッション状態の保持で説明されているように、
SESSION_STATEメッセージ インターセプタとRESUME_SESSIONメッセージ インターセプタをオーバーライドします。カスタムデータをセッション スナップショットの一部として保存する必要がある場合にのみ、これらをオーバーライドします。それ以外の場合、セッション状態を保持するためのデフォルトの実装はストリーム転送をサポートします。
セッションの状態を保持する
Web Receiver SDK は、現在のメディア ステータスのスナップショットを取得し、ステータスを読み込みリクエストに変換し、読み込みリクエストでセッションを再開することで、セッションの状態を維持する Web Receiver アプリのデフォルト実装を提供します。
必要に応じて、ウェブ レシーバによって生成された読み込みリクエストは SESSION_STATE メッセージ インターセプタでオーバーライドできます。読み込みリクエストにカスタムデータを追加する場合は、loadRequestData.customData に入れることをおすすめします。
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.SESSION_STATE,
function (sessionState) {
// Override sessionState.loadRequestData if needed.
const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
sessionState.loadRequestData.credentials = newCredentials;
// Add custom data if needed.
sessionState.loadRequestData.customData = {
'membership': 'PREMIUM'
};
return sessionState;
});
カスタムデータは、RESUME_SESSION メッセージ インターセプタの loadRequestData.customData から取得できます。
let cred_ = null;
let membership_ = null;
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.RESUME_SESSION,
function (resumeSessionRequest) {
let sessionState = resumeSessionRequest.sessionState;
// Modify sessionState.loadRequestData if needed.
cred_ = sessionState.loadRequestData.credentials;
// Retrieve custom data.
membership_ = sessionState.loadRequestData.customData.membership;
return resumeSessionRequest;
});
コンテンツのプリロード
Web レシーバは、キュー内の現在の再生アイテムの後にメディア アイテムをプリロードすることをサポートしています。
プリロード オペレーションでは、今後のアイテムの複数のセグメントが事前にダウンロードされます。この指定は、QueueItem オブジェクトの preloadTime 値で行われます(指定されていない場合はデフォルトで 20 秒)。この時間は、現在再生中のアイテムの終了を基準とした秒数で表されます。正の値のみが有効です。たとえば、値が 10 秒の場合、このアイテムは前のアイテムが終了する 10 秒前にプリロードされます。プリロードにかかる時間が currentItem の残り時間よりも長い場合、プリロードはできるだけ早く行われます。そのため、queueItem に非常に大きなプリロード値を指定すると、現在のアイテムを再生するたびに次のアイテムをプリロードする効果が得られます。ただし、この値は現在再生中のアイテムの帯域幅とストリーミング パフォーマンスに影響する可能性があるため、この設定と選択はデベロッパーに任されています。
プリロードは、デフォルトで HLS、DASH、Smooth ストリーミング コンテンツで機能します。
MP3 などの通常の MP4 動画ファイルと音声ファイルは、キャスト デバイスが 1 つのメディア要素のみをサポートし、既存のコンテンツ アイテムがまだ再生中の場合はプリロードに使用できないため、プリロードされません。
カスタム メッセージ
メッセージ交換は、ウェブ レシーバー アプリケーションの主要なインタラクション方法です。
送信者は、送信者が実行されているプラットフォーム(Android、iOS、ウェブ)の送信者 API を使用して、ウェブ レシーバにメッセージを発行します。イベント リスナーに渡されるイベント オブジェクト(メッセージの具現化)には、データが特定のイベント タイプのプロパティを取得するデータ要素(event.data)があります。
ウェブ レシーバー アプリケーションは、指定された名前空間でメッセージをリッスンするように選択できます。これにより、ウェブ レシーバー アプリケーションがその名前空間プロトコルをサポートしていることになります。その名前空間で通信を希望する接続された送信者は、適切なプロトコルを使用する必要があります。
すべての名前空間は文字列で定義され、「urn:x-cast:」で始まり、その後に任意の文字列が続きます。(「urn:x-cast:com.example.cast.mynamespace」など)。
接続された送信者からのカスタム メッセージをリッスンする Web レシーバーのコード スニペットは次のとおりです。
const context = cast.framework.CastReceiverContext.getInstance();
const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
// handle customEvent.
});
context.start();
同様に、ウェブ レシーバー アプリケーションは、接続されている送信者にメッセージを送信することで、ウェブ レシーバーの状態を送信者に通知できます。ウェブ レシーバー アプリケーションは、CastReceiverContext の sendCustomMessage(namespace, senderId, message) を使用してメッセージを送信できます。ウェブ レシーバは、受信したメッセージへの応答として、またはアプリケーションの状態の変化により、個々の送信者にメッセージを送信できます。ポイント ツー ポイント メッセージング(64 kb の制限あり)以外にも、ウェブ レシーバは接続されているすべての送信者にメッセージをブロードキャストできます。
オーディオ デバイスのキャスト
音声のみの再生については、オーディオ デバイス向け Google Cast ガイドをご覧ください。
Android TV
このセクションでは、Google Web Receiver が入力を再生として使用する方法と、Android TV の互換性について説明します。
アプリケーションとリモコンの統合
Android TV デバイスで実行されている Google Web Receiver は、デバイスの制御入力(ハンドヘルド リモコンなど)からの入力を、メディア再生メッセージで説明されているように、urn:x-cast:com.google.cast.media 名前空間で定義されたメディア再生メッセージとして変換します。Android TV のコントロール入力から基本的な再生コントロールを可能にするために、アプリケーションはこれらのメッセージをサポートして、アプリケーションのメディア再生を制御する必要があります。
Android TV の互換性に関するガイドライン
Android TV との互換性を確保するために、推奨事項と回避すべき一般的な落とし穴を以下に示します。
- ユーザー エージェント文字列には「Android」と「CrKey」の両方が含まれています。一部のサイトでは、「Android」ラベルが検出されるとモバイル専用サイトにリダイレクトされることがあります。ユーザー エージェント文字列の「Android」が常にモバイル ユーザーを示すとは限りません。
- Android のメディア スタックは、データを取得する際に透過的な GZIP を使用する場合があります。メディアデータが
Accept-Encoding: gzipに対応できるようにします。 - Android TV の HTML5 メディア イベントは Chromecast とは異なるタイミングでトリガーされるため、Chromecast では隠れていた問題が明らかになることがあります。
- メディアを更新するときは、
<audio>/<video>要素によって発生するメディア関連のイベント(timeupdate、pause、waitingなど)を使用します。progress、suspend、stalledなどのネットワーク関連のイベントは、プラットフォームに依存する傾向があるため、使用しないでください。レシーバーでのメディア イベントの処理について詳しくは、メディア イベントをご覧ください。 - 受信側サイトの HTTPS 証明書を構成する際は、中間 CA 証明書を必ず含めてください。Qualsys SSL テストページで、サイトの信頼できる認証パスに「extra download」というラベルの付いた CA 証明書が含まれている場合、Android ベースのプラットフォームで読み込まれない可能性があることを確認してください。
- Chromecast は 720p のグラフィック プレーンでレシーバー ページを表示しますが、Android TV などの他の Cast プラットフォームでは最大 1080p でページを表示できます。レシーバー ページがさまざまな解像度で適切にスケーリングされるようにします。