Introduction to FFmpeg

简介

一直以来就想介绍一下FFmpeg这个强大的多媒体工具。官方介绍为"A complete, cross-platform solution to record, convert and stream audio and video. "

FFmpeg包含三个部分:ffmpeg, ffplay和ffprobe,分别用于转换、播放和查看信息。当然查看信息用MediaInfo更加方便,文件右键即可。而播放,相信大家都有自己偏好的播放器,不会去用命令行工具播放。说句题外话,我目前用PotPlayer,另外K-Lite、VLC也不错。接下来主要就介绍ffmpeg。

很多播放器都用ffmpeg来软解码(与硬件解码相对),但除此之外,ffmpeg还可以用来转码,简单的剪辑,修改视频分辨率。使用各种库可以支持很多常见的编码操作。ffmpeg是命令行工具,方便批处理,还提供库以供再开发,完全开源。

ffmpeg的版本迭代很快,我一般用稳定版。由于GPL的限制,不包含非开源的内容,所以有一定的欠缺。可以自己编译非自由版本,但是难度很大,可能要花半天。我以前也试过,但现在已经放弃了,转而用自由版本。Windows可以直接获取二进制文件;一般的发行版都提供ffmpeg,可能版本比较旧,但其实影响不大。

多媒体基础

一个视频文件,一般包括视频(Video)、音频(Audio),可能还包含字幕(Subtitle)、章节等文本信息,甚至包含附件。所以这个包装方式称为容器(Container),或一般称为格式,与文件后缀有关。

一个容器中可以包含多个视频、音频、字幕,而这些流的格式称为编码,相当于不同的压缩算法。编码方式可以分为有损和无损编码,一般视频不会使用无损编码。

格式(容器)

一些简单的、并不专业的介绍。

Matroska

Matroska是较新的流行格式,开源,支持几乎所有编码,几乎什么都可以塞进去。但是比较旧的播放器可能不支持。推荐用MKVToolnix混流,而不是ffmpeg,前者输出文件的兼容性更好。我推荐自己制作或转码的视频用这个容器。

MPEG-4

MPEG-4也比较常见,大多数播放器都支持。可以使用的编码相比Matroska少,但能满足常见的需要。

AVI

AVI(Audio Video Interleave)是一种相当古老的格式,由微软设计,所以在Windows下支持很好。从Windows 3.1开始的Video for Windows就用这种格式。较新的编码也能支持,但是播放器就不一定了。不应该再使用这种格式。

FLV

FLV(Flash Video)是网络视频常见的格式,支持的编码很有限。

WMV

WMV(Windows Media Video)是微软的另一种容器,现在也已经比较少见了。不过Windows 7自带的视频Wildlife.wmv很经典。其使用的编码是专有的,因此无法用ffmpeg实现编码。

视频编码

H.264(AVC)

H.264是目前使用最为广泛的视频编码,也比较先进,在很多设备上有完善的硬件解码,有些还提供快速的硬件编码。适合1080p及以下,而2160p(4K)就会差些。

HEVC(H.265)

HEVC是较新的视频编码,压缩更为先进高效,但是并不普及。较新的硬件可能支持硬件解码,但是编码一般较慢。在4K上会大大超过H.264,较低的分辨率下也很理想。

VP9

Google开发的与HEVC竞争的视频编码,开源且免费,但是硬件支持可能不如前两个。

AV1(VP10)

宣称是HEVC的下一代视频编码,而且开源免费,效率全面超过以前的编码。但不久前发布,支持很少。优势也需要在4K以上。新的ffmpeg已经提供支持,可以去体验。

音频编码

AAC

与AVC一样流行的音频编码,超过前代的MP3。没有特殊要求一般都用AAC编码音频。

MP3

较为古老但仍然常见的音频编码,在视频中用的已经较少,但单独的容器还很常见。建议用AAC取代。

Opus

更先进的开源音频编码,但是很罕见。可以作为研究,但可能实际意义不大。

FLAC

常见的无损音频编码,同样开源,比raw的WAV要节约空间。如果需要无损音频主要考虑FLAC。

WAV

未压缩的音频数据,只是演示及作为中间状态,应该很少实际应用。

使用

最简单的转换只要ffmpeg -i input.mp4 output.avi,其中-i表示输入文件,后面表示输出文件。ffmpeg会自动选择合适的方法转换,但很可能不是最佳的。

ffmpeg的工作流程:

在实际使用中,有时可以跳过若干个步骤。

下面介绍一些常用的参数。

显示类

参数 解释
-version 显示版本
-formats 显示支持的格式(容器)
-decoders 显示支持的解码器
-encoders 显示支持的编码器
-filters 显示支持的过滤器
-h encoder=xxx 显示xxx编码器有关的信息,其他类型也可以

流复制

这是最简单的一种处理,也就是只改一下容器。此时,不用解码或编码,只要复制流即可。

示例:下载了input.flv,但是播放器不支持,需要转换成MP4容器。

命令:ffmpeg -i input.flv -c copy output.mp4

解释:-c指定输出编码,copy表示直接复制输入编码即可。

简单重编码

需要重新编码?也很简单。

示例:一个巨大的input.mp4,只包含一个视频流和一个音频流。要求压缩这个文件,视频用HEVC编码,音频直接复制(一般相比视频,音频占的空间不大)。

命令:ffmpeg -i input.mp4 -c:v libx265 -crf 20 -c:a copy output.mkv

解释:-c:v|a可以指定针对视频/音频编码,如果有多个视频/音频流,ffmpeg会自动选择质量最高的那个输出。-crf指HEVC用固定质量编码,质量为20。

H.264/HEVC都用CRF来指定固定质量,CRF越小质量越高,但也越大。H.264默认为-crf 23,HEVC默认为-crf 28,注意两者没有直接可比性,要根据实际需要确定CRF。使用CRF模式无法确定输出文件大小,因此适用于空间限制不高的情况。

关于适当CRF的选择,可以参考视频编码质量测试

无聊的测试