本文档翻译自: https://ffmpeg.org/ffmpeg.html
中间加入了部分笔者的个人理解。有翻译生硬之处,难登“信、达、雅”之境界。望读者不吝指正。
语法
1 | ffmpeg [global_options] {[input_file_options] -i input_file} ... {[output_file_options] output_file} ... |
概述
ffmpeg
是一个快速的音视频转换工具,它能在任意的采样率和视频大小之间转换并且获得高质量多态的过滤。
ffmpeg
根据 -i
选项读取任意数量的输入文件
(普通文件、管道流、网络流、可抓取设备等等),将转换结果写入到指定的多个输出 文件
。命令行参数中不能被解析为选项的所有参数都被视为一个输出文件名。
理论上讲,每个输入或输出文件都可以包含任意数量的多媒体流(视频、音频、字幕、附件及额外信息),但实际允许的多媒体流数量可能受限于转换格式。 通过 map
选项(参考流筛选章节)可自动地从某个输入文件的某个多媒体流映射到某个输出文件。
为了指定输入文件,你必须遵从从 0
开始的索引规律,第一个输入文件的索引为 0,第二个输入文件的索引为 1,以此类推。类似的,文件内的多媒体流也是从 0
开始计数,比如 2:3
指第三个输入文件的第四个多媒体流。
一般来说,参数选项都将应用于下一个文件。因此,命令行参数都顺序非常重要,你可以在命令行中多次使用同一个参数,将它用于不同的文件,每个参数都会应用于下一个输入或输出文件。除非是全局选项,它们必须在命令行中的最前面。
切勿混合使用输入和输出文件:首先指定输入文件选项,然后再指定输出文件选项。同样地,不要在不同文件间混合使用参数,所有的选项都只会应用于紧挨着它都下一个输入或输出文件。
- 将输出文件的比特率置为 64 kbit/s:
1
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi
强制输出文件的帧率为 24 fps:
1
ffmpeg -i input.avi -r 24 output.avi
强制输入文件(仅限于原始格式)的帧率为 1 fps,输出文件的帧率为 24 fps:
1
ffmpeg -r 1 -i input.m2v -r 24 output.avi
详细说明
ffmpeg
的转码过程可以用如下图表示:
1 | _______ ______________ |
ffmpeg
调用 libavformat
库来读取输入文件,从中获得压缩数据包,如果输入文件为多个,ffmpeg
尝试在每一个有效的输入流中将它们同步并记录最小时间戳。
然后,压缩数据包传递给相应的流解码器,输出原始的未压缩的数据流(原始视频或者 pcm 音频……),这些数据流经过过滤后传递给相应的编码器,对其进行编码、压缩,最后将压缩数据包写入到输出文件。
过滤
在编码之前,ffmpeg
能通过 libavfilter
库对原始音视频流进行过滤,多个过滤器构成了一幅过滤图,ffmpeg
识别简单
和复杂
的两种过滤图。
简单过滤
只有一种类型的输入和输出,如上图中,可在解码和编码之间插入一个简单过滤:
1 | _________ ______________ |
简单过滤根据每一个流的过滤选项(-vf
和 -af
)来配置,一个简单的视频过滤示例如下:
1 | _______ _____________ _______ ________ |
复杂过滤
当输入或输出为多个,或者输入和输出文件的媒体流类型不同时,不能对流进行简单地进行线性过程处理,这个过程如下图:
1 | _________ |
通过 -filter_complex
全局选项指定,-lavfi
等同于 -filter_complex
.
流拷贝
流拷贝是提供给 -codec
选项的一种流筛选模式,它让 ffmpeg
跳过解码和编码步骤,因此它只有解复用步骤。流拷贝对于修改容器格式或容器级别的元数据是很实用的。
1 | _______ ______________ ________ |
少了解码和编码步骤,拷贝过程是很快并且无损的。但是,受多种因素影响,在某些情况下它可能无法应用。流过滤因此也显然不可用,因为过滤必须工作于未压缩的原始数据上。
流筛选
ffmpeg
默认只从输入文件中选择一个同种流媒体类型(音频、视频、字幕等),将它们包装到输出文件中。基于如下标准,它挑选出最 好
的那个流:
- 对于视频,它是最高分辨率的那个流;
- 对于音频,它是通道数最大的那个流;
- 对于字幕,它是第一个字幕流。
- 如果有多个同类型流都符合标准,那么选择索引最小的那个流。
你可以通过 -vn/-an/-sn
等选项移除默认筛选的这些流,若要人工控制选择哪些流,可用 -map
选项。
参数选项
所有数值选项,如果没有另外的规定,表示接受数字作为输入,其可以随后 SI单位
前缀之一的字符串,例如:K
,M
,或G
。
如果i
被附加在SI单位前缀,则完整的前缀将被解释为一个以 1024
(而非 1000 )为基数的二进制倍数的单元前缀,将 B
附加到SI单位后缀将乘以 8。这允许使用,例如:“KB”,“MIB”,“G”和“B”为数字后缀。
选项不带参数的布尔选项,并设置相应的值设置为 true
, 它们可以通过与no
的前缀选项名称设置为 false
。例如使用-nofoo
将设置名称为foo
为flalse
的布尔选项。
流选择器
有些选项适用于每个媒体流,比如 bitrat
和 codec
。流选择器用于精确指定给定的选项适用于哪个流。
一个流选择器是一个字符串,它被追加到一个选项中并且用 :
分隔,比如 -codec:a:1 ac3
包含流 a:1
, 它匹配第二个音频流,因此,这个流选择器将在第二个音频流上采用 ac3
编码器。
一个流选择器可以匹配多个流,因此选项将默认用于所有的流。比如 -b:a 128k
将所有的音频流的比特率置为 128k。
一个空的流选择器匹配所有流,比如 -codec copy
或 -codec:copy
将拷贝所有的流。
流选择器的形式有:
stream_index
匹配中这个索引指代的流,比如,-threads:1 4
将会把第二个流的线程数设置为 4.stream_type[:stream_index]
stream_type可以是:v
orV
for video,a
for audio,s
for subtitle,d
for data, andt
for attachments。v
匹配所有的视频流,V
之匹配没有附加图片、视频缩略图或者封面的视频流。如果指定了stream_index,那么它指定该stream_index 索引对应的那个流,否则,它匹配该类型的所有流。p:program_id[:stream_index]
If stream_index is given, then it matches the stream with number stream_index in the program with the id program_id. Otherwise, it matches all streams in the program.stream_id or i:stream_id
Match the stream by stream id (e.g. PID in MPEG-TS container).m:key[:value]
Matches streams with the metadata tag key having the specified value. If value is not given, matches streams that contain the given tag with any value.u
Matches streams with usable configuration, the codec must be defined and the essential information such as video dimension or audio sample rate must be present.
Note that in ffmpeg, matching by metadata will only work properly for input files.
时间戳格式
1 | [-][HH:]MM:SS[.m...] |
或者
1 | [-]S[.m...] |
示例:55
,12:03:45
,23.189
, 适用于 -t
,-ss
,-sseof
,-t
等选项。
常用选项
-f fmt (input/output)
强制输入/输出的媒体格式。一般情况下,
ffmpeg
会自动从输入文件中识别出媒体格式,并且从输出文件名后缀猜测出输出格式,因此,大多数情况下,不需要此选项。-y (global)
不提示,覆盖同名的输出文件。
-n (global)
不准覆盖输出文件,如果存在同名文件,则立即退出程序。
-c[:stream_specifier] codec (input/output,per-stream)
-codec[:stream_specifier] codec (input/output,per-stream)
ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT
将所有视频流以 libx264 编码并且拷贝所有的音频流。
对每个流,起作用的是最后一个-c
选项。ffmpeg -i INPUT -map 0 -c copy -c:v:1 libx264 -c:a:137 libvorbis OUTPUT
将拷贝所有的流,除了第二个视频流以 libx264 编码,第 138 个音频流以 libvorbis 编码。
-t duration (input/output)
当用于输入选项(
-i
之前),限制从输入文件中最多读取的时长。
当用于输出选项(output_file
之前),当写入时长超过该时长时,将停止写入。
-to
和-t
不允许同时存在,-t
优先。-to position (output)
指定在何时停止写入,必须以 ffmpeg 允许的时间格式表示。
-ss position (input/output)
当用于输入选项时,定位到该文件的这个位置开始解码。
当用于输出选项时,解码当前位置前面的媒体但是忽略这些输入直到读取到该时间戳。-sseof position (input/output)
和
-ss
类似,但是相对于文件尾部而言,它是距离文件尾部的非正值,0
代表EOF
。ffmpeg -sseof -00:06 -t 00:05 -i input output
将从距离 input 末尾 6 秒的地方开始,解码 5 秒。
视频选项
-vframes number (output)
指定输出多少视频帧,等同于
-frames:v
。-r[:stream_specifier] fps (input/output,per-stream)
指定帧率
fps
。
作为输入,忽略原有的时间戳并且用新生成的时间戳代替。它和用于某些输入媒体的格式如
image2
或v4l2
的-framerate
选项不同,如有疑问,请用-framerate
代替-r
选项。作为输出,复制或丢弃某些帧以达到指定的帧率。
-s[:stream_specifier] size (input/output,per-stream)
指定帧尺寸,
w*h
或wxh
。-aspect[:stream_specifier] aspect (output,per-stream)
指定视频的显示宽高比,
4:3
,16:9
,1.3333
,1.7777
等。-vn (output)
不输出视频内容
-vcodec codec (output)
指定视频编码器,等同于
-codec:v
。
音频选项
-aframes number (output)
指定输出多少音频帧,等同于
-frames:a
。-ar[:stream_specifier] freq (input/output,per-stream)
指定音频采样率。
-ac[:stream_specifier] channels (input/output,per-stream)
指定音频声道数。
-an (output)
不输出音频内容
-acodec codec (input/output)
设置音频编解码器,等同于
-codec:a
.-sample_fmt[:stream_specifier] sample_fmt (output,per-stream)
指定音频采样格式。
高级选项
-map [-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]] | [linklabel] (output)
指定一个或多个输入流作为输出源。
每个输入流根据输入文件索引、输入文件id和输入流索引来标示。所有的索引从0
开始。第一个-map
选项确定输出流0
, 第二个-map
选项确定输出流1
, 以此类推。
-
符号表示不对该输入流进行映射。
示例:
将第一个输入文件的所有流映射至输出:
ffmpeg -i INPUT -map 0 -f FORMAT output ffmpeg -i INPUT -map 0 output.mp4
假设你有一个输入文件,其中含有两个音频流,分别以
0:0
,0:1
标示,只将第二个音频流输出:ffmpeg -i INPUT -map 0:1 out.wav
选取输入文件
a.mov
中第三个输入流,标示为0:2
,和输入文件b.mov
中第 7 个输入,流标示为1:6
,将它们拷贝到输出文件out.mov
:ffmpeg -i a.mov -i b.mov -c copy -map 0:2 -map 1:6 out.mov
从输入文件中选中所有的视频流和第三个音频流:
ffmpeg -i INPUT -map 0:v -map 0:a:2 OUTPUT
将所有流,除了第二个音频流,映射至输出:
ffmpeg -i INPUT -map 0 -map -0:a:1 OUTPUT
音视频转换
视频 ==> yuv
ffmpeg -i 2.mp4 2.yuv ffmpeg -i input.mp4 -f rawvideo -vcodec rawvideo -pix_fmt yuv420p -s 1920x1080 -r 25 rawvideo.yuv
yuv ==> 视频
必须指定输入的
yuv
分辨率-s
ffmpeg -s 320x240 -i 2.yuv -c:v mpeg4 output.mp4 ffmpeg -f rawvideo -vcodec rawvideo -s 1920x1080 -r 25 -pix_fmt yuv420p -i inputfile.yuv -s 320x240 -c:v libx264 -qp 0 output.mp4
audio + yuv ==> 视频
ffmpeg -i /tmp/a.wav -s 640x480 -i /tmp/a.yuv /tmp/a.mpg
音频转换
ffmpeg -i /tmp/a.wav -ar 22050 /tmp/a.mp2
通过映射流,将输入同时编码成多种格式到不同输出:
ffmpeg -i /tmp/a.wav -map 0:a -b:a 64k /tmp/a.mp2 -map 0:a -b:a 128k /tmp/b.mp2
从视频中抽取图像
从
foo.avi
中每一秒抽取一张大小为320x240
的图像到foo-001.jpeg
,foo-002.jpeg
…ffmpeg -i foo.avi -r 1 -s 320x240 -f image2 foo-%03d.jpeg
如果只想抽取指定数量的图像帧,可搭配使用
-vframes`
-t-ss`等选项。
根据图像序列生成视频
ffmpeg -f image2 -framerate 12 -i foo-%03d.jpeg -s 480x240 foo.avi
将多个 同类型 的输入媒体映射至输出
ffmpeg -i test1.avi -i test2.avi -map 1:1 -map 1:0 -map 0:1 -map 0:0 -c copy -y test12.nut
将
test1.avi
和test2.avi
的音视频流逆序映射至test12.nt
。(注意:这不是拼接视频,用ffplay
播放的话,可以看出只播放了前面的test.avi
部分)从视频中生成 GIF
ffmpeg -ss 00:10:00 -t 10 -i capx.mp4 -s 320x240 jilu.gif
拼接视频
前提条件
- 视频图像尺寸一样
编码格式相同
protocol
支持文件级别拼接(MPEG-1, MPEG-2 PS, DV),媒体类型必须一致。
ffmpeg -i 'concat:input1|input2' -codec copy output
在 `OS X 10.11` 下 `ffmpeg 2.8.2` 用该方式拼接后,只有 `input1` 部分。
demuxer
推荐使用此方法
支持媒体流级别拼接,比 protocol 更灵活,可用于不同的媒体类型。
1
2
3
4
5
6$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
$ ffmpeg -f concat -i mylist.txt -c copy output
编码格式不同
video filter
适用于不同编码格式、不同媒体类型的文件拼接。1
ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv -filter_complex '[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1 [v] [a]' -map '[v]' -map '[a]' output.mkv