Изменение размера видео с помощью 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 или letterbox, чтобы изображение соответствовало действительности, или
- Используйте фильтр обрезки, чтобы отрезать лишний
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, чтобы добавить границы с обеих сторон.
Мне кажется, что вам нужно сделать это в три этапа:
- Проверьте входное соотношение сторон
- Масштабируйте видео с DAR > 7/4 по ширине (измените ширину на 700 и масштабируйте высоту, чтобы сохранить соотношение сторон), и масштабируйте видео с DAR < 7/4 по высоте
- Дополните видео, чтобы оно уместилось в пространстве 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
Очевидно, вам придется адаптировать его к вашим потребностям.