morfizm (morfizm) wrote,
morfizm
morfizm

Category:

Кодирование видео в домашних условиях

С появлением камеры Sony A6000, возникли как новые возможности (снимать 1920x1080 @ 60fps), так и новые проблемы: полуторачасовая запись (5549 секунд) занимает 33.5 GB (36,049,184,027 байт). Это огромные объёмы с ними трудно что-то делать. Я бы с большим удовольствием брал меньше точек, или согласился бы на какое-то более агрессивное сжатие в самой камере, чтобы она выплёвывала меньшего размера файлы, но это невозможно. Все "пониженные" форматы не дают 60 fps.

Кстати, насчёт 60 fps - небольшое отступление. Есть распространённое заблуждение, что для видео нужно 25-30 кадров в секунду, а 60 нужны только, если будешь потом вдвое замедлять. Это пример так называемого bullshit'а. 25-30 кадров это минимальный frame rate, позволяющий видеть видео как "плавное", но глаз способен различать куда больше, и он офигенно наслаждается этим. Погуглите 60 fps видео, напр., вот это: https://www.youtube.com/watch?v=rql_F8H3h9E, или даже специальные сравнения 60 и 30: https://www.youtube.com/watch?v=IrK5cDU9AIA . В общем, если камера может делать 60, то необходимо это использовать, это просто ругой уровень качества.

Кстати, есть разница между 60p и 60i. i-это ненастоящие кадры в секунду, а интерполированные. Кадры чередуются, в одном идёт одна половина изображения (скажем, чётные горизонтальные сканлинии), а в следующем, скажем, нечётные. Эта буква "p" важна.

Ещё момент: для 60 fps при таком же "ощущаемом" качестве нужен более высокий битрейт. Я экспериментировал, и вывел для себя, что примерно 9-12 MBit/sec даёт приемлемое качество для 1080p60 (1920x1080 @ 60p), а 3 MBit/sec - это минимальное качество, которое уже выглядит плохо, но всё ещё сохраняются какие-то прелести высокой частоты кадров. Я для себя выбрал такую стратегию:
*) в 3 MBit/sec можно кодировать бросовые видео, когда плевать, получит ли зритель удовольствие от просмотра (например, информативные туториалы),
*) в 12 MBit/sec кодировать всё остальное, когда хочется хорошего качества,
*) но: в 9 MBit/sec кодировать, если хочется хорошего качества, но уж очень жалко места на диске. Как, скажем, пример с полуторочасовым исходником. Разница между 9 MBit/sec и 12 MBit/sec приводит к разнице между 6GB и 8GB в конечном файле.

Как кодировать? Я не разбираюсь в теме, но один мой друг посоветовал Sony Vegas (я не буду показывать пальцем, но, наверное, ты понял, что я о тебе ;)), и пробовал использовать его.

С ним такая проблема: он начинает глючить, когда работы слишком много. Downsample, чтобы уменьшить разрешение он не может делать вообще (виснет, падает с ошибками), но даже простое кодирование ему не под силу, в случае больших файлов. Он говорит, что работа займёт 18 часов, где-то на 5 часу вдруг перестают двигаться проценты прогресса (и потом этот процесс никогда не заканчивается), потом перезапускаешь, он работает 10 часов, и грязно виснет, и т.п. В общем, накопилось достаточно фрустрации, чтобы поискать достойную альтернативу.

Достойной альтернативой оказался опенсоурсный ffmpeg, который можно собрать самому, а можно скачать готовую сборку. Утилита для командной строки. Она может кодировать, может также делать какие-то простые преобразования. Я рассмотрю мой пример с 1.5 часовым видео, которое я склеивал из 6 кусочков.

ffmpeg -i C0001.MP4 -i C0002.MP4 -i C0003.MP4 -i C0004.MP4 -i C0005.MP4 -i C0006.MP4 -filter_complex concat=n=6:v=1:a=1 -c:v libx264 -crf 20 -c:a aac -b:a 192k Result.mp4

Параметр качества - это -crf 20. По умолчанию, кажется, 22. Чем ниже число, тем выше качество. 20 даёт как раз примерно 9-12 MBit/sec на 1080p60, то, что мне нужно. Считается, что ниже 17-18 для человеческого глаза разница в качестве заметна не будет, что подтверждается моими тестами. Уменьшение или увеличение числа на 6 приводит к изменению битрейта примерно вдвое. Но использование такого числа хорошо тем, что оно определяет качество, т.е. не нужно будет пересчитывать, какой же нужен битрейт, если у вас другой размер видео или другая частота кадров.

Кодирование заняло 5 часов. Отлично!
Но я решил пойти немножко дальше... я заметил, что он всё равно кушал 100% CPU, значит, он не использовал чип моей видеокарты (GPU), а использовать GPU должно быть эффективнее.

Мой настольный компьютер имеет такие железки:
*) NVIDIA GeForce GTX 645. Это бюджетная маленькая карточка для системных блоков с низкой мощностью, ей нужно до 130W, поэтому она подходит для системных блоков до 450W... если у вас SSD, и нет вращающихся хардов, то я бы и на 350W не побоялся её поставить; я покупал вариант от Dell'а (вроде такого) - он хорош тем, что ей не нужно дополнительное питание и ей хватает одного слота. С такими ограничениями это лучшая видеокарта из тех, что я нашёл, но она таки слабая и дешёвая по сравнению с крутыми геймерскими. У жены стоит GTX 960, и это уже совсем другой уровень.
*) Intel Core i7-2600 @ 3.40 GHz

Для того, чтобы ffmpeg работал с GPU, нужны три вещи:
*) Видеокарта, которая поддерживает CUDA или другие программные интерфейсы, для которых есть поддержка в ffmpeg. NVIDIA поддерживает CUDA.
*) Раздобыть бинарник ffmpeg, откомпилированный с флагом --enable-nvenc (для NVIDIA). Для линуксов это делается тривиально через configure, и ты собираешь свой вариант. Для винды - компилировать из исходников это гемор, поэтому пришлось поискать готовый бинарник. Он нашёлся вот здесь: https://github.com/illuspas/ffmpeg-hw-win32 (скачиваем репозиторий как ZIP-файл и копируем бинарники из x86_64/bin, там есть ffmpeg.exe)
*) Проинсталлировать NVidia CUDA - официальные драйвера для NVidia, поддерживающие программный интерфейс. Это не то же самое, что обычные драйвера для видеокарты. Гуглим "nvidia cuda drivers", идём сюда: https://developer.nvidia.com/cuda-downloads, скачиваем, ставим.

Вот команда, которой я сделал всё то же самое через GPU:

ffmpeg -i C0001.MP4 -i C0002.MP4 -i C0003.MP4 -i C0004.MP4 -i C0005.MP4 -i C0006.MP4 -filter_complex concat=n=6:v=1:a=1 -c:v nvenc_h264 -b:v 9500k -minrate 5000k -maxrate 18000k -preset llhq -c:a aac -b:a 192k Result.mp4

Мне пришлось вручную прописывать битрейт (-b:v 9500k -minrate 5000k -maxrate 18000k), потому что параметр -crf для этого кодека не поддерживается, а по умолчанию получается 3.5 MBit/sec, мне слишком мало.

Но... результат - это кодирование в реальном времени. 1.5 часа видео = 1.5 часа занимает кодирование.
Кроме того, процессор почти не загружен, вентилятор не шумит, можно параллельно использовать компьютер без неудобств. Да и памяти куда меньше жрёт. Лепота!

Резюмируя:
1. Sony Vegas - 18 часов, 100% CPU, 2GB RAM (working set), глючит и подвисает, нужно рестартовать.
2. ffmpeg, libx264 - 5 часов, 100% CPU, 1GB RAM - всё пучком.
3. ffmpeg nvenc_h264 - 1.5 часа (~= realtime, encoding FPS=61), 15% CPU, 370MB RAM.
Tags: 1, software
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 21 comments