3.5万円のミニPCでハードウェアエンコードして6倍時間短縮した話
経緯
動画が沢山あるけどストレージの容量は限られてる!
H.265でエンコードしたかったわけですが、4コア8スレッドとかだと0.7倍速くらいでしかエンコードできない... これではいつまで経っても終わらない!!
ということで、ハードウェアエンコードしまくればいいじゃないか!と思い立ったわけです。
環境
PC
Lenovo M75q-1 tiny
CPU: Ryzen 5 PRO 3400GE 4C8T
RAM: 16GB DDR4
GPU: Radeon Vega 11
OS : Ubuntu 18.04.4 LTS Desktop
Lenovo M75q-1 tinyについて
今回の隠れたテーマはこの激安Ryzen搭載小型デスクトップです。
週末特価を狙うとおよそ3.5万円で NVMeのSSD, 8GB RAM, Ryzen 5 PRO 3400GEの小型デスクトップが手に入って最高なシロモノですね。
なんとWindows 10 Proも入っています。※ 今回は吹き飛ばしてOSはUbuntuを入れてます。
あまりに安くそこそこの性能でめちゃくちゃ静かなので、我が家ではテレビのそばに付けっぱなしで設置して、NAS, VPNサーバー, リモート開発サーバーなどとして使ってます。
多少手間はかかりますが、そのへんの激安NASキットよりも100倍いいです。(当社比です)
Ryzen 5 PRO 3400GEは性能としてはまったくRyzen 5 3400GEと同じで、Ryzen 5 3400Gの35W版です。
RyzenシリーズのG付きモデルは所謂APUというやつで、内蔵グラフィックスとしてRadeon Vegaが載っているものになります。
このPCに付属するACアダプタが65Wなので問題なさそうなのですが、さすがにカツカツらしく、より大容量のACアダプタに交換すると主にGPU性能が爆アゲするらしいです(未確認)
ヤフオクで本物かわからない135WのACアダプタを買ったので、届いたら交換してレビューします。
Amazonで買うなら↓がよさそう。
本当はM75q-1 tinyのレビュー記事も書きたかったのですが、面倒なので↓を参考に。 little-beans.net
調査
ffmpegを利用したLinuxでのハードウェアエンコード事情
今回のキモは「Linuxでの」というところになります。
Windowsで使う場合は、Linux上でクロスコンパイルしたffmpegのバイナリをWindowsに持ってきて使ったりするらしいです。
参考: AMD VCE 対応の ffmpeg をつくる | ニコラボ
Linux上では、VA-API経由でのハードウェアエンコードにしか対応していないみたいなので、こいつを使います。
HWAccelIntro – FFmpeg
手順
1. ffmpeg 4系を入れる
ちょっと古いですが↓の資料をみると、VA-APIを使ったハードウェアエンコードはffmpeg 4.0で大幅な最適化が入ったそうです。
今時のLinuxにおけるGPUエンコード事情2018
ところがUbuntu 18.04.4 LTSで標準で入るffmpegは本記事の執筆時点で 3.4.6
です。
そのため、まずは野良aptリポジトリを使って4系を入れます。
野良リポジトリ追加
sudo add-apt-repository ppa:savoury1/ffmpeg4 sudo add-apt-repository ppa:savoury1/graphics sudo add-apt-repository ppa:savoury1/multimedia sudo apt-get update
ffmpegインストール
sudo apt-get install ffmpeg
ffmpeg -version
$ ffmpeg -version ffmpeg version 4.2.2-1ubuntu1~18.04.sav0 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04) configuration: --prefix=/usr --extra-version='1ubuntu1~18.04.sav0' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56. 31.100 / 56. 31.100 libavcodec 58. 54.100 / 58. 54.100 libavformat 58. 29.100 / 58. 29.100 libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100
無事 4.2.2
が入ったようです。
$ ffmpeg -h encoder=hevc_vaapi (0)[~] ffmpeg version 4.2.2-1ubuntu1~18.04.sav0 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04) configuration: --prefix=/usr --extra-version='1ubuntu1~18.04.sav0' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56. 31.100 / 56. 31.100 libavcodec 58. 54.100 / 58. 54.100 libavformat 58. 29.100 / 58. 29.100 libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100 Encoder hevc_vaapi [H.265/HEVC (VAAPI)]: General capabilities: delay hardware Threading capabilities: none Supported pixel formats: vaapi_vld h265_vaapi AVOptions: -low_power <boolean> E..V..... Use low-power encoding mode (only available on some platforms; may not support all encoding features) (default false) -idr_interval <int> E..V..... Distance (in I-frames) between IDR frames (from 0 to INT_MAX) (default 0) -b_depth <int> E..V..... Maximum B-frame reference depth (from 1 to INT_MAX) (default 1) -rc_mode <int> E..V..... Set rate control mode (from 0 to 6) (default auto) auto E..V..... Choose mode automatically based on other parameters CQP E..V..... Constant-quality CBR E..V..... Constant-bitrate VBR E..V..... Variable-bitrate ICQ E..V..... Intelligent constant-quality QVBR E..V..... Quality-defined variable-bitrate AVBR E..V..... Average variable-bitrate -qp <int> E..V..... Constant QP (for P-frames; scaled by qfactor/qoffset for I/B) (from 0 to 52) (default 0) -aud <boolean> E..V..... Include AUD (default false) -profile <int> E..V..... Set profile (general_profile_idc) (from -99 to 255) (default -99) main E..V..... main10 E..V..... rext E..V..... -tier <int> E..V..... Set tier (general_tier_flag) (from 0 to 1) (default main) main E..V..... high E..V..... -level <int> E..V..... Set level (general_level_idc) (from -99 to 255) (default -99) 1 E..V..... 2 E..V..... 2.1 E..V..... 3 E..V..... 3.1 E..V..... 4 E..V..... 4.1 E..V..... 5 E..V..... 5.1 E..V..... 5.2 E..V..... 6 E..V..... 6.1 E..V..... 6.2 E..V..... -sei <flags> E..V..... Set SEI to include (default hdr) hdr E..V..... Include HDR metadata for mastering display colour volume and content light level information
よくわからないけどどうやら使えそうです。()
2. VA-APIの準備
確認ツールのインストール
VA-APIの対応状況を確認しておくため、確認ツールを入れます。
sudo apt-get install vainfo
$ vainfo (0)[~] error: can't connect to X server! libva info: VA-API version 1.7.0 libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/radeonsi_drv_video.so libva info: Found init function __vaDriverInit_1_1 libva info: va_openDriver() returns 0 vainfo: VA-API version: 1.7 (libva 2.1.0) vainfo: Driver version: Mesa Gallium driver 19.2.8 for AMD RAVEN (DRM 3.33.0, 5.3.0-53-generic, LLVM 9.0.0) vainfo: Supported profile and entrypoints VAProfileMPEG2Simple : VAEntrypointVLD VAProfileMPEG2Main : VAEntrypointVLD VAProfileVC1Simple : VAEntrypointVLD VAProfileVC1Main : VAEntrypointVLD VAProfileVC1Advanced : VAEntrypointVLD VAProfileH264ConstrainedBaseline: VAEntrypointVLD VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice VAProfileH264Main : VAEntrypointVLD VAProfileH264Main : VAEntrypointEncSlice VAProfileH264High : VAEntrypointVLD VAProfileH264High : VAEntrypointEncSlice VAProfileHEVCMain : VAEntrypointVLD VAProfileHEVCMain : VAEntrypointEncSlice VAProfileHEVCMain10 : VAEntrypointVLD VAProfileJPEGBaseline : VAEntrypointVLD VAProfileVP9Profile0 : VAEntrypointVLD VAProfileVP9Profile2 : VAEntrypointVLD VAProfileNone : VAEntrypointVideoProc
リモートからつないでいるのでX serverにつながらん!といわれますが、 VAProfileHEVCMain
の VAEntrypointVLD
と VAEntrypointEnvcSlice
があるので、対応していそうですね。
ドライバは /usr/lib/x86_64-linux-gnu/dri/radeonsi_drv_video.so
となっていて、これはRadeonの標準ドライバだそうです。
利用するドライバを明示
今回はVGAデバイスが一つしか無くてドライバが一つしかロードされていないので指定しなくても問題ない気がしますが、ねんのためVA-APIで利用するドライバを指定しておきます。
export LIBVA_DRIVER_NAME=radeonsi
3. エンコード実行
では実際にエンコードしていきましょう。テストとして今回はH.264の動画を、音声はそのままでH.265に変換してみます。
ffmpeg -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -i hoge.mp4 -vf 'format=p010|vaapi,hwupload' -c:v hevc_vaapi -qp 28 -c:a copy -tag:v hvc1 hoge_hw.mp4
詳しいオプションは説明しませんが、vaapiと書いてある部分のオプションが重要です。
動画の品質は -qp
オプションで決定できます。
H.264の場合は以下のような感じです。
ffmpeg -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -i hoge.mp4 -vf 'format=nv12|vaapi,hwupload' -c:v h264_vaapi -qp 28 -c:a copy -tag:v hvc1 hoge_hw.mp4
4. 結論
実行したときの変換速度を比較してみます。
ソフトウェアエンコードの場合
$ ffmpeg -i hoge.mp4 -c:v libx265 -qp 28 -c:a copy -tag:v hvc1 hoge_hw.mp4 frame= 456 fps= 42 q=-0.0 size= 1280kB time=00:00:16.32 bitrate= 642.5kbits/s speed= 1.5x
ハードウェアエンコードの場合
$ ffmpeg -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -i hoge.mp4 -vf 'format=p010|vaapi,hwupload' -c:v hevc_vaapi -qp 28 -c:a copy -tag:v hvc1 hoge_hw.mp4 frame= 1148 fps=228 q=-0.0 size= 6912kB time=00:00:39.33 bitrate=1439.4kbits/s speed=7.83x
およそ6倍くらいのスピードが出ていますね。すごい。
Ryzen 5のG付きはAPUなので、GPUもCPUも大体同じくらいの温度になるのですが、
ソフトウェアエンコードのときは80℃近く、ハードウェアエンコードのときは50℃前後で落ち着いていました。
まとめ
h.265の変換で、およそ6倍程度の変換速度の差が出ました。
ただし、実際の変換結果は載せませんが傾向としてソフトウェアエンコードのほうが画質がよく、 -qp
でのクオリティ設定ではよりビットレートが低く、つまり容量が小さくなる傾向にあります。
容量をめちゃくちゃ重視するならソフトウェアエンコードでじっくり、現実的にはハードウェアエンコードで丁度いい画質設定を探してがっつりエンコードするのがよいのではないでしょうか。
参考
Ubuntu – bionic の ffmpeg パッケージに関する詳細
How to Install FFmpeg 4.2 in Ubuntu 18.04 / Linux Mint 19.x | UbuntuHandbook
www.sunmattu.net