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 нужны четные размеры, поэтому этот фильтр будет:
- Разделите оригинальную высоту и ширину на 2
- Округлите его до ближайшего пикселя
- Умножьте это на 2 снова, таким образом делая это четное число
- Добавить черные отступы до этого числа
Вы можете изменить цвет отступа, добавив параметр фильтра :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 теперь являются окончательными, коррекция соотношения сторон не должна применяться
Кто-то может найти это полезным.