fdk-aacとx264が使えるffmpegをビルドする

ffmpeg 内蔵のAACエンコーダは音質が悪いので音質がよいと評判の fdk-aac が使える ffmpeg をビルドする。

fdk-aac のバイナリは配布禁止なので自分でコンパイルする必要があるが、MSYS を使い簡単にビルドすることができる。

NeroAAC のような単体のAACエンコーダより、fdk-aac を組み込んだ ffmpeg の方が使い勝手がよい。

今までは音声と映像を別々にエンコードして結合していたが、一回でできるようになった。

3つの方法を試したので順番に説明する。


32bit版のビルド

とりあえず難易度の低そうな 32bit版 をビルドしてみる。

MSYS (XhmikosR's Builds) は展開するだけでよいので導入が簡単。(gcc 7.1.0)

ただし、64bit はコンパイルできないことが多い。


必要なファイルをダウンロード

MSYS (XhmikosR's Builds) のダウンロード(MSYS_MinGW-w64_GCC_710_x86-x64_Full.7z)

ffmpeg のダウンロード(ffmpeg-4.3.1.tar.bz2 2020.07.11)

fdk-aac のダウンロード(fdk-aac-2.0.1.tar.gz)

x264 のダウンロード(x264-stable.zip x264 core 160 2020.07.02)

x264.exe も必要な場合は

l-smash のダウンロード(l-smash-2.14.5.zip)

x264 のビルドには nasm(アセンブラ) と l-smash(muxer) が必要だが

nasm.exe については MSYS/bin にあるのでOK(2.13.01)

l-smash なしだと mp4 出力できない x264.exe になる

それぞれを展開する(7-Zip などを使って)


ffmpegのビルド 

MSYSのディレクトリの msys.bat を実行しソースコードを展開したディレクトリに移動

各ディレクトリは /fdk-aac /l-smash /x264 /ffmpeg とする

・fdk-aac のコンパイル

cd fdk-aac

./configure --prefix=/mingw/i686-w64-mingw32

make -j3

make install


--prefix= は install する場所、MSYSのディレクトリ構成に合わせる

-j3 はスレッド数、CPUに合わせて設定、デフォルトは1(遅い)


・l-smash のコンパイル (x264.exe も必要な場合)

cd ../l-smash

./configure --prefix=/mingw/i686-w64-mingw32

make lib -j3

make install-lib


・x264 のコンパイル

cd ../x264

./configure --prefix=/mingw/i686-w64-mingw32 --enable-static --enable-strip

make -j3

make install


・ffmpeg のビルド

cd ../ffmpeg

./configure --enable-gpl --enable-version3 --enable-nonfree --enable-libfdk-aac --enable-libx264 --extra-ldflags=-static --extra-cflags='-march=i686 -mtune=generic' --optflags=-O2

make -j3

ffmpeg のディレクトリに ffmpeg.exe と ffprobe.exe が作成される


x264の主要な部分はアセンブラで書かれていて影響ないので最適化なしとした(--extra-cflags は削除してもよい)

最適化する場合は

--extra-cflags='-march=native -mfpmath=sse'

この場合、そのCPUで使える命令をフル活用するので、命令に対応していないCPUでは動作しない


make をやり直す時は

make clean

install したファイルを削除するには

make uninstall


64bit版のビルド

最新の開発環境である MSYS2 を使って 64bit版 をビルドする。

32bit はエラーでコンパイルできないことが多い。

必要なファイルをダウンロード

MSYS2 のインストーラをダウンロード(msys2-x86_64-20200629.exe)

nasm のバイナリをダウンロード、2.13以上が必要(nasm-2.15.01-win64.zip)

ソースコードは32bit版と同じ


MSYS2のインストール  gcc 10.1.0

・MSYS2のインストーラを実行

デフォルトのインストール場所は C:\msys64


・プログラムメニューから MSYS2 の MSYS2 MSYS を起動しコマンド実行

pacman -Syuu

メッセージが出て一旦閉じて、再度 MSYS2 MSYS を開きもう一度コマンド実行


・MinGW-w64 (64bit) の開発環境をインストール

pacman -S base-devel

pacman -S mingw-w64-x86_64-toolchain

選択肢が出るがデフォルトの all にする


MinGW-w64 (32bit) をインストールする場合は

pacman -S mingw-w64-i686-toolchain


・ダウンロードした nasm.exe を C:\msys64\mingw64\bin にコピーする


ffmpegのビルド

MSYS2 MinGW 64-bit を開きソースコードを展開したディレクトリに移動

各ディレクトリは /fdk-aac /l-smash /x264 /ffmpeg とする


・fdk-aac のコンパイル

cd fdk-aac

./configure --prefix=/mingw64/x86_64-w64-mingw32

make -j3

make install


・l-smash のコンパイル (x264.exe も必要な場合)

cd ../l-smash

./configure --prefix=/mingw64/x86_64-w64-mingw32

make lib -j3

make install-lib


・x264 のコンパイル

cd ../x264

./configure --prefix=/mingw64/x86_64-w64-mingw32 --enable-static --enable-strip

make -j3

make install

サンプル動画による最適化(fprofiled)はしない(効果が見えないので)


・ffmpeg のビルド

cd ../ffmpeg

./configure --enable-gpl --enable-version3 --enable-nonfree --enable-libfdk-aac --enable-libx264 --extra-ldflags=-static --optflags=-O2

make -j3


staticの指定は --extra-libs=-static でもOK


ffmpeg 32bit → 64bit で x264 のエンコードは 7% 速くなった。(720p 64bit/32bit 126fps/118fps)

32bit と 64bit のエンコード速度の差は思ったより小さい。


64bit版のお手軽ビルド

MSYS2 でパッケージをインストールして ffmpeg のみビルドする。

エラーでコンパイルできないものがあったので試してみた。

欠点は、インストールするバージョンが選べない、余計なものが入る。(x264 は依存パッケージ多数)

組み込むものが多い場合はこの方法が簡単。


パッケージのインストール

MSYS2 MSYS を開き

pacman -Ss でパッケージを検索

インストール

pacman -S nasm mingw-w64-x86_64-x264-git mingw-w64-x86_64-fdk-aac


ffmpeg のビルド

MSYS2 MinGW 64-bit を開き

cd ffmpeg

./configure --enable-gpl --enable-version3 --enable-nonfree --enable-libfdk-aac --enable-libx264 --extra-ldflags=-static --optflags=-O2

make -j3


pacman -Rs [package] パッケージのアンインストール

pacman -Qqe インストール済みのパッケージ一覧

pacman -Sg パッケージグループの一覧


エンコード コマンドの例

音声のエンコード

AAC-LC

ffmpeg -y -i "input file" -c:a libfdk_aac -b:a 128k -vn "audio.m4a"

HE-AAC

ffmpeg -y -i "input file" -c:a libfdk_aac -profile:a aac_he -b:a 48k -vn "audio.m4a"

HE-AAC v2

ffmpeg -y -i "input file" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 48k -vn "audio.m4a"

AAC エンコードの詳しい使い方は Encode/AAC - FFmpeg

映像のエンコード

ffmpeg -y -i "input file" -threads 0 -vf yadif,fps=30000/1001 -s 1280x720 -aspect 16:9 -c:v libx264 -crf 23 -tune animation -an "video.mp4"

映像と音声の mux

ffmpeg -y -i "video.mp4" -i "audio.m4a" -c:v copy -c:a copy -brand mp42 "output.mp4"

動画のエンコード

ffmpeg -y -i "input file" -threads 0 -vf yadif,fps=30000/1001 -async 1 -s 1280x720 -aspect 16:9 -c:v libx264 -crf 23 -tune animation -c:a libfdk_aac -b:a 128k -brand mp42 "output.mp4"

-async 1 は音ズレ対策で最初だけ同期、1 以外なら常時同期(徐々にずれる場合の対策)

 常時同期は音への被害があるので、まずは -async 1 で様子を見るのがよい

 値の単位は spl/s なので例えば1時間に1秒の補正だと 1s * 48kspl / 3600s = 13.3

 この場合は -async 10 程度でよい(-async 100 を使うことが多いようだが、やり過ぎでは)

 実行時に出るメッセージ

 -async is forwarded to lavfi similarly to -af aresample=async=1:min_hard_comp=0.100000:first_pts=0

 オーディオフィルタと同様な動作になるようだ、0.1秒以上ずれたら補正

fps=30000/1001 はフレームが欠落した場合の対策(重複フレームで補間、多い場合は間引く)

 これは音ズレ対策にもなっている、-vf はビデオフィルタ

yadif はインターレース解除(非推奨のオプション -deinterlace でも yadif と同じ結果になった)

bwdif の方が画質は良いがその分遅い、画質が明瞭になるのでビットレートは増加

-threads 0 はデフォルトなので指定しなくてもよいが調整したい場合用に設定

-brand mp42 は コーデック ID を mp42 にする、指定した方がよい(デフォルトは isom)

-vn は 映像なし、-an は音声なし、入力ファイルが映像と音声を含む場合、指定しないとコピーされる

-y は上書き確認なし


その他のオプション

-x264opts x264 のオプションを直接指定(全てのオプションが使える)

例 -x264opts "b-adapt=2:fast-pskip=0:dct-decimate=0"

-ss hh:mm:ss 開始時間(秒) -i の前ならシークなし(速い)

-to hh:mm:ss 終了時間(秒)

-t hh:mm:ss 出力期間(秒)

映像と音声の mux は MP4Box や L-SMASH の muxer でもできるが ffmpeg では動画の詳細情報の欠落がないのでよい。(MP4Box や L-SMASH では音声の情報が変になる)

その後、NVENCとfdk-aacが使えるffmpegビルド