Як я можу підігнати відео до певного розміру, але не збільшувати його за допомогою FFmpeg?


13

Мені потрібно встановити відео до 640x360 (максимум, на який може працювати плеєр телефону), зберігаючи також співвідношення сторін , але я також хочу, щоб це відео було незмінним, якщо воно менше 640x360 (все-таки немає сенсу збільшувати його масштабність).

Чи є спосіб отримати таку поведінку, використовуючи командний рядок ffmpeg?


Я не думаю, що це можна зробити виключно у ffmpeg, але якщо ви готові його скриптувати, це однозначно можна зробити.
зол

Я вже це написав, але хотів очистити свій код, якщо він не потрібен.
sashoalm

Це, мабуть, можливо за допомогою фільтра масштабу, який використовує такі функції, min(…)але, безумовно, простіше за допомогою простого сценарію, який аналізує розміри. Дивіться тут мою команду для прикладу того, що можна зробити: superuser.com/questions/547296/…
slhck

Відповіді:


10

У нових версіях ffmpeg ви можете скористатися параметром scaleфільтра force_original_aspect_ratio. Наприклад, щоб встановити відео на 1280 × 720, не збільшуючи масштаб ( докладнішу інформацію див. У цій публікації ):

ffmpeg -i input.mp4 -filter:v "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Тут scaleфільтр масштабується до 1280 × 720, якщо вхідне відео більше цього. Якщо вона менша, вона не буде збільшена. padФільтр необхідний довести висновок відео до 1280 × 720, в разі , якщо його співвідношення сторін або розміру відрізняється від заданого розміру.


Що стосується старих версій ffmpeg, існує дещо хиткий спосіб вирішення. По-перше, визначте співвідношення ширини, висоти та сторін вашого результату. Це врятує нас від набору тексту.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Тепер застосуємо надскладну команду фільтру, яку написав Джим Ворралл :

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

Я не буду вникати в пояснення того, що це все робить, але в основному ви можете подати на нього будь-яке відео, і це буде лише зменшити масштаб, а не високий масштаб. Якщо ви готові до цього, ви можете розсічити фільтр на окремі вирази. Це може бути скорочено, але це також працює.


1
+1, але це справді жахлива команда: P
evilsoup

Я знаю правильно? Я витратив десять хвилин, намагаючись розбити її на логічні частини, а потім вставивши деякі значення, але я відмовився. Він трохи старий, і, можливо, можна було б написати це набагато коротше, ніж це.
slhck

14

Більш читана версія може виглядати наступним чином:

-filter_complex "scale=iw*min(1\,min(640/iw\,360/ih)):-1"

640 / iw - коефіцієнт горизонтального масштабування, а 360 / ih - коефіцієнт вертикального масштабування

Ви хочете помістити масштабоване зображення всередину вихідного поля і зберегти співвідношення сторін (зберігання). Для цього вибираєте найменший коефіцієнт масштабування з мінімальною функцією: min (640 / iw, 360 / ih)

Ви хочете запобігти збільшенню масштабу (тобто коефіцієнт масштабування> 1,0), тому ви додасте ще одну мінімальну функцію: min (1, min (640 / iw, 360 / ih))

Наступним кроком є ​​обчислення вихідної роздільної здатності шляхом множення коефіцієнта масштабування на ширину входу та висоту вводу:
вихідна ширина = iw * хв (1, хв (640 / iw, 360 / ih))
вихід-висота = ih * хв (1, хв (640 / iw, 360 / ih))

Останнім кроком є ​​побудова команди фільтра. Не потрібно вказувати висоту виходу, ви можете вказати -1, а ffmpeg збереже співвідношення сторін, застосувавши той же коефіцієнт масштабування, що і для ширини.


A + працює поза коробкою. Вибране рішення відповіді не зберегло співвідношення сторін. Це стискало кадри.
287352

5

У мене була така ж проблема, але її вирішили, розмістивши відео у квадраті 640x640 (через вертикальні відеоролики, зроблені зі смартфонів).

Отже, використовуючи логіку іммерзі та деякі дослідження, я закінчую це:

-vf "scale=iw*min(1\,if(gt(iw\,ih)\,640/iw\,(640*sar)/ih)):(floor((ow/dar)/2))*2"

остання частина призначена для того, щоб мати висоту, що ділиться на 2, що потрібно багатьом кодерам.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.