利用ffmpeg截图和生成gif

从视频中截取指定数量的图片 

ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 output.jpg

ffmpeg -i input.mp4 -ss 00:00:10 -vframes 180 output.jpg
-vframes 180代表截取180帧,
实测后发现如果视频是60fps,那么会从第10秒截取到第13秒
 
  • -i input.mp4:指定输入视频文件。
  • -ss 00:00:10:定位到视频的第10秒。
  • -vframes 1:指定只提取一帧。
  • output.jpg:输出截图文件。

从视频中提取多帧截图

ffmpeg -i input.mp4 -vf fps=1/60 output_%03d.jpg
  • fps=1/60fps=帧数/秒 的形式

  • 1/60 表示 1 帧每 60 秒(即每分钟 1 张图),通常用于长视频中低频截图(比如做缩略图或监控抽帧)

截取多张图时,通配符文件名规则

output_%03d.jpg:输出文件命名格式,%03d表示三位数字编号
举例:
output_%03d.jpg
输出
output_001.jpg
output_002.jpg
output_003.jpg

 从视频中提取特定时间段的截图

ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -vf fps=1/10 output_%03d.jpg
 
-vf 是 -filter:v 的简写,表示对视频流使用视频滤镜。

fps=1/10 指每10秒提取一帧。意味着1分钟内截6张图
  • -ss 00:01:00:开始时间,从第1分钟开始。
  • -to 00:02:00:结束时间,到第2分钟结束。
  • -vf fps=1/10:每10秒提取一帧,如果视频有1分钟,那么仅截图6张图

截图时长说明-t与-to区别

参数顺序影响行为​

-t是相对时间(持续时间)和-to​绝对时间

  • ​推荐将 -ss 和 -t/-to 放在 -i 之前​​:
    这样 FFmpeg 会直接跳转到指定时间点(快速但不精确,依赖关键帧)。
  • ​将 -ss 放在 -i 之后​​:
    FFmpeg 会解码到指定时间点(速度慢但精确到帧)。
  • #举例说明
    # 快速截取(依赖关键帧,可能不精确)
    ffmpeg -ss 10 -to 15 -i input.mp4 output.mp4
    
    # 精确截取(逐帧解码,速度慢)
    ffmpeg -i input.mp4 -ss 10 -to 15 output.mp4

设置截图质量

 如果需要提取高质量的截图,可以指定输出图片的质量:

ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 -q:v 2 output.jpg
  • -q:v 2:设置输出图片的质量,数值越小质量越高,范围是1-31。

截图并设置分辨率

ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 -s 640x360 output.jpg
  • -s 640x360:设置输出图片的分辨率为640x360。

关键帧限制​:若视频关键帧间隔大,快速定位(-ss-i前)可能无法精确到非关键帧。,所以为了精确,需要先-i然后再-ss

截取第5秒的第1帧(快速定位,可能不精确)

ffmpeg -ss 5 -i input.mp4 -vframes 1 -q:v 2 output.jpg

特点​​:-ss-i前,优先用关键帧定位,速度快但可能不精确。

精确截取第5秒的帧(较慢但准确)

ffmpeg -i input.mp4 -ss 5 -vframes 1 -q:v 2 output.jpg
  • ​特点​​:-ss-i后,逐帧解码到指定时间,速度慢但更精确。

截取第5.5秒的帧(精确到小数)

ffmpeg -ss 5.5 -i input.mp4 -vframes 1 output.png

 输出PNG格式并设置图片品质

ffmpeg -ss 5 -i input.mp4 -vframes 1 -compression_level 0 output.png

-compression_level:取值范围:0 到 9

含义:

0:最小压缩,生成的文件较大,但处理速度快

9:最大压缩,文件体积小,但处理速度慢

默认值:-compression_level 6

时间精度​:支持毫秒级时间(如00:00:05.500

文件名通配符

ffmpeg -ss 5 -i input.mp4 -vframes 1 output_%03d.jpg
  • 效果​​:生成 output_001.jpg
  • ​占位符说明​​:
    • %03d:3位数字编号(如 001002)。
    • %d:无填充编号(如 12)。

-r参数 

1.作为输出参数(控制编码帧率)​

当 -r ​​放在输出文件前​​时,它表示​​设置输出视频的帧率​​。例如:

ffmpeg -i input.mp4 -r 30 output.mp4
  • 作用​​:强制输出视频以 ​​30 FPS​​ 编码。
  • ​注意​​:
    • 如果原始视频帧率不等于30,FFmpeg 会通过​​丢帧或重复帧​​来匹配目标帧率(可能影响流畅度)。
    • 若想更精确地调整帧率,建议使用 -filter:v fps=30(动态插值帧)。

2.作为输入参数(控制读取帧率)

当 -r ​​放在输入文件前​​时,它表示​​设置读取输入文件的帧率​​。例如:

ffmpeg -r 10 -i input.mp4 output.mp4
  • ​作用​​:以 ​​10 FPS​​ 的速度读取输入文件,可能导致:
    • ​加速播放​​:如果原视频帧率高于10,会丢弃多余帧。
    • ​时间戳调整​​:输出视频时长变短(类似快放效果)。

常见用途示例​

  1. ​将视频转换为固定帧率​

  2. ffmpeg -i input.mp4 -r 24 output.mp4  # 输出24 FPS视频

    提取视频帧为图片序列​​:

  3. ffmpeg -i input.mp4 -r 1 image_%04d.jpg  # 每秒提取1帧

    强制输入以特定帧率读取​

  4. ffmpeg -r 1 -i input.mp4 output.gif  # 将视频转为1 FPS的GIF(快放效果)
  5. 帧率与播放速度​​:单纯修改输出帧率(如 -r 30)不会改变视频播放速度,但修改输入帧率(如 -r 10 -i input.mp4)会改变速度。
  6. ​保持原速​​:若想改变帧率同时保持原时长,使用滤镜 -vf "fps=30,setpts=PTS"
  7. ​查看原视频帧率​​:用 ffprobe input.mp4 可查看原始帧率信息。
  • 在 FFmpeg 的滤镜链中,setpts=PTS 是一个​​时间戳重设操作​​,它的作用是​​保持视频的原始播放速度​​,同时配合 fps=30 调整帧率。以下是详细解释:

  • setpts 是什么?​

  • ​全称​​:setpts = Set Presentation TimeStamp(设置呈现时间戳)
  • ​作用​​:修改视频帧的​​时间戳​​(PTS),控制帧的显示时机,从而影响视频的​​播放速度​​和​​总时长​​。
  • ​默认行为​​:如果直接使用 fps=30 调整帧率,FFmpeg 会插入或丢弃帧,但可能导致时间戳错乱,导致视频​​加速或变慢​​。
  • 2:setpts=PTS 的含义​

  • ​语法​​:setpts=PTS 表示​​不改变时间戳的原始值​​,直接沿用输入帧的时间戳。

  • ​核心目的​​:当滤镜链修改帧率(如 fps=30)时,通过 setpts=PTS 强制保持帧的原始时间间隔,从而​​保持视频原速​​。
  • 3:为什么需要 setpts=PTS?​

    假设原始视频是 ​​24 FPS​​,你希望转换为 ​​30 FPS​​:

  • ​不加 setpts​:FFmpeg 会插入新帧(如通过插值),但时间戳会被压缩,导致视频​​时长变短​​(加速播放)。
  • ​加 setpts=PTS​:插入新帧时,时间戳会按原速递增,保持总时长不变(播放速度不变)。
  • ffmpeg -i input.mp4 -vf "fps=30,setpts=PTS" output.mp4
    
    ​​作用​​:
    fps=30:将视频转换为 30 FPS(通过插帧或丢帧)。
    setpts=PTS:强制时间戳按原始速度递增,避免加速或减速

    对比实验​

  • ​​无 setpts​​:
    ffmpeg -i input.mp4 -vf "fps=30" output.mp4
    输出视频帧率是 30 FPS,但总时长可能缩短(例如原视频是 24 FPS,转换后时长变为原来的 24/30 = 0.8 倍,视频加速)。
    
    有 setpts​​:
    ffmpeg -i input.mp4 -vf "fps=30,setpts=PTS" output.mp4
    输出视频帧率是 30 FPS,总时长与原视频一致(播放速度不变)

    进阶用法​

  • 如果希望​​手动调整播放速度​​(如慢放或快放),可以修改 setpts 表达式:
  • 慢放 2 倍​​:
    ffmpeg -i input.mp4 -vf "setpts=2*PTS" output.mp4
    
    快放 2 倍​​
    ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4

    setpts注意事项​

  • ​音频同步​​:若视频速度改变(未用 setpts=PTS),音频会不同步,此时需用 -af aresample 或 asetpts 调整音频时间戳。
  • ​滤镜顺序​​:setpts 的位置会影响结果,通常放在帧率调整滤镜(如 fps)之后。
  • 总结:setpts=PTS 是控制时间戳的关键操作,与 fps=30 配合使用时,确保帧率变化不影响视频的原始播放速度。

把视频直接做成gif

体积小
./ffmpeg -ss 00:00:00 -to 00:00:10 -i ../input.mp4 -filter_complex "[0:v]fps=20,scale=400:-1" output_20fps.gif

颜色质量高,体积适宜,需要分2步
第一步:生成调节板
./ffmpeg -ss 00:00:00 -to 00:00:10 -i ../coe33.mp4 -vf "fps=10,scale=400:-1:flags=lanczos,palettegen" palette.png
第二步:参考调班板生成图片
./ffmpeg -ss 00:00:00 -to 00:00:10 -i ../input.mp4 -i palette.png -filter_complex "[0:v]fps=20,scale=400:-1:flags=lanczos[x];[x][1:v]paletteuse"  output_20fps.gif


以下命令无需预先生成调色板

#生成黑白色gif
./ffmpeg -ss 00:00:00 -to 00:00:10 -i ../input.mp4 -filter_complex "[0:v]fps=20,scale=400:-1,split[a][b];[a]palettegen=max_colors=2:reserve_transparent=0[p];[b][p]paletteuse=dither=floyd_steinberg" blackwhite.gif

#256色
./ffmpeg -ss 00:00:00 -to 00:00:10 -i ../input.mp4 -filter_complex "[0:v]fps=20,scale=400:-1,split[a][b];[a]palettegen=max_colors=256[p];[b][p]paletteuse=dither=floyd_steinberg" o256colors.gif

多个参数混用

./ffmpeg -ss 00:00:00 -to 00:00:10 -i ../input.mp4 -filter_complex "[0:v]fps=20,scale=400:-1:flags=lanczos,split[a][b];[a]palettegen=max_colors=256:stats_mode=diff[p];[b][p]paletteuse=dither=floyd_steinberg" o256colors.gif

上述代码的关键参数解析

  1. split[a][b]
    将视频流拆分为两个分支 [a] 和 [b],分别用于生成调色板和应用调色板。

  2. palettegen=max_colors=256

    • max_colors=256:设置调色板最大颜色数量(默认 256,GIF 支持的最大值)。
    • 若需减小文件体积,可降低此值(如 max_colors=128)。
  3. paletteuse=dither=floyd_steinberg

    • dither=floyd_steinberg:使用高质量抖动算法(推荐保留颜色过渡)。
    • 若需减小体积,可改用 dither=none 或 dither=bayer

dither=none表示不使用抖动,直接使用调色板中最接近的颜色替换原颜色。这会导致颜色过渡生硬,出现色带,但文件体积小,适合颜色简单的图像。

dither=bayer使用拜耳矩阵抖动,通过有序的图案扩散误差,模拟更多颜色。这种方法在低颜色深度下能减少色带,但可能引入可见的图案,体积比none大但比floyd_steinberg小。

实测发现生成gif体积排序是bayer>floyd_steinberg>none

如何选择?​

  • ​优先体积​​:选 dither=none(如生成文件大小敏感的 LOGO)。
  • ​优先画质​​:选 dither=floyd_steinberg(误差扩散算法,更平滑)。
  • ​平衡方案​​:选 dither=bayer(动态 GIF 或分辨率较高的静态图)。

dither=bayer时,bayer_scale可控制gif大小

paletteuse=dither=bayer:bayer_scale=0

./ffmpeg -ss 00:19:50 -t 5 -i ../input.mp4  -filter_complex "[0:v]fps=15,scale=700:-1:flags=lanczos,split[a][b];[a]palettegen=max_colors=128:stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=5" output.gif

bayer_scale取值范围[0,5],实测发现0体积最大,5体积最小

缩小gif体积的方法

1上文中提到的调色板

2:使用 gifsicle 后处理压缩​

# 安装 gifsicle(macOS: brew install gifsicle, Linux: apt-get install gifsicle)
gifsicle -O3 --lossy=80 input.gif -o output_compressed.gif

参数说明​​:
-O3:最高级别压缩优化。
--lossy=80:有损压缩(值越大,压缩率越高,画质损失越大)。

3:动态区域裁剪​

-vf "crop=300:200:20:50"  # 截取 300x200 区域(从坐标 x=20,y=50 开始)
-filter_complex后面也可以用crop
例如
./ffmpeg -ss 00:19:50 -t 5 -i ../input.mp4 -filter_complex "[0:v]scale=300:-1,crop=130:120:70:70" output.gif

避免 -fs​:除非接受尾部截断,否则不要使用 -fs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值