不懂鸟语的人
我的个人学习笔记

FFmpeg 学习

数据类型

AVRational

ffmpeg 为了保证数据的精度与完整性,有一个 AVRational 数据类型,就是一个有理数(分数)

1
2
3
4
typedef struct AVRational{
int num; // Numerator
int den; // Denominator
} AVRational;

常见 num / den 的形式

改变视频分辨率

指定分辨率

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

取帧

拆所有帧

1
ffmpeg -i data/temp1080/2.mp4 -f image2 -vframes 1441 -filter_complex 'scale=1920:1080' data/input/2.mp4/%07d.jpg
  • -vframes 1441 总视频帧数为 1441
  • -filter_complex 'scale=1920:1080' 指定输出的图片尺寸(scale 是一种滤镜),如果不指定此参数则按照原始分辨率

按照帧率

1
ffmpeg -i data/temp1080/2.mp4 -r 5 data/input/2.mp4/2.mp4%07d.jpg

属于截图,和原视频帧率无关

  • -i dirs 输入文件路径
  • -r 5 帧率为 5

帧率

1
ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate src.mp4

总帧数

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

图片集合成视频

1
ffmpeg -threads 6 -pattern_type glob -f image2 -r 30 -i 'LOL2/*.bmp' -c:v libx264 -b:v 30m 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 代替了)

画中画

这里画中画的实现方式是 overlay

1
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
    1. ; 分隔每一次操作
    2. [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]
    3. [a] 流的尺度设置(此处实际情况是拉伸)为 1920:1080 的分辨率(源流是第一步裁剪出的 960:540),结果视频流命名为 [b]
    4. [1:v][b]overlay[c][0:v] 第 2(下标 1)个视频流当作背景画面,将 [b] 视频流覆盖到其上面,定位到 (960, 540) 的位置(不指定默认在左上角),结果视频流命名为 [c]
  • -map [c] 输出 c 视频流
  • -y 不提示直接覆盖已存在文件

分析评测

在超分辨率工作中通常把 PSNRSSIM 两个指标结合看,因为常常视频非常模糊但是 PSNR 得分很高,这时候 SSIM 不会很高

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 来指定分辨率
  • -ffmt (input / output) 强制输入输出文件格式

SSIM

结构相似性

1
ffmpeg -i src.mp4 -i dst.mp4 -lavfi -f null -

色彩空间

-pix_fmts

Log 控制

-loglevel 参数控制 log 输出级别,包含以下值:

  • quiet
  • panic
  • fatal
  • error
  • warning
  • info
  • verbose
  • debug
  • trace