Изменение размера видео с помощью ffmpeg/avconv для размещения в плеере статического размера

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

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

Изображения

Это грубое представление о том, что мне нужно. Я не уверен, возможно ли это вообще. Это почти как CSS max-width/max-height. Я понимаю, что это может быть просто путаница слов, но если кто-то поймет, о чем я говорю, я был бы признателен за помощь, спасибо.

команда avconv:

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

3 ответа

Решение

Простой метод заключается в использовании force_original_aspect_ratio опция в масштабном фильтре.


Исходное изображение. Представляет видео с форматным соотношением 640x480, 4:3.

В этих примерах исходное изображение будет масштабировано для соответствия форматному соотношению 16:9 с сохранением исходного форматного соотношения. Для этого вы можете:

Pillarbox или почтовый ящик


Pillarboxed изображение. Установка входа 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

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

Сначала в вашей оболочке определите ширину и высоту вывода:

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, чтобы добавить границы с обеих сторон.

Мне кажется, что вам нужно сделать это в три этапа:

  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". В скрипте bash я бы использовал что-то вроде:

#!/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

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

Другие вопросы по тегам