FFmpeg视频处理工具 - PASSWORD PLAYER
2023-3-19|2023-3-19
骏龙

FFmpeg是一个开源多媒体处理工具,小小的可执行文件却有着强大的功能,因为是命令行工具,所以很适合用来做为视频批量处理、视频压缩使用。
ffmpeg下载使用很简单,Linux几乎都能通过包管理器直接安装安装ffmpeg,而Windows则可以去官网下载。
FFmpeg支持的所有格式
既然支持这么多格式,那么通常能用来做什么呢?下面就附上我个人所收集到的FFmpeg的命令。
基本用法
ffmpeg -i "input.mp4" "output.mp4"
使用-i来选择输入文件input.mp4,然后输出到output.mp4。默认情况下ffmpeg会使用一个“最合适”的参数进行音视频的压缩。输出的扩展名是mp4的话 视频编码器默认使用libx264 音频使用libfdk_aac,视频尺寸、帧数等等保持原样,输出的文件通常会比原文件更小,ffmpeg会使用CRF质量23进行编码,23算是比较佳的质量所以输出的文件肉眼查看画质区分不大 除了个别低分辨率高码率的视频转换后会看出画质的降低。
转换音视频
编解码器
ffmpeg的参数加在不同的地方有不同的作用,在一个输入文件的前面是输入的解码器的选项,而在输出文件的前面则是设定输出的编码器的选项。比如”-r 30”参数能够设定帧数为30,则:
ffmpeg -r 30 -i "intput.mp4" -r 25 "output.mp4"
表示将输入文件解码为30帧,编码输出为25帧的mp4。
通用选项
-r <视频帧数>(23.976、24、25、30、60等) -ar <音频采样率> (44100、48000等) -f <容器格式> (flv、mp4、webm、mkv等) -c <编/解码器> (所有流的编/解码器,包括音视频流,有copy libx264 libfdk_aac等) -c:v <视频编/解码器> (copy、libx264、libx265、libvpx、libvpx-vp9等) -c:a <音频编/解码器> (copy、libfdk_aac、libopus、libvorbis等) -b:v <视频比特率> (1000k、2M等,要加单位) -b:a <音频比特率> (128k、192k、320k等,要加单位) -vf <视频效果> (可以旋转视频、改变亮度对比度等) -af <音频效果> (可以改变音量等) -an (消除音频,只提取视频时使用,无后续参数) -vn (消除视频,只提取音频时使用,无后续参数) -ss <开始裁剪的时间点> (裁剪视频片段使用,设定裁剪开始的时间,单位为秒,或者为 HH:MM:SS) -to <裁剪结束的时间点> (设定裁剪持续的时间。单位为秒,或者为 HH:MM:SS)
H.264/AVC编码
ffmpeg官方的H.264指南:https://trac.ffmpeg.org/wiki/Encode/H.264
ffmpeg使用libx264来编解码H.264流。H.264编码时通常会使用两种模式,CRF和ABR的模式
- Constant Rate Factor(恒定速率因子/CRF):注重视频质量,在保持目标质量的情况下动态改变比特率,通过单次编码就可得出最佳的压缩效率。通过-crf参数指定质量,质量取值 0-51,数字越大质量越差。17-18被认为是视觉无损,20-28是常用取值,30以后通常会得出肉眼可见的质量损失。
- Average bitrate / Two-Pass ABR(平均比特率/两步平均比特率):注重最终输出的比特率大小,在保持固定的平均比特率的情况下,改变视频的质量。通过-b:v参数设定比特率,参数取值即为比特率,如2000k。通常效果会比CRF渣,只适合特定场景使用,比如视频直播使用平均比特率能够保持稳定,保持即时性,因为ABR的比特率只有小幅波动。单次平均平特率可用于低延迟,而两次平均比特率可用于更加精确的码率控制。
Constant Rate Factor
1.选择CRF的值
使用
-crf <质量数字> 来指定CRF的质量。CRF值的范围是0-51,数字越大质量越差。其中0是数据无损的,17-18被认为是视觉无损的,20-28是常用取值,23是默认值,30以后通常会得出肉眼可见的质量损失。2.选择编码预设
使用
-preset <配置名称> 来指定编码预设,在CRF质量固定的情况下,越慢的预设得出的比特率、文件体积越小。默认值为medium。- ultrafast
- superfast
- veryfast
- faster
- fast
- medium
- slow
- slower
- veryslow
- placebo
值得注意的是,压缩收益是递减的:placebo相比veryslow相比有助于只有约1%的压缩收益,但却会花费比veryslow多上很多的时间。veryslow相比slower有助于约3%的收益,slower相比slow有约5%的收益,而slow相比medium则会有约5-10%的收益。
3.选择视频调谐(可选项)
使用
-tune <视频特点> 来选择一组调谐,可以不使用这组选项,不使用会采用普通方式进行调谐。不过如果有符合调谐的视频特点,使用专门的调谐会得出更好的质量。- film – 用于高质量的电影内容; 低区块分割
- animation – 适合动画; 使用更高的区块分割和更多的参考帧
- grain – 保留颗粒、杂色的颗粒结构
- stillimage – 适用于静态、幻灯片式内容
- fastdecode – 通过禁用某些过滤器实现更快的解码
- zerolatency – 适用于快速编码和低延迟视频流
- psnr – 忽略它,因为它仅用于编解码器开发
- ssim – 忽略它,因为它仅用于编解码器开发
例如,如果输入是二次元动画,则使用animation调谐,或者如果要保留胶片中的颗粒,则使用grain调谐。不一定是严格的,比如在录制PC教程的时候,画面中大部分是固定的画面,这时候也可以使用animation调谐。stillimage只适合全屏都是静态图片的图片视频内容使用。
4.选择Profile(可选项)
还有两个ffmpeg不推荐的可选设置是
-profile:v 和 -level ,它将输出限制为特定的H.264配置文件。但除非目标设备仅支持某个配置文件,否则请忽略此项(参阅兼容性),因为使用低的Profile会大幅削弱质量或者压缩比。目前的配置文件有: baseline, main, high, high10, high422, high444 。兼容性(引用官方说明)
5.H.264保持质量转码示例
将.avi的二次元动画转换成压缩比较好的mp4:
ffmpeg -i anime.avi -c:v libx264 -crf 24 -preset slow -tune animation anime_h264.mp4
将序号01-50的图片序列转为每10秒更换一张图片的幻灯片mp4视频:
ffmpeg -r 0.1 -i %2d.jpg -r 24 -crf 24 -preset slow -tune stillimage -s 800x800 Movie.mp4
上面输入图片序列的 -r 使用了小于1的小数,这在ffmpeg是允许的。帧数的意思是每秒的画面张数,如果是解码使用,小于1的帧数则是相当于每张图片播放1秒以上。输入帧数0.1,输出帧数24,意思是解码器把每帧画面(每张图片)看做占用了10秒,并且编码器再把每一秒输出成24帧。
Average bitrate / Two-Pass ABR
1.计算想要的比特率
使用到固定的比特率通常目的是为了控制输出的文件大小,我们可以从目标文件大小推算出所需要的比特率。
计算公式:
(目标视频大小单位MB × 8192) ÷ 视频秒数 = 文件总比特率kB/s 文件总比特率 - 音频比特率 = 视频比特率
例如,想要把一个5分钟(300秒)的视频,控制文件大小在20MB,已知码率音频为96k:
(20 × 8192) ÷ 300 = 546 546 - 96 = 450
所以450K/s就是我们需要的视频比特率。
2.运行一次或两次编码
直接设定
-b:v <视频比特率> 即可,如:ffmpeg -i input.mp4 -b:v 450k -c:a copy output.mp4
需要运行
ffmpeg命令两次,两次使用相同的设置,除了:- 在第1和第2遍中,分别使用
-pass 1和-pass 2选项。
- 在第1遍中,输出到空文件描述符,而不是实际文件,这将生成第二次所需的日志。可加
-y忽略覆盖请求。
- 在第1遍中,需要指定一个输出格式(使用
-f),该输出格式与您在第2遍中使用的输出格式相匹配。
- 在第1遍中,可以通过指定
-an来忽略音频。
Linux:
ffmpeg -y -i input.mp4 -b:v 450k -pass 1 -an -f mp4 /dev/null && \ ffmpeg -i input.mp4 -b:v 450k -pass 2 -c:a copy output.mp4
Windows(CMD):
ffmpeg -y -i input.mp4 -b:v 450k -pass 1 -an -f mp4 NUL && ^ ffmpeg -i input.mp4 -b:v 450k -pass 2 -c:a copy output.mp4
Windows(Powershell):
ffmpeg -y -i input.mp4 -b:v 450k -pass 1 -an -f mp4 NUL ; ` ffmpeg -i input.mp4 -b:v 450k -pass 2 -c:a copy output.mp4
根据博主的个人经验,想设定ABR平均比特率的输出效果会很差。码率设定低时,复杂画面时画质损毁、只有平缓的画面是清晰的。而码率设定高时,不需要高码率的画面会被浪费空间。所以一般情况下还是用CRF才能让视频压缩充分得到利用。
HEVC/H.265编码
在H.264之后的更新版本是HEVC/H.265,全称High Efficiency Video Coding(高效率视频编码)。其能在更低码率的情况下达到同样于H.264的画质。
Google推出VP8的更新版VP9,HEVC和VP9都是比H.264压缩比更高的视频编码。从编码的角度来看,HEVC在编码速度明显胜出,且HEVC目前能在更多设备硬件加速编码、解码。不过从博主测试来看,HEVC视频在Chrome、Firefox浏览器视频播放是黑屏的,可能是由于版权费用问题并没有普及到网络视频,所以网络视频想要比H.264更高的压缩比目前只能用VP9(WebM)了。
ffmpeg使用libx265来编解码HEVC流,因为HEVC扩展名和容器和H.264一样都是mp4,所以使用HEVC时,注意记得加上
-c:v libx265,因为默认是libx264。HEVC和H.264一样都有CRF和ABR的模式。
Constant Rate Factor
1.选择CRF的值
和H.264一样,HEVC也使用
-crf <质量数字> 来指定CRF的质量。CRF值的范围是0-51,默认值28。和H.264都是数字越大质量越差,不一样的是HEVC只需要28就可以相当于H.264的23质量的效果,所以相同质量的情况下体积更小。2.选择编码预设
使用
-preset <配置名称> 来指定编码预设,在CRF质量固定的情况下,越慢的预设得出的比特率、文件体积越小。默认值为medium。- ultrafast
- superfast
- veryfast
- faster
- fast
- medium
- slow
- slower
- veryslow
- placebo
和H.264一样,压缩收益是递减的,越慢收益指数越低。
3.选择视频调谐(可选项)
使用
-tune <视频特点> 来选择一组调谐,不过目前实现的选项只有4个。- fastdecode – 通过禁用某些过滤器实现更快的解码
- zerolatency – 适用于快速编码和低延迟视频流
- psnr – 忽略它,因为它仅用于编解码器开发
- ssim – 忽略它,因为它仅用于编解码器开发
4.HEVC保持质量转码示例
将.avi转换成压缩比较好的HEVC-mp4:
ffmpeg -i anime.avi -c:v libx265 -crf 30 -preset slow anime_hevc.mp4
ABR / Two-Pass ABR
和H.264基本一致,不同的是需要把
-pass 1 改为 -x265-params pass=1 。把 -pass 2 改为 -x265-params pass=2。ffmpeg -i input.mp4 -c:v libx265 -b:v 2600k output.mp4
Linux:
ffmpeg -y -i input -c:v libx265 -b:v 2600k -x265-params pass=1 -an -f mp4 /dev/null && \ ffmpeg -i input -c:v libx265 -b:v 2600k -x265-params pass=2 -c:a aac -b:a 128k output.mp4
VP9编码/WebM格式
VP9是Google推出的视频编码器,容器格式使用了MKV,但后缀不使用MKV而是改为了WebM。WebM的音频编码使用Opus或者Vorbis,在ffmpeg可通过
-c:a libopus或者 -c:a libvorbis使用。视频VP8/VP9 + 音频Opus/Vorbis + 容器MKV = WebM
VP9和HEVC一样都是比H.264更高压缩比的视频编码器,但VP9是开放的,免版税的媒体编码器。这使得在使用上更加的开放,但也因为免费,推广力度不大,目前大面积使用WebM的只有Google的YouTube。
在视频编码方面,耗时较长,且没有像H.264/HEVC那么”傻瓜”的单次CRF模式,偏好两步编码,导致编码难度较大。
根据ffmpeg文档,VP9基本要在两次编码的情况下才能获得比较好的效果,所以文本只贴出两次编码的方法。
主要参数:
-c:v libvpx-vp9 使用VP9软件编码器对视频进行编码。-b:v 1000K 以1000 KB为目标对视频进行编码。-c:a libopus 使用Opus音频编码器-b:a 64k 以64 KB的目标音频编码。-tile-columns 6 -frame-parallel 1当前的大多数VP9解码器都使用基于图块的多线程解码。为了使解码器能够利用多个内核,编码器必须设置tile-columns和frame-parallel。-auto-alt-ref 1 -lag-in-frames 25设置-auto-alt-ref 1和-lag-in-frames> = 12将打开VP9的alt-ref帧,这是一个VP9功能,可以提高质量。-pass 1 -speed 4第一遍告诉VP9快速编码,从而牺牲质量。有助于加快第一遍。-pass 2 -speed 1第二遍使用-speed 1是速度与质量之间的妥协。产生的输出质量通常非常接近-speed 0,但编码速度通常更快。-threads > 1如果-threads > 1和 -tile-columns > 0,则可以使用多线程编码 。-crf 30对于VP9,CRF值取值0-63,数值越小越清晰。使用CRF模式时必须设置-b:v 0两次恒定质量编码
VP9也使用
-crf选项来选择一个质量,它的工作方式不等同H.264的CRF,不过在两次编码当中可以当成是类似的,通常使用-crf 30。使用恒定质量必须将-b:v 设置为0。在第1次和第2次中,分别使用-pass 1和-pass 2选项。Linux:
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -crf 30 -pass 1 -an -f webm /dev/null && \ ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -threads 8 -speed 2 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -crf 30 -pass 2 -c:a libopus output.webm
Windows(CMD):
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -crf 30 -pass 1 -an -f webm NUL && ^ ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -threads 8 -speed 2 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -crf 30 -pass 2 -c:a libopus output.webm
Windows(Powershell):
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -crf 30 -pass 1 -an -f webm NUL ; ` ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -threads 8 -speed 2 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -crf 30 -pass 2 -c:a libopus output.webm
两次平均比特率编码
根据文档,因为VP9单次平均比特率编码不具有压缩比,所以VP9使用ABR时基本都需要两次编码。
Linux:
ffmpeg -y -i input.mp4 -c:v libvpx-vp9 -b:v 2M -pass 1 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -an -f webm /dev/null && \ ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 2M -pass 2 -threads 8 -speed 1 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -c:a libopus output.webm
Windows(CMD):
ffmpeg -y -i input.mp4 -c:v libvpx-vp9 -b:v 2M -pass 1 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -an -f webm NUL && ^ ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 2M -pass 2 -threads 8 -speed 1 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -c:a libopus output.webm
Windows(Powershell):
ffmpeg -y -i input.mp4 -c:v libvpx-vp9 -b:v 2M -pass 1 -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -an -f webm NUL ; ` ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 2M -pass 2 -threads 8 -speed 1 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -c:a libopus output.webm