FFmpeg - 不仅仅是视频转码工具
前言
很久以前我曾经写过Introduction to FFmpeg,后来基本上弃坑了。最近我又打算略微换一下主题,重新深入介绍一下FFmpeg,准备去投稿洛谷日报。顺便提一下,之前我改编的博客文章Turbo Pascal的进化史有望在最近登上洛谷日报,敬请关注。
我发现,不管是在高中信息技术还是NOIp初赛中,对于多媒体的基础和常见操作并没有多少涉及,有的观念甚至是不正确的。而在信息时代,多媒体是相当重要的,有时就是需要一些格式转换或压缩,为此我写本文来做一些基础的科普。
FFmpeg是一个功能强大、跨平台的开源视频转码工具,被许多播放器和转换工具所使用,例如VLC、MPlayer、暴风影音等播放器,以及格式工厂等转换工具。其中FF是“Fast Forward”的缩写(貌似只在Git里看到过),FFmpeg的读法是先读字母f-f-m-,再读词peg。FFmpeg包含三个部分:ffmpeg、ffplay和ffprobe,分别用于转换、播放和查看信息。本文主要介绍命令行版的FFmpeg。
那么为什么要用FFmpeg而不是格式工厂等工具呢?首先FFmpeg是开源的,而且熟悉之后命令行比图形界面更高效,其扩展性也很好,可以整合许多编解码库,还能用于自己写的程序中。而格式工厂虽然免费但没有开源,所以违反了FFmpeg的GPL协议,曾经登上“耻辱厅”。
FFmpeg的很多中文文章并不是很适合入门,除了本文外,还可以浏览一下参考文献中的文章(系列)。本文只要求有一定的命令行基础。
快速入门
仿照The C Programming Language等书的第一章,这里先给出一些常用的例子,而不加以系统说明,以实现快速入门。mp4是最为常见的视频格式,而H.264则是最常见的视频编码。
下载与安装
对于Windows用户,在这个网站下载,我推荐使用稳定版、Shared。
对于Linux以及Mac,直接安装软件包吧,如果觉得版本太老可以尝试自己编译(高级操作)。如果没有ffmpeg,那么找替代品libav,libav是ffmpeg的一个分支,使用方法有一些不同。
简单转换
音视频转换从未那么简单:
1 | ffmpeg -i input.mp4 output.avi |
这个命令就是把input.mp4
转换为output.avi
。转换时,可以按q
来中止转换。ffmpeg会使用多线程来加速,因此CPU使用会接近100%。
这样转换太慢了?一般转换都比较慢,达不到实时(1x)。不妨试试“快速转换”(下文会作解释),如果格式适合,可以达到文件复制的速度。下面的例子将常见的网络视频格式flv转换为mp4。
1 | ffmpeg -i input.flv -c copy output.mp4 |
想要提取视频中的声音?这也很简单。
1 | ffmpeg -i input.flv output.mp3 |
下一个操作是去除视频中的音频,这也很常用。这样视频中将不包含任何音频数据。
1 | ffmpeg -i input.flv -an output.mp4 |
既然有提取,我们也需要合成视频。
1 | ffmpeg -i input.mp4 -i input.mp3 -c copy output.mp4 |
视频压缩
很多时候,由于大小限制或者网速限制,需要把一个视频压缩。下面的例子将一个4K的视频压缩到高清(1280x720,720p)。
1 | ffmpeg -i 4k.mp4 -s hd720 hd.mp4 |
两条命令是等价的,此外ffmpeg还内置了很多标准分辨率。
有时不想改变视频分辨率,而是想改变压缩的参数。
1 | ffmpeg -i input.mp4 -crf 18 output.mp4 |
注意,常见的mp4(其实是H.264)可以用crf来设定压缩质量,推荐在18~28之间,默认是23,数值越小质量越高,文件也越大。
当然,上述两种操作也是可以一起进行的,只要把两个选项都写上即可。
1 | ffmpeg -i 4k.mp4 -s hd720 -crf 28 hd.mp4 |
视频截取与拼接
截取从1:00开始的20秒内容:
1 | ffmpeg -i input.mp4 -ss 1:00 -t 20 output.mp4 |
可以发现,既可以用分、秒来表示时间,又可以直接用秒来表示。
拼接相对麻烦一点,需要创建一个拼接的文件列表:
1 | file input1.mp4 |
然后再用ffmpeg:
1 | ffmpeg -f concat -i concat.txt -c copy output.mp4 |
嵌入字幕
对于外挂字幕,一种方法是复制到视频中,需要播放器支持这种字幕,其实和外挂没多少区别;另一种方法是把字幕直接“刻”到视频里,我习惯称为“硬字幕”,这样就无需播放器支持字幕了。
第一种方法类似合成视频和音频:
1 | ffmpeg -i input.mp4 -i input.ass -c copy output.mkv |
而第二种方法就比较慢了:
1 | ffmpeg -i input.mp4 -vf subtitles=input.ass output.mkv |
多媒体基础
一个视频文件,一般包括视频(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
未压缩的音频数据,只是演示及作为中间状态,应该很少实际应用。