ffmpeg で GPU エンコードできるようにする

以前 ffmpeg を使ってコマンドラインから動画をエンコードする方法をまとめた。その際、GPU エンコードが上手くいかなかったので放置していたのだが、再トライしてみた次第。

当時どう上手くいかなかったのかというと、以下のようなエラーメッセージが出て異常終了していた。

driver does not support the required nvenc api version. required 11.1 found 11.0

割と簡単に何とかなったので紹介する。

目次

前提環境

当方環境は以下のとおり。

NVIDIA ドライバと SDK をインストールする

まずは NVIDIA のドライバと SDK の最新版をインストールしてみる。

上のページを参考に、以下2つをインストールした。

  1. NVIDIA ドライバ
    • NVIDIAドライバダウンロード
    • ↑ このページから、自分は GTX 1080 向けのドライバをダウンロードしインストール。ダウンロードタイプは安定している「Studio ドライバー (SD)」にしておいた
  2. CUDA Toolkit SDK

それぞれ、インストール直後は OS を再起動すること。「GeForce Experience」という GUI ツールからも必要なアップデートが確認できたりする。

ffmpeg をインストールする

コレまでは、Chocolatey 経由でインストールしていた ffmpeg をワケも分からず使っていたのだが、どうも GPU エンコードするためには本来、ffmpeg を自分でビルドしないといけないらしい。

手順はまとまっているものの、ビルドが面倒臭いので、ビルド済のモノを探したところ、以下にあった。

このページは定期的にビルド済の ffmpeg を配信しているようだ。最新版の ffmpeg-git-full.7z をダウンロードすれば良い。自分は本稿執筆時点の最新版である ffmpeg-2022-01-19-git-dd17c86aa1-full_build.7z をダウンロードした。

7-Zip で解凍すると、中から ffmpeg.exe が出てくるので、コレを PATH の通ったところに配置する。Chocolatey でインストールしていたモノよりも優先して使われることを確認しておこう。

# 自分で配置した ffmpeg を確認する
$ type ffmpeg
ffmpeg は /c/Users/Neo/bin/ffmpeg です

$ ffmpeg -version
ffmpeg version 2022-01-19-git-dd17c86aa1-full_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11.2.0 (Rev5, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
libavutil      57. 18.100 / 57. 18.100
libavcodec     59. 20.100 / 59. 20.100
libavformat    59. 17.101 / 59. 17.101
libavdevice    59.  5.100 / 59.  5.100
libavfilter     8. 26.100 /  8. 26.100
libswscale      6.  5.100 /  6.  5.100
libswresample   4.  4.100 /  4.  4.100
libpostproc    56.  4.100 / 56.  4.100

# エンコーダを確認する
$ ffmpeg -encoders | grep -i nvidia
 V....D h264_nvenc           NVIDIA NVENC H.264 encoder (codec h264)
 V....D hevc_nvenc           NVIDIA NVENC hevc encoder (codec hevc)

# デコーダも確認する
$ ffmpeg -decoders | grep -i nvidia
 V..... av1_cuvid            Nvidia CUVID AV1 decoder (codec av1)
 V..... h264_cuvid           Nvidia CUVID H264 decoder (codec h264)
 V..... hevc_cuvid           Nvidia CUVID HEVC decoder (codec hevc)
 V..... mjpeg_cuvid          Nvidia CUVID MJPEG decoder (codec mjpeg)
 V..... mpeg1_cuvid          Nvidia CUVID MPEG1VIDEO decoder (codec mpeg1video)
 V..... mpeg2_cuvid          Nvidia CUVID MPEG2VIDEO decoder (codec mpeg2video)
 V..... mpeg4_cuvid          Nvidia CUVID MPEG4 decoder (codec mpeg4)
 V..... vc1_cuvid            Nvidia CUVID VC1 decoder (codec vc1)
 V..... vp8_cuvid            Nvidia CUVID VP8 decoder (codec vp8)
 V..... vp9_cuvid            Nvidia CUVID VP9 decoder (codec vp9)

エンコーダの中に h264_nvenc が存在すれば、GPU を使った H.264 エンコードができる。hevc_nvenc の方は H.265 エンコードができるモノ。

GPU エンコードしてみる

いよいよ GPU エンコードを試してみる。-c:v h264_nvenc と GPU エンコードを指定すれば OK。適当な AVI ファイルを H.264 mp4 に変換する簡単な例。

# コチラは CPU エンコード。GPU を使わないので遅い
$ ffmpeg -i src.avi -c:v libx264    dest.mp4

# コチラが今回できるようになった GPU エンコード。速い
$ ffmpeg -i src.avi -c:v h264_nvenc dest.mp4

「タスクマネージャ」の「パフォーマンス」タブで目視しただけだが、GPU を使うようになったので処理速度はかなり向上した。GPU ってフルフル 100% で稼動するモノじゃないのね~。GPU エンコード時も CPU 使用率は 60% 台だった。CPU エンコード時はほぼ使用率 100% が続いていて遅かったので、改善できて良き良き。