4.调整和缩放视频的尺寸

FFmpeg中,我们可以使用一个特定的选项调整视频的宽度和高度;也可以使用 scale filter改变帧的尺寸,两者相比,scale提供了更高级的特征。

调整视频的尺寸

我们可以使用 -s 选项来设置输出视频的宽度和高度,该选项应放置在输出文件名称之前。-s 用于指定视频的分辨率,即宽度和高度,其形式为 w x h ,其中 w 表示宽度,h 表示高度,两者的单位都是像素。例如,想要将输出文件的尺寸改为320x240,命令如下:

ffmpeg -i input_file -s 320x240 output_file

预定义视频帧尺寸

我们一般并不直接输入视频的宽度和高度值,而是使用一系列预定义好的视频尺寸,它们各自适用于不同的平台,我们应该优先使用这些预定义尺寸。例如,以下两个命令的结果相同:

ffmpeg -i input.avi -s 640x480 output.avi
ffmpeg -i input.avi -s vga output.avi

javacv FFmpegFrameGrabber设置视频质量 ffmpeg改变视频尺寸_《ffmpeg basics》

javacv FFmpegFrameGrabber设置视频质量 ffmpeg改变视频尺寸_缩放_02

javacv FFmpegFrameGrabber设置视频质量 ffmpeg改变视频尺寸_缩放_03

调整尺寸的代价:Nyquist采样原理

为了在移动设备或者网络上使用,我们通常都会将视频从一个大尺寸调整为一个小尺寸,这种做法我们称之为降采样。我们必须认识到,视频在降低尺寸之后,一些细节可能会丢失,这可以由Nyquist采样原理做详细描述:在信号或者信息被采样时,如果我们想要获得良好采样数据(采样数据能表示的图形越是和源信息相似,且数据越小,采样越好),我们就必须使用源信息频率的2倍以上频率来采样。这意味着,如果想要在降采样视频中保留源视频的细节信息,那么我们采用的缩放率必须大于0.5。

例如,一个800x600的视频中包含一个宽为2像素的细节信息,当我们将它缩放到640x480时,它的缩放率为0.8,此时两个像素会被缩放为两个像素:

640 pixels / 800 pixels = 0.8
	2pixels * 0.8 = 1.6 pixel = 2 pixels

但当它缩放到160x120时,细节就会丢失:

160 pixels / 800 pixels = 0.2
	2pixels * 0.2 = 0.4 pixel = 0 pixels

这意味着,降采样后,只有宽度大于等于3像素的细节才会被保留下来。

特殊的放大过滤器

在实际操作中,我们很少会将视频的尺寸放大,虽然在所有的媒体播放器上都提供了视频放大的功能,但放大操作会导致生成的画面变得模糊,尤其是当源视频的分辨率很小时这种模糊非常明显。我们可以使用特殊的super2xsai filter来完成平滑的放大处理:

javacv FFmpegFrameGrabber设置视频质量 ffmpeg改变视频尺寸_中译本_04


描述:这个filter使用了一个特殊的像素扩大算法,在不丢失源图像清晰度的情况下,将视频帧尺寸放大2倍。其中“2xsai"表示”2 times scale and interpolate“(以像素插补完成2倍放大)。

例如,我们可以将一个128x96的视频放大2倍,命令如下:

ffmpeg -i phone_video.3gp -vf super2xsai output.mp4

高级缩放

除了使用 -s 选项来改变视频帧尺寸外,我们也可以使用 scale filter来完成类似的工作,scale filter应该放在它所在 filtergraphs 的末尾。

javacv FFmpegFrameGrabber设置视频质量 ffmpeg改变视频尺寸_视频播放_05

我们实际运行命令:ffmpeg -i 1.mp4 out.mp4,则可以看到输出中有:

    Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
    
PAR:Pixel aspect ratio 的简写,它可以理解为播放设备中像素块的长宽比,因此这个参数是和设备相关的,和视频文件无关。例如电脑上的PAR是1:1的,也就是说像素块是正方形的,因此想要在电脑上播放的视频,应该按照这个PAR来设置其他参数。而电视则由于标准不同,其PAR也不同,如使用NTSC标准的TV设备,其PAR=0.911,使用PAL标准的TV设备,其PAR=1.094。因此,720:480分辨率的视频播放在NTSC和720:576分辨率的视频播放在PAL上时,实际显示的长宽比都是4:3,也就是DAR为4:3.
注:NTSC和PAL中左右8个像素都不使用,都会抛弃掉,因此720:480实际中使用的其实是704:480.如下:
		702 * 0.911 : 480 ~ 4 :3	 ~表示约等于
		702 * 1.094 : 576 ~ 4 :3     ~表示约等于

因此,能在TV中正常播放的视频,如果直接在电脑中播放,那么画面必定会变形,会被压扁或者拉伸。因此电脑中会有专门用于播放DVD的程序,它们会去调整视频的大小使得实际播放时的DAR保持一致。当然这里的调整一般都不会完美,总有细微的变形。

DAR:Display Aspect Ratio,就是视频播放时,我们实际看到的图像宽高的比例。当我们对视频进行缩放时,也要按这个比例来,否则会使图像看起来被压扁或者拉长了似的。

SAR:Sample Aspect Ratio,是MEPG4引入的一个概念,仅在MEPG4中使用。它的含义是:按这个比例拉伸视频。例如,我们有一个704x480的视频,如果我们想要用4:3的宽高比显示这个视频,则它需要一个10:11的SAR。即
		704*10 : 480*11 = 4 : 3

A,AR:表示分辨率的宽高比,如 1280x720,则 a = 1280:720 = 16:9

总结:一个视频的DAR是固定的,如果实际播放时不是这个DAR,那么画面必定会有一定程度的变形。在知道DAR的前提下,只有知道视频的播放设备的PAR才能确定该设备匹配的分辨率,然而实际上,一个视频将来会在哪些设备上播放是不能确定的,因此SAR应理解为这个视频所需的PAR,而PAR是播放设备固有的一个属性。

也就是说,对于一个视频:
			DAR = A * SAR
但实际播放时真实的DAR(real):
			DAR(real) = A * PAR
因此,仅当实际播放设备的PAR = 所需的SAR,视频才能正确播放(不变形)

例如,下面两条命令的结果相同:

ffmpeg -i input.mpg -s 320x240 output.mp4
ffmpeg -i input.mpg -vf scale=320:240 output.mp4

scale filter高级的地方在于除了指定缩放尺寸之外,还能使用上表中描述的额外参数。

按比例缩放输入视频

在不知道输入视频的尺寸,我们仍然可以按比例来缩放源视频,我们通过使用 scale filter 中的 ih 和 iw 参数来实现比例缩放,例如如果想要创建一半原尺寸的视频,我们可以使用命令:

ffmpeg -i input.mpg -vf scale=iw/2:ih/2 output.mp4

缩放为原尺寸90%,命令:

ffmpeg -i input.mpg -vf scale=iw*0.9:ih*0.9 output.mp4

我们也可以用黄金分割比例 PHI = 1.61803398874989484820 来缩放视频:

ffmpeg -i input.mpg -vf scale=iw/PHI:ih/PHI output.mp4

缩放到预定义宽度或者预定义高度

在输入视频的尺寸和长宽比都未知的情况下,我们想将输出视频设置一个特定高度或者特定宽度,此时我们就可以使用scale filter中的aspect(简写为 a ) 参数来实现这一需求。例如,想要将输出的宽度设为400,高度按同比例缩放,那么我们可以使用以下命令:

ffmpeg -i input.avi -vf scale=400:400/a

将输出高度设置为300,宽度按同比例缩放,命令如下:

ffmpeg -i input.avi -vf scale=300*a:300

使用以下命令:

ffmpeg -i input.avi -vf scale=400:400/a

将输出高度设置为300,宽度按同比例缩放,命令如下:

ffmpeg -i input.avi -vf scale=300*a:300