Extract frames and thumbnails from video with FFmpeg
Pull individual frames as images, generate thumbnails at intervals, or extract keyframes as posters. The fps filter, the select filter, and the right pattern for each use case.
When to use this
You extract frames for thumbnail generation (ABR poster images, video preview grids, scrubber thumbnails), ML pipelines (object detection on every Nth frame, scene-change analysis), or content moderation (extract every 5 seconds, run image classifier). Three real patterns: extract at fixed intervals, extract specific keyframes, extract a single frame at a timestamp. Each has a different command pattern.
Command variants
ffmpeg -i input.mp4 \
-vf "fps=1" \
-q:v 2 \
thumb_%04d.jpgfps=1 emits one frame per second. q:v 2 gives high-quality JPEG (1-31 scale, 1=highest). %04d pads filename: thumb_0001.jpg, thumb_0002.jpg, ...
ffmpeg -ss 00:01:30 -i input.mp4 \
-vframes 1 \
-q:v 2 \
poster.jpg-ss before -i for fast seek; -vframes 1 emits exactly one frame. Best for poster/thumbnail at known timestamp.
ffmpeg -i input.mp4 \
-vf "select='eq(pict_type,I)'" \
-vsync vfr \
-q:v 2 \
keyframe_%04d.jpgselect filter with pict_type=I emits only I-frames. -vsync vfr prevents duplicate frames. Useful for scene-change detection.
ffmpeg -i input.mp4 \
-vf "fps=1/10,scale=160:90,tile=10x10" \
-q:v 3 \
mosaic.jpgOne frame every 10 seconds, scaled to 160×90, tiled into a 10×10 grid. Useful for video-scrubber preview thumbnails.
What each parameter does
fps=NFilter that drops to N frames per second. fps=1 = one frame per second. fps=1/10 = one frame every 10 seconds.
-vframes NStop after extracting N frames. Use 1 for single-frame extraction.
-q:v 2JPEG quality. 1=highest, 31=lowest. 2 is the production sweet spot — visually lossless at modest file size.
select='eq(pict_type,I)'Filter expression that keeps only I-frames (keyframes). Useful for content-aware thumbnail extraction.
tile=WxHCombine frames into a grid. Useful for storyboards, scrubber previews, content review.
What this outputs
JPEG (or PNG, BMP, etc.) image files at the specified intervals or timestamps. JPEG is the production default for thumbnails; PNG for lossless or transparency-required cases.
Pitfalls
- Default JPEG quality (-q:v unset) produces large files. Always set -q:v 2 or -q:v 3 for thumbnails.
- fps=1 doesn't guarantee one frame per second exactly — it interpolates from source fps. For exact-second extraction at variable framerates, use the select filter with explicit timestamps.
- PNG output without alpha is wasteful — use JPEG unless transparency or absolute fidelity is required.
- When extracting many thumbnails, write to disk in a sequential pattern (%04d.jpg). Random naming creates filesystem fragmentation at scale.
- Some MOV files have variable framerate (VFR) that confuses fps filter. Use fps=N:eof_action=pass to handle EOF gracefully on VFR sources.
At production scale
Thumbnail extraction is essentially decode-only — no re-encoding of video, just frame export. Throughput is decoder-bound. For petabyte-scale thumbnail generation (every 10 seconds across millions of hours of video), structure the pipeline as a parallel decode pass rather than running it through an encoder pool. NVENC GPU decoders accelerate substantially over CPU decoders for this workload.
MpegFlow models thumbnail extraction as a parallel DAG stage that runs alongside main encoding. The same source decode feeds both the encoder pool and the thumbnail extractor — saves significant compute over running them as separate jobs.
- FFmpeg
- thumbnails
- frames
- extraction
- video-operations