Nvidia GPUが存在するLinux環境では、NVIDIAのハードウェアエンコーディング/デコーディング機能であるNVENC/NVDECが利用可能ですが、openSUSEの標準パッケージとして利用可能なffmpegではNVENC/NVDECが有効化されていません。これはNVIDIAのライセンス規約により同機能を有効にしたffmpegのバイナリ再配布が許されていないためです。(おそらくほとんどのディストリビューション添付のffmpegも同じはず)
そこで、ffmpegをソースからビルドし、NVENC/NVDECを使えるようにします
zypperでffmpegに必要な各種ライブラリとツールをダウンロードします
zypper si -d ffmpeg
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のgithubリポジトリから最新のソースをダウンロードします
git clone git://github.com/FFmpeg/FFmpeg ffmpeg/
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
~略~
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
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ピクセルをトリミングしています
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
リアルタイムトランスコードの場合、これを付けるとストリーム開始の待ちがほぼなくなります
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)
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
ちょっと保存には使えないレベル、画質を気にしない番組ならまあ。ぐらい
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エンコードした同サイズ動画とブラインドテストしてもらったけど区別がつかなかった
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
単純にビットレートが増えた分サイズが大きくなる。保存用にしても良いと思えるレベル(主観)
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のソースであればこれで十分説。自分ちの録画サーバーのデフォルトはこの設定にしてる
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
スマホ観賞用サイズ。スマホ等で鑑賞する分には全く問題ない。出かける前に電車でこれ見ようとエンコードを開始して、駅までの間にエンコードが終わってるのは便利
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にてh264テストを行ったところ、エンコード速度は概ね2〜2.5倍程度(1440x810で20倍速ぐらい)になったが、最終サイズは1MB未満の差しかなく、画質面では有意な差は感じられなかった。最近NVENCが画質面でもQSVにかなり追いついたと言われるが、ドライバ層での改善による点が大きいと思われる
QSVと比較すると画質面で落ちる落ちると言われていたNVENCですが、最近はドライバとffmpegの改善により以前ほど差がない、というよりHEVCでは逆転現象すら起きている状態です。是非一度試してみてください