スマホとWebSocketで連携するテレビ用SPA(Single-Page Application)の作り方:Chromecastアプリ開発入門(2)(3/5 ページ)
メディアストリーミングデバイス「Chromecast」用アプリの開発方法を一から解説する連載。今回は、Senderのコマンドを受信してHTML5のvideo要素を使ってメディアを再生したり画面を写したりするReceiverアプリの概要と作り方などを解説します。
■プロパティの取得
メディアの再生時間/プログレスバーを更新する値は、MediaElementのプロパティから取得します。
以下のコード3では、再生中の再生位置を更新が発生するたびに取得して現在の再生時間とプログレスバーの長さを変更しています。
〜省略〜 // メディアの再生位置が変更された window.mediaElement.addEventListener('timeupdate', function() { //console.debug('######### MEDIA ELEMENT TIMEUPDATE ' + e); //(3.4)ステータスパネルの更新 //(3.4.1)現在の再生時間とコンテンツ時間を取得 var c = window.mediaElement.currentTime; var d = window.mediaElement.duration; //(3.4.2)ミリ秒の値を時刻フォーマットに変換して設定 window.current.innerHTML = format(c); window.duration.innerHTML = format(d); //(3.4.3)プログレスの長さを変更 window.progress.style.width = 950 * (c / d) + "px"; }); 〜省略〜 }; function format(ms) { return (ms / 36000 | 0) + (ms / 3600 % 10 | 0) + ":" + (ms % 3600 / 600 | 0) + (ms % 3600 / 60 % 10 | 0) + ":" + (ms % 60 / 10 | 0) + (ms % 60 % 10 | 0) }
■メディアを操作
次に、再生するメディアの操作方法について解説します。メディアを操作するにはメソッド呼び出しとプロパティの変更で行います。以下のような操作があります。
- load()メソッド:メディアの読み込みを行う
- play()メソッド:メディアの再生を行う
- pause()メソッド:メディアの一時停止を行う
- currentTimeプロパティ:再生時間
- volumeプロパティ:ボリューム
- mutedプロパティ:ミュート
Receiverアプリをユーザーは直接操作できません。このため、上記のようなメディア操作はユーザーがSenderアプリを操作することによって送信されるコマンドメッセージで行うことになります。
このコマンドメッセージをSenderアプリから受け取るためには、Google Cast Receiver SDKを利用する必要があります。以降で、コマンドメッセージを受け取る方法について解説します。
Senderアプリからコマンドメッセージを受け取ってメディアを操作する
Google Cast Receiver SDKで提供されている、以下の二つのクラスを使用することで、Senderからコマンドメッセージを受け取り、メディアの操作を行えます。
- MediaManager
- CastReceiverManager
これらのクラスを使って、メディア操作を実装していきましょう。
■MediaManager
MediaManagerは、load、play、pause、stopなど基本的なメディア操作のメッセージとイベントの送受信のために使用します。サポートされている全てのコマンドは「Media Playback Messages」の「Commands from sender to receiver」を参照してください。
コマンドメッセージを受け取ったときにビジネスロジックを実行したい場合は、処理したいイベントが発生した際にコールバックされるイベントハンドラーをオーバーライドします。
以下のコード4は、「新しいメディアを再生する」というコマンドメッセージを受け取ったときに実行されるonLoadメソッドをオーバーライドして、メディアのメタ情報からタイトルを取得して画面に表示しています。
//(4)Videoエレメントを指定してメディアマネージャを作成 window.mediaManager = new cast.receiver.MediaManager(window.mediaElement); //(4.1)onLoad をオーバーライド window.mediaManager.onLoad = (function() { var origOnLoad = mediaManager.onLoad; return function(event) { //(4.2)メディアのメタ情報からタイトルを表示 window.mediaTitle.innerHTML = event.data['media']['metadata']['title']; //(4.3)オリジナルのイベントを実行 origOnLoad(event); } }());
コラム「MediaManagerとMediaElementのハンドラーの使い分けについて」
MediaManagerはメディアコマンド発生をハンドラーで処理できますが、メディアの状態変更に伴うUIの更新はMediaElementのイベントハンドラーで処理することが推奨されています。それぞれのハンドラー内で推奨される操作は以下の通りです。
- MediaManagerのコマンドメッセージハンドラー内で記述するコード:Senderから送られるコマンドをトリガーとしたメディアの操作など
- MediaElementのイベントハンドラー内で記述するコード:メディアプレーヤーの状態変更に伴うUI更新
例えば、今回のサンプルアプリケーションに、メディアのシーク時にプログレスバーを表示する仕様を追加する場合、メディアのシークのイベントハンドリングはMediaManagerでは行わず、コード5のようにMediaElementのコールバックのイベントハンドラー内に記述します。
// シークコマンド発生 window.mediaManager.onSeek = (function() { var origOnSeek = mediaManager.onSeek; return function(event) { // UIの更新は行わない origOnSeek(event); } }()); // メディアのシークが始まった window.mediaElement.addEventListener('seeking', function(e) { console.log("######### MEDIA ELEMENT SEEKING ", e); // プログレスバー画像を表示する。 window.progress.style.display = "block"; }); // メディアのシークが終了した window.mediaElement.addEventListener('seeked', function(e) { console.log("######### MEDIA ELEMENT SEEKED ", e); // プログレスバー画像を非表示にする。 window.progress.style.display = "none"; });
また、MediaManagerについての詳細は、以下のAPIリファレンス「Class cast.receiver.MediaManager」を参考にしてください。
■CastReceiverManager
CastReceiverManagerは、Senderと通信ができるようにする仕組みで、システムからのメッセージとイベント、独自に定義したメッセージをSenderと送受信するために使用します。
Senderからコマンドメッセージを受け取ったときにビジネスロジックを実行する場合、イベントハンドラーをオーバーライドします。
以下のコード6は、このイベントハンドラーを使用して以下の処理を実施しています。
- Senderが接続されたときに接続数をログに表示
- Senderが切断されたときに接続数が0件かつ切断の理由がSenderからのリクエストであった場合、Receiverを閉じる。また、このとき切断の理由を確認して、Wi-Fiの通信切断が原因であった場合は、Receiverアプリを終了せずにメディアの再生をし続ける
//(5)レシーバーマネージャのシングルトンインスタンスを作成 window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance(); //(5.1)onSenderConnected をオーバーライド window.castReceiverManager.onSenderConnected = (function() { return function(event) { // 接続しているSenderの数をログに出力……1. var senders = castReceiverManager.getSenders(); console.debug('SenderCount', '' + senders.length); } }()); //(5.2)onSenderDisconnected をオーバーライド window.castReceiverManager.onSenderDisconnected = (function() { return function(event) { // 接続しているSenderの数が0件 かつ 切断の理由はリクエストか?……2. var senders = castReceiverManager.getSenders(); if(senders.length == 0 && event.reason == cast.receiver.system.DisconnectReason.REQUESTED_BY_SENDER) { window.close(); } } }()); //(5.3)レシーバーマネージャのスタート window.castReceiverManager.start();
システムメッセージ/イベント以外に、カスタムメッセージ/イベントを使用したい場合、CastMessageBusクラスを使用します(コード7)。
//(5.4)カスタムメッセージのインスタンスを作成する window.customMessageBus = castReceiverManager.getCastMessageBus('urn:x-cast:com.example.mymediaplayer'); customMessageBus.onMessage = function(event) { // メッセージのハンドリング }
castReceiverManager.getCastMessageBusメソッドの引数にアプリケーションで定義したネームスペースを指定してカスタムチャンネルを取得します。ネームスペースは必ず「urn:x-cast:」から始まる任意の文字列を定義する必要があります。
CastMessageBusを利用すると、接続中の全てのSenderにメッセージを送信したり、特定のSenderにだけメッセージを送信したりすることも可能です。Senderにメッセージを送信する例はコード8の通りです。
customMessageBus.broadcast(message); // 接続中の全てのSenderにメッセージ送信 customMessageBus.send(senderId, message); // 特定SenderIdにメッセージ送信
CastReceiverManagerとCastMessageBusの詳細については、各APIリファレンスを参照してください。
メディアプレーヤーのUI更新時にページ遷移させないように実装する
一般的なメディアプレーヤーは、ユーザーがメディアを再生したり停止したりといったコマンドが発生するたびに状態が変化し、それに応じてUIの更新を行います。メディアプレーヤーの状態変化を状態遷移図/表に表すと以下のようになります。
イベント | 状態 | UI更新処理 |
---|---|---|
load() | LOADING | ・処理中アニメーション画像を表示 ・ステータスパネルを表示 ・メディアのタイトルを表示 |
loaded buffered |
PLAYING | ・処理中アニメーション画像を隠す ・再生状態の画像を表示 ・一定時間後、ステータスパネルを隠す |
pause() | PAUSED | ・ステータスパネルを表示 ・一時停止状態の画像を表示 |
play() | PLAYING | ・再生状態の画像を表示 ・一定時間後、ステータスパネルを隠す |
buffering | BUFFERING | ・処理中アニメーション画像を表示 |
stop() | IDLE | ・アイドル画面を表示 ※メディアが再生されていない待機画面 |
状態遷移によりUIの更新が必要になりますが、UI更新のためにページ遷移させてはいけません。Receiverアプリは、必ずSPA(Single-Page Application)で実装する必要があります。なぜなら、ページ遷移してしまうと、Receiverアプリとして動作しなくなる仕様のため、Senderアプリからメッセージコマンドを受信できなくなってしまうからです。
なお、SPAの基本的な要素は以下の通りです。
- 単一ページによるWebアプリケーション
- ページ(UIの更新)はDOMの操作により切り替えを行う
- サーバーとの通信はAjax、スマホとの通信はWebSocketで行う
Google Cast Receiver SDK(MediaManagerやCastReceiverManager)とMedia Player Libraryは、サーバーのやりとりはAjax(XMLHttpRequest)で、SenderアプリとのやりとりはWebSocketを用いています。
メディアプレーヤーのイベント発生/状態変化によってUIを更新する際も、DOMを操作することで更新し、HTTPページ遷移は使わないでください。
例えば、アイドル画面でプロモーション的なリッチなコンテンツを表示したいために、HTTPリクエストでページ遷移を行ってしまうと、上記の通り、Senderとの接続が切れてしまい、SenderからReceiverアプリの操作ができなくなってしまいます。
「Google Cast Design Checklist - Google Cast - Google Developers」には、「メディアプレーヤーには、どのようなUIが必要で、ユーザーにどのように情報を伝えるべきか」の指針が記載されています。
また、メディアのイベントと状態の詳しい内容は「Custom Receiver Application - Google Cast - Google Developers」に記載されています。
これらは、デザイナーとプログラマーが、UIや状態遷移の設計するに当たり役立つと思います。メディアプレーヤーを実装する際は、ぜひ参考にしてください。
続いて次ページでは、Adaptive Bitrate Streaming/DRMのメディアの再生の方法について解説します。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Windows OS/Androidの画面をChromecast経由でテレビに表示する
会議室のテレビにWindows OSの画面を映してプレゼンテーションしたい。でもケーブルをつなぐのはスマートではない。こんなとき、テレビにChromecastを接続し、Windows OSにGoogle Chromeをインストールすれば、画面をWi-Fi経由でテレビに表示できるようになる。 - 米グーグルがChromecastのSDKを公開
モバイル端末とTVの垣根を超えるChromecast用のSDKをGoogleが公開。Chromeの拡張機能とiOS向けのGoogle Cast SDKは即日提供を開始、Android版も数日中にリリース予定だという。 - グーグルのプレスイベントで見るグーグル新時代の幕開け
新型Nexus 7タブレットやAndroid 4.3、さらには新デバイスChromecastの発表から、グーグルの新世代戦略を読み解きます。 - YouTube動画を家中のディスプレイで再生できたら
YouTubeビデオを、ブラウザからリビングのテレビやタブレットに飛ばせたら。HTML5のPlayコマンドをテレビに送信して再生する方法を紹介します - Android L、Android Wear、Android TV、Android Autoの開発者向け現状まとめ
米グーグルが「Google I/O 2014」で発表した次期Android「Android L」「Android TV」「Android Auto」の開発者プレビュー、そして「Android Wear」の正式版。これらに対応したアプリを開発するには、どこを見ればいいのか。概要とともに簡単にまとめてみた。 - 第17回 iPhoneの画面をApple TVでテレビに表示する
iPhoneの画面をテレビに映してプレゼンしたい。こんなとき、会議室にApple TVを用意しておくと便利。たった3ステップでiPhoneの画面をテレビに映せるようになる。 - Windows OSの画面をApple TV経由でテレビに表示する
会議室のテレビにWindows OSの画面を映してプレゼンテーションしたい。でもケーブルをつなげるのは少々スマートではない。こんなとき、テレビにApple TVを接続し、Windows OSに「AirParrot」をインストールすれば、画面をWi-Fi経由でテレビに表示できるようになる。 - WebSocketでスマートテレビをリアル接続するぷらら
ひかりTV独自のスマートテレビリモコンの接続方法はWebSocketを用いた常時接続だ。その仕組みと開発意図を聞いた。 - さまざまなデバイスがWebと結び付いていく
テレビやカーナビ、家電とWebが連携していく「Web of Things」。NHKなど、最前線の取り組みが語られたカンファレンスをレポートする - テレビのスマート化とYouTubeのテレビ化
YouTubeなどネットの攻勢に対し、何もしないと「テレビは死ぬ」。それは明らかだ。テレビ局がよいサービスを開発できるかどうかが要となる。 - スマートテレビはチャンスだぞ
テレビもスマート、なんだと。アメリカからGoogle TVやApple TVがやってくる。米テレビ局の映像配信Huluも上陸している。もちろん、日本だって手を打っている - 今度こそテレビとWebの統合なるか:「Google TV」は従来のWebテレビと何が違うのか?
- 頭脳放談第120回:Google TVがVIA Technologiesも救う?
- WebとUIをつなぐトリックスター(2):テレビでYahoo!デバイスが変わればUIデザインも変わる
制作の要となるエンジニアとデザイナのチームワークのツボを探る連載。今回はヤフーのテレビ向けサービスのデザイン担当に話を聞いた