FFMPEG (libx264) "высота не делится на 2"

Я пытаюсь кодировать видео .mp4 из набора кадров, используя FFMPEG, используя кодек libx264.

Это команда, которую я запускаю:

/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4

Иногда я получаю следующую ошибку:

[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)

После небольшого поиска кажется, что проблема имеет какое-то отношение к алгоритму масштабирования и может быть исправлена ​​путем добавления аргумента -vf.

Однако в моем случае я не хочу делать масштабирование. В идеале я хочу, чтобы размеры были точно такими же, как у фреймов. Любой совет? Есть ли какое-то соотношение сторон, которое обеспечивает h264?

Ответ 1

Ответ на оригинальный вопрос, который не хочет масштабировать видео:

-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

Команда:

ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

По сути,.h264 нужны четные размеры, поэтому этот фильтр будет:

  1. Разделите оригинальную высоту и ширину на 2
  2. Округлите его до ближайшего пикселя
  3. Умножьте это на 2 снова, таким образом делая это четное число
  4. Добавить черные отступы до этого числа

Вы можете изменить цвет отступа, добавив параметр фильтра :color=white. Смотрите документацию колодки.

Ответ 2

Просто используйте -2

Из документация по масштабу фильтра:

Если одно из значений -n с n > 1, масштабный фильтр также будет использовать значение, которое поддерживает соотношение сторон входного изображения, вычисленное из другого указанного измерения. После этого он, однако, сделает убедитесь, что вычисленный размер делится на n и отрегулирует при необходимости.

Примеры

Установите ширину до 1280, а высота будет автоматически рассчитана для сохранения соотношения сторон, и. Высота будет делиться на 2:

-vf scale=1280:-2

То же, что и выше, но с объявленной высотой; оставляя ширину для обработки фильтром:

-vf scale=-2:720

"делится на 2"

В соответствии с требованием x264, для разделителей с вычитанием по цветности, равным 1: 0, требуется "делиться на 2 по ширине и высоте". 4: 2: 2 потребуется "делиться на 2 для ширины", а 4: 4: 4 не имеет этих ограничений. Однако большинство игроков, не поддерживающих FFmpeg, могут только правильно декодировать 4: 2: 0, поэтому вы часто видите команды ffmpeg с опцией -pix_fmt yuv420p при выводе видео H.264.

Caveat

К сожалению, вы не можете использовать -2 для ширины и, но если вы уже указали один размер, то использование -2 является простым решением.

Ответ 3

Если вы хотите установить некоторую ширину вывода и иметь выход с тем же соотношением, что и оригинал

scale=720:-1 

и чтобы не упасть с этой проблемой, вы можете использовать

scale="720:trunc(ow/a/2)*2"

(Только для людей, которые ищут, как это сделать с масштабированием)

Ответ 4

Вероятно, из-за того, что видео H264 обычно преобразуется из RGB в пространство YUV как 4: 2: 0 перед применением сжатия (хотя само преобразование формата является алгоритмом сжатия с потерями, что дает 50% экономии пространства).

YUV-420 начинается с изображения RGB (Red Green Blue) и преобразует его в YUV (в основном один канал интенсивности и два канала "оттенок" ). Затем каналы Hue подбирают путем создания одного образца оттенка для каждого квадрата 2X2 этого оттенка.

Если у вас есть нечетное количество RGB-пикселей по горизонтали или по вертикали, у вас будут неполные данные для последнего столбца или строки пикселя в подвыборном цветовом пространстве кадра YUV.

Ответ 5

Проблема с scale решениями здесь заключается в том, что они искажают исходное изображение/видео, что почти никогда не соответствует желаемому.

Вместо этого я обнаружил, что лучшее решение - добавить 1-пиксельную панель в нечетное измерение. (По умолчанию накладка черного цвета, и ее трудно заметить.)

Проблема с другими решениями для pad заключается в том, что они не обобщаются на произвольные измерения, потому что они всегда дополняют.

Это решение добавляет 1-пиксельный планшет к высоте и/или ширине, если они нечетные:

-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"

Это идеально, потому что он всегда делает правильные вещи, даже когда нет необходимости дополнять.

Ответ 6

LordNeckbeard имеет правильный ответ, очень быстро

-vf scale=1280:-2

Для android, не забудьте добавить

"-preset ultrafast" and|or "-threads n"

Ответ 7

Вы также можете использовать функцию bitand вместо trunc:

бит и (х, 65534)

будет делать то же самое, что trunc(x/2)*2 и, на мой взгляд, это более прозрачно.
(Рассмотрим 65534 магическое число здесь;))


Моя задача состояла в том, чтобы автоматически масштабировать множество видеофайлов до половины разрешения.

scale=-2,ih/2 приводит к слегка размытым изображениям

причина:

  • у входных видео был установлен формат изображения (DAR)
  • scale масштабирует реальные размеры кадра
  • во время предварительного просмотра размеры нового видео должны быть скорректированы с использованием DAR, что в случае видео с довольно низким разрешением (360x288, DAR 16: 9) может привести к размытию

решение:

-vf "scale='bitand(oh*dar, 65534)':'bitand(ih/2, 65534)', setsar=1"

объяснение:

  • output_height = input_height/2
  • output_width = output_height * original_display_aspect_ratio
  • output_width и output_height теперь округляются до ближайшего меньшего числа, кратного 2
  • setsar=1 означает, что output_dimensions теперь являются окончательными, коррекция соотношения сторон не должна применяться

Кто-то может найти это полезным.