- Gistから転載
Nvidia GPUが存在するLinux環境では、NVIDIAのハードウェアエンコーディング/デコーディング機能であるNVENC/NVDECが利用可能ですが、openSUSEの標準パッケージとして利用可能なffmpegではNVENC/NVDECが有効化されていません。これはNVIDIAのライセンス規約により同機能を有効にしたffmpegのバイナリ再配布が許されていないためです。(おそらくほとんどのディストリビューション添付のffmpegも同じはず)
そこで、ffmpegをソースからビルドし、NVENC/NVDECを使えるようにします
- ビルド依存環境のダウンロード
- CUDA ToolkitとNVIDIA Video SDKのインストール
- ffmpegのソース取得
- configure
- make
- 使用可能オプション
- エンコードテスト
- まとめ
ビルド依存環境のダウンロード
zypperでffmpegに必要な各種ライブラリとツールをダウンロードします
1 | zypper si -d ffmpeg |
CUDA ToolkitとNVIDIA Video SDKのインストール
ffmpegでハードウェアによるリサイズやデインターレース等のフィルター機能を使う場合、CUDAライブラリの一つ、libnppが必要になりますのでこれもインストールします
1 | wget https://developer.download.nvidia.com/compute/cuda/repos/opensuse15/x86_64/cuda-repo-opensuse15-10.0.130-1.x86_64.rpm |
NVIDIA Video SDKはVLCプロジェクトがgitレポジトリをホストしていますのでこれを入れます1
2
3git 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 | $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 | install prefix /usr/local |
make
cudaを有効にしている場合、makeの中でcuda toolkitのnvccを使うので、PATHに/usr/local/cuda/binを追加で通してmakeします1
2PATH=$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
91h264_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では逆転現象すら起きている状態です。是非一度試してみてください