Змінення розміру відеозаписів за допомогою ffmpeg / avconv для вбудовування в програвач статичного розміру


65

У мене є відеоплеєр html 5, який становить 700 пікселів, висотою 400 пікселів. Я намагаюся avconvвикористовувати ffmpeg для зміни розміру (зберігаючи співвідношення сторін) і переконуюсь, що він вписується в мій програвач.

Вхідним файлом може бути будь-який розмір, тому мені потрібно змінити розмір великих розмірів, але менші розміщувати їх чорними смугами. Поки я намагався: -sі -aspectя бачив, як padвін використовується з -vfкомутатором, але не розумію, як він працює достатньо, щоб отримати те, що мені потрібно.

Зображення

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

команда avconv:

avconv -y -i control.avi -vcodec libx264 -b 2000k -bufsize 20M -acodec aac -strict experimental -ar 44100 -ab 256k bigbuck_out.mp4


4
Відповідь я напишу пізніше, але я подумав, що згадаю наступне: Перекодування відео просто для того, щоб додати фіксований стовп чи поштову скриньку - це жахлива ідея. Ви не тільки втратите якість в цьому процесі (або зайво збільшите розмір файлу), але і зробите неможливим позбутися барів пізніше. В ідеалі ваш програвач повинен просто подбати про це і змінити розмір відео під час його відображення. Який ваш випадок використання, якщо я можу запитати?
slhck

Ми зберігаємо оригінальний файл у відрі S3, тому це не проблема, і ми все-таки перекодуємо, оскільки ми приймаємо велику кількість типів відео, і все це має закінчитися як h.264 mp4-файли, придатні для передачі через браузер. Тож ви б запропонували змінити розмір відео, а потім зробити HTML / css стовп / поштові скриньки? Спасибі
Джеймі Тейлор

1
Як власник прийнятої відповіді, я б запропонував вам не прийняти мою посаду, а замість неї прийняти відповідь LordNeckbeard, оскільки вона є останньою та набагато простішою.
slhck

@slhck, я розглядав це, з твого благословення, зроблю так.
Джеймі Тейлор

Відповіді:


52

Простий метод - використовувати force_original_aspect_ratioпараметр у фільтрі масштабу .

оригінальне зображення
Оригінальне зображення. Представляє відео зі співвідношенням сторін 640x480, 4: 3.

У цих прикладах оригінальне зображення буде масштабуватися таким чином, щоб воно підходило до виходу співвідношення сторін 16: 9, зберігаючи вихідне співвідношення сторін. Для цього ви можете:

Стовпчик або поштовий ящик

зображення на стовпчиках
Зображення стовпчиком. Встановлення входу 640x480 (4: 3) у вихід 1280x720 (16: 9).

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output
  • Це збільшить масштаб зображення. Якщо ви хочете уникнути збільшення масштабу, див. Приклад нижче.

  • Натомість буквене позначення буде, якщо співвідношення сторін вводу буде ширшим за співвідношення сторін виводу Наприклад, вхід з співвідношенням сторін 2,35: 1, що вписується у вихід 16: 9, призведе до надсилання букв.

Те саме, що вище, але без збільшення масштабу

відхилення масштабів немає
640x480 (4: 3) вхід у вихід 1280x720 (16: 9) без збільшення масштабу.

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

Урожай, врожай

введіть тут опис зображення
Обрізане зображення. 4: 3 співвідношення вхідних сторін, співвідношення сторін 16: 9.

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" output

А мені додати порожню заливку?
Тіаго Ферезін

@TiagoFerezin Що таке "заповнення"?
логіан

о, вибачте,
залиште

2
@TiagoFerezin Ага, так. Легко зробити. У прикладах, що використовують фільтр для накладки, ви можете додати colorпараметр, наприклад pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=red(або ви можете використовувати шістнадцятковий, якщо бажаєте). Дивіться список кольорів .
llogan

61

Ось команда, яка додала б стовпчик або скриньку для фіксованої ширини виводу. Це довгий час, але вам доведеться якось вказувати прокладку.

Спочатку у своїй оболонці визначте вихідну ширину та висоту:

width=700
height=400

Потім запустіть команду:

ffmpeg -i in.mp4 -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih), pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:($height-ih*min($width/iw\,$height/ih))/2" out.mp4

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

Ось пояснення того, що відбувається:

  • Масштабування:
    • Спочатку нам потрібно розібратися, чи потрібно масштабувати по ширині чи висоті.
    • Для цього ми ділимо вихідну ширину на ширину входу, а вихідну висоту - на вхідну висоту. Це дасть нам масштабні коефіцієнти для кожного виміру.
    • Потім ми перевіряємо, який з них нижче (з min()), і вибираємо лише той коефіцієнт для зміни розміру.
    • Нарешті, множимо і вхідну ширину, і висоту на цей коефіцієнт ( iw*min(…):ih*min(…)).
  • Набивання:
    • $width:$height - вихідна ширина і висота
    • Щоб визначити, де розмістити отримане відео, нам потрібно відняти масштабовану ширину від максимальної вихідної ширини, а масштабну висоту - від максимальної висоти виходу.
    • Масштабовані ширини та висоти - це вирази від scaleфільтра.
    • Ділимо отримане зміщення на 2, щоб додати межі з обох сторін.

3
@JamieTaylor Подумайте про додавання -movflags +faststartдо прикладу slhck. Це дозволить поступово завантаженому відео починати відтворення до повного завантаження, а також дивіться Посібник з кодування FFmpeg та x264 та Посібник з кодування FFmpeg та AAC для отримання додаткових інструкцій та прикладів кодування.
llogan

Ви могли б скоротити фільтр для накладки до цього, я думаю:pad=$width:$height:(ow-iw)/2:(oh-ih)/2"
jdi

1
@jdi Це не спрацює, якщо ви зменшуєте масштаб, оскільки це призведе до негативних значень для ow-iw.
slhck

Дякуємо за вихідну точку! Однак, щоб отримати належне співвідношення сторін для відео із зразковим співвідношенням сторін! = 1, кожне значення "iw" потрібно помножити на "sar", таким чином, замінюючи ВСЕ випадки "iw" на "(sar * iw)" у фільтрі вираз працює для мене.
schieferstapel

@slhck Ей, я намагаюся в андроїд, але це, здається, не працює, ви можете мені допомогти з цим !!! ffmpeg -i input.mp4 -filter: v масштаб = 640 * хв (700 / 640,400 / 360): 360 * хв (700 / 640,400 / 360), pad = 700: 400: (700-640 * хв (700 / 640,400) / 360)) / 2: (400-360 * хв (700 / 640,400 / 360)) / 2
вихід.mp4

8

Мені здається, що вам потрібно зробити це в три етапи:

  1. Перевірте вхідне співвідношення сторін
  2. Масштабуйте відеоролики з розміром DAR> 7/4 по ширині (змініть ширину на 700 та масштабуйте висоту, щоб зберегти співвідношення сторін), а також масштабуйте ті, які мають DAR <7/4 з висотою
  3. Закладіть відео так, щоб воно вмістилося в просторі 700: 400.

FFmpeg / avconv може виконувати масштабування / набивання відеофільтрами за один крок, перекодуючи лише один раз. Наприклад, щоб зробити відео 16: 9, масштабуйте його по ширині, а потім отримайте результати з буквеної скриньки:

ffmpeg -i input.avi -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
-c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k output.mp4

... але для першого кроку (виявлення співвідношення сторін та порівняння його з потрібними 7: 4) вам доведеться скористатися певним сценарієм.

ffprobe input.avi 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0-9]*\)].*/\1/p'

... ви отримаєте співвідношення сторін відео, яке буде виглядати як "16: 9" або "4: 3". У баш-скрипті я б використав щось на кшталт:

#!/bin/bash

##  Get the aspect ratio in the form x/y
dar=$(ffprobe test0.mp4 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0:9]*\)].*/\1/p' | sed 's|:|/|')
##  use bc to do x/y*100 (bash can't handle floats)
DAR=$(bc <<< 'scale=2; $dar*100')

##  ${DAR%.00} will remove the trailing .00 left by bc
if [ ${DAR%.00} -ge 175 ]; then
    ffmpeg -i "$1" -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
else
    ffmpeg -i "$1" -filter:v 'scale=-1:400,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
fi

exit 0

Очевидно, вам доведеться адаптувати його до ваших потреб.


1
Це можна зробити за один крок, дивіться мою відповідь.
slhck

@slhck Тепер простіше. Дивіться відповідь з гітара-кефаль.
логін

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