数据类型
AVRational
ffmpeg 为了保证数据的精度与完整性,有一个 AVRational 数据类型,就是一个有理数(分数)1
2
3
4typedef struct AVRational{
int num; // Numerator
int den; // Denominator
} AVRational;
常见 num / den
的形式
输入输出
简单
1 | ffmpeg -i in.mp4 out.flv |
-i
是代表输入- 此命令默认会按照其默认编码器参数重新编码,而不是仅仅转封装
按照轨道(流)
1 | ffmpeg -i 1.mp4 -i 2.mp4 -map 0:v:0 -map 1:a:0 -c copy out.mp4 |
-map 0:v:0
代表选取第0
个输入文件的视频(v
是video,a
则是 audio)的第0
个轨道- ffmpeg 默认的选择:
- 视频:选择分辨率(品质)最高的
- 音频:选择 Channel 最多的
- 字幕:第一个找到的
改变视频分辨率
指定分辨率
1 | ffmpeg -i data/origin/2.mp4 -vf scale=1920:1080 -c:v libx264 -b:v 10m data/temp1080/2.mp4 -hide_banner |
-i dirs
输入文件路径-vf scale=1920\*1080
缩放到 1920*1080, scale 是一种 video filter
-vf
为 video filtergraph,-vf
是-filter:v
的简称
-vf scale
等同于-s
-hide_banner
选项用于在输出文件的详细信息时省略 ffmpeg 的版本信息和编译选项等-c:v libx264
指定编码器 libx264-b:v 10m
指定码率 10m
宽高比缩放
(不建议使用)1
ffmpeg -i data/origin/2.mp4 -vf scale=1920:-1 data/temp1080/2.mp4 -hide_banner
作用是:宽度设为 1920,高度自适应
- 不同之处在于宽度写了
-1
,代表根据宽度及宽高比自适应,猜测自适应那一方写负数就可以做到自适应
但是此方法遇到明确的那一方无法除尽的时候会报错
裁剪视频
使用 -ss 和 -t 选项,从第0秒开始,向后截取31秒视频,并保存1
ffmpeg -ss 00:00:00 -i video.mp4 -vcodec copy -acodec copy -t 00:00:31 output1.mp4
-t
是 Duration,换成-to
的话是切到指定时刻-ss
如果在-i
前,是直接 seek 到指定时刻(前的关键帧上),再进行切割;如果-ss
在-i
后,则是从头开始 decode,直到遇到指定时刻开始切割,会比较慢,后者比较精准。
注意:因为 ffmpeg 的 bug,如果视频第一帧不是从 0 开始,则起始截取位置可能会乱掉,如果想从头开始,则删掉-ss
参数即可
指定时长切片
1 | ffmpeg -y -nostdin -hide_banner -v error -analyzeduration 400000000 -i ./ori.mp4 -max_interleave_delta 0 -flags +global_header -max_muxing_queue_size 3000 -c copy -f segment -segment_time 600 -reset_timestamps 1 -segment_list ./origin.ffconcat -metadata description="Bilibili VXCode Swarm Transcoder v0.1.29" ./S%03d.mp4 |
-segment_time 600
每段时长 600s./S%03d.mp4
分段格式化文件名,此处为 S000.mp4 S001.mp4
取帧
拆所有帧
指定总帧数
1 | ffmpeg -i data/temp1080/2.mp4 -f image2 -vframes 1441 -filter_complex 'scale=1920:1080' data/input/2.mp4/2_%07d.bmp |
-vframes 1441
总视频帧数为 1441-filter_complex 'scale=1920:1080'
指定输出的图片尺寸(scale 是一种滤镜),如果不指定此参数则按照原始分辨率
指定帧率
1 | ffmpeg -i data/temp1080/2.mp4 -r 5 data/input/2.mp4/2_%07d.bmp |
属于截图,和原视频帧率无关,或者说一秒截几张图
-i dirs
输入文件路径-r 5
一秒截 5 张图
取指定时刻开始 n 帧
1 | ffmpeg -i LOL2_LR.mp4 -ss 1.0 -vframes 1 -vf scale=1920:1080 cover.jpg |
-ss 1.0
从第 1 秒开始-vframes 1
取 1 帧
图片集合成视频
1 | ffmpeg -threads 6 -pattern_type glob -f image2 -r 30 -i 'LOL2/*.bmp' -c:v libx264 -b:v 30m -pix_fmt yuv420p out.mp4 |
-threads 6
线程数 6-c:v libx264
-c:v libx264
等同于-vcodec libx264
等同于-codec:v libx264
reference: http://ffmpeg.org/pipermail/ffmpeg-user/2017-February/035335.html-r 30
帧率 30,需要放在-i
之前-b:v 30m
30m 视频码率(比特率)-crf 5
网上这样说:取值范围为0~51,其中0为无损模式,数值越大,画质越差,生成的文件却越小。从主观上讲,18~28是一个合理的范围。18被认为是视觉无损的(从技术角度上看当然还是有损的),它的输出视频质量和输入视频相当。 (本条命令没用到,用 -b:v 代替了)-pix_fmt yuv420p
音视频分离与合成
抽取音频
1 | ffmpeg -i full.mp4 -vn -y -acodec copy audio.aac |
抽取视频
1 | ffmpeg -i full.mp4 -vcodec copy –an video.mp4 |
音视频合成
1 | ffmpeg -i only_video.mp4 -i only_audio.aac -vcodec copy -acodec copy full.mp4 |
视频拼接
参考: wikiConcatenate
参数形式
1 | ffmpeg -i "concat:input1.mp4|input2.mp4" -c copy out.mp4 |
外部 txt 形式
1 | ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4 |
txt 的文件的格式:1
2
3
4# this is a comment
file '/path/to/file1.wav'
file '/path/to/file2.wav'
file '/path/to/file3.wav'
循环播放
1 | ffmpeg -stream_loop 10 -i clip1.mp4 -c copy out.mp4 |
-stream_loop 10
代表循环 10 次,如果写0
是不循环,如果写-1
则是无限循环(多用在直播推流)
画中画
这里画中画的实现方式是 overlay1
ffmpeg -i src1.mp4 -i src2.mp4 -lavfi "[0:v]crop=x=960:y=540:w=960:h=540[a];[a]scale=1920:1080[b];[1:v][b]overlay=x=960:y=540[c]" -map [c] -c:v libx264 dst.mp4 -y
-filter_complex
同-lavfi
;
分隔每一次操作[0:v]crop=x=960:y=540:w=960:h=540[a]
中[0:v]
代表选中-i
输入中第 1(下标 0)个视频流,经过裁剪(crop)出从横坐标x=960
纵坐标y=540
开始,宽度w=960
高度h=540
的画幅,结果视频流命名为[a]
[a]
流的尺度设置(此处实际情况是拉伸)为1920:1080
的分辨率(源流是第一步裁剪出的960:540
),结果视频流命名为[b]
[1:v][b]overlay[c]
中[0:v]
第 2(下标 1)个视频流当作背景画面,将[b]
视频流覆盖到其上面,定位到(960, 540)
的位置(不指定默认在左上角),结果视频流命名为[c]
-map [c]
输出 c 视频流-y
不提示直接覆盖已存在文件
直播推流
1 | ffmpeg -i in.mp4 "rtmp://xxx" |
- 仅需要将输出文件写成推流地址即可
视频质量控制
码率控制
指定码率
-b:v 2M
是在编码的时候控制视频固定码率为2M,音频则为-b:a 128K
恒定质量
-crf 18
-qp 18
-crf
恒定速率(constant rate factor)因子模式,是恒定质量的编码方式,与恒定码率(CBR)是相反的,crf 的范围在 0 - 51,0 是绝对无损,18 被认为是视觉无损-qp
恒定量化(constant quantizer)器模式,定义了从一个像素宏块中丢掉多少信息
CRF会用将每一帧的压缩不同的大小,为了让主观的质量感受差不多,会用不同的QP。他是通过把运动也考虑进来做到这一点的。在编码中,如果Qp=18,则每一帧都是QP=18,当然根据帧的类型不同会有一些微小的波动,忽略之。设置CRF=18的时候,对于运动比较大的场景,会把QP设得更高一些,对于运动比较比较不剧烈的帧,会降低QP。这会导致比特率的分配随时间变化不同5
2Pass(Multi-Pass)
通过转码两次,在恒定码率的模式下,可以使编码更高效1
2ffmpeg -i input.mp4 -c:v libaom-av1 -b:v 2M -pass 1 -an -f null /dev/null && \
ffmpeg -i input.mp4 -c:v libaom-av1 -b:v 2M -pass 2 -c:a libopus output.mkv
-pass 1
第一次转码,输出到空文件描述符/dev/null
-an
第一次转码可以排除音频
视频质量评估
在超分辨率(或其他图像重建)工作中通常把 PSNR 和 SSIM 两个指标结合看,因为常常图像非常模糊但是 PSNR 得分很高,这时候 SSIM 可能不高,因为 SSIM 比 PSNR 更符合人眼主观感受
PSNR
峰值信噪比1
ffmpeg -i src.mp4 -i dst.mp4 -lavfi psnr -f null -
此命令会打印出每一对对比帧的Y、U、V分量的 MSE 和 PSNR 及各自平均值
-lavfi
选项等同于-filter_complex
所以以上命令等同于-filter_complex psnr="stats_file=psnr.log"
-lavfi psnr
可以写为-lavfi psnr="stats_file=psnr.log"
将输出打印到 stats_file 所指定的文件如psnr.log
- src 及 dst 文件可各添加一个
-s WeightxHeight
来指定分辨率 -f
是fmt (input / output)
强制输入输出文件格式
SSIM
结构相似性1
ffmpeg -i src.mp4 -i dst.mp4 -lavfi ssim="stats_file=ssim.log" -f null -
VMAF
VMAF 是 Netflix 开发的感知视频质量评估算法4,ffmpeg 的 libvmaf 中已经集成
分析文件信息 (Probe)
帧率
1 | ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate src.mp4 |
时长
1 | ffprobe -show_entries format=duration -of default=nk=1:nw=1 test.mp4 |
-of default=nk=1:nw=1
-of
是-print_format
的简写- 设置输出格式为
default
;default=nk=1
:只输出值和换行;default=nw=1
:去掉[]和[/]两行字符3
总帧数
1 | ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 src.mp4 |
计算 GOP 大小
1 | ffprobe -show_frames input.mp4 | grep pict_type |
然后计算两个 I 帧 (pict_type=I) 之间的距离
查看编码器名称
1 | ffprobe -select_streams v:0 -show_entries stream=codec_name -of default=nk=1:nw=1 input.mp4 |
-select_streams v:0
代表选择此文件中的第一条视频流,v:1
则是第二条视频流,a:0
则是第一条音频流-of default=nk=1:nw=1
同 ### 时长 小结中的介绍
色彩空间
-pix_fmts
Log 控制
-loglevel
参数控制 log 输出级别,包含以下值:
- quiet
- panic
- fatal
- error
- warning
- info
- verbose
- debug
- trace
References
- [1] https://ffmpeg.org/ffmpeg.html
- [2] https://ffmpeg.org/ffprobe.html
- [3] https://github.com/iAvoe/FFprobe-Tutorial-Standalone/blob/master/%E6%95%99%E7%A8%8B.md#%E5%B8%B8%E7%94%A8%E5%8F%82%E6%95%B0
- [4] https://github.com/Netflix/vmaf
- [5] https://www.cnblogs.com/sunny-li/p/9979796.html
- [6] https://trac.ffmpeg.org/wiki/Encode/AV1
- [7] https://www.videoproc.com/resource/ffmpeg-commands.htm