H264 视频编码器指南
本指引着眼于x264编码器,这里假设你的FFmpeg 编译了--enable-libx264
支持。如果你需要编译支持的帮助请看这篇文档:https://trac.ffmpeg.org/wiki/CompilationGuide,看 HWAccelIntro关于支持H264编码器在逻辑上的支持;
有两种适用于大部分场景的码率控制模式:
Constant Rate Factor (CRF) : 恒定码率因子模式
Two-Pass ABR: 两遍式控制模式
码率控制是指每帧需要处理多少bits的数据。码率控制会决定视频文件的大小和质量的优劣。需要更多关于码率控制模式的区别,请看这篇文章
CRF-- 恒定码率因子模式
推荐在你需要保证视频的质量最佳,而完全不关心视频文件的大小的时候使用这种模式;
这种模式运行编码器当在不关心输出文件的大小时,得到一个一定质量的视频;这种方式可以让一次处理达到一个最大的压缩效果。也可以通过调整每帧所谓的量化因子,可以得到所需的比特率去保证要求的视频质量等级;不过缺点就是你不能指定输出文件的大小或者限制视频不能超过某个大小阈值,也就是说这种方式不推荐用到流式的视频编码。
1、设置CRF的值
CRF的取值范围是0-51
,0是画面质量最高的无损(只是针对8bit,10bit的话要用 -qp 0
),默认值是23,51的话是画质最差的。值越低,质量越高(可以理解为画面质量的损失值),主管的认为合理的值范围是17-28。
17或者18是肉眼区别不出来的无损或者几乎区分不出来的无损;这时看起来跟输入一样或者非常接近,但技术来说并不是无损的。
CRF的取值范围对画质的影响是指数级别的,所以,参数值+6的结果差不多只有原数值比特率/文件大小的一半。同样,参数值-6会导致大概比特率/文件大小是原来的两倍。
在视频质量可以接受的范围选择一个CRF最大的值。 如果输出画质依旧非常好,再选大一点,如果画质不行,再调小;
注意:0-51 的CRF取值范围仅适用于8-bit 的x264. 如果你编译了10bit的x264,CRF的取值范围是 0-63,(在x264的源码上,它是-12到51,只不过是 FFmpeg的 libx264给包装了一层,做了偏移处理。所以0依旧是无损的,但只在受支持的配置文件中,High 10 不支持无损)。
你可以通过FFmpeg编码处理的控制台输出判断你究竟在用哪种(yuv420p就是8-bit的,yuv420p10le就是10-bit的)。8-bit更常用;
2、选择一个预设值和Tune;
preset--预设值
译者:--preset的参数主要调节编码速度和质量的平衡
预设值是一系列保证确定的编码速度和压缩率的选项值的集合。慢的预设值能提供更好的压缩效率(也就是文件能压缩得更小)。例如,如果你设定了确定的文件大小或者固定的比特率,你能用更慢的预设值得到更好的质量。同样的,对于固定的质量编码,你能通过选择较慢的预设值到简单保存比特率;
选在你耐心范围内最慢的预设值。所有的预设值由慢到快的速度排序如下:
ultrafast
(很快,但文件很大 几乎没怎么压缩)superfast
veryfast
faster
fast
medium
-- 默认预设值slow
slower
veryslow
(很慢,但压缩率很高 文件很小)placebo
-- 忽略这个,这个没啥用 (参考 FAQ)
你可以通过参数:-preset help
看到当前的所有预设值。如你安装了x264
的库,你也可以用x264 --fullhelp
查看完整的预设设置;
Tune
译者:--tune的参数主要配合视频类型和视觉优化的参数。
你可以用-tune
参数去改变你指定的输入的设置,当前的turn有如下值:
film
-- 适用于高质量的电影,降低去块效应。use for high quality movie content; lowers deblockinganimation
-- 适用于动画,使用更高级的去块处理和更多的参考帧。 good for cartoons; uses higher deblocking and more reference framesgrain
-- 保留旧的、颗粒状的影片材料中的颗粒结构。 preserves the grain structure in old, grainy film materialstillimage
-- 适用于幻灯片式的内容。good for slideshow-like contentfastdecode
-- 通过关掉某些路径,实现更快的编码。allows faster decoding by disabling certain filterszerolatency
-- 适用于快的编码和低延迟的流。 good for fast encoding and low-latency streamingpsnr
-- 忽略此项,编码器开发用的。ignore this as it is only used for codec developmentssim
-- 忽略此项,编码器开发用的。ignore this as it is only used for codec development
例如,如果你的输入是一个动画你可以用animation
,或者你你保留颗粒状在影片里你可以用grain
选项。如果你不确定你要用那个选项或者不知道你的输入适用何选项你可以忽略 -tune
选项。你可以用 -tune help
查看所用的tune选项列表,或者用 x264 --fullhelp
看这些选项设置的含义。
Profile(配置文件)
译者:限制输出文件的profile。这个参数将覆盖其它所有值,此选项能保证输出profile兼容的视频流。如果使用了这个选项,将不能进行无损压缩(qp 0 or crf 0)。
一般不建议设置;
-profile:v
参数将输出限定为特定的H264配置。一般来说你不想理用这个选项,建议忽略这个设置h264会自动选择合适的配置文件;
某些设备(一般是老掉牙的)只支持更多限制的Constrained Baseline 和 Main profiles。你可以设置这些选项值为 -profile:v baseline
or -profile:v main
. 新设备一般都支持更高级的 High
配置文件。
另外要用这个参数的原因是,要去匹配其他用 concat demuxer连接的视频文件。
注意:-profile:v
参数不兼容无损的编码,setting -profile:v high444
也是无效的。
x264支持的配置文件如下:
baseline
main
high
high10
(first 10 bit compatible profile)high422
(支持yuv420p, yuv422p, yuv420p10le and yuv422p10le)high444
(supports as above as well as yuv444p and yuv444p10le)
列出预算和tunes
用以下命令列出当前的预算和tunes:
ffmpeg -hide_banner -f lavfi -i nullsrc -c:v libx264 -preset help -f mp4 -
注意: windows环境要改为:
ffmpeg -hide_banner -f lavfi -i nullsrc -c:v libx264 -preset help -f mp4 NUL
CRF 示例
下面命令用更慢的预设值与更好的压缩,将视频重新编码为质量好的视频。
ffmpeg -i input -c:v libx264 -preset slow -crf 22 -c:a copy output.mkv
注意,这条示例直接用简单拷贝的方式将输入的音频流拷贝到输出而没有重新编码;
如果你要处理一批相似的视频,用统一的设置,能保证这样这批视频的输出质量都接近;
译者:这里的-preset控制的是压缩率和编码速度的,-crf控制输出质量的。
Two-Pass--两遍式
如果你要输出指定大小的文件,并且输出质量和每帧的质量要求没那么高的时候, 那就用这种码率控制模式。这是用示例最好的解释。你的视频时长600秒并且需要输出大小是200MB。根据:bitrate = file size / duration
:
(200 MB * 8388.608 [转换MB到KBit(1024*8/1000); 注意不是8192,因为1KBit是1000bit。]) / 600 seconds = ~2796 kBit/s 总比特率
2796 - 128 kBit/s (减去音频比特率) = 2668 kBit/s 是视频的比特率
你也可以忽略什么的计算公式如果你已经知道最终的模板比特率的话。
译者:通过上面的公式,你就能得到一个最终输出文件大小确定的视频;
两遍式示例
对应两遍式,你要用差不多一样参数跑两次,参数不同点如下:
- 在第一遍和第二遍,用
-pass 1
和-pass 2
选项区别; - 在第一遍,输出是一个空描述,没有一个显式的输出(但会生成一个日志文件ffmpeg在第二遍需要用);
- 在第一遍,你可以用
-an
参数剥离音频文件;
注意:第一遍,当用-an参数可能最终得到报段内存错误或者顺坏的文件。这样的话,去掉-an参数改为-vsync cfr就行;
例如:
ffmpeg -y -i input -c:v libx264 -b:v 2600k -pass 1 -an -f null /dev/null && \
ffmpeg -i input -c:v libx264 -b:v 2600k -pass 2 -c:a aac -b:a 128k output.mp4
windows下空输出"/dev/null"要改成"NUL",'\' 要改成'`';
跟CRF一样,可用可以接受的-preset
和 -tune
、 -profile:v
参数以得到不同的目标视频;
无损的H.264
如果设置了-profile:v high444
参数你可以用 -crf 0
生成无损的视频,否则用 -pb 0(High 10 profile 配置不支持无损视频, 详看 https://code.videolan.org/videolan/x264/-/blob/master/x264.c#L579)。 ultrafast
和veryslow
这两个预设值是非常常用的,因为更快的编码速度和更好的压缩一般来说都是挺重要的考虑因素。
更快的编码示例:
ffmpeg -i input -c:v libx264 -preset ultrafast -qp 0 output.mkv
更好的压缩效果示例:
ffmpeg -i input -c:v libx264 -preset veryslow -qp 0 output.mkv
提示:无损的视频文件一般来说都非常大,不是基于ffmpeg的播放器可能不能解码播放。所以,如果兼容性和文件大小问题不可忽略,就别用无损了。
提示:如果你要的视频是"视觉上无损"而不是技术上的无损的话,用-crf 17或者18就行(你自己试哪个数值可以接受)。这样不会像真正的无损模式一样搞出一个非常大和兼容性有问题的视频文件;
覆盖默认预设设置
虽然 -preset
已经预设好了可能是最优默认设置给你,但你还是可以用 x264-params
参数去覆盖默认设置,也可以用libx264 的私有参数(ffmpeg -h encoder=libx264)。当然这些参数不推荐初学者使用。预设值是ffmpeg开发人人给出的最优解你去调这些参数一般都是浪费时间。
示例:
ffmpeg -i input -c:v libx264 -preset slow -crf 22 -x264-params keyint=123:min-keyint=20 -c:a copy output.mkv
注意: 不要用'x264opts'这个参数, 这个参数后续版本会被删的。用'x264-params'就行;
【原文】
https://trac.ffmpeg.org/wiki/Encode/H.264
测试示例命令
crf输出示例
#修改编码速度与压缩率
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast ultrafast.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow veryslow.mp4
#加入crf,速度快
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 18 ultrafast_18.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 23 ultrafast_23.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 51 ultrafast_51.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 39 ultrafast_39.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 45 ultrafast_45.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 0 ultrafast_0.mp4
#加入crf,压缩率高
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 18 veryslow_18.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 23 veryslow_23.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 51 veryslow_51.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 0 veryslow_0.mp4
两遍式示例
ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2097k -pass 1 -an -f null NUL && ffmpeg -i input.mp4 -c:v libx264 -b:v 2097k -pass 2 -c:a aac -b:a 128k tow_pass_3MB_2097k.mp4