神器FFmpeg的使用
以前进行视频转换,用这个那个工具,最后发现神器FFmpeg
太强大了。FFmpeg
参数众多,以下记录ffmpeg
的一些用法。
1.FFmpeg简介
以下内容来自维基百科 > FFmpeg是一个自由软件,可以运行音频和视频多种格式的录影、转换、流功能,包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库,以及libavformat——一个音频与视频格式转换库。
2. FFmpeg命令行工具组成
FFmpeg命令行工具包含以下三个基本工具: 1) ffmpeg
:视频文件转换命令行工具,支持经过实时电视卡抓取和编码成视频文件; 2) ffserver
:基于HTTP、RTSP用于实时广播的多媒体服务器。也支持时间平移; 3) ffplay
:用 SDL和FFmpeg库开发的一个简单的媒体播放器;
3. FFmpeg的下载
FFmpeg的下载地址:FFmpeg下载 ,一般下载static版本,解压后设置环境变量即可使用。
4. FFmpeg命令格式
FFmpeg工具的基本格式为: 1
ffmpeg [global_options] [[infile options] -i infile]... {[outfile options] outfile}...
-i
参数表示输入参数;之后的参数是输出参数。
ffmpeg 的一般工作流,是从源文件开始,依次经过分流器、解码器、编码器、混流器,最后完成输出文件。下图是官网给出的示意: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 _______ ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |
v
_________
| |
| decoded |
| frames |
|_________|
________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|
一些基本的概念: - 流(stream):视频文件中,一般具有视频流与音频流,有的具有字幕流。它们需要不同的解码/编码器。想要混合/分离视频与音频,就需要混流/分流器。 - 流复制(stream):如果某种数据流的内容不需要任何改动,那么可以直接跳过该数据流的解码与编码步骤。分离出该数据流后,直接等待参与混流即可。
ffmpeg 在有多个流的情况下,不会全部保留;默认只会选择同类流中质量最佳的。如果质量同样,那么选择索引号靠前的流。你可以选择手动控制流的选择,这需要额外的参数,我们下文介绍。
5. 主要参数
下表中: 1. 以 <>
包裹的表示由用户具体指定;以 []
包裹的表示是可选参数,可以指定也可以省略。 2. 括号内的 i
表示该参数用于输入流,o
表示用于输出流,i/o
表示均可,global
表示全局参数。 3. 关键字 duration
, position
或 offset
满足:[-][HH:]MM:SS[.m...]
这种时间戳格式。或者以秒为单位的 SS[.m...]
格式。
常用的如下: - -b[:stream_specifier] (o)
:输出比特率。 - -f <fmt> (i/o)
:指定 fmt
作为输入或输出的视频格式。一般会根据文件扩展名自动选择,但有时需要手动指定。
- -i <filename> (i)
:指定 filename
作为源文件。
- -y (global)
:文件存在时直接覆盖。
- -n (global)
:文件存在时不覆盖并立即退出。
- -bsf[:stream_specifier] <bitstream_filters> (o)
:设置比特流滤镜。bitstream_filters
是一个逗号分隔的滤镜列表。 - -stream_loop <num> (i)
:指定输入流的循环次数。0 表示不循环,-1 表示无限循环。
- -c[:stream_specifier] <codec> (i/o)
:-c
可写为-codec
。选择一个 codec
,即编码器(输出时)或一个解码器(输入时),参与到 stream_specifier
指定的一个或多个流的编码/解码中。在输出时,<codec>
可以被指定为 copy
,表示复制数据流。
- -t <duration> (i/o)
:(在参数 -i
之前指定)工作持续 duration
时长。一般用于指定剪辑数据流的范围。 它与 -to
参数相互冲突,但本参数优先。
- -to <position> (o)
:到 position
位置后,终止输出。与 -t
参数冲突,本参数优先级低。 - -fs <limit_size> (o)
:输出文件大小达到 limit_size
后停止输出,单位是 byte.
- -ss <position> (i/o)
:(在参数 -i
之前指定)从 position
指定的位置开始工作。注意:大多数情形下,工作起始位置是不精确的。ffmpeg会找到其前部的一个点作为真正的起始,并在结束工作后将该点与用户指定点之间的内容抛弃。然而,如果你使用了 copy 参数,这部分内容却会被保留。
- -sseof <position> (i/o)
:类似 -ss
参数,只不过是从数据流末端向前寻找 position
。此时 0 表示数据流末。
- -itsoffset <offset> (i)
:指定输入流以原时间戳加上 offset
作为其输入时间戳。
- -metadata[:metadata_specifier] key=value (o)
:以键值对的形式设置元数据。
- -frames[:stream_specifier] <num> (o)
:在输出 num
帧后停止写入。 - -qscale[:stream_specifier] q (o)
:使用固定质量(VBR)。
- stats (global)
:输出编码过程,是系统默认值。可以使用 -nostats
关闭。
- -attach <filename> (o)
:将 filename
文件附加到输出文件。附件流作为文件的最后一个流,只有很少的文件类型被支持(例如字体)。
6. 视频参数
-vframes <num>
:文件的总帧数。-frames:v
的别名。-r[:steam_specifier] <fps> (i/o)
:文件的帧率。-s[:steam_specifier] <size> (i/o)
:帧尺寸。参数size
需要满足格式<width>x<height>
,例如320x240
。 -aspect[:steam_specifier] <asp> (o)
:宽高比,例如4:3
。如果使用了-vcodec copy
,那么指定容器的宽高比而不是视频的。-vn (o)
:禁止输出视频。-vcodec <codec> (o)
:设置视频编码器。-codec:v
的别名。-pass[:stream_specifier] <n>
:选择当前编码数(1或者2),常用于二次编码的情况。在第一次编码中,音频输出往往被设置为 NULL,对于 Windows 与 Unix 系统分别是:1
2ffmpeg -i foo.mov -c:v libxvid -pass 1 -an -f rawvideo -y NUL
ffmpeg -i foo.mov -c:v libxvid -pass 1 -an -f rawvideo -y /dev/null
7. 音频参数
-aframes <num> (o)
:文件的总帧数。-frames:a
的别名。-ar[:stream_specifier] <freq> (i/o)
:采样率。默认输出等于输入。仅当输入文件为真实设备或者 raw 数据时,该参数才能用于输入过程。-aq <q> (o)
:音频品质(VBR)。-q:a
的别名。-ac[:stream_specifier] <channel> (i/o)
:设置音频通道数。默认输出等于输入。仅当输入文件为真实设备或者 raw 数据时,该参数才能用于输入过程。-an (o)
:禁止输出音频。-acode <codec> (i/o)
:设置音频的解码器或编码器。-codec:a
的别名。
8. 字幕参数
-scodec <codec> (i/o)
:字幕解码器或编码器。codec:s
的别名。-sn (o)
:禁止输出字幕。canvas_size <size>
:设置字幕渲染区域的尺寸。
9. 其他参数
以下直接在 ffmpeg
后使用,例如:ffmpeg -version
。
-bsfs
:可用的比特流滤镜。-h [arg]
:帮助。arg 的内容可以是:decoders
:可用的解码器。或特指:decoder=<name>
。encoders
:可用的编码器。或特指:encoder=<name>
。filters
:所有滤镜。或特指:filter=<name>
。formats
:可用的分流器与混流器。或特指分流器:demuxer=<name>
,或特指混流器:muxer=<name>
。
-protocols
:支持的协议。-version
:版本信息。
10.FFmpeg 实用例子
10.1 合并视频
第一种方案:将这几个视频放在一个新文件夹内,Shift 右键运行 cmd,输入(注意:如果要保存为批处理文件,请循环变量的双写百分号。): 1
2(for %i in (*.flv) do @echo file '%i') > mylist.txt
ffmpeg -f concat -i mylist.txt -c copy output.flv
另一种方案:先将这几个视频无损地转为 mpegts 文件,再通过 concat 协议合并。以常见的 H.264 视频与 aac 音频为例:
1 | ffmpeg -i "1.flv" -c copy -bsf:v h264_mp4toannexb -f mpegts 1.ts |
这种方案是早期方案,支持更广,包括非 mpeg 容器的 mpeg 编码内容(H.264, MPEG4, MPEG2, AAC, MP3等)。不过这样会产生中间文件。
10.2 分割视频
指定视频的起始与持续时长就可以分割视频了。下例截取了视频的前 5 秒(00:05:00),注意-t
后接“截取视频段长度”而不是“截取终点时刻”:
1 | ffmpeg -i "input.mp4" -ss 00:00:00 -t 5 -c copy "output.mp4" |
建议使用规范的 mp4 格式文件,否则可能出现视频无法正常混流的现象。
10.3 批量格式转换
比如,对于数据流用 mpeg 编码的一个 flv 文件,可以这样转为 mp4 文件: 1
ffmpeg -i "input.flv" -c copy "output.mp4"
因此一个批量转换也很容易通过 for 语句实现(%~n
表示保留不含扩展名的文件名): 1
for %i in (*.mp4) do ffmpeg -i "%i" -c copy "%~ni.flv"
10.4 静态图水印
下例添加 png 或其他静态格式的水印,放置在距左侧 20 像素,距顶端 40 像素的地方。水印与视频的基准点都是左上角点。
1 | ffmpeg -i input.mp4 -i wm.png -filter_complex "overlay=20:40" output.mp4 |
如果要放在右下角使用overlay= main_w-overlay_w:main_h-overlay_h
,参数的含义应该较好理解。
如果要指定水印的大小,比如 384x216: 1
ffmpeg -i input.mp4 -i wm.png -filter_complex "[1:v]scale=384:216[wm];[0:v][wm]overlay=0:0" output.mp4
参数 0:v
表示第1个输入的视频流(本例即input.mp4的视频流),1:v
表示第2个输入的视频流(本例即wm.gif)。分号前的[wm]用于引用。
10.5 GIF水印
添加 gif 水印与静态图水印有一些不同之处: - 需要将 ignore_loop
参数指明为 0,表示 gif 无限循环。 - 需要用到复合过滤器 filter_complex
。 - 需要过滤器的 shortest=1
选项,表示至少在一个视频流循环一次后,再终止输出。如果不加该选项,输出将无法自行停止。
一个指定 50x50 大小 GIF 水印在左上角的例子: 1
ffmpeg -y -i input.mp4 -ignore_loop 0 -i wm.gif -filter_complex "[1:v]scale=50:50[wm];[0:v][wm]overlay=0:0:shortest=1" output.mp4
10.6 外挂字幕
将字幕作为单独的数据流(而不是混入视频流中),封装到容器内。一般对此特性有良好支持的容器是 mkv。在封装时,一般需要转为 ass 格式。 1
ffmpeg -i input.mp4 -i input.srt -c:v copy -c:a copy -c:s ass output.mkv
一些注意点: - 字幕文件请用 UTF-8 编码。 - Windows 系统缺少一个字体接口,因此需要自己配置 fonts.conf 文件,放在 %FONTCONFIG_PATH%
这个环境用户变量里(往往需要你自己新建)。该变量应该指向C:\Users\用户名\
。
网上流传了一份 fonts.conf 文件内容(见附录),请复制后粘贴到你对应文件夹的 fonts.conf 文件中。
10.7 内嵌字幕
在播放器不支持独立字幕流的场合,需要将字幕混入视频流中(因此需要重编码)。 1
ffmpeg -i input.mp4 -vf subtitles=input.srt output.mp4
如果字幕以字幕流的形式位于一个视频文件中,可以直接调用: 1
ffmpeg -i input.mkv -vf subtitles=input.mkv output.mp4
如果希望在嵌入字幕时保留以前多个音轨,可以使用: 1
2
3
4
5
6ffmpeg -i "input.mp4" -map 0:0 -map 0:1 -map 0:2 -vf subtitles=input.Chs.srt output.mp4
# 一个实际的例子
for I in `ls ../*.mp4`;do ffmpeg -y -i "../$I" -map 0:0 -map 0:1 -map 0:2 -vf subtitles=../${I%.*}.Chs.srt "${I##*/}";done
同样,Windows 用户需要配置 fonts.conf 文件(参加附录11)。
10.8 将多个图片制作为视频
使用Python绘制了一系列顺序命名的图像,现在将其转为视频: 1
ffmpeg -r 25 -f image2 -s 1200x800 -i result_png/epo_%05d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p test.mp4
result_png/epo_%05d.png
表示 result_png
目录下的epo_xxxxx.png
文件,xxxxx
从00000
到99999
。 -r
帧率(fps); -crf
画质,越低表示质量越好,通常 15-25 已经不错了; -s
解析度 -pix_fmt yuv420p
指定pixel format, 根据需要修改 输出文件名为 test.mp4。
10.9 截取视频片段
自开始时间(-ss
参数,格式为HH:MM:SS
)到结束时间(-to
参数,格式为HH:MM:SS
)截取视频, 1
ffmpeg -ss 00:02:40 -i "old_file.mp4" -to 00:43:24 -vcodec copy -acodec copy "new_file.mp4"
ffprobe 文件名
进行检测。Python脚本参见博文链接
10.10 下载m3u8视频流
用法比较简单,如下所示,该命令有时无法下载视频: 1
ffmpeg -i http://...../abc.m3u8 "输出文件名.mp4"
11. 附录:Windows 的 fonts.conf
参考页面:该用户的 Github。
1 |
|