まめ畑

ゆるゆると書いていきます

Adobe HTTP Dynamic Streamingを使ってみた

先日、Adobeから「Adobe HTTP Dynamic Streaming」が公開されたので、使ってみました。
これは、動画ファイルの配信や従来はRTMPなどを使用していたLive配信をHTTPで配信出来るようにするもので、HTTPを使用するため、80番ポートを開けておくだけでよく運用も楽になり、配信されるフラグメントファイルも従来のキャッシュサーバにキャッシュ出来ます。
また、Apacheやキャッシュサーバを増やすだけでスケールが可能になります。
動画データを全て読み込むのではなく、順次フラグメントファイルを要求するので、フラグメントファイルの転送が遅いと再生が止まってしまいます。シーク時にはシーク先の時間に該当するフラグメントファイルから読込みをするだけなので、シーク後すぐに再生が開始されます。
クライアントとしては、Flash Player10.1から対応していて、同時に公開された、Open Source Media Framework(OSMF)を使用することで簡単に動画Playerを作成する事が可能になりました。
Adobe Flash Accessを使用した動画のライセンス管理も簡単に行える構造になっています。

仕組み

HTTP Dynamic Streamingを利用するにはApache2.2が必要です
ApacheにHTTP Origin Moduleを導入するだけで利用可能になります
しかし、動画をそのまま配置するだけではダメで、同時に配布されているFile Packagerを使用して変換する必要があります
対応動画形式は

  • F4V/MP4 compatible files
  • FLV

です

File Packagerは動画ファイルから

  • f4f 動画ファイル本体。内部はセグメントに分割されている
  • f4m マニフェストファイル。この中に動画情報が格納されており、可変ビットレートやライセンス管理の情報も記述される
  • f4x インデックスファイル。Playerから要求される各フラグメントファイルのf4fファイル中でのインデックスを持っている

以上の3つのファイルを生成します


サーバでの処理の流れは

  1. Playerにはマニフェストファイルのアドレスを渡します

http://www.hoge.com/fuga.f4m

  1. ApacheはOrigin Moduleに処理を渡して、Origin ModuleからPlayerにマニフェストファイルが返される
  2. Playerはマニフェストファイル中のBootstrapセクションを参照してタイムコード(segment#/fragment#)に変換する
  3. Playerが「http://www.hoge.com/media/fugaSeg1-Frag1」のようなアドレスを生成しリクエストを投げます
  4. ApacheはOrigin Moduleに処理を渡し、Origin Moduleはセグメント番号とフラグメント番号からf4fファイルのビットオフセットを算出し指定のフラグメントをPlayerに返します

このような流れで動画が再生されます
シークバーを動かした時は、シーク先の時間に対応するフラグメントが要求されるのでキャッシュサーバにキャッシュがあればOrigin Moduleに処理が渡らずキャッシュサーバ中のキャッシュを返すだけです


可変ビットレートな動画使用する時は、動画の変換時に指定します

導入してみる

http://www.adobe.com/jp/products/httpdynamicstreaming/のリンクから

  • HTTP Origin Module
  • File Packager
  • OSMFのサンプル

をダウンロードしておきます
Windows用とLinux用があるので使用する環境にあったものをダウンロードしてください。今回はCentOS5.5で試しています

  • HTTP Origin Moduleの導入
    • ダウンロードしたファイルを解凍し、Apacheのmodulesディレクトリに必要なファイルをコピーします
unzip adobe_f4f_apache_module100_linux_x86.zip
cd /adobe_f4f_apache_module100_linux_x86/adobe/f4fmodule
cp libF4V.so /etc/httpd/modules 
cp libexpat.so.1 /etc/httpd/modules 
cp mod_f4fhttp.so /etc/httpd/modules
    • 配信用ファイルを配置するディレクトリを作成
mkdir -p /var/www/vod
    • configファイルを作成

今回はhttp://www.piyo.com/vod/***でアクセスされた場合にOrigin Moduleに処理を渡します
Live配信用の設定項目などはhttp://help.adobe.com/en_US/HTTPStreaming/1.0/Using/WS7b362c044b7dd076-735e76121260080a90e-7ffc.html#WS8ec1569f90918c1b-457ae32d1282caecc18-8000を参照してください

vim /etc/httpd/conf.d/dstreaming.conf
LoadModule f4fhttp_module modules/mod_f4fhttp.so

<Location /vod>
    HttpStreamingEnabled true
    HttpStreamingContentPath "/var/www/vod"
</Location>
  • 動画を変換
    • Packagerを解凍します
unzip adobe_f4fpackager100_linux_x86.zip
cd adobe_f4fpackager100_linux_x86/adobe/f4fpackager
    • 動画を変換します

リファレンス:
Adobe HTTP Dynamic Streaming * File Packager reference
Adobe HTTP Dynamic Streaming * Packaging on-demand media

./f4fpackager --input-file 変換元動画 --output-file 変換後動画情報を書出すディレクトリ

これだけです。


可変ビットレート対応にするには

f4fpackager --input-file=sample1_150kbps.f4v --bitrate=150
f4fpackager --input-file=sample1_700kbps.f4v --manifest-file=sample1_150kbps.f4m --bitrate=700
f4fpackager --input-file=sample1_1500kbps.f4v --manifest-file=sample1_700kbps.f4m --bitrate=1500

の様にビットレートの低い動画から変換を行い、変換時に生成されたコンフィグファイルを使用して次の動画を変換していきます
Playerに指定するマニフェストファイルは一番ビットレートの高い動画の物を指定します。このマニフェストファイルには全てのビットレートの情報が入っているためです

    • 生成されたファイルを先程していしたパスに配置します

OSMFサンプルプレイヤーで再生してみる

OSFMPlayer_zeri2.zipを解凍して、配置してブラウザからアクセスします
取り出しボタンを押すとアドレスが指定出来るので、マニフェストファイルのアドレスを指定すれば再生出来ます

http://www.hoge.com/OSMFPlayer.html?url=http://www.hoge.com/vod/piyo.f4m

とURLで再生ファイルを指定出来ます
Apacheのログを見ると

/vod/hogeSeg1-Frag19

のようなアドレスでフラグメント毎にリクエストが来ている様子が分かります


Nginxでキャッシュしてみた

シークする度にオフセット計算して、指定位置のファイルを生成して送り返す処理をいちいちやるのはなんなのでフラグメントファイルをキャッシュします
今回は、nginx0.7.67を使用しました

  • インストール
wget http://sysoev.ru/nginx/nginx-0.7.67.tar.gz
tar xzvf nginx-0.7.67.tar.gz
cd nginx-0.7.67
./configure --without-http_rewrite_module --without-http_fastcgi_module
make
make install
  • 設定
    • 今回は同一ホストでApcheとngixを動作させ、nginxを80番ポートで動かすので、Apacheのポートを80番意外にします(今回は81)
    • キャッシュ置き場は「/tmp/nginx/cache」
worker_processes  4;

error_log  logs/error.log;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    access_log  logs/access.log;

    sendfile        on;

    keepalive_timeout  0;
    gzip  on;

    proxy_cache_path /tmp/nginx/cache levels=1:2 keys_zone=STATIC:10m max_size=1g inactive=24h;

    server {
        listen       80;
        server_name  cache.hoge.com
        location / {
            proxy_pass http://127.0.0.1:81;
            proxy_set_header Host $host;
            proxy_cache STATIC;
            proxy_cache_valid 200 1d;
            proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

cache関係のディレクティブの解説は
HttpProxyModule
を参照してください

    • confファイルの確認
/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
  • nginx起動
/usr/local/nginx/sbin/nginx

後はログを見ると、初回アクセスのみApacheにアクセスがいき、その後の同一フラグメントへのアクセスはキャッシュから返されている事がわかります


動画へのアクセス急増時にはキャッシュサーバを増やすだけで対応が可能です


メタデータが気になったから

マニフェストファイルのメタデータが気になったので見てみた

<metadata>
  AgAKb25NZXRhRGF0YQgAAAAAAAhkdXJhdGlvbgBAdTtHrhR64QAMYXVkaW9jb2RlY2lkAgAEbXA0YQAFd2lkdGgAQI
  4AAAAAAAAABmhlaWdodABAhoAAAAAAAAAMdmlkZW9jb2RlY2lkAgAEYXZjMQAKYXZjcHJvZmlsZQBAWQAAAAAAAAAI
  YXZjbGV2ZWwAQD8AAAAAAAAABmFhY2FvdAAAAAAAAAAAAAAPYXVkaW9zYW1wbGVyYXRlAEDliIAAAAAAAA1hdWRpb2
  NoYW5uZWxzAEAAAAAAAAAAAA52aWRlb2ZyYW1lcmF0ZQBAPerJYubiRgAJdHJhY2tpbmZvCgAAAAIDAAZsZW5ndGgA
  QWySeGAAAAAACXRpbWVzY2FsZQBA5YiAAAAAAAAIbGFuZ3VhZ2UCAAN1bmQAAAkDAAZsZW5ndGgAQWNiYUAAAAAACX
  RpbWVzY2FsZQBA3TdAAAAAAAAIbGFuZ3VhZ2UCAAN1bmQAAAkAB2N1c3RkZWYKAAAAAAAACQ==
</metadata>


Base64でデコード

\002\000\nonMetaData\b\000\000\000\000\000\bduration\000@u;G\256\024z\341\000
\faudiocodecid\002\000\004mp4a\000\005width\000@\216\000\000\000\000\000\000
\000\006height\000@\206\200\000\000\000\000\000\000\fvideocodecid\002\000\004avc1\000
\navcprofile\000@Y\000\000\000\000\000\000\000\bavclevel\000@?\000\000\000\000\000
\000\000\006aacaot\000\000\000\000\000\000\000\000\000\000\017audiosamplerate\000@
\345\210\200\000\000\000\000\000\raudiochannels\000@\000\000\000\000\000\000\000\000
\016videoframerate\000@=\352\311b\346\342F\000\ttrackinfo\n\000\000\000\002\003\000
\006length\000Al\222x`\000\000\000\000\ttimescale\000@\345\210\200\000\000\000\000
\000\blanguage\002\000\003und\000\000\t\003\000\006length\000Acba@\000\000\000\000
\ttimescale\000@\3357@\000\000\000\000\000\blanguage\002\000\003und\000\000\t\000
\acustdeb\200\000\000\000\000\000\002

こんな感じでした