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

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

  • Gistから転載

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

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

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

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

1
zypper si -d ffmpeg

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

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

1
2
3
4
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レポジトリをホストしていますのでこれを入れます

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

ffmpegのソース取得

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

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

configure

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$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現在、どうにも依存関係が解決できなかったのと、無くてもさほど困らないと判断して)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    --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を実行すると依存関係であれがないこれがないと言われるはずなのでそれらを導入します

1
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です

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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します

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

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

使用可能オプション

基本形

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

デコーダ(mpeg2_cuvid)

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

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

1
2
3
4
5
6
7
8
9
10
11
$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)

リサイズ

1
-resize 1280x720

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

インターレース解除

1
-deint adaptive -drop_second_field 1

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

クロップ(トリミング)

1
-crop 10x10x80x80

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

エンコーダ(h264_nvenc)

hevc_nvenc等もありますが基本的には同じです
たくさんあるので主に使うものだけ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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指定より良好な結果が出ました)

1
-vb 3M -rc vbr_hq

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

プリセット

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

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

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

ゼロレイテンシ

1
-zerolatency 1

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

エンコードテスト

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のみ

1
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のみ

1
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

1
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のみ

1
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

1
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のみ

1
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では逆転現象すら起きている状態です。是非一度試してみてください

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×