Шпаргалка по сборке FFmpeg с NVENC H.264 и H.265 на последней Ubuntu LTS (18.04). Использование мощи видеокарты от NVIDIA для обработки видео, в моем случае 1080p60 обработалось быстрее в 4 раза чем на процессоре, ну и при этом совершенно не грузило систему (видеокарта тоже даже не нагрелась).

Лирическое отступление

Вот уже пару лет есть работающая схема по добавлению потока RTSP камер наблюдения в HomeKit и вот она. Это плагин для HomeBridge, есть иные костыли, но суть одна, всё завязано на конвертации RTSP потока в RTMP и скармливании его home.app. Самым простым способом сделать это является перекодировка, а так как обычно под рукой линуксоподобная система — ffmpeg (avconv, прочее, но в первую очередь именно ffmpeg).

Для умных домов преимущественно используют Raspberry Pi и оно не может нормально кодировать видео в силу слабого процессора. Сборка ffmpeg (в дистрибутивах Raspbian его нет именно потому что нормальный человек не должен встречаться с такими тормозами) на малинке занимает 40-50 минут и работает оно откровенно плохо, кадры дропаются, малинка греется даже при одном потоке, а если двое хотят одновременно посмотреть камеры происходит коллапс. Даже h264_omx проблему полностью не решает, нужно нормальное железо и это обычный компьютер. Даже вшивый Celeron вполне прилично справляется с задачей, но есть способ еще лучше.

У меня есть ненужная система на Intel(R) Celeron(R) CPU G3930 @ 2.90GHz и GeForce GTX 1060, с этим железом можно добиться удивительных результатов малой кровью, не загружая особо процессор и одновременно показывая видео с камер на 7 устройств (может и больше, у меня нету просто столько конечных устройств).

Сейчас мы соберем на последней серверной убунте FFmpeg с аппаратной поддержкой кодирования H.264 и оно будет быстрым, очень быстрым. В тестах видео fullhd кодировалось в 4-6 раз быстрее, чем стандартным кодеком x264 через процессор.

Всякое:

Ставим пакеты

sudo apt install build-essential git yasm unzip wget mc sysstat nasm 
libavcodec-dev libavformat-dev libavutil-dev pkgconf g++ freeglut3-dev 
libx11-dev libxmu-dev libxi-dev libglu1-mesa libglu1-mesa-dev libx265-dev libnuma-dev

Драйвера:

Ставим CUDA с родного сайта, инструкции тут (но они могли измениться, лучше кликнуть по ссылке)

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
sudo apt-get update
sudo apt-get -y install cuda
reboot

Проверяем что всё работает и драйвера встали

nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.00    Driver Version: 418.87.00    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 106...  Off  | 00000000:01:00.0 Off |                  N/A |
| 33%   28C    P0    28W / 120W |      0MiB /  3019MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

Добавляем переменные в PATH. И так каждый раз после перезагрузки для сборки ffmpeg, потом не нужно.

export PATH=/usr/local/cuda-10.1/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-10.1/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

Качаем и ставим NVIDIA video codek SDK (нужна регистрация), указываем свою версию, а не 9.0.20:

unzip Video_Codec_SDK_9.0.20.zip
sudo cp Video_Codec_SDK_9.0.20/Samples/common.mk /usr/local/include/

Ставим FFmpeg

Самое нужное это собсно поддержка nv-codec

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

Поддержка H.264. Не уверен что оно нужно на 18.04 (у меня был автоматически установлен), но на всякий случай последняя версия:

git clone https://code.videolan.org/videolan/x264.git
cd x264/
./configure --disable-cli --enable-static --enable-shared --enable-strip
make
sudo make install
sudo ldconfig

Сам FFmpeg:

git clone git://source.ffmpeg.org/ffmpeg.git
cd ffmpeg/
./configure --enable-nonfree --enable-nvenc --enable-libx264 --enable-libx265 --enable-gpl --enable-cuda --enable-cuvid
make
sudo make install

Убеждаемся что мы можем кодировать H.264 и H.265 с помощью видеокарты:

ptath@castle:~/ffmpeg$ ffmpeg -codecs | grep nvenc
ffmpeg version N-94809-g12b909ba31 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
  configuration: --enable-nonfree --enable-nvenc --enable-libx264 --enable-libx265 --enable-gpl --enable-cuda --enable-cuvid
  libavutil      56. 35.100 / 56. 35.100
  libavcodec     58. 56.101 / 58. 56.101
  libavformat    58. 32.104 / 58. 32.104
  libavdevice    58.  9.100 / 58.  9.100
  libavfilter     7. 58.102 /  7. 58.102
  libswscale      5.  6.100 /  5.  6.100
  libswresample   3.  6.100 /  3.  6.100
  libpostproc    55.  6.100 / 55.  6.100
 DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_v4l2m2m h264_cuvid ) (encoders: libx264 libx264rgb h264_nvenc h264_v4l2m2m nvenc nvenc_h264 )
 DEV.L. hevc                 H.265 / HEVC (High Efficiency Video Coding) (decoders: hevc hevc_cuvid ) (encoders: libx265 nvenc_hevc hevc_nvenc )

О да, мы можем =) А теперь тесты:

wget http://download4.dvdloc8.com/trailers/divxdigest/i_am_legend-1080p_blu-ray_trailer.zip
unzip i_am_legend-1080p_blu-ray_trailer.zip 

time ffmpeg -i I\ Am\ Legend\ -\ Trailer.mp4 -vcodec libx264 -b:v 5M -acodec copy Output_libx264.mp4
...
real	2m33,211s
user	4m58,844s
sys	0m0,608s

time ffmpeg -i I\ Am\ Legend\ -\ Trailer.mp4 -vcodec libx265 -b:v 5M -acodec copy Output_libx265.mp4
...
real	8m17,279s
user	15m57,109s
sys	0m0,588s

time ffmpeg -i I\ Am\ Legend\ -\ Trailer.mp4 -vcodec h264_nvenc -b:v 5M -acodec copy Output_h264_nvenc.mp4
...
real	0m20,966s
user	0m27,845s
sys	0m0,620s

time ffmpeg -i I\ Am\ Legend\ -\ Trailer.mp4 -vcodec hevc_nvenc -b:v 5M -acodec copy Output_hevc_nvenc.mp4
...
real	0m20,990s
user	0m28,007s
sys	0m0,650s

Собственно мы наблюдаем космическую скорость, особенно когда дело доходит до H.265 — с нашим новым кодеком мы справляемся за 20 секунд вместо 8 с половиной минут через x265 (стоит отметить что процессор — Celeron, на i7 должно быть побыстрей конечно).

Практическое применение — обработка видео со всяких там action-камер, ну и конечно же в системах умного дома на базе HomeKit. В дополнение к малинке ничто не мешает отдельно использовать нормальный сервер исключительно под видео.