NginxとFFmpegを利用したHTTP Live Streaming配信

HTTP Live Streaming(HLS)配信の基本的な手順をまとめます。

去年の記事 「NginxのHTTP Pseudo-Streamingを試す」 ではNginxの疑似ストリーミング配信モジュールを試してみましたが、機能不足のため実サービスで使うのは難しいです。そのためWebサーバでストリーミング配信を行いたい場合は今回紹介するHLSなどの利用が推奨されます。

HTTP Live Streaming(HLS)とは

Apple公式のドキュメントを読む方が理解は進むと思いますが、一応ここでも簡単に概要を。

HTTP Live Streaming (also known as HLS) is an HTTP-based media streaming communications protocol implemented by Apple Inc.

HTTP Live Streaming(HLS)はHTTPベースのストリーミング配信プロトコルでAppleが開発しました。iOS 3.0/Android 4.0以降を搭載しているデバイスで利用可能です。

http live streaming
HTTP Live Streamingのアーキテクチャ概要

アーキテクチャは上図のように”Server”/”Distribution”/”Client”の3つで構成されています。まず、”Server”コンポーネントで元素材をMPEG-2 TS形式にエンコードし、ストリームセグメンタと呼ばれるツールを使って細かく分割されたメディアセグメントファイル(一連の低容量TSファイル)とインデックスファイル(M3U8プレイリスト)を生成します。そのファイル群を”Distribution”コンポーネント(一般的なWebサーバ)にデプロイします。ここまでで配信準備は完了です。あとはHLSに対応している”Client”ソフトウェア(動画再生プレイヤー)が”Distribution”に設置されたインデックスファイルにアクセスすれば配信が開始されます。

インデックスファイル(M3U8プレイリスト)

HLSのインデックスファイルはM3U形式(MP3プレイリスト)を拡張したM3U8プレイリストです。簡単な例を以下に示します。これはストリーム全体が各10秒の3つのメディアファイルに分割されているプレイリストになります。

HLSはRTSPやMMSなどのストリーミング用プロトコルではなくHTTPを使うため、特別なストリーミングサーバを調達する必要がなく、ApacheやNginxなどの一般的なWebサーバで動画像を配信できるのでコスト面でも大きなメリットがあります。

HLS配信対応のよくあるシチュエーション

これまでPC向けにFlash Videoによる映像配信サービスを提供していたが、今の時代、スマートフォンやタブレットPCへも確実にリーチする必要がある。そのため、Flashを再生できないiOS/Android端末向けにはHTTP Live Streamingによる配信を行うことになった。

環境

CentOS 5.8 (x86_64, 仮想2コア) さくらのVPS 1Gプラン
GCC 4.4.7 (rpm: gcc44-4.4.7-1.el5/gcc44-c++-4.4.7-1.el5)
FFmpeg 1.1.1
Nginx 1.3.0
検証デバイス: iPhone 5(iOS 6.1), iPad 2(iOS 6.0), AQUOS PHONE ZETA SH-02E(Android 4.0.4)

CentOSのバージョンは5.x系としました。大規模配信インフラを運用している現場だと6.x系への移行はまだ難しいのでは、という判断からです。そう考えるとGCC4.4.7も新しいですけど、最適なバイナリを作るために一部のコンパイルオプションをどうしても使いたかったので4.4.7としました。また、動画像の配信を行うHTTPサーバはなんでも良いです。ここではNginxを使いますが、もちろんApacheでも問題なくHLS対応可能です。

FFmpegのインストール

MPEG-2 TSファイルへの変換やセグメント分割、プレイリスト(M3U8)作成にはFFmpegを利用しました。以前はオープンソースのストリームセグメンタ(segmenter)を併用することが多かったですが、現在ではFFmpeg単体でプレイリスト作成まで可能です。

yumでインストールする場合

yumでインストールする場合はRPMForgeリポジトリを追加しておきます。

バージョンが0.65と古いです。ストリームセグメンタも実装されていないので前述のセグメンタを別途インストールする必要があります。

ソースからコンパイルしてインストールする場合

最新安定版のFFmpegを使いたい場合はソースコードからコンパイルしてインストールします。せっかく自前でコンパイルするなら環境に合わせて最適なバイナリを作ると良いです。また、ディスクスペースは100MB以上必要になりますので注意してください。

最新版のFFmpegではストリームセグメンタが実装されているので、セグメンタの別途インストールは不要です。

上記オプションで作られたバイナリは libfaac を組み込んでいるため再配布はできません。
配布を考えないのであれば --march=native をつけてコンパイルして良いかと思います。これを付けると環境に合わせて最適なオプションに展開してくれます。ただし、古いGCCだとこのオプションは効かないので注意してください。ちなみに僕の環境(さくらのVPS 1Gプラン)では以下のように展開されるようです。

各種コーデック/コンテナライブラリの紹介

FFmpegに別途組み込んだコーデック/コンテナライブラリと各プロダクトへのリンクを載せておきます。基本的に ./configure make make install でインストールできます。
参考: Install FFMPEG & x264 on CentOS

x264 VideoLAN – x264, the best H.264/AVC encoder
Ogg Xiph.org: Downloads
Theora Xiph.org: Downloads
Vorbis Xiph.org: Downloads
LAME LAME MP3 Encoder :: Software Downloads
FAAC AudioCoding.com – Downloads
OpenCore AMR opencore-amr – Project Web Hosting – Open Source Software

FFmpegは大きなソフトウェアなのでスムーズにコンパイルできないこともよくあります。僕の環境で発生したエラーとその対応方法を載せておきます。

* 「yasm not found, use –disable-yasm for a crippled build」 とエラーが出る場合
–disable-yasm は使わずにちゃんとyasmをインストールしておきます。yumで入るものは古すぎてx264のビルドができないため、こちらもソースからコンパイルして入れます。また、yasmのビルドにはCMakeを使うので、もし入っていなければ予めインストールしておきます(最近はCMake対応しているプロダクトが増えてきましたね)。

* 「Unknown option “–enable-XXXX”.」とエラーが出る場合
古いバージョンのFFmpegで使われていたオプションを指定している可能性が高いです。configureオプションから外しておきます。

* 「ERROR: libx264 must be installed and version must be >= XXXX」とエラーが出る場合
x264のバージョンが古いです。もしyumでインストールしてしまっている場合は削除して、こちらもソースからコンパイルして入れます。

--extra-cflags オプションは各自環境に合わせて指定してください。

エンコード/プレイリスト作成

FFmpegを利用してHLS配信用に動画像ファイルのエンコードとプレイリストの作成を行います。

* MPEG-2 TS 1280×720(16:9) 映像: H.264/AVC [email protected] 24fps 256kbps, 音声:AAC 128kbps
* HLS: VOD, 10秒毎に分割指定 (segment_time), キャッシュ許可

x264のプリセットは以下のように品質重視の設定にしました。今回の検証デバイスは全てHigh Profileに対応してるのですが、ここではMain Profile Level 3.1で作っています。詳細なエンコードパラメータについてはこれから煮詰めていこうと思いますが、実際にはエンコードサーバの資源(CPU/RAMなど)や配信開始までの猶予時間、再生保障するデバイスなどいろいろ折り合いがあるでしょうし、なかなか難しいところです。。

* libx264-hls.ffpreset

生成されたM3U8プレイリストは以下のような内容になりました。FFmpegで指定できる分割時間は目安程度のものなんでしょうか? ここでは10秒指定にしたのですがTARGETDURATIONは15秒になりました。

Nginxの設定

mime.typesファイルにMIME Typeを以下のように2つ追加しておきます。

* mime.types

これだけ、簡単ですね。Apacheの場合も同様にMIME Typeの設定だけでOKです。

クライアントWebページの作成

HTML5 videoタグを利用してクライアントWebページ(プレイヤー)を作ります。videoタグのsrc属性にはプレイリストファイルを指定してください。

* /test/hls/index.html

再生試験

* 構成

あとは、/test/hls/index.html にアクセスしてプレイヤーの再生ボタンを押すだけです。無事にコンテンツが再生されたら成功。

* アクセスログ例
Nginxのアクセスログを確認。クライアントは約10秒ごとに対応したTSファイルをリクエストしていることがわかります(以下のログはNginxのデフォルトフォーマットのログをIPなど一部情報を削って載せています)。

今回使った検証デバイスは新しい(2013/02現在)デバイスということもあり、高品質な設定でエンコードしたHD動画でもスムーズに再生してくれました(^^ エンコードパラメータの調整には時間をかけましたが、再生確認までは特につまづくところもありませんでした。あとは暗号化によるコンテンツ保護や帯域制御などを試していきたいと思います。

HTTP Live Streaming Test
HTTP Live Streaming Test

余談 「ITU、次世代コーデックのHEVC/H.265を承認」

つい先日、次世代ビデオコーデックのHEVC(High Efficiency Video Coding)/H.265がITUに承認されました。今ではインターネット業界でのサービス開発はスマートフォン向けにシフトしましたが、低帯域のモバイルネットワークでも高品質の映像をユーザーに届けられるというのは素晴らしいと思います。以前AdobeがFlashは「プレミアムビデオとゲーム市場にフォーカスする」と言ってましたが(参照: Flashランタイムのロードマップ)、もし本当ならいち早く対応してほしいなぁと願うところです。

* 参考:
HTTP Live Streaming Resources – Apple Developer
Install FFMPEG & x264 on CentOS
[iPhone] HTTP Live Streaming
HTTP Live Streaming(Encrypt)

あわせて読む:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です