FFmpeg って使ってもダイジョブなの?
クライアントに提供するシステムで音声データを扱う必要があったのですが、手短に FFmpeg を使うと楽なのでは、ということになりました。……が、法的に問題ないと言い切れるのか、という懸念もあって1、物理的に WAV 形式以外扱えない FFmpeg を作ろう、ということになりました。
といっても、とてもシンプルです。
環境
- Amazon Linux 2 (amzn2-ami-hvm-2.0.20190823.1)
- t3.micro インスタンス
手順
curl のダウンロード、展開
$ curl https://ffmpeg.org/releases/ffmpeg-4.2.1.tar.bz2
$ tar jxvf ffmpeg-4.2.1.tar.bz2
開発ツールの導入
今回は(といっても私の場合いつもですが) Amazon Linux 2 を使ったので、標準で開発ツールは入っていません。なのでサクッと入れます。
$ sudo yum install gcc
$ sudo yum install nasm
configure, make
最初にすべてのコーデックを無効にして PCM/ADPCM だけを有効に、同様にマルチプレクサもすべて無効にして WAV コンテナだけ有効に。これだけです。
(AVX-512 命令を disable した理由は後述します)
今回はバイナリのサイズを小さくする --enable-small
も加えましたが、ここは環境にあわせてお好みで。
$ cd ffmpeg-4.2.1
$ ./configure \
--disable-encoders --disable-decoders \
--enable-encoder='pcm*' --enable-decoder='pcm*' \
--enable-encoder='adpcm*' --enable-decoder='adpcm*' \
--disable-muxers --disable-demuxers \
--enable-muxer='wav' --enable-demuxer='wav' \
--disable-avx512 --disable-debug
--enable-small
成功したら、あとは make するだけです。
$ make
できあがったバイナリは他のマシンに持っていくので make install
はしません。
確認
他のマシンで動作するか、ざっくり確認します。
FFmpeg は指定しなければほとんどすべてのライブラリを静的リンクするため、動的ライブラリへの依存はかなり小さいです2。
実際に確認してみます。
$ readelf -d ffmpeg
Dynamic section at offset 0x448e00 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x402db8
0x000000000000000d (FINI) 0x6d7980
0x0000000000000019 (INIT_ARRAY) 0xa48df0
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0xa48df8
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x400298
0x0000000000000005 (STRTAB) 0x401478
0x0000000000000006 (SYMTAB) 0x400350
0x000000000000000a (STRSZ) 1566 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0xa49000
0x0000000000000002 (PLTRELSZ) 4272 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x401d08
0x0000000000000007 (RELA) 0x401ca8
0x0000000000000008 (RELASZ) 96 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x401c08
0x000000006fffffff (VERNEEDNUM) 3
0x000000006ffffff0 (VERSYM) 0x401a96
0x0000000000000000 (NULL) 0x0
NEEDED
となっている Shared library は libm.so.6
、libpthread.so.0
、libc.so.6
の3つだけです。しかもこれらはすべて現行の glibc パッケージに入っていますし、glibc 自体も基本的なパッケージなので3、よほど特殊な環境でなければ最初から導入されているでしょう。
ということで、Intel/AMD の64ビットCPUで動く Linux では、だいたい動きそうです。試しに Ubuntu 18.0.4 に持って行ってみましたがちゃんと動きました。
注意点
命令セットへの依存
configure のときに --disable-avx512
オプションを付けた理由を説明します。
一般に、とくに指定しない場合、configure はそれを動作させた環境で使えるものを使うように構成します。FFmpeg は音声・動画コンバーターなので、変換スピードをあげるため、拡張命令を使えるようなら使えるように構成されます。
しかし、今回つかった AWS EC2 のT3インスタンスは Xeon CPU を搭載した高級サーバ上の仮想環境なので AVX-512 命令セットが使えます。そのため指定がなければ configure はAVX-512 を使えるように build を構成します4。
しかし手元で使うようなPCで AVX-512 を使えるものはかなり限られます。今回 build するバイナリは AWS の上で動作させるので問題ないのですが、手元の環境で試す可能性を考えてセットしました。
感想
他の環境で動作させるバイナリを作るのは、本来は結構めんどうくさいです。しかし FFmpeg は他のマシンに持っていくことを非常によく考えて作られているな、という印象をうけました。
最近、自分で build することが少なくなっているので、今はこれが普通なのかもしれないですけど……。