Skip to content

Instantly share code, notes, and snippets.

@zgock999
Last active March 27, 2022 02:42
Show Gist options
  • Save zgock999/199a937a085e376365e76bf03f6173ca to your computer and use it in GitHub Desktop.
Save zgock999/199a937a085e376365e76bf03f6173ca to your computer and use it in GitHub Desktop.

openSUSE Leap 15でNVENCを有効にしたffmpegをビルドし、mpeg2-tsのGPUエンコードを行う

Nvidia GPUが存在するLinux環境では、NVIDIAのハードウェアエンコーディング/デコーディング機能であるNVENC/NVDECが利用可能ですが、openSUSEの標準パッケージとして利用可能なffmpegではNVENC/NVDECが有効化されていません。これはNVIDIAのライセンス規約により同機能を有効にしたffmpegのバイナリ再配布が許されていないためです。(おそらくほとんどのディストリビューション添付のffmpegも同じはず)

そこで、ffmpegをソースからビルドし、NVENC/NVDECを使えるようにします

ビルド依存環境のダウンロード

zypperでffmpegに必要な各種ライブラリとツールをダウンロードします

zypper si -d ffmpeg

CUDA ToolkitとNVIDIA Video SDKのインストール

ffmpegでハードウェアによるリサイズやデインターレース等のフィルター機能を使う場合、CUDAライブラリの一つ、libnppが必要になりますのでこれもインストールします

wget https://developer.download.nvidia.com/compute/cuda/repos/opensuse15/x86_64/cuda-repo-opensuse15-10.0.130-1.x86_64.rpm
sudo zypper in ./cuda-repo-opensuse15-10.0.130-1.x86_64.rpm
sudo zypper ref
sudo zypper in cuda-toolkit-10-0 cuda-npp-dev-10-0

NVIDIA Video SDKはVLCプロジェクトがgitレポジトリをホストしていますのでこれを入れます

git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
sudo make install

ffmpegのソース取得

ffmpegのgithubリポジトリから最新のソースをダウンロードします

git clone git://github.com/FFmpeg/FFmpeg ffmpeg/

configure

ffmpegになにもオプションを与えずに実行すると、そのffmpegがどういうオプションでコンパイルされているかを把握できるので、これをどこかにメモするなりコピペするなりで覚えておきます

$ffmpeg

ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 7 (SUSE Linux)
  configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --incdir=/usr/include/ffmpeg --extra-cflags='-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g' --optflags='-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g' --disable-htmlpages --enable-pic --disable-stripping --enable-shared --disable-static --enable-gpl --disable-openssl --enable-avresample --enable-gnutls --enable-ladspa --enable-nvenc --enable-libfdk_aac --enable-nonfree --enable-nvdec --enable-libx264 --enable-libx265 --enable-vaapi --enable-vdpau --enable-libxvid --enable-cuda --enable-cuvid --disable-cuda --disable-cuvid --enable-libass --enable-libbluray --enable-libcelt --enable-libcdio --enable-libdc1394 --enable-libdrm --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libv4l2 --enable-libvpx --enable-libwebp --enable-libxml2 --enable-libzvbi --enable-vaapi --enable-vdpau
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

Use -h to get full help or, even better, run 'man ffmpeg'

上記で確認したオプションに少々手を加えてconfigureします。ポイントとしては

  • /usr/local/lib/cuda /usr/local/include/cudaをパスに加える
  • prefixを/usr/localにする
  • --enable-cuda-sdkと--enable-libnppを入れる
  • --disable-cuda等があったら抜く
  • --enable-libzbviを外す(2019/1/16現在、どうにも依存関係が解決できなかったのと、無くてもさほど困らないと判断して)
--prefix=/usr/local --libdir=/usr/lib64 --shlibdir=/usr/lib64 \
--extra-cflags='-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g' \
--optflags='-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g' \
--disable-htmlpages --enable-pic --disable-stripping --enable-shared --disable-static --enable-gpl --disable-openssl --enable-avresample \
--enable-gnutls --enable-ladspa --enable-nvenc --enable-libfdk_aac --enable-nonfree --enable-nvdec --enable-libx264 --enable-libx265 \
--enable-vaapi --enable-vdpau --enable-libxvid --enable-cuda --enable-cuvid --enable-libass \
--enable-libbluray --enable-libcelt --enable-libcdio --enable-libdc1394 --enable-libdrm \
--enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgsm \
--enable-libjack --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse \
--enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libv4l2 \
--enable-libvpx --enable-libwebp --enable-libxml2 --enable-vaapi --enable-vdpau \
--enable-cuda-sdk --enable-npp \
--extra-cflags="-I/usr/local/cuda/include/" \
--extra-ldflags=-L/usr/local/cuda/lib64/

configureを実行すると依存関係であれがないこれがないと言われるはずなのでそれらを導入します

sudo zypper in libx264-devel libx265-devel fdk-aac-devel openjpeg2-devel libssh-devel libxvidcore-devel 

configureが通ると、このconfigで使用可能になっているデコーダー/エンコーダー/フィルタ等がリストアップされますので、この中にh264_cuvid、h264_nvenc、yadif_cuda、scale_npp等があればOKです

install prefix            /usr/local
source path               .
C compiler                gcc
~略~
External libraries providing hardware acceleration:
cuda			libnpp			v4l2_m2m
cuda_sdk		nvdec			vaapi
cuvid			nvenc			vdpau
ffnvcodec

Enabled decoders:
~略~
adpcm_ima_wav		cpia			h264_cuvid
~略~
Enabled encoders:
~略~
h264_nvenc		pcm_s24le_planar	wmav2
~略~
Enabled hwaccels:
~略~
h264_nvdec		mpeg1_vdpau		vc1_vdpau
~略~
Enabled filters:
~略~
mcompand		scale_npp		tile
~略~
pixdesctest		silenceremove		yadif_cuda
~略~

make

cudaを有効にしている場合、makeの中でcuda toolkitのnvccを使うので、PATHに/usr/local/cuda/binを追加で通してmakeします

PATH=$PATH:/usr/local/cuda/bin make
sudo make install

これで/usr/local/binにnvencが有効になったffmpegが配置されます

使用可能オプション

基本形

ffmpeg -c:v mpeg2_cuvid [デコーダ側オプション] -i input.ts [必要ならフィルター指定] -c:v h264_nvenc [エンコーダ側オプション] output.mp4 

デコーダ(mpeg2_cuvid)

h264_cuvid,hevc_cuvid等もありますが基本的には同じです

以下のようなオプションがありますので、cuvidを使う場合はリサイズやインターレース解除といった基本的な処理はfilterを使わずにデコーダで行います

$ffmpeg -h decoder=mpeg2_cuvid
mpeg2_cuvid AVOptions:
  -deint             <int>        .D.V..... Set deinterlacing mode (from 0 to 2) (default weave)
     weave                        .D.V..... Weave deinterlacing (do nothing)
     bob                          .D.V..... Bob deinterlacing
     adaptive                     .D.V..... Adaptive deinterlacing
  -gpu               <string>     .D.V..... GPU to be used for decoding
  -surfaces          <int>        .D.V..... Maximum surfaces to be used for decoding (from 0 to INT_MAX) (default 25)
  -drop_second_field <boolean>    .D.V..... Drop second field when deinterlacing (default false)
  -crop              <string>     .D.V..... Crop (top)x(bottom)x(left)x(right)
  -resize            <string>     .D.V..... Resize (width)x(height)

リサイズ

-resize 1280x720

地上デジタル放送や一部BS/CSにある、1440x1080といったソースは、デコーダ側で16:9にリサイズしてエンコーダに渡したほうが良好な結果が出ます (1440x1080を1920x1080にリサイズしてエンコードしても最終サイズは誤差レベルでした)

インターレース解除

-deint adaptive -drop_second_field 1

-deintオプション単独で付与すると、その時点でフレーム数が2倍になるので、一般的録画エンコード目的では-drop_second_fieldとセットで使用します

クロップ(トリミング)

-crop 10x10x80x80

上記の例では、上下10ピクセル、左右80ピクセルをトリミングしています

エンコーダ(h264_nvenc)

hevc_nvenc等もありますが基本的には同じです

h264_nvenc AVOptions:
  -preset            <int>        E..V..... Set the encoding preset (from 0 to 11) (default medium)
     default                      E..V..... 
     slow                         E..V..... hq 2 passes
     medium                       E..V..... hq 1 pass
     fast                         E..V..... hp 1 pass
     hp                           E..V..... 
     hq                           E..V..... 
     bd                           E..V..... 
     ll                           E..V..... low latency
     llhq                         E..V..... low latency hq
     llhp                         E..V..... low latency hp
     lossless                     E..V..... 
     losslesshp                   E..V..... 
  -profile           <int>        E..V..... Set the encoding profile (from 0 to 3) (default main)
     baseline                     E..V..... 
     main                         E..V..... 
     high                         E..V..... 
     high444p                     E..V..... 
  -level             <int>        E..V..... Set the encoding level restriction (from 0 to 51) (default auto)
     auto                         E..V..... 
     1                            E..V..... 
     1.0                          E..V..... 
     1b                           E..V..... 
     1.0b                         E..V..... 
     1.1                          E..V..... 
     1.2                          E..V..... 
     1.3                          E..V..... 
     2                            E..V..... 
     2.0                          E..V..... 
     2.1                          E..V..... 
     2.2                          E..V..... 
     3                            E..V..... 
     3.0                          E..V..... 
     3.1                          E..V..... 
     3.2                          E..V..... 
     4                            E..V..... 
     4.0                          E..V..... 
     4.1                          E..V..... 
     4.2                          E..V..... 
     5                            E..V..... 
     5.0                          E..V..... 
     5.1                          E..V..... 
  -rc                <int>        E..V..... Override the preset rate-control (from -1 to INT_MAX) (default -1)
     constqp                      E..V..... Constant QP mode
     vbr                          E..V..... Variable bitrate mode
     cbr                          E..V..... Constant bitrate mode
     vbr_minqp                    E..V..... Variable bitrate mode with MinQP (deprecated)
     ll_2pass_quality              E..V..... Multi-pass optimized for image quality (deprecated)
     ll_2pass_size                E..V..... Multi-pass optimized for constant frame size (deprecated)
     vbr_2pass                    E..V..... Multi-pass variable bitrate mode (deprecated)
     cbr_ld_hq                    E..V..... Constant bitrate low delay high quality mode
     cbr_hq                       E..V..... Constant bitrate high quality mode
     vbr_hq                       E..V..... Variable bitrate high quality mode
  -rc-lookahead      <int>        E..V..... Number of frames to look ahead for rate-control (from 0 to INT_MAX) (default 0)
  -surfaces          <int>        E..V..... Number of concurrent surfaces (from 0 to 64) (default 0)
  -cbr               <boolean>    E..V..... Use cbr encoding mode (default false)
  -2pass             <boolean>    E..V..... Use 2pass encoding mode (default auto)
  -gpu               <int>        E..V..... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from -2 to INT_MAX) (default any)
     any                          E..V..... Pick the first device available
     list                         E..V..... List the available devices
  -delay             <int>        E..V..... Delay frame output by the given amount of frames (from 0 to INT_MAX) (default INT_MAX)
  -no-scenecut       <boolean>    E..V..... When lookahead is enabled, set this to 1 to disable adaptive I-frame insertion at scene cuts (default false)
  -forced-idr        <boolean>    E..V..... If forcing keyframes, force them as IDR frames. (default false)
  -b_adapt           <boolean>    E..V..... When lookahead is enabled, set this to 0 to disable adaptive B-frame decision (default true)
  -spatial-aq        <boolean>    E..V..... set to 1 to enable Spatial AQ (default false)
  -temporal-aq       <boolean>    E..V..... set to 1 to enable Temporal AQ (default false)
  -zerolatency       <boolean>    E..V..... Set 1 to indicate zero latency operation (no reordering delay) (default false)
  -nonref_p          <boolean>    E..V..... Set this to 1 to enable automatic insertion of non-reference P-frames (default false)
  -strict_gop        <boolean>    E..V..... Set 1 to minimize GOP-to-GOP rate fluctuations (default false)
  -aq-strength       <int>        E..V..... When Spatial AQ is enabled, this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive) (from 1 to 15) (default 8)
  -cq                <float>      E..V..... Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control (from 0 to 51) (default 0)
  -aud               <boolean>    E..V..... Use access unit delimiters (default false)
  -bluray-compat     <boolean>    E..V..... Bluray compatibility workarounds (default false)
  -init_qpP          <int>        E..V..... Initial QP value for P frame (from -1 to 51) (default -1)
  -init_qpB          <int>        E..V..... Initial QP value for B frame (from -1 to 51) (default -1)
  -init_qpI          <int>        E..V..... Initial QP value for I frame (from -1 to 51) (default -1)
  -qp                <int>        E..V..... Constant quantization parameter rate control method (from -1 to 51) (default -1)
  -weighted_pred     <int>        E..V..... Set 1 to enable weighted prediction (from 0 to 1) (default 0)
  -coder             <int>        E..V..... Coder type (from -1 to 2) (default default)
     default                      E..V..... 
     auto                         E..V..... 
     cabac                        E..V..... 
     cavlc                        E..V..... 
     ac                           E..V..... 
     vlc                          E..V..... 
  -b_ref_mode        <int>        E..V..... Use B frames as references (from 0 to 2) (default disabled)
     disabled                     E..V..... B frames will not be used for reference
     each                         E..V..... Each B frame will be used for reference
     middle                       E..V..... Only (number of B frames)/2 will be used for reference
  -a53cc             <boolean>    E..V..... Use A53 Closed Captions (if available) (default true)

たくさんあるので主に使うものだけ

ビットレート指定

基本的にファイルへのエンコードであれば -rc vbr_hqを、リアルタイムトランスコードであればcbr_ld_hqを指定すれば大丈夫です

(手元の環境では-vbr-hq指定がqp指定やcq指定より良好な結果が出ました)

-vb 3M -rc vbr_hq

デコーダでソースを1280x720等にリサイズ済であればデフォルトの2M、1920x1080の場合で3Mぐらいあれば十分かと思います

プリセット

ファイルエンコードであれば無指定(medium)で良いと思います

(もっともslowにして2passにしても劇的に画質が改善されるというほどでもない説)

リアルタイムトランスコードであればfastか無指定で良いかと

ゼロレイテンシ

-zerolatency 1

リアルタイムトランスコードの場合、これを付けるとストリーム開始の待ちがほぼなくなります

NVENCエンコードテスト

2019/01/16現在でのffmpegのエンコードテスト結果を残しておきます

テスト環境

openSUSE Leap 15 on openSUSE Leap 15 with KVM(GPUパススルーで750Tiを渡しています)

  • GPU: NVIDIA Geforce 750Ti
  • CPU: Intel Xeon E3 1245V2(Ivybridge) 3.0GHz VCPU 4Core
  • Mem 4GB
  • ソース:地デジタル放送録画ファイル(30分のアニメ3.7GB 1440x1080)

サイズ1920x1080/-vbr_hqのみ

ffmpeg -c:v mpeg2_cuvid -resize 1920x1080 -i input.ts -c:v h264_nvenc -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 -f mp4 -aspect 16:9 output.mp4
  • エンコード速度 : 7.5倍速
  • ファイルサイズ : 532M

ちょっと保存には使えないレベル、画質を気にしない番組ならまあ。ぐらい

サイズ1920x1080&インターレース解除/-vbr_hqのみ

ffmpeg -c:v mpeg2_cuvid -resize 1920x1080 -deint 2 -drop_second_field 1 -i input.ts -c:v h264_nvenc -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 -f mp4 -aspect 16:9 output.mp4
  • エンコード速度 : 6倍速
  • ファイルサイズ : 508M

インターレース解除によりサイズが縮む。画質もかなり見られるようになる。家族にQSVエンコードした同サイズ動画とブラインドテストしてもらったけど区別がつかなかった

サイズ1920x1080&インターレース解除/ビットレート3M

ffmpeg -c:v mpeg2_cuvid -resize 1920x1080 -deint 2 -drop_second_field 1 -i input.ts -c:v h264_nvenc -vb 3M -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 -f mp4 -aspect 16:9 output.mp4
  • エンコード速度 : 6倍速
  • ファイルサイズ : 680M

単純にビットレートが増えた分サイズが大きくなる。保存用にしても良いと思えるレベル(主観)

サイズ1440x810&インターレース解除/-vbr_hqのみ

ffmpeg -c:v mpeg2_cuvid -resize 1440x810 -deint 2 -drop_second_field 1 -i input.ts -c:v h264_nvenc -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 -f mp4 -aspect 16:9 output.mp4
  • エンコード速度 : 9倍速
  • ファイルサイズ : 492M

速度とサイズと画質のバランスが非常に良い(主観)。1440x1080のソースであればこれで十分説。自分ちの録画サーバーのデフォルトはこの設定にしてる

サイズ1280x720&インターレース解除/ビットレート1.5M

ffmpeg -c:v mpeg2_cuvid -resize 1280x720 -deint 2 -drop_second_field 1 -i input.ts -c:v h264_nvenc -vb 1500k -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 -f mp4 -aspect 16:9 output.mp4
  • エンコード速度 : 11倍速
  • ファイルサイズ : 372M

スマホ観賞用サイズ。スマホ等で鑑賞する分には全く問題ない。出かける前に電車でこれ見ようとエンコードを開始して、駅までの間にエンコードが終わってるのは便利

サイズ1080x810(4:3トリミング)&インターレース解除/-vbr_hqのみ

ffmpeg -c:v mpeg2_cuvid -crop 0x0x180x180 -resize 1080x810 -deint 2 -drop_second_field 1 -i input.ts -c:v h264_nvenc -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 -f mp4 -aspect 4:3 output.mp4
  • エンコード速度 : 9.5倍速
  • ファイルサイズ : 402M

4:3のソースをトリミングして容量削減を狙った設定。もともと4:3ソースという時点でソースの画質自体がわりとお察しなのもあり余裕で綺麗。

GTX1080との比較

別マシンのGTX1080にてh264テストを行ったところ、エンコード速度は概ね2〜2.5倍程度(1440x810で20倍速ぐらい)になったが、最終サイズは1MB未満の差しかなく、画質面では有意な差は感じられなかった。最近NVENCが画質面でもQSVにかなり追いついたと言われるが、ドライバ層での改善による点が大きいと思われる

まとめ

QSVと比較すると画質面で落ちる落ちると言われていたNVENCですが、最近はドライバとffmpegの改善により以前ほど差がない、というよりHEVCでは逆転現象すら起きている状態です。是非一度試してみてください

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment