ADOBE® MEDIA SERVER 5.0.3
デベロッパーズガイド
![]() ![]() ![]() |
翻訳:株式会社サムライズ |
---|
注意
Adobe Media Server® バージョン 5についての本ドキュメントは第三者によって翻訳されたものであり、Adobe Systems Incorporated(アドビ システムズ社)は本翻訳物の正確性や完全性を査閲していません。
動的ストリーミング
注意:上記の動的ストリーミング API は、Flash Media Server 3.5 以降および Flash Player 10 以降でサポートされています。
Adobe Media Serverは、異なるビットレートでエンコードされているコンテンツストリームのバージョンを切り替えるためのコマンドを受信します。この機能により、メディアアプリケーションをネットワーク状況の変化に合わせることができます。また、処理能力が低く画面が小さいモバイルデバイスなどの、機能の異なるクライアントにアプリケーションを適合させることもできます。例えば、サーバーが高画質ビデオをクライアントアプリケーションにストリーミングする際に、ネットワーク状況が不十分である場合を考えてみます。この場合、サーバーは、低いビットレートの標準画質のストリームに切り替えることができます。ネットワーク状況が改善された場合、サーバーは HDビデオに戻すことができます。トランジションは、クライアントでシームレスに行われます。ネットワーク状況が変化した場合でも、クライアントへのビデオストリーミングは中断されません。
![]() |
サーバーは、QoS を維持するため、帯域幅の変更に応じたストリームを配信します。
最適なユーザー操作性のためには、動的ストリーミングでは次のことが必要です。
• コンテンツの異なるバージョンまたはコンテンツの一部が同期されている(ビデオのタイムラインが一致している必要がある)。
• 各コンテンツストリームのオーディオデータまたは他のデータは、そのストリーム内のビデオデータと同期されている必要がある。
サーバーは、記録されたコンテンツの 2 つの部分の間でトランジションを実装します。トランジションの実装は、ストリーミングされているコンテンツの種類に応じて 3 つの方法で行われます。
• ビデオのみのストリーム。トランジションは、ターゲットのタイムライン内の最も近いキーフレームで行われます。
•ビデオとオーディオのストリーム。トランジションは、ターゲットストリームのタイムライン内で最も近いキーフレームの直前にあるオーディオサンプルで行われます。開始ストリームとターゲットストリームのオーディオのタイムラインは一致している必要があります。一致していない場合、オーディオアーティファクトが作成されます。
• オーディオのみのストリーム。トランジションは、最も近いサンプルで行われます。
ライブビデオコンテンツ間でのトランジションの実装は、これよりも少し複雑です。サーバーが正確なトランジション位置を選択することができるように、ストリームには 3 ~ 5 ミリ秒以内の十分に近い位置で同期されたタイムスタンプが含まれている必要があります。
ActionScriptを使用したストリームの切り替え
ストリームのトランジションはサーバーで行われますが、ストリームを切り替えるコマンドおよび切り替えの決定は、クライアントアプリケーションから送信されます。アプリケーション開発者は、ダウンロードと再生の統計を監視したり、必要に応じて古いストリームを新しいストリームに切り替えたりするロジックを含めることができます。
ActionScript 3.0 NetStream.info プロパティと NetStreamInfo クラスを使用して、ダウンロードと再生の統計を監視します。NetStream.play2() メソッドと関連する NetStreamPlayOptions クラスを使用して、再生中のストリームを変更します。
NetStreamPlayOptions.offset プロパティは、ストリーム間の高速切り替えを行うために使用します。NetStreamPlayOptions.offset のデフォルト値である -1 を使用します。デフォルト値 -1 は、netstream.time + 3 の高速切り換え時間を示します。netstream.offset + 4 などのより大きい値を指定することもできますが、より小さい値は使用しないでください。
重要:デフォルト値よりも小さい値をNetStreamPlayOptions.offset に使用しないでください。
アプリケーション開発者は、トランジションによって発生した遅延を解消するのに十分な大きさの再生バッファーをクライアントアプリケーションが保持するようにする必要があります。遅延の原因になる 2 つの要素としては、ライブストリームのキーフレーム間隔と、切り換えられた 2つのストリームが同期されていないことが挙げられます。例えば、2 秒分のバッファーでは、3 秒のトランジションの遅延に対応することはできません。
重要:NetStream.bufferTime の値は、10秒以上に設定してください。
アドビは、NetStream クラスを拡張する DynamicStream という新しいクラスを開発しました。DynamicStream クラスには、帯域幅、バッファーの使用状況および削除されたフレームを監視するイベントリスナーが含まれています。クラスはこの情報に基づいてストリームを切り替えます。DynamicStream クラスを使用して動的ストリーミングを実装したり、DynamicStream クラスをリファレンスとして使用して、独自の動的ストリーミングアルゴリズムを記述したりすることができます。レガシーコードをマイグレートする場合は、DynamicStream クラスを使用することをお勧めします。
ActionScript クラスファイルとこれらのクラスのドキュメントは、www.adobe.com/go/fms_dynamicstreaming からダウンロードします。
注意:これらのクラスは ActionScript 3.0 ライブラリの一部ではありません。アドビが Adobe Media Server ユーザー向けに開発したカスタムクラスです。
動的ストリーミングを使用する状況の判断
次の条件のいくつかまたはすべてを満たすコンテンツに対して動的ストリーミングを使用することをお勧めします。
• 長時間のビデオ
• ファイルサイズの大きいビデオ
• HD ビデオ
• 全画面ビデオなど、解像度の大きいビデオ
• 企業ユーザーではなく、帯域幅の問題に影響されやすい自宅ユーザーなどのユーザーに配信されるコンテンツ
エンコードの推奨事項
ユーザーに最良の視聴環境を提供するために、コンテンツのエンコード時にこの DevNet の記事および Adobe MAX 2008の Will Law のプレゼンテーションの推奨事項に従ってください。
推奨事項の要約を次に示します。
• 最もスムーズな切り替えのためには、オーディオは AACでエンコードします。
• MP3オーディオ付きのストリームでは、オーディオのビットレートを一定に保ちます。
• 可能な場合、同じオーディオのサンプルレートを使用します。
• 低帯域幅の使用向けにストリームをエンコードするには、1 チャンネル(モノラル)でオーディオをエンコードします。
• ストリームのビデオのタイムラインが関連付けられ、互換性があることを確認します。
• すべてのストリームで同じコーデックと同じオーディオビットレートを使用します。そうしない場合、ストリームの切り替え時にポンという小さな音が聞こえることがあります。
• 必須ではありませんが、コンテンツのバージョンが異なってもキーフレーム間隔(キーフレーム頻度)とフレームレート(fps)が一致していることが推奨されます。キーフレーム間隔を短くすると、サーバーはストリームの切り替えを頻繁に行うことになり、クライアントはより小さい再生バッファーを持つことになります。
次の表は、1 つのコンテンツのエンコードに使用できる様々なビットレートを示しています。
ビットレート |
150 Kbps |
300 Kbps |
500 Kbps |
700 Kbps |
1.5 Mbps(完全 Web HD) |
どの時点でストリームを切り替えるかは、バッファー長、ダウンロードされたバイト数、ドロップされたフレーム数など、さまざまな要因を考慮して決定できます。adobe.com からダウンロードできる DynamicStream クラスと DynamicStreamItem クラスは、これらの要因を考慮して構築されており、動的なストリーミングアプリケーションに必要なロジックが含まれています。
アプリケーションロジックを独自に開発する場合は、ストリーミングビデオに関する次の戦略が役立ちます。
1 初回の再生時には、画面またはデバイスに適する最小のビットレートを選択します。例えば、標準のコンピューターのWebブラウザー上でビデオを再生する場合、初回の再生に適するストリームは 300 kbps、320 x 240です。
2 再生を即座に開始するには、小さい値のバッファー長を選択します。
3 再生が開始されたら、バッファー長を 10秒以上に増やします。
4 デフォルト値よりも小さい値を NetStreamPlayOptions.offset に使用しないでください。
5 クライアント帯域幅(NetStream.info.maxBytesPerSecond)とバッファーサイズ(NetStream.bufferLength)の使用について監視を開始します。
現在の帯域幅が十分である場合は、バッファーがすぐに満杯になり、安定します。帯域幅が不足し始めると、バッファーが空になり始めます。
6 クライアントの帯域幅がストリームの必要条件を超え、バッファーが増えるか満杯になると、解像度の高いコンテンツに切り替えることができます。
切り替える前に、クライアントの帯域幅が十分であることを確認してください。クライアントの帯域幅とバッファー長に加えて、ドロップされたフレーム数(NetStream.info.droppedFrames)など、その他の統計を確認することもできます。
7 解像度の高いコンテンツにそれぞれ移行した場合は、タイマーを使用して、5 秒単位でバッファーの監視を続行します。バッファーが空になり始めた場合は、解像度の低いコンテンツに切り替え、バッファーを監視する頻度を増やします(2秒単位など)。
8 帯域幅が十分でバッファーが増えるか満杯になっているときに、アップグレードを続けます。最良のユーザー操作性のためには、慎重に設定を行う必要があります。アップグレードは、報告された帯域幅が必要なストリーム条件を十分に超えている場合のみ行います。
関連項目
ActionScript Guide to Dynamic Streaming
クライアントの帯域幅の確認
ストリームの切り替えが必要な状況を判断するために、クライアントの帯域幅を監視します。クライアントの帯域幅が適切な場合、クライアントアプリケーションはサーバーに対して、より高いビデオのビットレートに切り替えるよう要求することができます。クライアントの帯域幅が小さい場合、クライアントアプリケーションはサーバーに対して、より低いビットレートに切り替えるよう要求することができます。
帯域幅を測定するには、NetStream.info プロパティを使用します。NetStream.info の呼び出しによって、受信するストリームのオーディオ、ビデオおよびデータバイトのレートを反映したプロパティと共に NetStreamInfoオブジェクトが返されます。受信するデータレートに関する情報によって、帯域幅の品質を推測することができます。
具体的には、NetStreamInfo クラス(ActionScript 2.0 の場合は NetStream.getInfo() によって返されたオブジェクト)の*byteCount および *bytesPerSecond プロパティを使用します。これらのプロパティの詳細については、『ActionScriptLanguage References』を参照してください。
クライアントの帯域幅を測定するための 1 つの方法は、NetStream.Buffer.Full ステータスのイベントを受信した際に、NetStreamInfo.byteCount プロパティを一定時間測定して一秒あたりのバイト値を取得することです。この値は、使用可能な最大帯域幅に近似したものになります。次に、使用可能な帯域幅と使用可能なビットレートを比較し、必要に応じてトランジションを実装します。
注意:byteCount プロパティは、サーバーの Access ログにある sc-stream-bytes と同じ値は返しません。byteCount プロパティは、ユーザーがストリーム切り替えのタイミングを判断できるデータを提供するQoS(クオリティオブサービス)です。byteCount プロパティは請求書には使用しないでください。
削除されたフレームの確認
バッファーの監視に加えて、削除されたフレームを確認します。削除されたフレームが多すぎる場合は、より低いビットレートのストリームに切り替えます。NetStreamInfo.droppedFrames プロパティを使用します。この読み取り専用のプロパティは数値であり、現在の NetStream再生セッションでドロップされたビデオフレームの数を返します。
削除されたフレームのレートを決定する方法の 1 つは次のとおりです。タイマーを使用して、削除されたフレームの現在の値と前の値との違いを計算します。その違いを変数 droppedFPSに格納します。現在の 1秒あたりの受信フレーム数を、別の変数 currentFPSで監視します。droppedFPSが currentFPS値の 20%を超えている場合、より低いビットレートに切り替えます。
同じコンテンツを異なるビットレートでエンコードするストリーム間のトランジションを要求する場合、クライアントアプリケーションは NetStream.play2() メソッドを使用します。このメソッドでは、NetStreamPlayOptions オブジェクトをパラメーターとして使用します。このオブジェクトにはサーバーがストリームを切り替える方法を指定します。
注意:NetStream.play2() メソッドは NetStream.play() メソッドを拡張したものです。
NetStreamPlayOptions オブジェクトには次のプロパティが含まれています。
プロパティ |
説明 |
oldStreamName |
現在再生されているストリームの名前(古いストリーム)。 |
streamName |
再生する新しいストリームの名前(ストリームの切り替え先)。 |
start |
再生する新しいストリームの開始時間。 ほとんどの動的ストリーミングでは、デフォルト値の -2 が最適です。この値によって、streamName で指定されたライブストリームを再生するようにアプリケーションに通知されます。もし、その名前のライブストリームが見つからない場合は、streamName で指定された記録ストリームが再生されます。ライブストリームも記録ストリームも見つからない場合は、だれもパブリッシュしていなくても、streamName という名前のライブストリームを開きます。そのストリーム上でだれかがパブリッシュを開始すると、アプリケーションがそれを受信します。 |
プロパティ |
説明 |
len |
再生の継続時間(長さ)。 ほとんどの動的ストリーミングでは、デフォルト値の -1 が最適です。この値は、ライブストリームが使用できなくなるまで、または記録ストリームが終了するまで、アプリケーションがそれらを再生することを示します。 |
transition |
トランジションのモード。 使用可能な値は、NetStreamPlayTransition クラスの定数です。同じコンテンツを異なるビットレートで切り換えるために最適な値は SWITCH です。その他のモードの詳細については、『ActionScript 3.0 Language Reference』の「NetStreamPlayTransition クラス」を参照してください。 |
次のコード例では、SWITCHオプションを使用して、より高いビットレートストリームに切り替えるようサーバーに通知します。この例では、新しいストリームを次の論理キーフレームでサーバーに切り替えるよう通知する oldStreamNameの値を渡しません。この方法によって、最もスムーズなビデオ環境が提供されます(再生リストを使用する場合は、 oldStreamNameに値を渡します。「再生リスト内のストリームのスワップ」を参照)。動的なストリームをビデオおよびオーディオの記録ストリームに切り替える際、ほとんどの場合は、例にあるようにデフォルト値の start および len を保持することができます。
クライアントがトランジションを要求した場合、サーバーは NetStatusEvent.NET_STATUS イベントをコードNetStream.Play.Transitionと共に送信します(ActionScript 2.0では、onStatusイベントを同じコードと共に送信します)。サーバーはこのイベントをクライアントに直ちに送信します。これは、操作が正常に終了したことを示します。新しいストリームの最初のフレームがレンダリングされると、サーバーは onPlayStatusメッセージをコード NetStream.Play.TransitionComplete と共に送信します。このイベントによって、クライアントはいつ新しいストリームのレンダリングが開始されるのかを正確に知ることができます。
Flash Playerが NetStream.Play.Transitionメッセージを送信したあとでクライアントが検出を行うとストリームは正常に切り替わりますが、Flash Playerは NetStream.Play.TransitionCompleteメッセージを送信しません。Playerは、検出のあとで新しい状態に入り、古い状態のステータスイベントを送信することができないので、メッセージを送信しません。Player は、onMetaData()などの他のコールバックメソッドでも同じように動作します。
次の例では、ストリームのトランジションを処理します。
var stream:NetStream = new NetStream(connection);
stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
stream.client = new CustomClient();
var video:Video = new Video();
video.attachNetStream(stream);
stream.play("streamA_150kbps");
addChild(video);
...
//Set up the transition to 700 kpbs content
var param:NetStreamPlayOptions = new NetStreamPlayOptions();
param.streamName = streamA_700kpbs;
param.transition = NetStreamPlayTransitions.SWITCH;
stream.play2(param);
//Handler function for the Transition event
class CustomClient{
public function onPlayStatus(info:Object):void {
trace("switch time: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
}
NetStream.Play.Transition ステータスイベントには、reason フィールドが含まれます。トランジション要求の状態についての追加情報を取得するには、このフィールドを使用します。通常、reason フィールドには "NetStream.Transition.Success" というコードが含まれ、トランジション要求が成功して正常に処理されたことを示します。ライブストリーム間を切り替えるとき、サーバーが 2 つのストリームの間の同期ポイントを検出できない場合があります。このような場合、サーバーは任意のフレームに対して強制的にトランジションを実行し、reasonフィールドにコード "NetStream.Transition.Forced"を設定します。このような状況は、以下のような場合に発生する可能性があります。
• 切り替え対象の 2 つのストリームのタイムラインが同じではないため、サーバーが切り替えを実行する時点を選択できません。
•新しいストリームのキーフレーム間隔が、クライアントの再生バッファーより長いです。再生バッファーの長さは、サーバーがトランジションを待機する時間の上限です。サーバーからキーフレームが見えないため、サーバーは切り替えのフレームを選択できません。
• ライブストリームのライブキュー遅延が、クライアントの再生バッファーより長いです。長いキーフレーム間隔と似た遅延が発生します。
Adobe Media Server は、ストリームのトランジションの一部がクライアントにレンダリングされる際にNetStream.Play.TransitionComplete ステータスのイベントを送信します。新しいストリームに切り替えられると、NetStream.Play.TransitionComplete ステータスのイベントに続いて、新しいストリームの onMetadata メッセージが直ちに送信されます。メタデータをキャプチャする前に TransitionComplete イベントをリッスンします。ストリームがライブである場合、ストリームに関連付けられているすべてのデータキーフレームが送信されます。
バッファリングは、ビデオの再生中の帯域幅の変動を管理します。
ユーザーが最良の機能を利用できるようにするには、最初はバッファーを小さい値に設定します。値を小さくすると、ストリームの再生が比較的早く開始します。再生が開始した場合は、バッファーを大きい値に設定します。値を大きくすることで、ネットワークのノイズまたは中断の有無に関わらず、ストリームがよりスムーズに再生されます。
最良の視聴環境を作成してユーザーに提供するには、ビデオの進行状況を監視し、ビデオのダウンロードするときのバッファーを管理します。最良の再生環境を提供するには、それぞれのユーザーごとに異なるバッファーサイズを設定することを検討します。これを行う方法の 1 つとして、クライアントの帯域幅を測定し、この帯域幅に基づいて初期バッファーサイズを設定する方法があります。
ストリームを切り替える状況を判断するために、クライアントのバッファーサイズを監視します。クライアントの帯域幅が適切な場合、バッファー内のデータ量が増加するか、バッファーがいっぱいになります。クライアントはサーバーに対してより高いビデオのビットレートに切り替えるよう要求することができます。クライアントの帯域幅が小さい場合、バッファー内のデータ量が減少するか、バッファーが空になります。クライアントはサーバーに対してより低いビットレートに切り替えるよう要求することができます。
NetStream.info() を呼び出し、ストリームの現在の統計を反映した次のプロパティと共に NetStreamInfoObject を取得します。バッファーを制御するプロパティは BufferLength および BufferByteLength プロパティです。これらのプロパティについて詳しくは、「ActionScript 3.0 リファレンスガイド」を参照してください。
また、ストリームの再生中に、netStatusイベントを検出して処理することもできます。例えば、バッファーがいっぱいになったとき、netStatusイベントは NetStream.Buffer.Fullの info.code値を返します。バッファーが空になったときは、NetStream.Buffer.Emptyの code値によって別のイベントが発生します。データのストリーミングが完了すると、NetStream.Buffer.Flush イベントがディスパッチされます。これらのイベントをリッスンすることによって、バッファーが空になった場合バッファーサイズを小さくし、バッファーがいっぱいになった場合バッファーサイズを大きくすることができます。
注意:Flash Player 9 アップデート 3 以降では、ストリームが一時停止されたときにバッファーがクリアされなくなりました。この機能により、視聴者が間を空けずに再生を再開できるようになりました。コードで NetStream.pause() を使用してデータをバッファーすることができます。例えば、閲覧者がコマーシャルを見ている間にデータをバッファーし、メインのビデオが開始されたときにストリームの一時停止を解除することができます。詳細については、「NetStream.pause()」を参照してください。
バッファー時間の設定
バッファー時間を秒単位で変更するには、NetStream.bufferTime プロパティを設定します。
ns.bufferTime(10);
バッファーに適するサイズは、ユーザーの帯域幅によって異なります。次に示す値は推奨値です。接続が高速な場合は、5~ 10秒が初期バッファーサイズとして適切な値です。より低速な接続では、10秒が適切な初期バッファーサイズです。再生の開始後は、バッファーサイズとして適切な値は30~ 60秒です。
バッファーイベントの処理
この例では、バッファーイベントを検出して、イベントの発生に合わせてバッファー時間を動的に調整する方法を示しています。ここでコードの主要部分を示しています。完全なサンプルについては、Buffer.asサンプルファイルを参照してください。
1 メインクライアントクラスのコンストラクター関数内で、NetConnection オブジェクトを作成し、サーバーに接続します(Adobe Media Server のルートインストールディレクトリ内の documentation/samples/Buffer ディレクトリにある Buffer.as を参照してください)。
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
nc.connect("rtmp://localhost/Buffer");
2 netStatusイベントハンドラーを記述します。成功したか、失敗したかおよびバッファーがいっぱいになったときおよびバッファーが空になったときのイベントを確認し、それに応じてバッファーサイズを変更します。
private function netStatusHandler(event:NetStatusEvent):void {
switch (event.info.code) {
case "NetConnection.Connect.Success":
trace("The connection was successful");
connectStream(nc);
break;
case "NetConnection.Connect.Failed":
trace("The connection failed");
break;
case "NetConnection.Connect.Rejected":
trace("The connection was rejected");
break;
case "NetStream.Buffer.Full":
ns.bufferTime = 30;
trace("Expanded buffer to 30");
break;
case "NetStream.Buffer.Empty":
ns.bufferTime = 8;
trace("Reduced buffer to 8");
break;
}
}
3 ストリームを再生するためのカスタムメソッドを記述します。このメソッドの中で、初期のバッファー時間を設定します。たとえば、2 秒に設定します。
private function connectStream(nc:NetConnection):void {
ns:NetStream = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
ns.client = new CustomClient();
video = new Video();
video.attachNetStream(ns);
ns.play( "bikes", 0 );
ns.bufferTime = 8;
trace("Set an initial buffer time of 8 seconds");
addChild(video);
}
4 onMetaData() イベントハンドラーおよび onPlayStatus() イベントハンドラーを作成します。
public function onMetaData(info:Object):void {
trace("Metadata: duration=" + info.duration + "width=" + info.width + " height=" + info.height + "framerate=" + info.framerate);
}
public function onPlayStatus(info:Object):void {
switch (info.code) {
case "NetStream.Play.Complete":
trace("The stream has completed");
break;
}
}
これらのイベントハンドラーは、NetStream.play() を呼び出すときに必要になります。
アクセスログでストリームのイベントを追跡できます。ログを使用すると、トランジションがある単一のストリーム再生と、ストリームの複数の再生や異なるストリームの再生を区別できます。単一のコンテンツストリームのトランジションが行われると、サーバーはトランジションとしてストリームのステータスを追跡します。サーバーは、元のストリームに対して stopイベントを、新しいストリームに対して playイベントをログに記録します。通常の stopイベントおよび playイベント(トランジションを使用しない stopまたは play)のステータスコードは 200です。ストリームのトランジションのステータスコードは 210です。アクセスログには、次の追加情報が提供されます。
フィールド |
説明 |
x-sid |
ストリームの ID。この ID は、そのクライアントセッションでは一意ですが、セッション間では一意ではありません。 |
x-trans-sname |
サーバーがトランジションしたストリームの名前(元のストリーム) |
x-trans-sname-query |
サーバーがトランジションしたストリームのストリーム名のクエリー部分 |
x-trans-file-ext |
サーバーがトランジションしたストリームのストリーム名のファイル名拡張子部分 |
ログプロセッサーを使用する場合、ステータスコードと x-sid値の両方が参照されていることを確認してください。単一の論理ストリーム上で行われたトランジションを識別するには両方の値を参照します。通常のストリームでは、ストリームのトランジションは再生 /停止のペアで行われます。同じストリーム上の 210のステータスコードの playイベントと、それに続く 210のステータスコードの stopイベントを識別することで、ログプロセッサーはストリームのトランジションを追跡できます。ステータスコードを参照することで、ログプロセッサーはトランジションのない playイベントまたは stopイベントからのストリームのトランジションを区別することができます。
最終更新日 2013/9/30