ffmpeg简单上手图片的简单处理
ffmpeg堪称多媒体处理的瑞士军刀,通过一些简单的指令便可对多媒体文件进行处理来满足不同的需求
下载
官网提供不同平台的安装包 http://www.ffmpeg.org/download.html
win:https://github.com/BtbN/FFmpeg-Builds/releases
安装
win平台
两种方法
1.直接使用主程序 ffmpeg.exe 使用时必须要指定路径
2.配置环境变量(推荐)
解压程序包→复制ffmpeg主程序路径(一般在bin文件夹)→右键此电脑→属性→高级系统设置→环境变量→系统变量中的path,双击→新建→复制刚刚的路径
linux平台
https://www.linuxidc.com/Linux/2018-10/154934.htm
一、概念
介绍 FFmpeg 用法之前,需要了解一些视频处理的基本概念。
1.1 容器
视频文件本身其实是一个容器(container),里面包括了视频和音频,也可能有字幕等其他内容。
常见的容器格式有以下几种。一般来说,视频文件的后缀名反映了它的容器格式。
- MP4
- MKV
- WebM
- AVI
下面的命令查看 FFmpeg 支持的容器。
ffmpeg -formats
1.2 编码格式
视频和音频都需要经过编码,才能保存成文件。不同的编码格式(CODEC),有不同的压缩率,会导致文件大小和清晰度的差异。
常用的视频编码格式如下。
- H.262
- H.264
- H.265
上面的编码格式都是有版权的,但是可以免费使用。此外,还有几种无版权的视频编码格式。
- VP8
- VP9
- AV1
常用的音频编码格式如下。
- MP3
- AAC
上面所有这些都是有损的编码格式,编码后会损失一些细节,以换取压缩后较小的文件体积。无损的编码格式压缩出来的文件体积较大,这里就不介绍了。
下面的命令可以查看 FFmpeg 支持的编码格式,视频编码和音频编码都在内。
$ ffmpeg -codecs
1.3 编码器
编码器(encoders)是实现某种编码格式的库文件。只有安装了某种格式的编码器,才能实现该格式视频/音频的编码和解码。
以下是一些 FFmpeg 内置的视频编码器。
- libx264:最流行的开源 H.264 编码器
- NVENC:基于 NVIDIA GPU 的 H.264 编码器
- libx265:开源的 HEVC 编码器
- libvpx:谷歌的 VP8 和 VP9 编码器
- libaom:AV1 编码器
音频编码器如下。
- libfdk-aac
- aac
下面的命令可以查看 FFmpeg 已安装的编码器。
$ ffmpeg -encoders
二、FFmpeg 的使用格式
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
FFmpeg 的命令行参数非常多,可以分成五个部分。
$ ffmpeg {1} {2} -i {3} {4} {5}
上面命令中,五个部分的参数依次如下。
- 全局参数
- 输入文件参数
- 输入文件
- 输出文件参数
- 输出文件
参数太多的时候,为了便于查看,ffmpeg 命令可以写成多行。
$ ffmpeg \ [全局参数] \ [输入文件参数] \ -i [输入文件] \ [输出文件参数] \ [输出文件]
下面是一个例子。
$ ffmpeg \ -y \ # 全局参数 -c:a libfdk_aac -c:v libx264 \ # 输入文件参数 -i input.mp4 \ # 输入文件 -c:v libvpx-vp9 -c:a libvorbis \ # 输出文件参数 output.webm # 输出文件
上面的命令将 mp4 文件转成 webm 文件,这两个都是容器格式。输入的 mp4 文件的音频编码格式是 aac,视频编码格式是 H.264;输出的 webm 文件的视频编码格式是 VP9,音频格式是 Vorbis。
如果不指明编码格式,FFmpeg 会自己判断输入文件的编码。因此,上面的命令可以简单写成下面的样子。
$ ffmpeg -i input.avi output.mp4
三、常用命令行参数
FFmpeg 常用的命令行参数如下。
-c
:指定编码器-c copy
:直接复制,不经过重新编码(这样比较快)-c:v
:指定视频编码器-c:a
:指定音频编码器-i
:指定输入文件-an
:去除音频流-vn
: 去除视频流-preset
:指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。-y
:不经过确认,输出时直接覆盖同名文件。
a) 通用选项
-L license
-h 帮助
-fromats 显示可用的格式,编解码的,协议的。。。
-f fmt 强迫采用格式fmt
-i filename 输入文件
-y 覆盖输出文件(即如果test.***文件已经存在的话,不经提示就覆盖掉了)
-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持
-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持。使用-ss参数的作用,可以从指定时间点开始转换任务,-ss后的时间单位为秒
-title string 设置标题(比如PSP中显示影片的标题)
-author string 设置作者
-copyright string 设置版权
-comment string 设置评论
-target type 设置目标文件类型(vcd,svcd,dvd) 所有的格式选项(比特率,编解码以及缓冲区大小)自动设置 ,只需要输入如下的就可以了:ffmpeg -i myfile.avi -target vcd vcd.mpg
-hq 激活高质量设置
-itsoffset offset 设置以秒为基准的时间偏移,该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss[.xxx]的格式也支持。
b) 视频选项
-b bitrate
设置比特率,缺省200kb/s
-vb bitrate set bitrate (in bits/s)
-vframes number
设置要编码多少帧
-r fps
设置帧频 缺省25
-s size
设置帧大小 格式为W*H 缺省160X128.也可以直接使用简写,也认:Sqcif qcif cif 4cif 等
-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用:
Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576
-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777
-croptop size 设置顶部切除带大小 像素单位
-cropbottom size -cropleft size -cropright size
-padtop size 设置顶部补齐的大小 像素单位
-padbottom size -padleft size -padright size -padcolor color 设置补齐条颜色(hex,6个16进制的数,红:绿:兰排列,比如 000000代表黑色)
-vn 不做视频记录
-bt tolerance 设置视频码率容忍度kbit/s (固定误差)
-maxrate bitrate设置最大视频码率容忍度 (可变误差)
-minrate bitreate 设置最小视频码率容忍度(可变误差)
-bufsize size 设置码率控制缓冲区大小
-vcodec codec 强制使用codec编解码方式,如-vcodec xvid 使用xvid压缩 如果用copy表示原始编解码数据必须被拷贝。
-sameq 使用同样视频质量作为源(VBR)
-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率
-passlogfile file 选择两遍的纪录文件名为file
c)高级视频选项
-g gop_size 设置图像组大小 这里设置GOP大小,也表示两个I帧之间的间隔
-intra 仅适用帧内编码
-qscale q
使用固定的视频量化标度(VBR) 以质量为基础的VBR,取值0.01-255,约小质量越好,即qscale 4和-qscale 6,4的质量比6高 。此参数使用次数较多,实际使用时发现,qscale是种固定量化因子,设置qscale之后,前面设置的-b好像就无效了,而是自动调整了比特率。
-qmin q 最小视频量化标度(VBR) 设定最小质量,与-qmax(设定最大质量)共用
-qmax q 最大视频量化标度(VBR) 使用了该参数,就可以不使用qscale参数
-qdiff q 量化标度间最大偏差 (VBR)
-qblur blur 视频量化标度柔化(VBR)
-qcomp compression 视频量化标度压缩(VBR)
-rc_init_cplx complexity 一遍编码的初始复杂度
-b_qfactor factor 在p和b帧间的qp因子
-i_qfactor factor 在p和i帧间的qp因子
-b_qoffset offset 在p和b帧间的qp偏差
-i_qoffset offset 在p和i帧间的qp偏差
-rc_eq equation 设置码率控制方程 默认tex^qComp
-rc_override override 特定间隔下的速率控制重载
-me method 设置运动估计的方法 可用方法有 zero phods log x1 epzs(缺省) full
-dct_algo algo 设置dct的算法 可用:
0 FF_DCT_AUTO 缺省的DCT
1 FF_DCT_FASTINT
2 FF_DCT_INT
3 FF_DCT_MMX
4 FF_DCT_MLIB
5 FF_DCT_ALTIVEC
-idct_algo algo 设置idct算法。可用的有:
0 FF_IDCT_AUTO 缺省的IDCT
1 FF_IDCT_INT
2 FF_IDCT_SIMPLE
3 FF_IDCT_SIMPLEMMX
4 FF_IDCT_LIBMPEG2MMX
5 FF_IDCT_PS2
6 FF_IDCT_MLIB
7 FF_IDCT_ARM
8 FF_IDCT_ALTIVEC
9 FF_IDCT_SH4
10 FF_IDCT_SIMPLEARM
-er n 设置错误残留为n
1 FF_ER_CAREFULL 缺省
2 FF_ER_COMPLIANT
3 FF_ER_AGGRESSIVE
4 FF_ER_VERY_AGGRESSIVE
-ec bit_mask 设置错误掩蔽为bit_mask,该值为如下值的位掩码 1 FF_EC_GUESS_MVS (default=enabled) 2 FF_EC_DEBLOCK (default=enabled)
-bf frames 使用frames个B 帧,支持mpeg1,mpeg2,mpeg4(即如果-bf 2的话,在两个非b帧中间隔的b帧数目为2,即IBBPBBPBBP结构)
-mbd mode 宏块决策
0 FF_MB_DECISION_SIMPLE 使用mb_cmp
1 FF_MB_DECISION_BITS 2 FF_MB_DECISION_RD
-4mv 使用4个运动矢量 仅用于mpeg4
-part 使用数据划分 仅用于mpeg4
-bug param 绕过没有被自动监测到编码器的问题
-strict strictness 跟标准的严格性
-aic 使能高级帧内编码 h263+
-umv 使能无限运动矢量 h263+
-deinterlace 不采用交织方法
-interlace 强迫交织法编码 仅对mpeg2和mpeg4有效。当你的输入是交织的并且你想要保持交织以最小图像损失的时候采用该选项。可选的方法是不交织,但是损失更大
-psnr 计算压缩帧的psnr
-vstats 输出视频编码统计到vstats_hhmmss.log
-vhook module 插入视频处理模块 module 包括了模块名和参数,用空格分开
-bitexact 使用标准比特率
-max_qdiff 视频中所有桢(包括i/b/P)的最大Q值差距
-b_qfactor 表示i/p与B的Q值比例因子,值越大B桢劣化越严重
-b_qoffset 表示1/p与B的Q值比例的偏移量,值越大B桢劣化越严重.如果大于0,那么下一个B的Q=前一个P的Q乘以b_quant_factor再加上offset,如果小于0,则B的Q=负的normal_Q乘以factor加上offset.
-i_qfactor p和i的Q值比例因子,越接近1则P越优化.
-i_qoffset p和i的Q的偏移量
D)音频选项
-ab bitrate 设置音频码率
-ar freq 设置音频采样率
-ac channels 设置通道 缺省为1,即单通道
-an 不使能音频纪录
-acodec codec 使用codec编解码 如:-acodec AAC 使用AAC音频编码
好了,先整理这些吧,其实键入ffmpeg -h后给出的参数等说明还有更多,这里就不一一列举了。红色部分标注了测试中经常使用到的,其他的以后用到了再一一补充吧。
四、常见用法
下面介绍 FFmpeg 几种常见用法。
4.1 查看文件信息
查看视频文件的元信息,比如编码格式和比特率,可以只使用-i
参数。
$ ffmpeg -i input.mp4
查看音视频文件的流信息
ffprobe -show_streams inputFile
[STREAM]
// 当前流的索引信息,对应于AVStream->index
index=0
// AVCodecDescriptor * cd = avcodec_descriptor_get(AVStream->codecpar->codec_id)
// 编码名称,即cd->name
codec_name=h264
// 编码全称,即cd->long_name
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
// 一个编码参数,可以为Baseline、Main、High等,Baseline无B帧,Main及以后可以包含B帧
// 通过avcodec_profile_name(AVStream->codecpar->codec_id, AVStream->codecpar->profile)获得
profile=High
// 流类型,即av_get_media_type_string(AVStream->codecpar->codec_type)
codec_type=video
// 即AVStream->codec->time_base
codec_time_base=14777/877500
// 通过宏av_fourcc2str(AVStream->codecpar->codec_tag)获得
codec_tag_string=avc1
// 对应AVStream->codecpar->codec_tag
codec_tag=0x31637661
// 有效区域的宽度,即AVStream->codecpar->width
width=1920
// 有效区域的高度,即AVStream->codecpar->height
height=1080
// 视频帧宽度,可能与上面的宽度不同,即AVStream->codec->coded_width,例如:当解码帧在输出前裁剪或启用低分辨率时
coded_width=1920
// 视频帧高度,可能与上面的高度不同,即AVStream->codec->coded_height,例如:当解码帧在输出前裁剪或启用低分辨率时
coded_height=1088
// 视频的延迟帧数,即AVStream->codecpar->video_delay
has_b_frames=0
// sar,图像采集时,横向采集点数与纵向采集点数的比例
// FFmpeg提供了多个sar:AVStream->sample_aspect_ratio、AVStream->codecpar->sample_aspect_ratio、AVFrame->sample_aspect_ratio
// 通过av_guess_sample_aspect_ratio获取最终的sar
sample_aspect_ratio=1:1
// dar,真正展示的图像宽高比,在渲染视频时,必须根据这个比例进行缩放
// 通过av_reduce计算得到,par * sar = dar
display_aspect_ratio=16:9
// 像素格式,即av_get_pix_fmt_name(AVStream->codecpar->format)
pix_fmt=yuvj420p
// 编码参数,即AVStream->codecpar->level
level=40
// 额外的色彩空间特征,即av_color_range_name(AVStream->codecpar->color_range),AVCOL_RANGE_MPEG对应tv,AVCOL_RANGE_JPEG对应pc
color_range=pc
// YUV彩色空间类型,即av_color_space_name(AVStream->codecpar->color_space)
color_space=bt470bg
// 颜色传输特性,即av_color_transfer_name(AVStream->codecpar->color_trc)
color_transfer=smpte170m
// 即av_color_primaries_name(AVStream->codecpar->color_primaries)
color_primaries=bt470bg
// 色度样品的位置,即av_chroma_location_name(AVStream->codecpar->chroma_location)
chroma_location=left
// 交错视频中字段的顺序,即AVStream->codecpar->field_order
field_order=unknown
// av_timecode_make_mpeg_tc_string处理AVStream->codec->timecode_frame_start获得
timecode=N/A
// 参考帧数量,即AVStream->codec->refs
refs=1
is_avc=true
// 表示用几个字节表示NALU的长度
nal_length_size=4
id=N/A
// 当前流的基本帧率,这个值仅是一个猜测,对应于AVStream->r_frame_rate
r_frame_rate=30/1
// 平均帧率,对应于AVStream->avg_frame_rate
avg_frame_rate=438750/14777
// AVStream的时间基准,即AVStream->time_base
time_base=1/90000
// 流开始时间,基于time_base,即AVStream->start_time
start_pts=0
// 转换(start_pts * time_base)之后的开始时间,单位秒
start_time=0.000000
// 流时长,基于time_base,即AVStream->duration
duration_ts=945728
// 转换(duration_ts * time_base)之后的时长,单位秒
duration=10.508089
// 码率,即AVStream->codecpar->bit_rate
bit_rate=19983544
// 最大码率,即AVStream->codec->rc_max_rate
max_bit_rate=N/A
// Bits per sample/pixel,即AVStream->codec->bits_per_raw_sample
bits_per_raw_sample=8
// 视频流中的帧数,即AVStream->nb_frames
nb_frames=312
nb_read_frames=N/A
nb_read_packets=N/A
// 下面TAG为AVStream->metadata中的信息
// 逆时针的旋转角度(相当于正常视频的逆时针旋转角度)
TAG:rotate=90
// 创建时间
TAG:creation_time=2019-08-11T03:37:28.000000Z
// 语言
TAG:language=eng
TAG:handler_name=VideoHandle
// SIDE_DATA为AVStream->side_data数据
[SIDE_DATA]
// side_data数据类型,Display Matrix表示一个3*3的矩阵,这个矩阵需要应用到解码后的视频帧上,才能正确展示
side_data_type=Display Matrix
displaymatrix=
00000000: 0 65536 0
00000001: -65536 0 0
00000002: 0 0 1073741824
// 顺时针旋转90度还原视频
rotation=-90
[/SIDE_DATA]
[/STREAM]
[STREAM]
// 当前流的索引信息,对应于AVStream->index
index=1
// AVCodecDescriptor * cd = avcodec_descriptor_get(AVStream->codecpar->codec_id)
// 编码名称,即cd->name
codec_name=aac
// 编码全称,即cd->long_name
codec_long_name=AAC (Advanced Audio Coding)
// 通过avcodec_profile_name(AVStream->codecpar->codec_id, AVStream->codecpar->profile)获得
profile=LC
// 流类型,即av_get_media_type_string(AVStream->codecpar->codec_type)
codec_type=audio
// 即AVStream->codec->time_base
codec_time_base=1/48000
// 通过宏av_fourcc2str(AVStream->codecpar->codec_tag)获得
codec_tag_string=mp4a
// 对应AVStream->codecpar->codec_tag
codec_tag=0x6134706d
// 采样点格式,通过av_get_sample_fmt_name(AVStream->codecpar->format)获取
sample_fmt=fltp
// 采样率,即AVStream->codecpar->sample_rate
sample_rate=48000
// 通道数,即AVStream->codecpar->channels
channels=2
// 通道布局,与channels是相对应,通过av_bprint_channel_layout获取,stereo表示立体声
channel_layout=stereo
// 每个采样点占用多少bit,即av_get_bits_per_sample(par->codec_id)
bits_per_sample=0
id=N/A
r_frame_rate=0/0
avg_frame_rate=0/0
// AVStream的时间基准,即AVStream->time_base
time_base=1/48000
// 流开始时间,基于time_base,即AVStream->start_time
start_pts=0
// 转换(start_pts * time_base)之后的开始时间,单位秒
start_time=0.000000
// 流时长,基于time_base,即AVStream->duration
duration_ts=502776
// 转换(duration_ts * time_base)之后的时长,单位秒
duration=10.474500
// 码率,即AVStream->codecpar->bit_rate
bit_rate=156002
// 最大码率,即AVStream->codec->rc_max_rate
max_bit_rate=156000
// Bits per sample/pixel,即AVStream->codec->bits_per_raw_sample
bits_per_raw_sample=N/A
// 音频流中的帧数,即AVStream->nb_frames
nb_frames=491
nb_read_frames=N/A
nb_read_packets=N/A
TAG:creation_time=2019-08-11T03:37:28.000000Z
TAG:language=eng
TAG:handler_name=SoundHandle
[/STREAM]
上面命令会输出很多冗余信息,加上-hide_banner
参数,可以只显示元信息。
$ ffmpeg -i input.mp4 -hide_banner
json多媒体信息,保存成json
ffprobe -show_streams -select_streams 0 -of json -i IMG_6896.mov >> 00.json
json查看所有多媒体信息
ffprobe -print_format json -select_streams v -show_format -show_streams -i "input.jpg" -hide_banner
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 input.mp4
#1280x720
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of default=nw=1 input.mp4
#width=1280
#height=720
查看音视频文件解码后的帧信息
# -select_streams表示选择音频或者视频
ffprobe -show_frames -select_streams 0 -of json -i ./1.jpg
ffprobe -print_format json -show_frames -select_streams v:0 -i ./1.jpg >> frames.json
ffprobe -v error -select_streams v:0 -show_entries frames=width,height -of csv=s=x:p=0 ./1.jpg
帧信息tags里面Orientation的值对应的旋转信息
/*
1 = Horizontal (normal)
2 = Mirror horizontal
3 = Rotate 180
4 = Mirror vertical
5 = Mirror horizontal and rotate 270 CW
6 = Rotate 90 CW
7 = Mirror horizontal and rotate 90 CW
8 = Rotate 270 CW
*/
4.2 转换编码格式
转换编码格式(transcoding)指的是, 将视频文件从一种编码转成另一种编码。比如转成 H.264 编码,一般使用编码器libx264
,所以只需指定输出文件的视频编码器即可。
$ ffmpeg -i [input.file] -c:v libx264 output.mp4
下面是转成 H.265 编码的写法。
$ ffmpeg -i [input.file] -c:v libx265 output.mp4
4.3 转换容器格式
转换容器格式(transmuxing)指的是,将视频文件从一种容器转到另一种容器。下面是 mp4 转 webm 的写法。
$ ffmpeg -i input.mp4 -c copy output.webm
上面例子中,只是转一下容器,内部的编码格式不变,所以使用-c copy
指定直接拷贝,不经过转码,这样比较快。
4.4 调整码率
调整码率(transrating)指的是,改变编码的比特率,一般用来将视频文件的体积变小。下面的例子指定码率最小为964K,最大为3856K,缓冲区大小为 2000K。
$ ffmpeg \ -i input.mp4 \ -minrate 964K -maxrate 3856K -bufsize 2000K \ output.mp4
4.5 改变分辨率(transsizing)
下面是改变视频分辨率(transsizing)的例子,从 1080p 转为 480p 。
$ ffmpeg
-i input.mp4
-vf scale=480:-1
output.mp4
参数解读:scale=480:-1 , 宽度480 高度随宽度比例改变
可能的错误
ffmpeg -i input.mp4 -vf "scale=-1:240" ~/output1.mp4
input的原尺寸是1280720, 目标尺寸427240,427是奇数,出现报错:width not divisible by 2 (427x240)
根据stackoverflow(这里)的解释,似乎是因为某个视频格式要求视频的宽高尺寸必须是偶数?(不太懂视频编码,不确定)
不过解决方案我也成功地摸索出来了,就是使用过滤器链,scale完后再padding,这样生成的新视频尺寸就是偶数了。
ffmpeg -i input.mp4 -vf "scale=-1:240,pad=ceil(iw/2)*2:ceil(ih/2)*2" ~/output1.mp4
ceil 取整
4.6 提取音频
有时,需要从视频里面提取音频(demuxing),可以像下面这样写。
ffmpeg -i input.mp4 -vn -c:a copy output.aac
ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
上面例子中,-vn
表示去掉视频,-c:a copy
表示不改变音频编码,直接拷贝。
4.7 添加音轨
添加音轨(muxing)指的是,将外部音频加入视频,比如添加背景音乐或旁白。
$ ffmpeg \ -i input.aac -i input.mp4 \ output.mp4
上面例子中,有音频和视频两个输入文件,FFmpeg 会将它们合成为一个文件。
替换音频
先删除再添加
删除音频最简单的方法是:只将视频复制到一个新的文件中,而不复制音频。这个方法之所以简单,是因为它无需将视频重新编码。下面是删除音频的命令行:
#删除音频
ffmpeg -i videoWithAudio.mp4 -c:v copy -an videoWithoutAudio.mp4
#添加
ffmpeg -i videoWithoutAudio.mp4 -i audio.mp3 -c copy -map 0:v:0 -map 1:a:0 videoWithAudio.mp4
(为无音轨视频)添加循环背景音乐
ffmpeg -i input.mp4 -stream_loop -1 -i 欢快的背景音乐1.mp3 -ss 0 -t 450 -y out.mp4
-ss 0 #开始时间
-t 450 #视频时长 秒
!!!!一定要加时长,不然就是无限增加
(有音轨视频)音频替换并循环背景音乐
ffmpeg -an -i input.mp4 -stream_loop -1 -i 背景音乐.mp3 -t 450 -y out.mp4
-t 450 #视频时长 秒
4.8 截图
然后从视频中提取图片的命令如下:
ffmpeg -i [视频路径] -r 1 -q:v 2 -f image2 image-%d.jpeg
视频路径:如 “myvideo.mp4”(这时这个视频也在bin文件目录下才可以直接这么写),或者完整路径的
-r:每秒提取的帧数,如上面为每秒1帧,即一张图像
-q:v :图片质量
-f:图片格式,上述为image2
image-%d.jpeg:生成图像的文件名,可以加上完整路径,%d会使文件名按整数编号,如上述生成图像为image-1.jpeg, image-2.jpeg, …
还有其他参数:
-t:持续时间,如-t 4表示持续4s
-ss:起始时间,如-ss 01:30:14,从01:30:14开始
-vframes:指定抽取的帧数,如-vframes 120,指定抽取120张
-s:格式大小,如-s 640x360
-y:覆盖,直接使用
下面的例子是从指定时间开始,连续对1秒钟的视频进行截图。
$ ffmpeg -y -i input.mp4 -ss 00:01:24 -t 00:00:01 output_%3d.jpg
如果只需要截一张图,可以指定只截取一帧。
$ ffmpeg \ -ss 01:23:45 \ -i input \ -vframes 1 -q:v 2 \ output.jpg
上面例子中,-vframes 1
指定只截取一帧,-q:v 2
表示输出的图片质量,一般是1到5之间(1 为质量最高)。
4.9 截取视频片段
裁剪(cutting)指的是,截取原始视频里面的一个片段,输出为一个新视频。可以指定开始时间(start)和持续时间(duration),也可以指定结束时间(end)。
$ ffmpeg -ss [start] -i [input] -t [duration] -c copy [output] $ ffmpeg -ss [start] -i [input] -to [end] -c copy [output]
下面是实际的例子。
$ ffmpeg -ss 00:01:50 -i [input] -t 10.5 -c copy [output] $ ffmpeg -ss 2.5 -i [input] -to 10 -c copy [output]
上面例子中,-c copy
表示不改变音频和视频的编码格式,直接拷贝,这样会快很多。
4.10 为音频添加封面
有些视频网站只允许上传视频文件。如果要上传音频文件,必须为音频添加封面,将其转为视频,然后上传。
下面命令可以将音频文件,转为带封面的视频文件。
$ ffmpeg \ -loop 1 \ -i cover.jpg -i input.mp3 \ -c:v libx264 -c:a aac -b:a 192k -shortest \ output.mp4
上面命令中,有两个输入文件,一个是封面图片cover.jpg
,另一个是音频文件input.mp3
。-loop 1
参数表示图片无限循环,-shortest
参数表示音频文件结束,输出视频就结束。
4.11 ffmpeg 多个图片生成GIF
ffmpeg -f image2 -framerate 5 -i D:\myself\a\IMG000%02d.bmp D:\c.gif
D:\myself\a文件夹中有多个bmp图片(jpg的当然也可以),所有的图片名字是IMG000开头后面跟着两位数,一共42张 从IMG00001.bmp到IMG00042.bmp,%02d代表后面是两位
framerate 帧率
4.12 调整比特率
ffmpeg -i input.avi -b:v 1500k output.mp4
4.13添加滚动字幕
从左往右
给视频文件“input.mp4”添加静态字幕(该字幕实际上是水印)。添加的字幕的颜色为白色,字体大小为40,要添加的文本为“一二三四”,在相对于视频左上角坐标(0,100)的位置添加字幕。最终生成output.mp4文件。
ffmpeg -i input.mp4 -vf "drawtext=text='侯瑞环是大聪明':expansion=normal:fontfile=simkai.ttf:y=h-line_h-50:x=(mod(2*n\,w+tw)-tw):fontcolor=white:fontsize=80:shadowx=2:shadowy=2" output-80.mp4
- x=(mod(5*n,w+tw)-tw) =>5为速度变量
中文乱码的产生该问题的原因是FFmpeg找不到字体库。在windows下的C:\Windows\Fonts目录下存放着很多字体文件,比如下图中的这个msyh.ttc(微软雅黑 常规)复制到当前命令执行目录:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nsh7Ij2e-1689560648568)(ffmpeg的命令.assets/image-20230107115132004.png)]
从右往左滚
"drawtext=text=string1:fontfile=foo.ttf:y=h-line_h-10:x=w-(t-4.5)*w/5.5:fontcolor=white:fontsize=40:shadowx=2:shadowy=2"
从右往左滚,单次滚动时长10秒,间隔30秒滚一次
ffmpeg -i input.mp4 -filter:v drawtext="fontfile=Microsoft YaHei Mono.ttf:text='Hello World':fontcolor=white@1.0:fontsize=36:y=h-line_h-10:x=w-tw-w/10*mod(t\,30):enable=gt(mod(t\,20)\,10)" -vcodec libx264 -codec:a copy -y output.mp4
4.14直播 推流
ffmpeg -re -i "/wusp/video/kda/01.mp4" -preset ultrafast -vcodec libx264 -g 60 -b:v 1500k -c:a aac -b:a 96k -strict -2 -f flv ”rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_111592071_9089977&key=65d2d1408d9fb1a79cca463800f75004&schedule=rtmp&pflag=1“
命令行案例
实现图片格式的转换,以常见的png转jpg为例
ffmpeg -i input.jpg output.png
图片的简单压缩
ffmpeg -i input.jpg output.jpg
在不指定参数的情况下,ffmpeg将自动为图片执行压缩(图片质量约为7?)
指定一个压缩质量, q 5
ffmpeg -i input.jpg -q 5 output.jpg
⚠:图片压缩后方向会改变,查看下面的说明
增加逆时针旋转90参数 -vf “transpose=2”
ffmpeg -i input.jpg -vf "transpose=2" -q 5 output.jpg
执行批量压缩,这个比较实用
新建记事本,编辑为 .bat文件, 输出文件夹需要自己建立
for %%a in ("*.png" and "*.jpg" and "*.jpeg") do ffmpeg -i "%%~a" -q 5 "new/%%~na1.jpg"
图片约束尺寸按比例压缩,并旋转复位
#约束宽为1920,比例不变
ffmpeg -i input.jpg -vf "scale=1920:-1,transpose=2" output.jpg
#约束高为1080,比例不变
ffmpeg -i input.jpg -vf "scale=-1:1080,transpose=2" output.jpg
#批量
for %%a in ("*.png" and "*.jpg" and "*.jpeg") do ffmpeg -i "%%~a" -vf "scale=-1:1080,transpose=2" -q 5 "./完成/%%~na.jpg"
图片剪裁
语法
ffmpeg -i input.mp4 -filter:v "crop=w:h:x:y" output.mp4
-vf
是-filter:v
的简写:– 表示视频过滤器。input.jpg
– 源视频文件。crop
– 表示裁剪过滤器。w
– 我们想自源视频中裁剪的矩形的宽度。h
– 矩形的高度。x
– 我们想自源视频中裁剪的矩形的 x 坐标 。y
– 矩形的 y 坐标。
宽高不一样,图片会旋转,需要纠正
#默认于中心向四周剪裁1000*1000的图片
ffmpeg -i input.jpg -vf crop=1000:1000 output.jpg
#指定坐标点为500:500,向四周裁剪1000*1000的图片
ffmpeg -i input.jpg -vf crop=1000:1000:500:500 output.jpg
#同上
ffmpeg -i input.jpg -filter:v crop=1000:1000:500:500 output.jpg
ffmpeg -i input.png -vf crop=1000:1920:80:0 output.jpg
调整尺寸
ffmpeg -i input.avi -s 720x480 -c:a copy output.mkv
-
-s:是 --scale 的短选项,用于指定输出文件的画面宽高比;
-
-c:a:是输出音视频的盒子,
-
copy 说明了是不做任何处理,原样输出。
画面进行宽高50%的收缩。
ffmpeg -i input.avi -vf scale="iw/1:ih/2" output.avi
你应该会注意到我们使用了两个变量。
- iw:输入文件的画面宽度
- ih:输入文件的画面高度
这两个是系统的常量,可以拿来直接使用。
图片不自动旋转复制图片
ffmpeg -noautorotate -i input.jpg -vf "scale=iw:ih" output.jpg
合并多个mp4视频ts拼接(√)
- 先将 mp4 转化为同样编码形式的 ts 流,因为 ts流是可以 concate 的,先把 mp4 封装成 ts ,然后 concate ts 流, 最后再把 ts 流转化为 mp4。
ffmpeg -i 1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 1.ts
ffmpeg -i 2.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 2.ts
ffmpeg -i "concat:1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
角度问题
压缩图片的时候有时候会发现图片的旋转角度改变了,那是因为图片EXIF信息有的设备拍摄会自带旋转角度,压缩图片操作的时候没有把这个默认的选择角度复制过去。
https://exif.tuchong.com/ 图虫EXIF查看器alpha版
exiftool工具查看默认旋转信息
exiftool -Orientation input.jpg
#Orientation : Rotate 90 CW
查看多媒体信息
ffprobe -print_format json -select_streams v -show_format -show_streams -i "input.jpg" -hide_banner
逆时针选择任意度数
ffmpeg -i "0001.jpg" -metadata:s:v:0 rotate=90 "0001-r60.jpg"
顺时针旋转画面90度
ffmpeg -i test.mp4 -vf "transpose=1" out.mp4
逆时针旋转画面90度
无损 逆时针旋转90度
ffmpeg -i StartMP4.mp4 -map_metadata 0 -metadata:s:v rotate=90 -codec copy StartMP4out90.mp4
#顺时针无损90 (逆时针旋转270度)
ffmpeg -i StartMP4.mp4 -map_metadata 0 -metadata:s:v rotate=270 -codec copy StartMP4out90.mp4
有损 把视频文件重新编码后 按照 顺时针方向旋转90度
ffmpeg -i test.mp4 -vf "transpose=2" out.mp4
顺时针旋转画面90度再水平翻转
ffmpeg -i test.mp4 -vf "transpose=3" out.mp4
逆时针旋转画面90度水平翻转
ffmpeg -i test.mp4 -vf "transpose=0" out.mp4
水平翻转视频画面
ffmpeg -i test.mp4 -vf hflip out.mp4
垂直翻转视频画面
ffmpeg -i test.mp4 -vf vflip out.mp4
FFmpeg filter的使用介绍
1. 参考
- [1] ffmpeg.org/libavfilter documentation
- [2] ffmpeg.org/Filters Documentation
- [3] 北雨南萍/FFmpeg-4.0 的filter机制的架构与实现.之一 Filter原理
2. FFmpeg filter简介
FFmpeg filter提供了很多音视频特效处理的功能,比如视频缩放、截取、翻转、叠加等。
其中定义了很多的filter,例如以下常用的一些filter。
- scale:视频/图像的缩放
- overlay:视频/图像的叠加
- crop:视频/图像的裁剪
- trim:截取视频的片段
- rotate:以任意角度旋转视频
支持的filter的列表可以通过以下命令获得。
ffmpeg -filters
也可以查看文档[2],具体某个版本的支持情况以命令行获取到的结果为准。
以下是filter的一个简单的应用示例,对视频的宽和高减半。
ffmpeg -i input -vf scale=iw/2:ih/2 output
3. filter的使用方法
学习filter的使用,先需要了解一下filter的语法。
FFmpeg中filter包含三个层次,filter->filterchain->filtergraph。
具体参考下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XE3RSuEl-1689560648569)(D:\WuWorkSpace\md文档中心\ffmpeg\8744338-9de3fa45488e8d8e.png)]
filter_syntax.png
说明:
- 第一层是 filter 的语法。
- 第二层是 filterchain的语法。
- 第三层是 filtergraph的语法。
filtergraph可以用文本形式表示,可以作为ffmpeg中的-filter/-vf/-af和-filter_complex选项以及ffplay中的-vf/-af和libavfilter/avfilter.h中定义的avfilter_graph_parse_ptr()函数的参数。
为了说明可能的情况,我们考虑下面的例子“把视频的上部分镜像到下半部分”。
处理流程如下:
- 使用split filter将输入流分割为两个流[main]和[temp]。
- 其中一个流[temp]通过crop filter把下半部分裁剪掉。
- 步骤2中的输出再经过vflip filter对视频进行和垂直翻转,输出[flip]。
- 把步骤3中输出[flip]叠加到[main]的下半部分。
以下整个处理过程的一个图示,也就是对filtergraph的一个描述[2]。
[main]
input --> split ---------------------> overlay --> output
| ^
|[tmp] [flip]|
+-----> crop --> vflip -------+
可以用以下的命令来实现这个流程。
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
处理结果如下图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-24Q9cJGc-1689560648570)(D:\WuWorkSpace\md文档中心\ffmpeg\8744338-b2bc6c9ed1b6e061.PNG)]
vertical_mirror.PNG
下面具体了解每一层的语法,从而理解上面这个命令的含义。
3.1 filter的语法
用一个字符串描述filter的组成,形式如下
[in_link_1]…[in_link_N]filter_name=parameters[out_link_1]…[out_link_M]
参数说明:
- [in_link_N]、[out_link_N]:用来标识输入和输出的标签。in_link_N是标签名,标签名可以任意命名,需使用方括号括起来。在filter_name的前面的标签用于标识输入,在filter_name后面的用于标识输出。一个filter可以有多个输入和多个输出,没有输入的filter称为source filter,没有输出的filter称为sink filter。对输入或输出打标签是可选的,打上标签是为了连接其他filter时使用。
- filter_name:filter的名称。
- “=parameters”:包含初始化filter的参数,是可选的。
“=parameters”有以下几种形式
- 使用’:'字符分隔的一个“键=值”对列表。如下所示。
ffmpeg -i input -vf scale=w=iw/2:h=ih/2 output
- 使用’:'字符分割的“值”的列表。在这种情况下,键按照声明的顺序被假定为选项名。例如,scale filter的前两个选项分别是w和h,当参数列表为“iw/2:ih/2”时,iw/2的值赋给w,ih/2的值赋给h。如下所示。
ffmpeg -i input -vf scale=iw/2:ih/2 output
- 使用’:’ 字符分隔混合“值”和“键=值”对的列表。“值”必须位于“键=值”对之前,并遵循与前一点相同的约束顺序。之后的“键=值”对的顺序不受约束。如下所示。
ffmpeg -i input -vf scale=iw/2:h=ih/2 output
filter类定义了filter的特性以及输入和输出的数量,某个filter的使用方式可以通过以下命令获知。
ffmpeg -h filter=filter_name
也可以查看文档[2],但具体某个版本的参数形式以命令行获取到的结果为准。
以下是rotate filter的使用方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3YXHFhIn-1689560648570)(D:\WuWorkSpace\md文档中心\ffmpeg\8744338-314a772db83c09e7.PNG)]
filter_rotate.PNG
- 可以看出它支持slice threading。
- Inputs下面定义的是输入。可以看出rotate filter有一个输入,格式为Video。
- Outputs下面定义的是输出。可以看出rotate filter有有一个输出,格式为video。
- AVOptions下面定义了支持的参数,后面有默认值描述。为了简化输入参数,对长的参数名提供一个简化的名称。比如rotate filter中,“angle”的简化名称是“a”。
以下是使用到fiter的标签名的一个示例:抽取视频Y、U、V分量到不同的文件
ffmpeg -i jack.mp4 -filter_complex "extractplanes=y+u+v[y][u][v]" -map "[y]" jack_y.mp4 -map "[u]" jack_u.mp4 -map "[v]" jack_v.mp4
extractplanes filter指定了三个输出,分别是 [y][u][v],抽取后,将不同的输出保存到不同的文件中。
3.2 filterchain的语法
用一个字符串描述filterchain的组成,形式如下
"filter1, filter2, ... filterN-1, filterN"
说明:
- 由一个或多个filter的连接而成,filter之间以逗号“,”分隔。
- 每个filter都连接到序列中的前一个filter,即前一个filter的输出是后一个filter的输入。
比如示例
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
示例说明:
- crop、vflip在同一个filterchain中,
3.3 filtergraph的语法
用一个字符串描述filtergraph的组成,形式如下
“filterchain1;filterchain2;…filterchainN-1;fiterchainN”
说明:
- 由一个或多个filter的组合而成,filterchain之间用分号";"分隔。
- filtergraph是连接filter的有向图。它可以包含循环,一对filter之间可以有多个连接。
- 当在filtergraph中找到两个相同名称的标签时,将创建相应输入和输出之间的连接。
- 如果输出没有被打标签,则默认将其连接到filterchain中下一个filter的第一个未打标签的输入。例如以下filterchain中。
nullsrc, split[L1], [L2]overlay, nullsink
说明:split filter有两个输出,overlay filter有两个输入。split的第一个输出标记为“L1”,overlay的第一个输入pad标记为“L2”。split的第二个输出将连接到overlay的第二个输入。
- 在一个filter描述中,如果没有指定第一个filter的输入标签,则假定为“In”。如果没有指定最后一个filter的输出标签,则假定为“out”。
- 在一个完整的filterchain中,所有没有打标签的filter输入和输出必须是连接的。如果所有filterchain的所有filter输入和输出pad都是连接的,则认为filtergraph是有效的[2]。
比如示例
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
其中有三个filterchain, 分别是:
- “split [main][tmp]”。它只有一个filter,即 split,它有一个默认的输入,即INPUT解码后的frame。有两个输出, 以 [main], [tmp] 标识。
- “[tmp] crop=iw:ih/2:0:0, vflip [flip]”。它由两个filter组成,crop和vflip,crop的输入 为[tmp],vflip的输出标识为[flip]。
- “[main][flip] overlay=0:H/2”。它由一个filter组成,即overlay。有两个输入,[main]和[flip]。有一个默认的输出。