法的に問題ないFFmpegをbuildした

# FFmpeg って使ってもダイジョブなの？

クライアントに提供するシステムで音声データを扱う必要があったのですが、手短に FFmpeg を使うと楽なのでは、ということになりました。……が、法的に問題ないと言い切れるのか、という懸念もあって[^patent]、物理的に WAV 形式以外扱えない FFmpeg を作ろう、ということになりました。

[^patent]: パッケージで配られているものはきちんとチェックされているはずで、問題ないと思います。しかし FFmpeg というとどうしてもグレーなイメージが付きまとうので、懸念が出るのは仕方ないかなあ、と思うのです。

といっても、とてもシンプルです。

## 環境

* Amazon Linux 2 (amzn2-ami-hvm-2.0.20190823.1)
* [t3.micro インスタンス](https://aws.amazon.com/jp/ec2/instance-types/t3/)

## 手順

### 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 は指定しなければほとんどすべてのライブラリを静的リンクするため、動的ライブラリへの依存はかなり小さいです[^static]。

[^static]: その結果、バイナリが大きいわけです。ただ configure には動的ライブラリを利用するオプションもあります。

実際に確認してみます。

```
$ 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 自体も基本的なパッケージなので[^glibc]、よほど特殊な環境でなければ最初から導入されているでしょう。

[^glibc]: glibc は「GNU C Library」といい、Linux ではもっとも基本的なライブラリです。

ということで、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 を構成します[^avx512]。

しかし手元で使うようなPCで AVX-512 を使えるものはかなり限られます。今回 build するバイナリは AWS の上で動作させるので問題ないのですが、手元の環境で試す可能性を考えてセットしました。

[^avx512]: WAV しか使えないように指定しているので、構成はされても使われない可能性が大きいんじゃないか、とも思っています。

## 感想

他の環境で動作させるバイナリを作るのは、本来は結構めんどうくさいです。しかし FFmpeg は他のマシンに持っていくことを非常によく考えて作られているな、という印象をうけました。

最近、自分で build することが少なくなっているので、今はこれが普通なのかもしれないですけど……。