Сохранение соотношения сторон с помощью FFmpeg

Мне нужно преобразовать кучу видеофайлов с помощью FFmpeg. Я запускаю файл Bash, который хорошо конвертирует все файлы, однако возникает проблема, если преобразованный файл имеет формат не 16: 9.

Поскольку я устанавливаю размер экрана на -s 720x400, если соотношение сторон оригинала составляет 4: 3, FFmpeg создает выходной файл 16: 9, занижая соотношение сторон.

Есть ли настройка, позволяющая установить соотношение сторон в качестве основного параметра с изменяемым размером (например, путем фиксации только размера X или Y)?


person 0-alpha    schedule 21.11.2011    source источник


Ответы (8)


-vf "scale=640:-1"

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

[libx264 @ 0x2f08120] height not divisible by 2 (640x853)

Итак, наиболее общий подход - использовать выражения фильтра:

scale=640:trunc(ow/a/2)*2

Он берет выходную ширину (ow), делит ее на соотношение сторон (a), делит на 2, обрезает цифры после десятичной точки и умножает на 2. Это гарантирует, что результирующая высота делится на 2.

Кредиты на ffmpeg trac

ОБНОВЛЕНИЕ

Как указано в комментариях, более простым способом было бы использовать -vf "scale=640:-2". Кредиты @BradWerth за элегантное решение

person mente    schedule 11.01.2013
comment
Или, если вы хотите указать высоту и позволить ffmpeg установить ширину пропорционально, scale=trunc(oh*a/2)*2:min(480\,iw). - person Christian Davén; 12.06.2013
comment
@BradWerth это где-нибудь задокументировано? - person Adam; 04.04.2018
comment
@ Адам, я не припомню. Я считаю, что просто читал варианты и играл с настройками, реализуя этот отличный ответ. - person Brad Werth; 04.04.2018
comment
Незначительное примечание: scale=640:trunc(ow/a/2)*2 и scale=640:-2 являются достаточными ответами, но не обязательно эквивалентными. Усечение в первом случае может дать значение, например 2 пикселя, меньше в зависимости от размера источника входного сигнала. - person systemexit; 07.06.2018
comment
Что это за требование, чтобы высота делилась на 2? Это относится только к кодеку x264 или это все кодеки? И применимо ли это также к ширине? - person Anders Emil; 24.10.2018
comment
@AndersEmil, насколько я знаю, это только для x264 и имеет отношение как к ширине, так и к высоте - person mente; 30.10.2018

Например:

Соотношение сторон 1920 x 1080 16: 9 => соотношение сторон 640 x 480 4: 3:

ffmpeg -y -i import.media -aspect 16:9 scale=640x360,pad=640:480:0:60:black output.media

соотношение сторон 16: 9, ширина 640 пикселей => высота 360 пикселей:
Окончательный размер вывода 640 x 480 и 60-пиксельное черное изображение (сверху и снизу):

"-vf scale=640x360,pad=640:480:0:60:black"
person cool2ikou    schedule 10.09.2012
comment
Мне просто нужно было перейти с 640x480 на 1280x720 и использовать -aspect 16:9 -vf scale=960x720,pad=1280:720:160:0:white (мне тоже нужен белый отступ вместо черного). Спасибо! - person Peter K.; 18.03.2016
comment
Мне нужно было пойти противоположным путем, с 640х480 до 1920х1080 с боксом: -vf "scale=1440x1080,pad=1920:1080:240:0:black" - person whereisalext; 13.04.2017
comment
Я заставил его работать с этим: ffmpeg -y -i 01.mp4 -vf "scale=640x360,pad=640:480:0:60:black" 02.mp4 - person John Trichereau; 11.07.2017

Я спросил об этом давным-давно, но на самом деле у меня есть решение, которое мне не было известно в то время - чтобы сохранить соотношение сторон, вы должны использовать масштаб видеофильтра, который является очень мощным фильтр.

Вы можете просто использовать это так:

-vf "scale=640:-1" 

Это зафиксирует ширину и предоставит высоту, необходимую для сохранения соотношения сторон. Но вы также можете использовать многие другие параметры и даже математические функции, проверьте документацию здесь - http://ffmpeg.org/ffmpeg.html#scale

person 0-alpha    schedule 16.03.2012
comment
это сработало хорошо, но я все же обнаружил, что могу столкнуться с проблемами, если высота не делится на 2. Есть идеи, как обойти эту проблему? - person DevDave; 03.10.2012
comment
обратите внимание на -vf "scale=640:-2" ответы здесь. - person coco; 01.09.2015

Хотя большинство из этих ответов прекрасны, я искал команду, которая могла бы изменить размер до целевого размера (ширина или высота) при сохранении соотношения сторон. Мне удалось добиться этого с помощью Expression Evaluation от ffmpeg.

Вот соответствующий видеофильтр с целевым размером 512:

-vf "thumbnail,scale='if(gt(iw,ih),512,trunc(oh*a/2)*2)':'if(gt(iw,ih),trunc(ow/a/2)*2,512)'"


Для выходной ширины:

'if(gt(iw,ih),512,trunc(oh*a/2)*2)'

Если ширина больше высоты, верните цель, в противном случае верните пропорциональную ширину.


Для выходной высоты:

'if(gt(iw,ih),trunc(ow/a/2)*2,512)'

Если ширина больше высоты, верните пропорциональную высоту, в противном случае верните цель.

person Charlie    schedule 14.05.2014

Используйте force_original_aspect_ratio из ffmpeg trac:

ffmpeg -i input.mp4 -vf scale=720:400:force_original_aspect_ratio=decrease output.mp4
person xmedeko    schedule 29.08.2016
comment
Это не удается, когда ваше видео имеет странный размер, например, 1438x800, тогда результат будет 719x400 и выдает ошибку, потому что ширина не делится на 2 ... - person Daniel Carrasco Marín; 04.02.2017
comment
@ DanielCarrascoMarín Ага, когда у вас нет контроля над размером входного видео, тогда проблема делимости на 2 не может быть решена самим ffmpeg (к сожалению). Я решил это, вычислив соотношение сторон в скрипте Python, а затем передав нужные мне параметры ffmpeg scale=. - person xmedeko; 06.02.2017
comment
Я только что протестировал его с помощью ffmpeg 3.4 и 3.2.9, и он работает как шарм. Видео стало: 719x400 но ошибок не было. Я мог воспроизвести его с помощью медиаплеера VLC (справа увидел лишний пиксель). Встроенный видеоплеер Ubuntu также хорошо его воспроизводил. И ffmpeg мог прочитать файл после и преобразовать в другой - person Kostanos; 02.11.2017

Если вы пытаетесь установить ограничивающую рамку, то использование force_original_aspect_ratio в соответствии с ответом xmedeko является хорошей отправной точкой.

Однако это не работает, если ваше входное видео имеет странный размер и кодируется в формат, который требует, чтобы размеры делились на 2, что приводит к ошибке.

В этом случае вы можете использовать оценку выражения в функции scale, как в ответе Чарли.

Предполагая ограничивающую рамку вывода 720x400:

-vf "scale='trunc(min(1,min(720/iw,400/ih))*iw/2)*2':'trunc(min(1,min(720/iw,400/ih))*ih/2)*2'"

Чтобы разбить это:

  • min(1,min(720/iw,400/ih) находит коэффициент масштабирования, соответствующий ограничивающей рамке (здесь), ограничивая его максимумом 1, чтобы гарантировать его только уменьшение масштаба, и
  • trunc(<scaling factor>*iw/2)*2 и trunc(<scaling factor>*iw/2)*2 гарантируют, что размеры делятся на 2 путем деления на 2, превращая результат в целое число, а затем умножая его обратно на 2.

Это избавляет от необходимости определять размеры входного видео перед кодированием.

person tvStatic    schedule 16.07.2018

вы можете использовать ffmpeg -i, чтобы получить размеры исходного файла, и использовать их в своих командах для кодирования. На какой платформе вы используете ffmpeg?

person box86rowh    schedule 21.11.2011
comment
Привет, я использую его в Linux. В идеале я хотел бы иметь сценарий bash, который работает независимо от соотношения сторон. Думаю, я могу настроить его вручную для неширокого разрешения, но с множеством опций в ffmpeg я думал, что просто не знаю настройки трюка ... - person 0-alpha; 22.11.2011
comment
Да, это ответ, потому что, используя исходные размеры и уменьшая (или увеличивая) их путем простого вычисления, OP может решить проблему вручную. - person Alfe; 28.02.2014
comment
Я нашел это полезным в любом случае. Лично я рад, что этот ответ был опубликован. - person TripleAntigen; 29.08.2014

Если присутствует '-aspect x: y' и формат выходного файла - это ISO Media File Format (mp4), тогда ffmpeg добавляет pasp-atom (PixelAspectRatioBox) в stsd-box на видеодорожке, чтобы указать игрокам ожидаемое соотношение сторон. Игроки должны соответственно масштабировать видеокадры. Нет необходимости масштабировать видео перед кодированием или перекодированием, чтобы подогнать его под соотношение сторон, это должно выполняться плеером.

person Shevach Riabtsev    schedule 30.09.2019