FFmpeg не сохраняет цвета после изменения размера

Я хотел бы изменить размер видео 4K mkv до 1920 × 1080 с помощью ffmpeg version 3.4.6-0ubuntu0.18.04.1Ubuntu 18.04. Исходный файл имеет следующие особенности:

Input #0, matroska,webm
encoder         : libebml v1.3.9 + libmatroska v1.5.2
Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x2160 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)

Эта версия FFmpegможет не поддерживать x265. Я скомпилировал новую версию из текущего репозитория Git , явно включивx265 . Теперь ffmpeg -hide_banner -pix_fmtsимеет в своем выводе:

FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL
-----
IO... yuv420p10le            3            15

Этот формат теперь должен поддерживаться как для кодирования, так и для декодирования. Я пытался:

ffmpeg -i original_file.mkv -c:v libx265 -pix_fmt + -vf scale=1920:1080 -colorspace bt709 -c:a copy test_output.mkv

Это производит:

Input #0, matroska,webm, from 'test_output.mkv':
  Metadata:
    ENCODER         : Lavf58.35.100
    Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt709/unknown/unknown), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)

Так что, видимо, нормально. Тем не менее, test_output.mkvцвета по-прежнему кажутся вдвое менее интенсивными, чем исходные, как если бы серый слой накладывался на видео 4K. Я открыл файл с помощью обоих vlcи mpvбез разницы.

  1. Как максимально сохранить исходные цвета?

  2. Если есть возможность, то хотелось бы еще и битрейт понизить, но моя попытка

    ffmpeg -i original_file.mkv -s 1920x1080 -b 1700 output.mkv
    

    произвел сплошное серое видео с несколькими движущимися квадратами.


Я всегда получаю это сообщение:

[matroska,webm @ 0x55a5507ad100] Could not find codec parameters for stream 1 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options

FFmpegпостроенный из исходников, имеет следующую конфигурацию:

ffmpeg version N-95768-gd831edc387 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 7 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
configuration: --enable-gpl --enable-libx264 --enable-libx265
libavutil      56. 36.100 / 56. 36.100
libavcodec     58. 62.100 / 58. 62.100
libavformat    58. 35.100 / 58. 35.100
libavdevice    58.  9.101 / 58.  9.101
libavfilter     7. 66.100 /  7. 66.100
libswscale      5.  6.100 /  5.  6.100
libswresample   3.  6.100 /  3.  6.100
libpostproc    55.  6.100 / 55.  6.100

Ответы (2)

Объявление 1:

Попробуйте добавить -pix_fmt yuv420p10leпараметр (например, перед -vf). Или только -pix_fmt +для использования того же формата пикселей, что и входное видео.

Если не поможет, то у вас явно неподходящая, хотя и более распространенная версия FFmpeg — только для 8-битных цветов. (В исходном видео используются 10-битные цвета, и в этом случае FFmpeg попытается использовать наилучший 8-битный формат пикселей — конечно, с ухудшением цвета.)

FFmpeg может быть создан для 8-битных цветов или для 10-битных цветов, или — в последнее время — для обоих из них (для вашего видео в кодировке HEVC).

Поэтому вам необходимо собрать (или получить другим способом) версию для 8-/10- или 10-битной глубины цвета.

Объявление 2:

Битрейт 1700очень низкий — всего 1700 бит в секунду, т.е. около 212 байт в секунду .

Чтобы достичь такого низкого битрейта и в то же время достичь ваших 23.98кадров в секунду, кодировщик ограничен средним размером для 1 кадра около 212 / 24 = всего 9 байт!

Вы видели картинку такой маленькой памяти? Информации почти нет, поэтому изображение серое.

Вы, вероятно, хотели 1700 000 000 000 000 000 000 (Килобит в секунду) — или, что более вероятно — 170 000 000:

-b:v 170k

поэтому исправьте свою команду таким образом.


Дополнение к объявлению 1:

Вы используете (по умолчанию) субдискретизацию цветности 4:2:0 (с неизбежным ухудшением цвета и контраста).
Попробуйте максимальное качество, т.е. 4:4:4 (без подвыборки), или — если вам будет достаточно — 4:2:2.

Для этого используйте -pix_fmt yuv444p10leи измените профиль видео на main444-10 (с опцией -profile:v main444-10).

Спасибо за все очень полезные пояснения. Я попробовал версию, скомпилированную из исходного кода (с поддержкой x265), FFmpegа также более новую версию. Даже при использовании (в обоих случаях) -pix_fmt yuv420p10leпроблема та же. Проверьте сообщение об ошибке, которое я добавил в вопрос, если оно полезно. Более того, FFmpegсоздает x264вывод по умолчанию; как сохранить оригинал HEVCвместо этого?
Используйте ffmpeg -hide_banner -pix_fmts, чтобы узнать, есть ли в вашей сборке пиксельный формат yuv420p10le . Если нет, ваша сборка не поддерживает 10-битную глубину цвета. Добавьте -c:v libx265в свои команды для получения вывода HEVC. Сообщение об ошибке, добавленное к вашему вопросу, не имеет ничего общего с вашими проблемами.
Я знаю, что это очень сложно. В любом случае, вы найдете всю процедуру, которой я следовал (и ее результаты), в моем обновленном вопросе. Проблема все еще существует, независимо от формата выходного файла yuv420p10le.
Попробуйте добавить опцию -color_range pc(для полного цветового диапазона от 0 до 255 вместо 16 до 235 для ТВ).
Ваш ввод имеет набор нестандартных параметров цвета ( bt2020nc/bt2020/smpte2084). Используйте фильтр цветового пространства для преобразования в стандартный bt709. Цветовой диапазон здесь не при чем, а низкий битрейт будет ухудшать цветность изображения, но не основной фактор в данном случае.
@MarianD К сожалению, -color_range pcэто не меняет результат.
@Gyan Я отредактировал вопрос с этой новой попыткой. Видео по-прежнему с "неправильными" цветами. Однако обратите внимание на tv, bt709/unknown/unknownвывод. Может также colormatrixи что-то еще надо доработать? Я пытался добавить опцию -colormatrix bt709, но это вызывает ошибку: Unrecognized option 'colormatrix'..
Фильтр цветового пространства, а не вариант.
@Gyan Хорошо. Надеюсь, синтаксис правильный: при использовании -vf "scale=1920:1080, colorspace=bt709"выдает ошибку: [Parsed_colorspace_1 @ 0x560001239540] Unsupported input transfer characteristics 16 (smpte2084) Error while filtering: Invalid argument Failed to inject frame into filter network: Invalid argument Error while processing the decoded data for stream #0:0. То же самое, даже если я использую только -vf colorspace=bt709.
Я займусь этим завтра.
Смотрите обновление моего ответа ( дополнение к объявлению 1 ).

Здесь уже есть решение . Но я постараюсь изложить его вкратце.

Вам необходимо указать правильные флаги для свойств цвета исходного файла. Ваш исходный файл (как, вероятно, и многие другие файлы) имеет следующие свойства: yuv420p10le(tv, bt2020nc/bt2020/smpte2084). Поэтому вам нужно добавить следующие аргументы соответственно: -pix_fmt, -color_range, -colorspace, -color_primariesи -color_trc. Последние четыре — это просто флаги (те, что в скобках), поэтому, если вы уже закодировали файл, вам не нужно делать это снова, просто добавьте правильные флаги. Тогда ваши аргументы должны выглядеть так:

-c:v libx265
-pix_fmt +
-color_range tv 
-colorspace bt2020nc
-color_primaries bt2020 
-color_trc smpte2084  
-vf scale=1920:1080

Как упоминалось в другом месте, свойство формата цвета -pix_fmtсо значением +означает «использовать тот же формат пикселей», но вы можете указать его вручную: -pix_fmt yuv420p10le.