FFmpegでHTML5 readyな動画ファイルを作成 (MP4, WebM)

# 下準備 (OS Xだけですみません...)

HomebrewでもFFmpegを導入できますが、ここではMacPortsでの手順を紹介します。Homebrewの場合、FFmpegのインストールに加えて別途各種依存ライブラリのインストールが必要となりますのでご注意下さい。([[参考]](http://kujirahand.com/blog/index.php?Mac+OS+XでFFmpegのインストールとWebM動画の作り方))

## MacPorts

[MacPortsのサイト](http://www.macports.org)よりダウンロードしてインストールする。

## FFmpeg

ターミナルでMacPortsを使ってビルドとインストールを行います。(よって、それなりの時間が必要です。)

```bash
$ sudo port install ffmpeg +nonfree
```

`+nonfree`はAACのエンコードに必要(libfaac)。

ちなみに、(HTML5では使わないがAndroid端末等で)AMR等の一部のコーデックに対応するには、

```bash
$ sudo port install ffmpeg +gpl3+nonfree
```

とする必要があります。

FFmpegのビルドとインストールの前に、関連するライブラリ(libvpx, libvorbis, x264, 等)もビルド・インストールされます。なお、デフォルトではX11(X.Org)もインストールされますので、これを避けたい場合は、`-x11`オプションを付与するとよいでしょう。

```bash
$ sudo port install ffmpeg +gpl3+nonfree-x11
```

# MP4のエンコード

## 画面サイズもフレームレートも変えない場合

```bash
$ ffmpeg -i [入力ファイル名] -vcodec libx264 -vb [動画のビットレート] -acodec libfaac -ac 2 -ab [音声のビットレート] [出力ファイル名.mp4]
```

ビットレートはビット/秒で指定しますが、`k`(キロ)や`M`(メガ)を単位として指定できます(例: `4M`, `128k`)。また、サンプリングレートを指定したい場合は`-ar [レート]`を追加します(ここでも`k`(キロ)が使えます)。

`-ac`オプションでは音声のチャンネル数を指定します。1ならモノラル、2ならステレオ。入力ファイルが5.1chサラウンド等で収録されている場合は明示的に`-ac 2`としてステレオミックスされるようにします。

## 画面サイズやフレームレートを変更する場合

```bash
$ ffmpeg -i [入力ファイル名] -vcodec libx264 -vb [動画のビットレート] -r [フレームレート] -s [画面サイズ] -acodec libfaac -ac 2 -ab [音声のビットレート] [出力ファイル名.mp4]
```

画面サイズは`[横画素数]x[縦画素数]`で指定します(例: `1280x720`)。

# WebMのエンコード

```bash
$ ffmpeg -i [入力ファイル名] -vcodec libvpx -vb [動画のビットレート] -acodec libvorbis -ac 2 -ab [音声のビットレート] [出力ファイル名.webm]
```

フレームレート、画面サイズ等、各種オプションは基本的にMP4と同じなので省略。

# HTTPストリーミング対応のフォーマットに変換

Media Source ExtensionsやMPEG-DASHを利用した、セグメント単位のHTTPストリーミングに対応したフォーマットになるようにエンコードする方法を示します。

## WebMの場合

元々、Clusterに区切ってエンコードする方式のため、特別な配慮は不要ですが、セグメント区切り(Cluster)の長さを調整する方法を示します。

```bash
$ ffmpeg -i [入力ファイル名] -vcodec libvpx -vb [動画のビットレート] -r [フレームレート] -keyint_min [キーフレーム間隔] -g [キーフレーム間隔] -acodec libvorbis -ac 2 -ab [音声のビットレート] [出力ファイル名.webm]
```

上記において、[キーフレーム間隔] = [フレームレート] × Clusterの時間長(秒) となるようにキーフレーム間隔を調整します(例えば、フレームレートが30fpsでClusterの時間長を5秒にしたい場合は、キーフレーム間隔は150)。

詳細については、Mozillaの[DASH Adaptive Streaming for HTML 5 Video](https://developer.mozilla.org/en-US/docs/Web/HTML/DASH_Adaptive_Streaming_for_HTML_5_Video)の記事が参考になります。

Media Source Extensionsで再生する際にメディアセグメント分割を行う等、ファイルフォーマット解析が必要となる場合は、[Media Source Extensionsを使ってみた (WebM編)](http://qiita.com/tomoyukilabs/items/57ba8a982ab372611669)を参考にして下さい。

## MP4の場合

MP4の場合は、FFmpegに加えて、[MP4Box](http://gpac.wp.mines-telecom.fr/mp4box/)というツールが追加で必要になります。

```bash
$ svn co svn://svn.code.sf.net/p/gpac/code/trunk/gpac gpac
$ cd gpac
$ ./configure
$ make
$ sudo make install
```

FFmpegでのエンコードは次のようにします。

```bash
$ ffmpeg -i [入力ファイル名] -vcodec libx264 -vb [動画のビットレート] -r [フレームレート] -x264opts no-scenecut -g [キーフレーム間隔] -acodec libfaac -ac 2 -ab [音声のビットレート] -frag_duration [フラグメントの時間長] -movflags frag_keyframe+empty_moov [出力ファイル名.mp4]
```

セグメント区切り(フラグメント)の時間長を指定する`-frag_duration`オプションは、**マイクロ秒**で指定する点に注意が必要です(例えば、5秒なら5000000)。

動画(H.264)のエンコードでは、デフォルトでは(エンコーダであるx264が)キーフレームの位置をシーン切り替えなどの特徴分析を用いて動的に調整するようになっていますので、`-x264opts no-scenecut`を指定してキーフレーム間隔を固定にします。

その上で、[フラグメントの時間長] × [フレームレート] ÷ [キーフレーム間隔]が整数になるように、`frag_duration`と`-g`を調整します。(キーフレーム間隔をフレームレートと同じか、フレームレートの半分くらいにしておくとよいでしょう(例: `-r 30 -g 15 -frag_duration 5000000`))。

このようにして出力されたMP4ファイルを、MP4BoxでMPEG-DASH対応フォーマットに変換します。

```bash
$ MP4Box -dash [フラグメントの時間長] -frag-rap -profile ondemand [MP4ファイル名]
```

MP4Boxの場合は、変換後のファイルが**[元のファイル名(拡張子除く)]_dashinit.mp4**となります。また、DASHストリーミング用の記述ファイル(MPD)が**[元のファイル名(拡張子除く)]_dash.mpd**という名前のXMLファイルとして、併せて出力されます。

フラグメントの時間長は**ミリ秒**で指定します。

なお、Media Source Extensions等で使うことを想定して、初期化セグメントと各メディアセグメントを別ファイルに分割したい場合は、次のようにします。

```bash
$ MP4Box -dash [フラグメントの時間長] -frag-rap -segment-name [メディアセグメントのファイル名の接頭辞] -profile ondemand [MP4ファイル名]
```

この時、分割されたメディアセグメントが**[-segment-nameで指定した接頭辞]_[連番].m4s**、初期化セグメントが**[-segment-nameで指定した接頭辞]_init.mp4**というファイル名で出力されます。なお、MPDのファイル名は上記と同様です(すなわち、`-segment-name`でMPDのファイル名が変わることはありません)。