使用ffmpeg / avconv调整视频大小以适合静态大小的播放器


65

我有一个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


4
稍后我会写出答案,但我想提一提以下内容:重新编码视频以添加固定的大写字母或大写字母装箱是一个糟糕的主意。在此过程中,您不仅会失去质量(或不必要地增加文件大小),而且以后也将无法摆脱障碍。理想情况下,您的播放器应该只是照顾好它并在显示视频时调整其大小。请问您的用例是什么?
slhck

我们将原始文件存放在S3存储桶中,所以这没问题,而且由于我们接受了广泛的视频类型,因此无论如何我们都在重新编码,所有这些最终都必须以h.264 mp4文件的形式适合流式传输浏览器。因此,您建议调整视频大小,然后制作html / css支柱/信箱?谢谢
杰米·泰勒

1
作为接受的答案的所有者,我建议您不接受我的帖子,而接受LordNeckbeard的答案,因为它是最新且更简单的方法。
slhck

@slhck,我正在考虑中,带着您的祝福,我会做到的。
杰米·泰勒

Answers:


51

一种简单的方法是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

为我添加一个空白填充?
Tiago Ferezin

@TiagoFerezin什么是“空白填充”?
llogan

哦,抱歉,以其他颜色代替黑色代替,例如
Tiago Ferezin

2
@TiagoFerezin啊,是的。容易做。在使用pad过滤器的示例中,您可以添加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

这被归结为调整大小和填充所需的基本要素-根据需要添加其他视频和音频选项。请注意,这些数字widthheight具有2以便为多数编解码器工作整除。

以下是发生的情况的说明:

  • 缩放比例:
    • 首先,我们需要弄清楚是按宽度还是按高度缩放。
    • 为此,我们将输出宽度除以输入宽度,然后将输出高度除以输入高度。这将为我们提供每个维度的比例因子。
    • 然后,我们检查哪个值较低(带有min()),并仅选择调整大小的系数。
    • 最后,我们通过因子乘以两个输入宽度和高度(iw*min(…):ih*min(…))。
  • 填充:
    • $width:$height 是输出的宽度和高度
    • 为了弄清楚放置结果视频的位置,我们需要从最大输出宽度中减去缩放的宽度,并从最大输出高度中减去缩放的高度。
    • 缩放的宽度和高度是scale过滤器的表达式。
    • 我们将所得偏移量除以2,以在两侧添加边框。

3
@JamieTaylor考虑添加-movflags +faststart到slhck的示例中。它将允许您逐步下载的视频在完全下载之前开始播放,并且有关更多编码说明和示例的信息,请参阅FFmpeg和x264编码指南FFmpeg和AAC编码指南
llogan 2013年

我认为您可以将pad filter缩短为:pad=$width:$height:(ow-iw)/2:(oh-ih)/2"
jdi 2014年

1
@jdi如果缩小比例,此方法将无效,因为它将导致的值为负ow-iw
slhck

感谢您的起点!但是,要为样本宽高比!= 1的视频获得合适的宽高比,则每次出现的“ iw”都必须乘以“ sar”,因此将每个出现的“ iw”都替换为“(sar * iw)”在过滤器表达式中对我有用。
schieferstapel

@slhck嘿,我正在android中尝试,但似乎没有用,您能帮我吗! ffmpeg -i input.mp4 -filter:v标度= 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 * min(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

显然,您必须根据需要对其进行调整。


1
不过,有可能一步完成,请参阅我的答案。
slhck

@slhck现在更容易了。请参阅吉他mul鱼的答案。
llogan

@LordNeckbeard谢谢!我最近看到了这个选项,确实使它变得容易得多。
slhck
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.