我该如何使用ffmpeg
通过降低质量来减小视频的大小(自然地,尽可能最小,因为我需要它在没有太多可用空间的移动设备上运行)?
我忘了提及,当视频可以使用字幕(*.srt 或 *.sub)时,我也想将它们转换为适合转换后的视频文件的参数。
答案1
2020 年更新:这个答案写于 2009 年。自 2013 年以来,一种比 H.264 更好的视频格式被广泛使用,即 H.265(更好的是它在相同质量下压缩更多,或者在相同大小下提供更高的质量) 。要使用它,请将 libx264 编解码器替换为 libx265,并通过增加 CRF 值(例如添加 4 或 6)进一步推动压缩杆,因为 H.265 的合理范围可能是 24 到 30。请注意降低CRF值对应于更高比特率,从而产生更高优质视频。
ffmpeg -i input.mp4 -vcodec libx265 -crf 28 output.mp4
您还可以指定 libx265预设,这会影响文件大小和质量。
要查看使用较旧的 H.264 格式应用此技术,请参阅这个答案,为方便起见,引用如下:
通过将目标大小(以位为单位)除以视频长度(以秒为单位)来计算所需的比特率。例如,目标大小为 1 GB(一千兆字节,即 8 GB位)和 10 000 秒的视频(2 小时 46 分 40 秒),使用 800 000 位/秒(800 kbit/s)的比特率:
ffmpeg -i input.mp4 -b 800k output.mp4
可能值得考虑的其他选项是设置恒定速率因子,这降低了平均比特率,但保留了更好的质量。将 CRF 在 18 到 24 之间变化——越低,比特率越高。
ffmpeg -i input.mp4 -vcodec libx264 -crf 20 output.mp4
答案2
您提到想要减小文件大小以在移动设备上容纳更多视频,这也是我的用例。这里所有的答案都是为了降低压缩质量,但没有人提到减小视频帧大小。它的速度要快得多,最高可达数倍,具体取决于您的源,并且分辨率会降低,因为要编码的像素较少。结果,文件大小可以显着减小。
缺点是您还会损失大量质量,因为像素越少意味着图像细节越少。但当转换为小型设备时,这可能是可以接受的。
请参阅 FFmpeg 文档缩放了解更多信息。
要缩放到一半大小:
ffmpeg -i input.mkv -vf "scale=trunc(iw/4)*2:trunc(ih/4)*2" half_the_frame_size.mkv
三分之一尺寸:
ffmpeg -i input.mkv -vf "scale=trunc(iw/6)*2:trunc(ih/6)*2" a_third_the_frame_size.mkv
四分之一尺寸:
ffmpeg -i input.mkv -vf "scale=trunc(iw/8)*2:trunc(ih/8)*2" a_fourth_the_frame_size.mkv
五分之一尺寸:
ffmpeg -i input.mkv -vf "scale=trunc(iw/10)*2:trunc(ih/10)*2" a_fifth_the_frame_size.mkv
在这些示例中,大小除以值的两倍并乘以 2,以确保像素大小是 2 的倍数,这是某些编解码器(包括 H265)所必需的。
-2
您还可以在一个参数中缩放到特定大小,并自动为另一个参数保持相同的比例。例如,一个方向上的 360 像素将使用:
-vf "scale=-2:360"
请注意更改分辨率总是需要重新编码,因此其他答案的所有来龙去脉也适用于此,并且这些示例与 H265 选项兼容,例如-c:v libx265 -crf 28
.
答案3
我测试了这个问题的大多数其他建议答案。测试数据结论如下。这些是我测试过的建议答案:
(BR) 修改比特率,使用:
ffmpeg -i $infile -b $bitrate $newoutfile
(CR) 改变恒定速率因子,使用:
ffmpeg -i $infile -vcodec libx264 -crf 23 $outfile
(SZ) 更改视频屏幕大小(例如,更改为像素大小的一半),使用:
ffmpeg -i $infile -vf "scale=iw/2:ih/2" $outfile
(BL) 使用以下命令将 H.264 配置文件更改为“基线”:
ffmpeg -i $infile -profile:v baseline $outfile
(DF) 使用默认的ffmpeg处理,使用:
ffmpeg -i $infile $outfile
数据
- “大小”- 转换后的视频相对于原始视频的像素大小百分比。
- “比特率”- 原始视频和转换后视频的比特率。
- “定义”-视频的像素大小。
- “转换”- 转换视频的时间(以秒为单位)。
我使用所提出的方法计算了 (BL) 的目标比特率。
=== 文件 A - Node 如何帮助推动 Angular-Fnbixa7Ts6M.mkv ===
original BR CR SZ BL DF
-------- --- -- -- -- --
size 64152 kb 214% 76% 40% 83% 76%
bitrate 411 kb/s 883 313 165 342 313
definition 1920x1080 1920x1080 1920x1080 960x540 1920x1080 1920x1080
convert -- 648 509 225 427 510
=== 文件 B - 将 GraphQL 与 Angular 一起使用 _ 作者:Lee Costello-OGyFxqt5INw.mkv ===
original BR CR SZ BL DF
-------- --- -- -- -- --
size 410301 kb 33% 109% 28% 143% 109%
bitrate 2687 kb/s 880 2920 764 3843 2920
definition 3840x2160 3840x2160 3840x2160 1920x1080 3840x2160 3840x2160
convert -- 2307 3188 1116 2646 3278
结论
(SZ)方法绝对是最快的方法。速度快了 2 到 4 倍。对于高清视频来说,这可能是一个很大的问题,因为所有其他方法的转换时间都比视频的实际长度长!例如,(CR)方法花了53分钟来转换21分钟的视频。
如果视频的清晰度大于将要显示该视频的屏幕的清晰度,则 (SZ) 方法绝对是最佳方法。例如,如果您的手机只能显示 1080p 图片,则向其发送 3840x2160 视频只是浪费。最好将其大小减半至 1080p。
一些建议的答案实际上增加了一些视频的大小。例如,(BR) 方法将 1080p 样本的大小增加了一倍以上。然而,它确实使 2160p 尺寸缩小了三分之一。对于高清样本,(CR)、(BL) 和 (DF) 方法都增加了视频的大小。
正确(或最佳)答案
最好先将分辨率降低到目标显示器支持的最大分辨率。
如果想进一步减小文件大小,就看个人选择了。您可以减少信息内容或增加压缩。
如果您不担心的话,您可以进一步降低分辨率。
如果视频不包含快速动作场景,您可能需要降低帧速率。
如果您拥有强大的处理器并且空间是唯一的问题,则可以提高压缩率。
比特率是多种因素的组合。因此,仅仅告诉 ffmpeg 降低比特率可能不会给你想要的结果。
降低信息内容的另一种方法是降低颜色深度。如何做到这一点尚未讨论。