debianlinux

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を積極的に使うべきであろう。

Leave a Reply

Your email address will not be published. Required fields are marked *