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

65

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

Входными данными может быть файл любого размера, поэтому мне нужно изменить размер больших, но отцентрировать меньшие с черными полосами. До сих пор я пробовал: -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

Джейми Тейлор
источник
4
Я напишу ответ позже, но я подумал, что упомяну следующее: перекодирование видео только для добавления фиксированного столба или почтового ящика - ужасная идея. Мало того, что вы потеряете качество в этом процессе (или излишне увеличите размер файла), вы также сделаете невозможным избавиться от полос позже. В идеале ваш плеер должен просто позаботиться об этом и изменить размер видео во время его отображения. Каков ваш вариант использования, если я могу спросить?
Slhck
Мы храним исходный файл в корзине S3, так что это не проблема, и мы все равно перекодируем, так как принимаем большое количество типов видео, все они должны заканчиваться как файлы h.264 mp4, подходящие для потоковой передачи через браузер Итак, вы бы предложили изменить размер видео, а затем сделать html / css pillar / letterboxes? Спасибо
Джейми Тейлор
1
Как владелец принятого ответа, я бы посоветовал вам не принимать мой пост и вместо этого принять ответ LordNeckbeard, так как он самый последний и гораздо более простой.
slhck
@slhck, я думал об этом, с твоего благословения, я сделаю это так.
Джейми Тейлор,

Ответы:

52

Простой способ - использовать 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
llogan
источник
А для меня добавить пустую заливку?
Тиаго Ферезин
@TiagoFerezin Что такое "пустое заполнение"?
Llogan
ой извините, залейте другим цветом вместо черного, как пример
Тиаго Ферезин
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, чтобы добавить границы с обеих сторон.
slhck
источник
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 Привет, я пытаюсь в Android, но он не работает, не могли бы вы помочь мне с этим !!! ffmpeg -i input.mp4 -filter: v scale = 640 * min (700/640 400/360): 360 * min (700/640 400/360), pad = 700: 400: (700-640 * min (700/640 400) / 360)) / 2: (400-360 * мин (700 / 640,400 / 360)) / 2 output.mp4
Nisarg
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». В скрипте 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

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

evilsoup
источник
1
Это возможно сделать за один шаг, см. Мой ответ.
slhck
@slhck Теперь стало проще. Смотрите ответ с гитарой-кефалью.
Llogan
@LordNeckbeard Спасибо! Я недавно видел этот вариант, он действительно облегчает задачу.
slhck