首页 / FFmpeg 入门教程 / 图片与视频互转

FFmpeg 入门教程

图片与视频互转

本教程共 32 篇 · 第 16 篇 · 更新于 2026-08-09 · 约 6 分钟阅读

FFmpeg图片序列image2幻灯片slideshow帧导出视频合成

本节目标:把连续编号的图片合成视频,反过来把视频导出成一帧帧图片;还能让一张静态图片配合音频生成视频。

做动画、做延时摄影、做幻灯片、从视频里抽帧分析,都需要在「图片序列」和「视频」之间切换。FFmpeg 内置的 image2 格式专门干这件事。

从图片合成视频

连续编号的图片

假设你有 img001.pngimg002.pngimg003.png…… 这样连续命名的图片:

ffmpeg -framerate 24 -i img%03d.png -c:v libx264 -pix_fmt yuv420p output.mp4
  • -framerate 24:输入帧率,每秒放 24 张图。这个参数要放在 -i 前面。
  • img%03d.png:文件名模式,%03d 是三位数字,不足补零。
  • -pix_fmt yuv420p:保证兼容性,不然某些播放器打不开。

不加 -framerate 时默认是 25 fps。

从指定编号开始

图片从 img126.png 开始:

ffmpeg -start_number 126 -framerate 24 -i img%03d.png -pix_fmt yuv420p output.mp4

用 glob 匹配(Linux/macOS)

如果图片命名不连续或没有数字规律,可以用 shell 的通配符:

ffmpeg -framerate 10 -pattern_type glob -i '*.jpg' -c:v libx264 -pix_fmt yuv420p output.mp4

*.jpg 会按字母顺序读入当前目录下所有 jpg。注意 glob 模式在 Windows 构建上不可用,Windows 下要么改成连续编号,要么用 concat demuxer。

每张图显示不同时长

默认每张图显示 1/帧率 秒。想让某张图停 5 秒、另一张停 1 秒,用 concat demuxer。写一个清单文件 slides.txt

file 'slide1.png'
duration 5
file 'slide2.png'
duration 1
file 'slide3.png'
duration 3
file 'slide3.png'
Important

最后一张图必须写两次:第二次不带 duration。这是 concat demuxer 的已知要求,少写会导致最后一帧一闪而过。

然后:

ffmpeg -f concat -i slides.txt -vsync vfr -pix_fmt yuv420p -c:v libx264 output.mp4
  • -vsync vfr:可变帧率,让每张图按它的 duration 显示,而不是强行补帧。

单张图片生成视频

让一张图片静止显示 30 秒:

ffmpeg -loop 1 -i cover.jpg -c:v libx264 -t 30 -pix_fmt yuv420p output.mp4
  • -loop 1:无限循环输入图片。
  • -t 30:输出 30 秒后停止。

图片加音频成视频

做音频分享、播客视频时常需要这招——一张封面图 + 一条音频:

ffmpeg -loop 1 -i cover.jpg -i audio.m4a \
  -c:v libx264 -c:a copy -shortest \
  -pix_fmt yuv420p output.mp4
  • -c:a copy:音频直接复制,不重编码(AAC 在 MP4 里没问题)。
  • -shortest:音频结束就停,不会因为图片无限循环而输出无限长的视频。

如果音频不是 AAC,比如是 WAV 或 FLAC,需要转码:

ffmpeg -loop 1 -i cover.jpg -i audio.wav \
  -c:v libx264 -c:a aac -b:a 192k -shortest \
  -pix_fmt yuv420p output.mp4

输入帧率和输出帧率

-framerate 是「输入」帧率,决定每张图持续多久。-r 是「输出」帧率,决定最终视频的帧率。两者可以不同。

比如每张图想停留 5 秒(输入 1/5 fps),但输出视频要做成标准 30fps:

ffmpeg -framerate 1/5 -i img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p output.mp4

FFmpeg 会自动复制帧来填充:每张图在输出里重复 150 次(30 ÷ 1/5),正好持续 5 秒。

Tip

遇到「第一帧被跳过」或「最后一张图只闪一下」的问题,把 -r 30 换成 fps=30 滤镜:

ffmpeg -framerate 1/5 -i img%03d.png -c:v libx264 -vf fps=30 -pix_fmt yuv420p output.mp4

从视频导出图片序列

每一帧都导出

ffmpeg -i input.mp4 frame_%04d.png

输出 frame_0001.pngframe_0002.png…… 一秒 30 帧的视频,10 秒就是 300 张图,磁盘占用很快会爆炸,谨慎用。

导出为 JPG 能省空间:

ffmpeg -i input.mp4 -q:v 2 frame_%04d.jpg

每隔 N 帧/秒导一张

fps 滤镜:

# 每秒 1 张
ffmpeg -i input.mp4 -vf fps=1 frame_%04d.jpg

# 每 10 秒 1 张
ffmpeg -i input.mp4 -vf fps=1/10 frame_%04d.jpg

# 每分钟 1 张
ffmpeg -i input.mp4 -vf fps=1/60 frame_%04d.jpg

导出某个时间区间的帧

# 从第 30 秒开始,导出 5 秒内的所有帧
ffmpeg -ss 30 -t 5 -i input.mp4 frame_%04d.png

只导关键帧

ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -vsync vfr keyframe_%03d.png

select='eq(pict_type,I)' 只选 I 帧(关键帧),-vsync vfr 避免复制帧补齐时间戳。

指定时间段+按比例抽帧

# 第 10 到 20 秒之间,每秒 2 张
ffmpeg -ss 10 -to 20 -i input.mp4 -vf fps=2 frame_%03d.png

通过管道输出

Linux/macOS 可以把图片通过管道传给其他工具:

ffmpeg -i input.mp4 -f image2pipe -vcodec png - | some-process

不同尺寸图片的统一

如果输入图片尺寸不一致,直接合成会被 FFmpeg 按第一张的分辨率处理,其他图可能变形或报错。先统一尺寸:

ffmpeg -framerate 24 -i img%03d.png \
  -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,format=yuv420p" \
  -c:v libx264 output.mp4

所有图都被塞进 1920×1080 的画布里,比例不对就补黑边。这也是做幻灯片最常用的滤镜链。

常见问题

输出视频打不开或全黑。 加上 -pix_fmt yuv420p。从 PNG 合成时 FFmpeg 可能保留了 4:4:4 像素格式,部分播放器不支持。

图片顺序不对。 %03d 模式严格按数字顺序;glob 模式按字母顺序。命名时用 001、002、…、010 而不是 1、2、…、10,否则字母排序会错乱。

文件数量巨大。fps=1/N 降采样,或者只导出关键帧。导出前先算一下:时长 × 帧率 = 总张数

合成出来视频特别大。 图片序列输入时源数据是无损的,编码器会忠实压缩。加 -crf 23(H.264)控制体积,或者降低分辨率。

小结

  • 图片序列合成:-framerate N -i img%03d.png,配合 -pix_fmt yuv420p 保证兼容。
  • 每张图不同时长用 concat demuxer,最后一张写两次。
  • 单图循环:-loop 1 -t 30,加音频用 -shortest
  • 导出帧:直接 frame_%04d.png,定时抽帧用 fps=1/N
  • 尺寸不统一先 scale + pad 再编码。

下一章讲字幕:软字幕和硬字幕的区别,怎么封装字幕、怎么烧录到画面上。