ffmpeg操作集锦

  |  

摘要: 本文介绍 ffmpeg 中常见的操作和小功能,持续更新

【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:算法题刷刷
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings


参考资料:


$0 疑难杂症

降低速率

1
ffmpeg -i origin.mp4 -vf "setpts=0.25*PTS" output.mp4

无损输出

1
ffmpeg -i origin.mp4 -qp 0 output.mp4

去掉视频末尾 3 秒钟的平台签名

1
2
3
4
5
6
7
8
9
10
in_filename = "video.mov"
prop = ffmpeg.probe(in_filename)
out_filename = "output.mp4"
duration = float(prop["format"]["duration"])

stream = ffmpeg.input(in_filename)
v = stream.video.filter("trim", duration=duration-3.0)
a = stream.audio.filter("atrim", duration=duration-3.0)
out = ffmpeg.output(v, a, out_filename)
ffmpeg.run(out)

缩放

缩放到固定值

1
ffmpeg -i input.avi -vf scale = 320:240

等比例缩放

1
ffmpeg -i ${FILE} -strict -2 -vf scale=1280:1280/a tmp${FILE}

单图转任意长度视频

输入 a.bmp,输出 b.mp4,其中 -t 控制时间长度。

1
ffmpeg -r 25 -loop 1 -i ./a.bmp -pix_fmt yuv420p -vcodec libx264 -b:v 600k -r:v 25 -preset medium -crf 30 -vframes 250 -r 25 -t 10 ./a.mp4

多张图转幻灯片视频

要求多张图的尺寸一样,files.txt 如下:

1
2
3
4
5
6
7
8
9
file 1.jpg
duration 3
file 2.jpg
duration 3
file 3.jpg
duration 3
file 4.jpg
duration 3
file 5.jpg

此后执行以下命令:

1
ffmpeg -f concat -i files.txt output.mp4

$1 基础知识

1. 命令语法

1
ffmpeg [global_options] {[input_file_options] -i input_file} ... {[output_file_options] output_file} ...

2. 概览

ffmpeg 从任意数量/形式的输入文件中进行读取(可以是普通文件,管道,网络流,设备源等等),通过输入文件选项对输入文件进行设定,通过 -i 进行标记,并写入到任意数量/形式的输出文件中,任何在命令行中不能被解释为选项的字符串信息(当然也不是被 -i 指定为输入文件的信息)都被作为一个输出文件。

原则上每个输入或输出文件都可包含数量不同的数据流(视频/音频/字幕/附件/数据….),具体文件中包含的数量和/或数据类型是文件的容器格式限定的,具体选择那些流从输入文件到输出文件则可能是自动或者依据 -map 选项(在流的选择章中介绍)来指定。

所有的选项仅仅作用于紧接着的输入或者输出文件,除非重复指定选项才能作用于其他需要同样设定的文件。

3. 详细说明

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
|________| |______________|

ffmpeg调用 libavformat 库(含分离器)读取输入文件,分离出各类编码的数据包(流),当有多个输入文件时,ffmpeg 试图跟踪最低时间戳实现任意输入流同步。

滤镜处理/Filtering

在编码前,ffmpeg 可以对 raw(真实/原)音频和视频使用 libavfilter 库中的滤镜进行处理。多个滤镜可以组成滤镜链图(滤镜链图 filtergraphs )。在 ffmpeg 看来只有 2 种滤镜:简单滤镜,复合滤镜。

(1) 简单滤镜

简单滤镜就是只有1个输入和输出的滤镜,滤镜两边的数据都是同一类型的,可以理解为在非压缩数据帧到再次编码前简单附加了一步:

1
2
3
4
5
6
7
8
9
10
 _________                        ______________
| | | |
| decoded | | encoded data |
| frames |\ _ | packets |
|_________| \ /||______________|
\ __________ /
simple _\|| | / encoder
filtergraph | filtered |/
| frames |
|__________|

简单滤镜一般用于配置每个流 -filter 选项(-vf 和 -af 分别对应视频和音频)。

(2) 复合滤镜

复合滤镜是那些不能简单描述为一个线性处理过程应用到一个流的情况,例如当过程中有多个输入和/或输出,或者输出流类型不同于输入时,示意图如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 _________
| |
| input 0 |\ __________
|_________| \ | |
\ _________ /| output 0 |
\ | | / |__________|
_________ \| complex | /
| | | |/
| input 1 |---->| filter |\
|_________| | | \ __________
/| graph | \ | |
/ | | \| output 1 |
_________ / |_________| |__________|
| | /
| input 2 |/
|_________|

复合滤镜由-filter_complex选项进行设定。注意这是一个全局选项,因为一个复合滤镜必然是不能只关联到一个单一流或者文件的。-lavfi选项等效于-filter_complex

流拷贝

流拷贝(Stream copy)是一种对指定流数据仅仅进行复制的拷贝(copy)模式。这种情况下 ffmpeg 不会对指定流进行解码和编码步骤,而仅仅是分离和混合数据包。这种模式常用于文件包装格式的转换或者修改部分元数据信息,这个过程简单图示如下:

1
2
3
4
5
 _______              ______________            ________
| | | | | |
| input | demuxer | encoded data | muxer | output |
| file | ---------> | packets | -------> | file |
|_______| |______________| |________|

$2 操作集锦

(1) 截图

截取一张格式为 jpg 的图片,resize 为 200x50

image2

1
ffmpeg -i input.mp4 -y -f image2 -t 0.001 -s 50,200 output.jpg 2>&1 | tee log

把视频的前 50 帧转换成一个 Animated Gif

-vframes

1
ffmpeg -i input.mp4 -vframes 50 -y -f gif output.gif

在视频的第 8.01 秒处截取 50x200 的缩略图

mjpeg

1
ffmpeg -i input.mp4 -y -f mjpeg -ss 8 -t 0.001 -s 200,50 output.jpg

每隔一秒截一张图

image2, -vf

1
ffmpeg -i input.mp4 -f image2 -vf fps=fps=1 result/out%d.png

每隔20秒截一张图

image2, -vf

1
ffmpeg -i file.mp4 -f image2 -vf fps=fps=1/20 result/out%d.png

多张截图合并到一个文件里(2x3)每隔一千帧(秒数=1000/fps25)即40s截一张图

-frames, -vf

1
ffmpeg -i out.mp4 -frames 3 -vf "select=not(mod(n\,1000)),scale=320:240,tile=2x3" out.png

从视频中生成GIF图片

1
ffmpeg -i input.mp4 -t 10 -pix_fmt rgb24 out.gif

转换视频为图片(每帧一张图)

1
ffmpeg -i input.mp4 out%4d.png

图片转换为视频

1
ffmpeg -f image2 -i out%4d.png -r 25 video.mp4

(2) 切分视频并生成M3U8文件

  1. M3U8 文件是指 UTF-8 编码格式的M3U文件。
  2. M3U 文件是记录了一个索引纯文本文件, 打开它时播放软件并不是播放它, 而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。
  3. M3U8 是一种常见的流媒体格式, 主要以文件列表的形式存在, 既支持直播又支持点播, 尤其在 Android、iOS 等平台最为常用。
1
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_time 20 -hls_list_size 0 -hls_wrap 0 output.m3u8

参数说明

1
2
3
4
5
6
7
8
-i 输入视频文件
-c:v 输出视频格式
-c:a 输出音频格式
-strict
-f hls 输出视频为HTTP Live Stream(M3U8)
-hls_time 设置每片的长度,默认为2,单位为秒
-hls_list_size 设置播放列表保存的最多条目,设置为0会保存所有信息,默认为5
-hls_wrap 设置多少片之后开始覆盖,如果设置为0则不会覆盖,默认值为0。这个选项能够避免在磁盘上存储过多的片,而且能够限制写入磁盘的最多片的数量。

播放列表的 sequence number 对每个 segment 来说都必须是唯一的,而且它不能和片的文件名(当使用wrap选项时,文件名可能会重复使用)混淆。

(3) 分离视频音频流

分离视频流

1
ffmpeg -i input_file -vcodec copy -an output_file_video

分离音频流

1
ffmpeg -i input_file -acodec copy -vn output_file_audio

(4) 视频解复用

解复用: 把一路输入信号划分为多路输出信号的过程;或者在具有层次结构的网络中把一条第 N 层连接的流量划分到多条第 N + 1 层连接中去的操作。

1
2
ffmpeg -i input.mp4 -vcoder copy -an -f m4v input.264
ffmpeg -i input.avi -vcoder copy -an -f m4v input.264

(5) 视频转码

转码为码流原始文件

1
ffmpeg -i input.mp4 -vcoder h264 -s 352*278 -an -f m4v input.264

转码为码流原始文件

1
ffmpeg -i input.mp4 -vcoder h264 -bf 0 -g 25 -s 352-278 -an -f m4v input.264

转码为封装文件 -bf B帧数目控制, -g 关键帧间隔控制, -s 分辨率控制

1
ffmpeg -i input.avi -vcoder mpeg4 -vtag xvid -qsame input_xvid.avi

(6) 视频封装

1
ffmpeg -i video_file -i audio_file -vcoder copy -acodec copy output_file

(7) 视频剪切

1
2
3
4
5
# 视频截图
ffmpeg -i test.avi -r 1 -f image2 image.jpeg

# 剪切视频 -r 提取图像频率, -ss 开始时间, -t 持续时间
ffmpeg -i input.avi -ss 0:1:30 -t 0:0:20 -vcoder copy -acoder copy output.avi

(8) 视频录制

RTSP协议一般传输的是 ts、mp4 格式的流。

1
ffmpeg -i rtsp://hostname/test -vcoder copy out.avi

(9) YUV序列

YUV序列播放

YUV(也称YCbCr)是电视系统所采用的一种颜色编码方法。

1
ffplay -f rawvideo -video_size 1920x1080 input.yuv

YUV序列转AVI

1
ffmpeg -s w*h -pix_fmt yuv420p -i input.yuv -vcoder mpeg4 output.avi

视频参数

1
2
3
4
5
-b 设定视频流量,默认是200Kbit/s
-s 设定画面的宽和高
-aspect 设定画面的比例
-vn 不处理视频
-vcoder 设定视频的编码器,未设定时则使用与输入流相同的编解码器

音频参数

1
2
3
4
-ar 设定采样率
-ac 设定声音的Channel数
-acodec 设定沈阳的Channel数
-an 不处理音频

(10) 合并MP4文件

对于 MPEG 格式的视频,可以直接:

1
ffmpeg -i "concat:input1.mpg|input2.mpg|input3.mpg" -c copy output.mpg

对于⾮ MPEG 格式容器,但是是 MPEG 编码器(H.264、DivX、XviD、MPEG4、MPEG2、AAC、MP2、MP3 等),可以包装进 TS 格式的容器再合并:

1
2
3
4
5
ffmpeg -i "Tutorial-Part1.mp4" -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i "Tutorial-Part2.mp4" -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "Tutorial-Part3.mp4" -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate3.ts
ffmpeg -i "Tutorial-Part4.mp4" -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate4.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts|intermediate3.ts|intermediate4.ts" -c copy -bsf:a aac_adtstoasc "Tutorial.mp4"

通过文本文件 files.txt 中转:

1
2
file input1.mov
file input2.mov

然后:

1
ffmpeg -f concat -i files.txt -c copy output.mov

(11) 格式转换

flv转换mp4

1
ffmpeg -i input.flv -vcodec copy -acodec copy output.mp4

将编码方式转换为 H.264

1
ffmpeg -i input.mp4 -c:v libx264 output.mp4

(12) 水印

视频添加水印, 水印居中

1
ffmpeg -i input.mp4 -i watermark -filter_complex overlay="(main_w/2)-(overlay_w/2):(main_h/2)-(overlay_h)/2" output.mp4

(13) 视频翻转和旋转

翻转

1
2
ffplay -i out.mp4 -vf hflip
ffplay -i out.mp4 -vf vflip

旋转

transpose={0,1,2,3}

1
2
3
4
0:逆时针旋转90°然后垂直翻转
1:顺时针旋转90°
2:逆时针旋转90°
3:顺时针旋转90°然后水平翻转
1
2
3
4
5
6
顺时针旋转90度
ffplay -i out.mp4 -vf transpose=1
水平翻转(左右翻转)
ffplay -i out.mp4 -vf hflip
顺时针旋转90度并水平翻转
ffplay -i out.mp4 -vf transpose=1,hflip

(14) 字幕

添加字幕

一般见到的字幕以srt字幕为主,在ffmpeg里需要首先将srt字幕转化为ass字幕,然后就可以集成到视频中了(不是单独的字幕流,而是直接改写视频流)。

1
2
ffmpeg -i my_subtitle.srt my_subtitle.ass
ffmpeg -i inputfile.mp4 -vf ass=my_subtitle.ass outputfile.mp4

其中 my_subtitle.srt 需要使用UTF8编码,字幕中有中文必须考虑这件事;

到这里还没完,将字幕直接写入视频流需要将每个字符渲染到画面上,因此需要处理字体的问题。

嵌入字幕

已有 subtitles.srt 文件。

  • 在播放器里选择字幕
1
ffmpeg -i input.mp4 -i subtitles.srt -c:s mov_text -c:v copy -c:a copy output.mp4
  • 字幕直接显示出来
1
2
ffmpeg -i subtitle.srt subtitle.ass
ffmpeg -i input.mp4 -vf ass=subtitle.ass output.mp4

(15) 倒放

视频倒放滤镜 reverse,音频倒放滤镜 areverse。

1
ffmpeg -i video.mov -vf reverse -af areverse output.mp4

(16) 去掉音频

1
ffmpeg -i input.mp4 -an -vcodec copy output.mp4

Share