ADOBE®   MEDIA SERVER 5.0.3

デベロッパーズガイド


翻訳:株式会社サムライズ

 

注意

Adobe Media Server® バージョン 5についての本ドキュメントは第三者によって翻訳されたものであり、Adobe Systems Incorporated(アドビ システムズ社)は本翻訳物の正確性や完全性を査閲していません。

 

ライブビデオへのDVR機能の追加

 

DVRサポートについて

Flash Media Server 3.5

 

注意Adobe Media Server Standard DVR 機能をサポートしていません。

 

DVR(デジタルビデオレコーダー)を使用すると、ビューアでライブビデオを一時停止したり、一時停止の地点から再生を再開したりすることができます。また、ビューアではライブイベントの巻き戻し、記録されたセクションの再生およびライブセクションの再検出も可能です数行のコードを記入するだけで、ビデオ PlayerDVRのように動作させることができます。DVRアプリケーションの例には、即時再生および「追いかけ」サービスがあります。

注意FLVPlayback コンポーネントのバージョン 2.5 では、DVR をサポートしています。このコンポーネントを、Adobe Media Server ツールからダウンロードします。

 

 

動的ストリーミングでの DVRの使用

Flash Media Server 4.0Flash Player 10.1

 

動的ストリーミングアプリケーションで DVRを使用するには、サーバーで絶対時間コードを有効にします。絶対時間コードにより DVR対応のマルチビットレートストリームはサーバーで同期し続けます。

エンコーダーは、絶対時間コードを使用する必要があります。Flash Media Live Encoder は、絶対時間コードをサポートしますが、Flash Player はサポートしません。サードパーティのエンコーダーも絶対時間コードを使用します。お手持ちのエンコーダーで絶対時間コードを有効にする方法については、エンコーダーのベンダーに問い合わせてください。

重要ストリームは同期する必要がありますが、サーバーはストリームを同期しません。絶対時間コードは、エンコーダーの同期されているストリームを同期し続けるのに必要なすべての情報をサーバーに必ずキャプチャーさせます。

 

絶対時間コードの有効化

Application.xml 設定ファイル内の絶対時間コードをアプリケーションレベルで有効にします。有効になると、サーバーは、着信ライブストリームには、エンコーダーの入力ソース内に含まれる SMPTE 時間信号といった絶対時刻ベースのタイムスタンプがあるとみなします。デフォルト値は false です。

1    新しいテキストまたは XML ファイルを作成して、アプリケーションのフォルダー (Application.xml) に保存します。

注意アプリケーションレベルの Application.xml ファイルの一例として、rootinstall/applications/vod/Application.xml をテキストエディターで開きます。

 次を XML をファイルに追加します。

 

<Application>

<StreamManager>

<Live>

<AssumeAbsoluteTime>true</AssumeAbsoluteTime>

</Live>

</StreamManager>

</Application>

 ファイルを保存します。

設定ファイルの操作の詳細については「単一アプリケーションの設定」を参照してください。

 

動的ストリーミングでの DVR 向けストリームのパブリッシュと記録

DVRストリームを動的ストリーミングでパブリッシュして記録するにはappendWithGapNetStream.publish()またはStream.record()メソッドに渡しますストリームを appendWithGapモードでパブリッシュまたは記録するとき記録されるストリームには、ストリームの停止および再開時に作成されたギャップが保持されますappendモードでは、サーバーはギャップを除去するため、ストリームの同期が失われる可能性があります。ギャップは、エンコーダーがオフラインになってオンラインに戻るときに発生します。ギャップは、記録されたファイルの再生時にクライアントから表示可能です。

 

DVR ビデオのパブリッシュ、再生およびシーク

DVR ビデオ Player 用のストリームをクライアントからパブリッシュするには、次の例のようにrecordフラグまたはappendフラグを使用します。

 

NetStream.publish("myvideo", "record")

NetStream.publish("myvideo", "append")

DVR ビデオ Player 用のストリームをサーバーからパブリッシュするにはStream.record() を呼び出します。 Stream.record() メソッドには、ストリームの最大長とファイルサイズが指定可能な maxDuration maxSize 2 つの新規パラメーターがあります。次のコードは、最大記録長 10 分(600 秒)およびファイルサイズ無制限でストリームをパブリッシュします。

 

Stream.record("record", 600, -1)

 

DVRビデオ Player用にパブリッシュされたストリームをクライアントが再生する場合、クライアントはライブストリームは再生せず、記録されたストリームを再生します。クライアントがストリームを「ライブ」で表示する場合、記録された直後に記録ストリームを実際に表示しています。

DVR ビデオ Player 用にパブリッシュされたストリームをサブスクライブするには、次のコードを使用します。 NetStream.play("myvideo", 0, -1)

前記のコードを使用すると、イベントに遅れて参加したビューアでも、ストリームを最初から表示できます。

いつでもストリームの最初に戻るには、次のコードを呼び出します。

 

NetStream.seek(0)

 

イベントの途中で記録を開始するには、サーバーサイド ActionScriptStream.record()メソッドを呼び出します。このメソッドを呼び出すことで、いつでも記録の開始や停止が可能になります。

「ライブ」と見なされる)記録の使用可能な最新の部分をシークするボタンを作成するには、ストリームの再生時間(サーバー上で記録されたデータの長さ)から NetStream.bufferTimeの値を引いた位置をシークします。瞬間的な位置にできるだけ近い位置で再生するにはbufferTimeを引き算します。Flash Playerは、バッファーがいっぱいになるまで再開されません。

ストリームの再生時間を計算するにはonMetaData  コールバック関数にタイムスタンプを設定します。

 

public function onMetaData(info:Object):void{

trace("metadata:duration=" + info.duration);

duration = info.duration;

trace("stamp: " + stamp);

stamp = getTimer();

}

seek()メソッドに渡す値を計算するには、現在の再生時間を計算し、念のために bufferTimeから 2秒をさらに引きます。

 

private function getSeekToLiveValue():uint{

currentDuration = Number((getTimer()-stamp)/1000) + duration;

trace("currentDuration: " + currentDuration);

seekVal = (currentDuration - nsPlayer.bufferLength) - 2;

return seekVal;

}

「ライブ」をシークするには、再生 NetStream オブジェクトで getSeekToLiveValue() 関数を呼び出します。

 

private function onClick(event:MouseEvent):void {

switch(event.currentTarget){

case rewindBtn:

nsPlayer.seek(nsPlayer.time - 5);

break;

case seekBtn:

trace("seekToEndValue " + getSeekToEndValue());

nsPlayer.seek(getSeekToLiveValue());

break;

}

}

 

注意上述のコードは、サーバー上の rootinstall/documentation/samples/dvr フォルダー内にある DVR サンプルにあります。

 

 

Flash Media Live Encoder を使用した DVR 再生用ビデオのキャプチャ

Flash Media Live Encoder 3 を使用して、DVR 再生用のビデオをキャプチャすることができます。Flash Media Live Encoder の以前のバージョンは、サーバーへの記録をサポートしていません。詳細については、www.adobe.com/jp/products/flashmediaserver/flashmediaencoder/  を参照してください。

 

 

例:カスタムキャプチャ、パブリッシュおよび DVR 再生

この例では、クライアントアプリケーションは以下の動作を行います。

•   ビデオをキャプチャしエンコードします。

•   キャプチャした状態でビデオを表示します。

•    ビデオをクライアントから Adobe Media Server にストリーミングします。

•    逆にビデオをAdobe Media Server からクライアントにストリーミングします。

•   サーバーからストリーミングされたビデオを、ライブビデオの巻き戻しと一時停止が可能な Playerに表示します。

注意このコードをテストするには、サーバーに RootInstall/applications/dvr フォルダーを作成します。次に、RootInstall/documentation/samples/dvr/DVR.swf ファイルを開いてアプリケーションに接続します。

1    Adobe Media Server に、RootInstall/applications/dvr フォルダーを作成します。

2    Flash で、ActionScript ファイルを作成し、DVR.as という名前で保存します。

 次のコードを Script ウィンドウにコピーアンドペーストします。

 

package {

import flash.display.MovieClip;

import flash.utils.getTimer;

import flash.net.NetConnection;

import flash.events.*;

import flash.net.NetStream;

import flash.media.Video;

import flash.media.Camera;

import flash.media.Microphone;

import fl.controls.Button;

public class DVR extends MovieClip

{

private var nc:NetConnection;

private var ns:NetStream;

private var nsPlayer:NetStream;

private var vid:Video;

private var vidPlayer:Video;

private var cam:Camera;

private var mic:Microphone;

private var pauseBtn:Button;

private var rewindBtn:Button;

private var playBtn:Button;

private var seekBtn:Button;

private var dvrFlag:Boolean;

private var stamp:uint;

private var duration:uint;

private var currentDuration:uint;

private var seekVal;uint;

public function DVR()

{

nc = new NetConnection();

nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);

nc.connect("rtmp://localhost/dvr");

setupButtons();

dvrFlag = true;

}

private function onNetStatus(event:NetStatusEvent):void{

trace(event.info.code);

switch(event.info.code){

case "NetConnection.Connect.Success":

publishCamera();

displayPublishingVideo();

displayPlaybackVideo();

break;

case "NetStream.Play.Start":

trace("dvrFlag " + dvrFlag);

if(dvrFlag){

nsPlayer.seek(getSeekToLiveValue());

dvrFlag = false;

}

break;

}

}

private function onAsyncError(event:AsyncErrorEvent):void{

trace(event.text);

}

private function onClick(event:MouseEvent):void {

switch(event.currentTarget){

case rewindBtn:

nsPlayer.seek(nsPlayer.time - 5);

break;

case pauseBtn:

nsPlayer.pause();

break;

case playBtn:

nsPlayer.resume();

break;

case seekBtn:

nsPlayer.seek(getSeekToLiveValue());

break;

}

}

private function publishCamera() {

cam = Camera.getCamera();

mic = Microphone.getMicrophone();

ns = new NetStream(nc);

ns.client = this;

ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);

ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);

ns.attachCamera(cam);

ns.attachAudio(mic);

ns.publish("video", "record");

}

private function displayPublishingVideo():void {

vid = new Video(cam.width, cam.height);

vid.x = 10;

vid.y = 10;

vid.attachCamera(cam);

addChild(vid);

}

private function displayPlaybackVideo():void{

nsPlayer = new NetStream(nc);

nsPlayer.client = this;

nsPlayer.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);

nsPlayer.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);

nsPlayer.play("video", 0, -1);

vidPlayer = new Video(cam.width, cam.height);

vidPlayer.x = cam.width + 20;

vidPlayer.y = 10;

vidPlayer.attachNetStream(nsPlayer);

addChild(vidPlayer);

}

 

private function getSeekToLiveValue():uint{

currentDuration = Number((getTimer()-stamp)/1000) + duration;

trace("currentDuration: " + currentDuration);

seekVal = (currentDuration - nsPlayer.bufferTime) - 2;

trace("seekVal: " + seekVal);

return seekVal;

}

private function setupButtons():void {

rewindBtn = new Button();

pauseBtn = new Button();

playBtn = new Button();

seekBtn = new Button();

rewindBtn.width = 52;

pauseBtn.width = 52;

playBtn.width = 52;

seekBtn.width = 100;

rewindBtn.move(180,150);

pauseBtn.move(235,150);

playBtn.move(290,150);

seekBtn.move(345, 150);

rewindBtn.label = "Rew 5s";

pauseBtn.label = "Pause";

playBtn.label = "Play";

seekBtn.label = "Seek to Live";

rewindBtn.addEventListener(MouseEvent.CLICK, onClick);

pauseBtn.addEventListener(MouseEvent.CLICK, onClick);

playBtn.addEventListener(MouseEvent.CLICK, onClick);

seekBtn.addEventListener(MouseEvent.CLICK, onClick);

addChild(rewindBtn);

addChild(pauseBtn);

addChild(playBtn);

addChild(seekBtn);

}

 

public function onMetaData(info:Object):void {

trace("metadata:duration = " + info.duration);

stamp = getTimer();

trace("stamp: " + stamp);

duration = info.duration;

}

}

}

 DVR.as ファイルを保存します。

5    File New Flash FileActionScript 3.0)を選択しOK」をクリックします。

 ファイルを DVR.as ファイルと同じフォルダーに DVR.flaという名前で保存します。

 コンポーネントパネルを開き、Buttonをステージまでドラッグして削除します。

この操作により、ボタンがライブラリに追加されます。ボタンは実行時にアプリケーションに追加されます。

8    ファイル/パブリッシュ設定を選択しますFlash」タブをクリックしますScript Settings」をクリックし、DVR Document クラスとして入力します。チェックマークをクリックしてパスを検証します。

9    ファイルを保存し、Control Test Movie を選択してアプリケーションを実行します。

 

記録のサイズと時間の制限

Application.xml 設定ファイルのパラメーター、サーバーサイド ActionScript および Authorization プラグインを使用して、記録の最大サイズと時間を制限することができます。これらの値を設定してディスクスペースの使い過ぎを防ぎます。

以下は、Application.xml ファイルのパラメーターです。

 

XML 要素

説明

Application/StreamManager/Recording/MaxDuration

秒単位の最大記録時間。デフォルト値は -1 で、最大時間は適用されません。

Application/StreamManager/Recording/MaxDurationCap

秒単位の最大記録キャップ時間。デフォルト値は -1 で、最大時間のキャップは適用されません。

サーバーサイド Stream.record() メソッドはこの値より優先されません。Authorization  プラグインはこの値より優先されます。

Application/StreamManager/Recording/MaxSize

キロバイト単位の最大記録サイズ。デフォルト値は -1 で、最大サイズは適用されません。

Application/StreamManager/Recording/MaxSizeCap

キロバイト単位の最大記録キャップサイズ。デフォルト値は -1 で、最大サイズのキャップは適用されません。

サーバーサイド Stream.record() メソッドはこの値より優先されません。Authorization  プラグインはこの値より優先されます。

 

Application.xmlファイルでは、最大値の設定に加え、最大キャップ値を設定することもできます。サーバーサイドスクリプトはこれらのキャップより優先されません。CDNはこれらのキャップを使用して、クライアントが優先されない制限を設定することができます。

注意Authorization プラグインは、Application.xml ファイルに設定されたすべての値より優先されます。

サーバーサイド ActionScript で値を設定するにはStream.record() を呼び出しmaxDuration および maxSize パラメーターの値を渡します。次のコードは記録を 5 分に制限しMaxSizeCap の値まで)無制限の最大ファイルサイズを設定します。

 

s.record("record", 300, -1);

サーバーはMaxCapSizeおよび MaxCapDurationを上回る記録を切り捨てます。

 

関連項目

Authorization プラグインの開発

 

DVRアプリケーションのスケーリング

大規模なアプリケーションを構築するには、サーバーサイド NetConnectionクラスを使用して、複数のサーバーをまとめてチェーン化します。このシナリオでは、クライアントは接続したサーバー上にないストリームを要求することができます。

サーバーサイド ProxyStreamクラスを使用して、サーバーチェーンでストリームを探す検索メカニズムを作成します。

Vhost.xml設定ファイルに値を設定して、ストリームを格納するディスクキャッシュを設定することができます。

 

XML 要素

属性

説明

VirtualHost/Proxy/CacheDir

enabled

ディスクキャッシュが有効かどうかを判断します。

 

useAppDir

アプリケーションでキャッシュのサブディレクトリを分割するか指定します。

VirtualHost/Proxy/CacheDir/Path

 

ディスクキャッシュのルートディレクトリ。

VirtualHost/Proxy/CacheDir/MaxSize

 

ギガバイト単位の最大ディスクサイズ。デフォルト値は 32 です。

値が 0 の場合ディスクキャッシュが無効になります値が -1 の場

合、最大値は指定されません。

VirtualHost/Proxy/RequestTimeout

 

上流サーバーからの要求(メタデータではコンテンツなど)に対する応答を待つ、秒単位の最大時間。デフォルト値は 2 秒です。

サーバーに複数の仮想ホストがある場合は、仮想ホストをそれぞれのキャッシュディレクトリに指定します。

 

サーバーが CacheDir への書き込み中に中間またはエッジサーバーでディスクスペースを使い果たすとディスクへの書き込みに失敗した各セグメントの core.xx.log に次の警告メッセージが記録されます。I/O Failed on cached stream file C:\Program Files\Adobe\Adobe Media Server 5\cache\streams\00\proxyapp\<IP>\C\Program Files\Adobe\Adobe Media Server 5\applications\primaryapp\streams\_definst_\sample1_1500kbps.f4v\0000000000000000 duringwrite: 28 No space left on device.

 

 

Logging

DVRビデオ Playerで再生したストリームは、記録されたストリームとして再生されます。これらのストリームは、すべて記録されたストリームとして同じイベントをログファイルに記録します。

 

関連項目

動的ストリーミング

 

 

 

最終更新日 2013/9/30