Ubuntu 20.04 と FFmpeg 4.3 で 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 で確認することができます。

NVIDIA Developer

Sort a HTML Table Alphabetically Video Encode and Decode GPU…

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

まず、必要と思われるパッケージを 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

== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v0000
vendor   : NVIDIA Corporation
model    : GP107 [GeForce GTX 1050]
driver   : nvidia-driver-440 - distro non-free recommended
driver   : nvidia-driver-435 - distro non-free
driver   : nvidia-driver-390 - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

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

sudo ubuntu-drivers autoinstall
sudo reboot

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

$ nvidia-smi
Wed Jul  8 19:08:07 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.100      Driver Version: 440.100      CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1050    Off  | 00000000:01:00.0  On |                  N/A |
| 41%   39C    P0    N/A /  75W |    457MiB /  1997MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0       875      G   /usr/lib/xorg/Xorg                           101MiB |
|    0      1473      G   /usr/lib/xorg/Xorg                           189MiB |
|    0      1671      G   /usr/bin/gnome-shell                         122MiB |
|    0      4054      G   ...AAAAAAAAAAAACAAAAAAAAAA= --shared-files    33MiB |
+-----------------------------------------------------------------------------+

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

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

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

GitHub

automatic mirror of https://git.videolan.org/?p=ffmpeg/nv-co…

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

なお、最新の nv-codec-headers は、私の環境 (Ubuntu 20.04, nvidia-driver-440, GTX-1050) をサポートしていませんでした。そのため、古いバージョンである sdk/9.1 をチェックアウトしています。最先端の環境を整えている場合は、git checkout sdk/9.1 の行は必要ないかもしれません。

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

FFmpeg のインストール

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

cd ~/working_directory && \
    wget http://ffmpeg.org/releases/ffmpeg-4.3.1.tar.gz && \
    tar zxvf ffmpeg-4.3.1.tar.gz && \
    cd ffmpeg-4.3.1 && \
    ./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

エラーメモ

前述の通り、私の環境では最新の nv-codec-headers をインストールすると、FFmpeg 実行時に下記のようなエラーとなりました。そのため、nv-codec-headers のバージョン 9.1 をインストールした後、FFmpeg 再度ビルドし、インストールし直しました。

Error while decoding stream #0:2: Invalid data found when processing input
[hevc_nvenc @ 0x55cbbfb26ec0] Driver does not support the required nvenc API version. Required: 10.0 Found: 9.1
[hevc_nvenc @ 0x55cbbfb26ec0] The minimum required Nvidia driver for nvenc is (unknown) or newer
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height