連載
» 2014年11月14日 18時00分 公開

スマホとWebSocketで連携するテレビ用SPA(Single-Page Application)の作り方Chromecastアプリ開発入門(2)(4/5 ページ)

[大西克己,オープンストリーム]

Adaptive Bitrate Streaming/DRMのメディアの再生

 前回の記事でも解説しましたが、Adaptive Bitrate Streamingはネットワーク状況に応じてビデオ/オーディオの品質を変化させる技術、DRMはデジタルデータのコンテンツの著作権を保護して利用を制限する技術です。

Video on HTML5のAdaptive Bitrate Streaming/DRMメディア拡張

 HTML5では、Adaptive Bitrate Streaming/DRMのメディアを扱えるようにいくつかの拡張がされています。

Media Source Extensions(MSE)

 MSEはAdaptive Bitrate StreamingをサポートするためのHTMLMediaElementの拡張で、メディアソースに対してより細かい制御ができるようになります。これにより、JavaScriptでチャンク単位にストリームを扱えるようになるため、ネットワークやメディア レンダリングのさまざまなボトルネックに対応して、品質レベルを調整してストリーミングすることが可能となります。Chromecastでは、HTTP Live Streaming (HLS)、MPEG-DASH、Smooth Streamingがサポートされています。

Encrypted Media Extensions(EME)

 EMEはDRMをサポートするためのHTMLMediaElement の拡張で、ブラウザーでサポートされている保護システムを検出し、DRM保護されたメディアを再生するために、キーの交換、暗号化されたメディアの複合を行うためのAPI仕様を提供します。実際の暗号解除処理は後述のCDMが行います。

Content Decryption Modules(CDM)

 CDMはDRM暗号解除処理モジュールです。各暗号方式ごとに用意され、クライアントサイドに実装されたソフトウェアまたはハードウェアモジュールです。クライアントアプリケーションは、前述のEMEのAPIを通して、メディアのDRM方式に応じて複合化を行います。Chromecastでは、PlayReadyとWidevineのCDMが組み込まれています。

 より詳しい内容は、W3Cや以下のサイトで確認してください。

 Chromecastでは、アプリケーションが上記の拡張機能を簡単に使用できるように、「Media Player Library」が提供されています。このライブラリを使用してAdaptive Bitrate Streaming/DRMメディアを再生可能です。

Adaptive Bitrate Streaming/DRMメディア再生

 それでは、Media Player Libraryを使用してAdaptive Bitrate Streaming/DRMメディア再生の実装を進めていきます。

Media Player Libraryを組み込む

 まずはコード9の通りMedia Player LibraryをReceiverに組み込みます。

<html>
<head>
  <!-- (1)Google Cast Receiver SDKの設定 -->
  <script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
  <!-- (a)Media Player Libraryの参照設定 -->
  <script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/mediaplayer/1.0.0/media_player.js">
  </script>
</head>
<body>
〜省略〜
コード9 Media Player Libraryの組み込み

(a)Media Player Libraryの参照を設定

 Google Cast Receiver SDKの参照の設定と同じように、セルフホストせずに、Googleのサーバーを指定します。ライブラリのアップデートの内容は、「Google Cast Release Notes」で確認できます。

メディア情報の取得

 Media Player Libraryを利用すると、メディアを再生するようにコマンドメッセージを受け取ったときに、メディア情報を取得できます。ChromecastのSDKで定義されているメディアプレーヤーのメッセージから取得できるメディア情報は表3の通りです。

表3 MediaInformation
Name Type Description
contentId string メディアのURL
streamType enum (string) メディアの種類:NONE、BUFFERED、LIVE
contentType string MIME:メディアのコンテントタイプ
metadata object (オプション)メタ情報
0:GenericMediaMetadata
1:TvShowMediaMetadata
2:MovieMediaMetadata
3:MusicTrackMediaMetadata
4:PhotoMediaMetadata
duration double (オプション)メディアの長さ
customData object (オプション)アプリケーションで固有のカスタムデータ。SenderとReceiverで扱えるようにデータ定義する

 メタ情報はいくつか定義があり、取得するメタ情報を指定できますが、今回は汎用的に利用できるGenericMediaMetadataを使用する前提とします。GenericMediaMetadataから取得できるメタ情報は表4の通りです。

表4 GenericMediaMetadata
Name Type Description
metadataType integer 0 GenericMediaMetadata
title string (オプション)メディアのタイトル
subtitle string (オプション)メディアのサブタイトル
images Image[] (オプション)メディアのサムネイル画像のURLの配列
releaseDate string (ISO 8601) (オプション)メディアのリリース日時
参照:MediaInformation

 メディアを再生するようにコマンドメッセージを受け取ったときに実行されるonLoadメソッドで、上記のメディア情報とメタ情報を取得できます。メディア情報からコンテンツのURLを取得するにはコード10のように記述します。

〜省略〜
 
//(4.1)onLoad をオーバーライド
window.mediaManager.onLoad = (function() {
    var origOnLoad = mediaManager.onLoad;
    return function(event) {
        // (4.2) メディアのメタ情報からタイトルを表示
        window.mediaTitle.innerHTML = event.data['media']['metadata']['title'];
 
        //(b)メディアの情報からコンテンツのURLを取得
        var url = event.data['media']['contentId'];
〜省略〜
コード10 メディア情報の取得

Adaptive Bitrate Streamingのメディアを再生

 Adaptive Bitrate Streamingのメディアを再生するには、Media Player Libraryで提供されている、Host/Player/Protocolクラスを使用します。

 Hostは、Receiverとメディアプレーヤーとのやりとりのために使用します。Receiverがメディアプレーヤーの動作をカスタマイズする場合、Hostクラスの各メソッドをオーバーライドします。

 MediaElementとURLを指定してHostのコンストラクターを呼び出します(コード11)。それぞれ以下の値を設定します。

  • mediaElement:ページ内のvideo要素
  • uri:メディアのURL
//(c)ホストのオブジェクトを作成
window.mediaHost = new cast.player.api.Host({
    'mediaElement': mediaElement,
    'url': url
});
コード11

Cookie、カスタムヘッダーを利用する

 メディアサーバーが、メディアにアクセス時にCookieとカスタムヘッダーが必要とされる場合、コード12のように記述します。

  1. HostのupdateSegmentRequestInfoメソッドをオーバーライド
  2. XML HTTP request 情報を表すcast.player.api.RequestInfoクラスの withCredentials のプロパティを有効に設定
  3. カスタムヘッダーを設定
//(d)withCredentials とカスタムヘッダーの設定
window.mediaHost.updateSegmentRequestInfo = function(requestInfo) { //……1.
   requestInfo.withCredentials = true; //……2.
   requestInfo.headers['content-type'] = 'text/xml;charset=utf-8'; //……3.
};
コード12

プレーヤーのエラーハンドリング

 プレーヤーのエラーをハンドリングしたい場合は、HostクラスのonErrorメソッドをオーバーライドします(コード13)。

//(e)エラーハンドリング
window.mediaHost.onError = function (errorCode, requestStatus) {
    console.error('### HOST ERROR - Fatal Error: code = ' + errorCode);
    if (window.mediaPlayer !== null) {
        window.mediaPlayer.unload();
        window.mediaPlayer = null;
    }
}
コード13

 Playerは、MediaElementとメディアソースと通信するために使用します。Hostを指定してPlayerのコンストラクターを呼び出します(コード14)。

//(f)Playerのインスタンスを作成
window.mediaPlayer = new cast.player.api.Player(window.mediaHost);
コード14

 Protocolは、HostにAdaptive Bitrate Streamingの種類を伝えるために使用します。Adaptive Bitrate Streamingの種類によってそれぞれクラスが提供されています。

 URLに含まれる拡張子でAdaptive Bitrate Streamingの種類を判断して、適切なProtocolのインスタンスを作成します(コード15)。

//(g)Protocolのインスタンスを作成
var protocol = null;
if (url.lastIndexOf('.m3u8') >= 0) {
    // HLS
    protocol =  cast.player.api.CreateHlsStreamingProtocol(window.mediaHost);
} else if (url.lastIndexOf('.mpd') >= 0) {
    // MPEG-DASH
    protocol = cast.player.api.CreateDashStreamingProtocol(window.mediaHost);
} else if (url.lastIndexOf('.ism/') >= 0 || url.lastIndexOf('.isml/') >= 0) {
    // Smooth Streaming
    protocol = cast.player.api.CreateSmoothStreamingProtocol(window.mediaHost);
}
コード15

 Protocolと再生開始位置を指定して、メディアをロードします(コード16)。

//(h)Protocolを指定してメディアをロード
window.mediaPlayer.load(protocol, initStart);
コード16

 以上の処理で、Adaptive Bitrate Streamingのメディアを再生することが可能となります。

DRMの処理

 Chromecastデバイスには、DRMエージェント機能が搭載されています。Media Player Library(MPL)を介してデバイスのDRMエージェント機能を使用することで、ReceiverでのDRM処理が可能となります。HTML5の拡張機能であるEMEのAPIやCDMを、Receiverが直接呼び出す必要はありません。

 Receiverは、ライセンスを取得する先のURLと、カスタムデータの指定を行うだけでよく、後はMPLが処理してくれます。また、MPLを利用してライセンス処理時のレスポンスデータの取得を行うこともできます(コード17)。

//(i)ライセンス取得先URLを指定
window.mediaHost.licenseUrl = licenseUrl;
 
//(j)カスタムデータを設定
window.mediaHost.licenseCustomData = customData;
 
//(k)レスポンスデータの処理をオーバーライド
window.mediaHost.processLicense = function(responseArray) {
  // Uint8ArrayをStringへ変換
  var response = String.fromCharCode.apply(null, responseArray); 
 
  // TODO: レスポンスデータの処理
 
  // 必ず最後にレスポンスデータをリターンする必要がある
  return responseArray;
}
コード17

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。