Ubuntu 20.04 と FFmpeg 4.4 で NVENC による HEVC/H.265 ハードウェアエンコード (GTX-1050)

FFmpeg 3.x 以前ではソースコードから FFmpeg をビルドしてインストールする場合、NVENC でサポートされる GPU とそのドライバがインストールされていればデフォルトで NVENC が有効になっていました。つまり、h264_nvenc, hevc_nvenc が有効 (–enable-nvenc) であり、HEVC/H.265 にトランスコード(エンコード)できるようになっていました。

しかし、FFmpeg 4.0 以降では、FFmpeg をソースコードからビルドしてインストールした後、

ffmpeg -encoders | grep nvenc

を実行しても何も表示されませんでした。

そのため、FFmpeg 4.0 以降でも FFmpeg で NVENC を有効にし、HEVC/H.265 にトランスコード(エンコード)するための手順を記載していきます。私の GPU は、GTX-1050 です。

なお、NVENC でサポートされる GPU は、NVIDIA のホームページの Video Encode and Decode GPU Support Matrix で確認することができます。

https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new

必要と思われるパッケージのインストール

まず、必要と思われるパッケージを APT でインストールします。私にとって必要なパッケージをインストールしており、他者にとっては過剰なインストールになっているかもしれません。

sudo apt install -y build-essential git wget libasound2-dev \
  autoconf libtool pcsc-tools pkg-config libpcsclite-dev pcscd \
  cmake yasm curl ssh dkms

GPU ドライバのインストール

NVIDIA のホームページからドライバをダウンロードするのではなく、Ubuntu 内のコマンドでダウンロードすることにしました。

まず、ubuntu-drivers コマンドを実行し、インストールできるドライバの選択肢を確認します。

$ ubuntu-drivers devices

WARNING:root:_pkg_get_support nvidia-driver-390: package has invalid Support Legacyheader, cannot determine support level
== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v000010DEd00001C81sv00001462sd00008C97bc03sc00i00
vendor   : NVIDIA Corporation
model    : GP107 [GeForce GTX 1050]
driver   : nvidia-driver-460 - distro non-free recommended
driver   : nvidia-driver-460-server - distro non-free
driver   : nvidia-driver-450-server - distro non-free
driver   : nvidia-driver-390 - distro non-free
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-450 - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

recommended であり、バージョン番号が最も大きい最新のドライバである nvidia-driver-460 をインストールします。recommended のドライバは、ubuntu-drivers コマンドの autoinstall オプションでインストールすることができます。インストール後、Ubuntu を再起動します。

sudo ubuntu-drivers autoinstall
sudo reboot

Ubuntu 再起動後、nvidia-smi コマンドを実行すると、ドライバのバージョン、CUDA のバージョンを確認することができます。

$ nvidia-smi

Mon May 10 02:56:19 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.73.01    Driver Version: 460.73.01    CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| 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  GeForce GTX 1050    Off  | 00000000:01:00.0  On |                  N/A |
| 43%   41C    P8    N/A /  75W |    333MiB /  1999MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A       768      G   /usr/lib/xorg/Xorg                180MiB |
|    0   N/A  N/A      1056      G   /usr/bin/gnome-shell               87MiB |
|    0   N/A  N/A      1703      G   gnome-control-center               33MiB |
|    0   N/A  N/A      1756      G   ...AAAAAAAAA= --shared-files       28MiB |
+-----------------------------------------------------------------------------+

nv-codec-headers のインストール

FFmpeg の wiki によると、NVENC のために nv-codec-headers が必要になります。

https://trac.ffmpeg.org/wiki/HWAccelIntro

nv-codec-headers は、GitHub でソースコードが公開されています。

https://github.com/FFmpeg/nv-codec-headers

適当な作業用ディレクトリを作成し、ソースコードをダウンロードし、ビルドし、インストールします。

mkdir ~/working_directory
cd ~/working_directory && \
    git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers && \
    cd nv-codec-headers && \
    make -j$(nproc) && \
    sudo make install

FFmpeg のインストール

このポストを書いている 2021 年 5 月時点で最新の 4.3.1 をインストールしました。

cd ~/working_directory && \
    wget http://ffmpeg.org/releases/ffmpeg-4.4.tar.gz && \
    tar zxvf ffmpeg-4.4.tar.gz && \
    cd ffmpeg-4.4 && \
    ./configure --disable-shared --enable-static && \
    make -j$(nproc) && \
    sudo make install

トランスコード(エンコード)確認

実際に ffmpeg コマンドを実行し、動作を確認してみます。例えば下記のように、任意のビデオファイルを HEVC/H.265 の MP4 にトランスコードしてみます。

ffmpeg -i input.ts -vcodec hevc_nvenc -tag:v hvc1 output.mp4

FFmpeg のログを確認すると、hevc_nvenc が使用されていることがわかります。つまり、NVENC で HEVC/H.265 へのトランスコードがされています。変換速度も 10 倍であり、ハードウェアアクセラレーションによる変換であることがわかります。

Stream mapping:
  Stream #0:8 -> #0:0 (mpeg2video (native) -> hevc (hevc_nvenc))
  Stream #0:2 -> #0:1 (aac (native) -> aac (native))

Output #0, mp4, to 'output.mp4':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Video: hevc (hevc_nvenc) (Main) (hvc1 / 0x31637668), yuv420p, 1440x1080 [SAR 4:3 DAR 16:9], q=-1--1, 2000 kb/s, 29.97 fps, 30k tbn, 29.97 tbc
    Metadata:
      encoder         : Lavc58.91.100 hevc_nvenc
    Side data:
      cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 4000000 vbv_delay: N/A
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s
    Metadata:
      encoder         : Lavc58.91.100 aac

frame=  546 fps=304 q=25.0 Lsize=    4488kB time=00:00:18.18 bitrate=2021.7kbits/s dup=17 drop=0 speed=10.1x