DebianでffmpegをNVENCに対応させる
Debianのパッケージ版のffmpegはnvidiaのGPUで利用できるハードウエアエンコード・デコード機能であるNVENC/NVDECが有効化されていない。
そこで、Debian的お作法に則ってNVENC対応のffmpegをビルドするための備忘録を書いておく。
前提条件
前提条件として、NVENC対応のnvidiaのGPUが乗っており、対応するドライバとCUDAがインストールされている必要がある。
ちゃんとインストールされていれば、nvidia-smiで以下のようにドライババージョンとCUDAが確認できるはずである。
$ nvidia-smi
Sun Mar 26 20:58:11 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.161.03 Driver Version: 470.161.03 CUDA Version: 11.4 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA GeForce ... On | 00000000:09:00.0 Off | N/A |
| 30% 24C P8 6W / 75W | 1MiB / 3908MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
ffmpegをビルドするためのパッケージを導入する
ffmpeg自体を再ビルドする必要があるので、debian公式レポジトリからパッケージ版ffmpegのソースパッケージをもらってくる。
また、ビルドに必要なパッケージのインストールも行う。
一般的には apt build-dep ffmepg などとして、ソースパッケージのビルドに必要な依存のあるパッケージを導入するが、build-depは導入したパッケージを自動的にアンインストールする方法を提供していないためパッケージツリーを汚してしまう。
そこで、mk-build-deps を導入する。mk-build-deps は、ビルドに必要な依存のあるパッケージを仮想的なパッケージにまとめてくれるユーティリティで、これを導入することによってビルドパッケージが不要になった場合にアンインストールを楽に行うことができる。
mk-build-deps は以下のようにして導入できる。
$ sudo apt install devscripts
mk-build-deps をbuild-depの代わりに利用することで、依存パッケージをダミーパッケージとしてまとめてくれる。
例えば ffmpeg をビルドするために必要なパッケージを導入するには以下のようにする。
$ mk-build-deps ffmpeg --install --root-cmd sudo --remove
このようにすると、
$ dpkg -al|grep ffmpeg-build-deps
ii ffmpeg-build-deps 7:4.3.5-0+deb11u1 amd64 build-dependencies for ffmpeg
このように、ビルドに必要なパッケージを導入するためのダミーパッケージが作成されてインストールされる。
つまり、不要になった時はこのパッケージを purge するだけでパッケージツリーを汚すことなく導入されたパッケージを削除できる。
ffmpegを再ビルドする
nv-codec-headersの導入
ffmpegでNVENCを利用するために必要なヘッダファイルを導入する。
これは、ffmpegのgithubレポジトリかVLCのgithubレポジトリにあるので、利用してるCUDAのバージョンにあったものを導入する。
$ git clone https://github.com/FFmpeg/nv-codec-headers.git -b sdk/11.1
Cloning into 'nv-codec-headers'...
remote: Enumerating objects: 936, done.
remote: Counting objects: 100% (181/181), done.
remote: Compressing objects: 100% (89/89), done.
remote: Total 936 (delta 106), reused 125 (delta 71), pack-reused 755
Receiving objects: 100% (936/936), 278.24 KiB | 9.59 MiB/s, done.
Resolving deltas: 100% (543/543), done.
$ cd nv-codec-headers/
$ make
sed 's#@@PREFIX@@#/usr/local#' ffnvcodec.pc.in > ffnvcodec.pc
$ sudo make install
sed 's#@@PREFIX@@#/usr/local#' ffnvcodec.pc.in > ffnvcodec.pc
install -m 0755 -d '/usr/local/include/ffnvcodec'
install -m 0644 include/ffnvcodec/*.h '/usr/local/include/ffnvcodec'
install -m 0755 -d '/usr/local/lib/pkgconfig'
install -m 0644 ffnvcodec.pc '/usr/local/lib/pkgconfig'
ffmpegソースパッケージの導入
$ mkdir -p ffmpeg/src
$ cd ffmpeg/src
$ apt source ffmpeg
Reading package lists... Done
NOTICE: 'ffmpeg' packaging is maintained in the 'Git' version control system at:
https://salsa.debian.org/multimedia-team/ffmpeg.git
Please use:
git clone https://salsa.debian.org/multimedia-team/ffmpeg.git
to retrieve the latest (possibly unreleased) updates to the package.
Need to get 9,493 kB of source archives.
Get:1 http://deb.debian.org/debian bullseye/main ffmpeg 7:4.3.5-0+deb11u1 (dsc) [5,439 B]
Get:2 http://deb.debian.org/debian bullseye/main ffmpeg 7:4.3.5-0+deb11u1 (tar) [9,398 kB]
Get:3 http://deb.debian.org/debian bullseye/main ffmpeg 7:4.3.5-0+deb11u1 (asc) [520 B]
Get:4 http://deb.debian.org/debian bullseye/main ffmpeg 7:4.3.5-0+deb11u1 (diff) [89.0 kB]
Fetched 9,493 kB in 2s (5,292 kB/s)
dpkg-source: info: extracting ffmpeg in ffmpeg-4.3.5
dpkg-source: info: unpacking ffmpeg_4.3.5.orig.tar.xz
dpkg-source: info: unpacking ffmpeg_4.3.5-0+deb11u1.debian.tar.xz
dpkg-source: info: using patch list from debian/patches/series
dpkg-source: info: applying 0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch
dpkg-source: info: applying 0002-Fix-build-on-powerpc-and-ppc64.patch
これでソースパッケージが展開される。
ffmpegのNVENCの有効化
$ cd ffmpeg-4.3.5
$ vim debian/rules
rulesのCONFIGに –enable-cuda –enable-nvenc を追記してリビルドする。
$ dpkg-buildpackage -r -nc -j4 --no-sign
....
....
....
$ cd ..
$ ls
ffmpeg-4.3.5 libavfilter-extra_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5-0+deb11u1_amd64.buildinfo libavfilter-extra7_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5-0+deb11u1_amd64.changes libavfilter-extra7-dbgsym_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5-0+deb11u1_amd64.deb libavformat58_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5-0+deb11u1.debian.tar.xz libavformat58-dbgsym_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5-0+deb11u1.dsc libavformat-dev_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5.orig.tar.xz libavresample4_4.3.5-0+deb11u1_amd64.deb
ffmpeg_4.3.5.orig.tar.xz.asc libavresample4-dbgsym_4.3.5-0+deb11u1_amd64.deb
ffmpeg-dbgsym_4.3.5-0+deb11u1_amd64.deb libavresample-dev_4.3.5-0+deb11u1_amd64.deb
ffmpeg-doc_4.3.5-0+deb11u1_all.deb libavutil56_4.3.5-0+deb11u1_amd64.deb
libavcodec58_4.3.5-0+deb11u1_amd64.deb libavutil56-dbgsym_4.3.5-0+deb11u1_amd64.deb
libavcodec58-dbgsym_4.3.5-0+deb11u1_amd64.deb libavutil-dev_4.3.5-0+deb11u1_amd64.deb
libavcodec-dev_4.3.5-0+deb11u1_amd64.deb libpostproc55_4.3.5-0+deb11u1_amd64.deb
libavcodec-extra_4.3.5-0+deb11u1_amd64.deb libpostproc55-dbgsym_4.3.5-0+deb11u1_amd64.deb
libavcodec-extra58_4.3.5-0+deb11u1_amd64.deb libpostproc-dev_4.3.5-0+deb11u1_amd64.deb
libavcodec-extra58-dbgsym_4.3.5-0+deb11u1_amd64.deb libswresample3_4.3.5-0+deb11u1_amd64.deb
libavdevice58_4.3.5-0+deb11u1_amd64.deb libswresample3-dbgsym_4.3.5-0+deb11u1_amd64.deb
libavdevice58-dbgsym_4.3.5-0+deb11u1_amd64.deb libswresample-dev_4.3.5-0+deb11u1_amd64.deb
libavdevice-dev_4.3.5-0+deb11u1_amd64.deb libswscale5_4.3.5-0+deb11u1_amd64.deb
libavfilter7_4.3.5-0+deb11u1_amd64.deb libswscale5-dbgsym_4.3.5-0+deb11u1_amd64.deb
libavfilter7-dbgsym_4.3.5-0+deb11u1_amd64.deb libswscale-dev_4.3.5-0+deb11u1_amd64.deb
libavfilter-dev_4.3.5-0+deb11u1_amd64.deb
これでdebパッケージが生成されるので、これらをインストールする。
速度比較
Ryzen9 x5950(16c32t)のマシンでCPUエンコード(libx264)とGPU(GTX 1650 (TU117))のNVENC(h264_evenc)の速度を比較してみる。
比較対象として1時間のm2tsをH.264でエンコードする。
$ ffmpeg -y -i test.m2ts -c:v libx264 -preset veryfast output.mp4
....
frame=108127 fps=404 q=-1.0 Lsize= 1636440kB time=01:00:07.73 bitrate=3715.8kbits/s dup=16118 drop=0 speed=13.5x
....
$ ls -alh output.mp4
-rw-r--r-- 1 root root 1.6G Mar 27 12:44 output.mp4
$ ffmpeg -y -i test.m2ts -c:v h264_nvenc -preset fast output.mp4
....
frame=108127 fps=846 q=28.0 Lsize= 905428kB time=01:00:07.80 bitrate=2055.9kbits/s dup=16118 drop=0 speed=28.2x
....
$ ls -alh output.mp4
-rw-r--r-- 1 root root 885M Mar 27 12:49 output.mp4
今回、マシンがRyzen9の16c32tなのでCPUエンコードでも結構早いのだが、GPUエンコードだとさらにその2倍くらいで爆速エンコードできることがわかる。
presetが違うのでファイルサイズは違うのだが、消費電力的にもGPU使ったほうが断然省電力なのでGPUを積極的に使うべきであろう。