Keyframes and GOP size
I, P and B frames, what a Group of Pictures is, and why keyframe placement decides how your video seeks, streams and cuts.
Updated
Video compression’s core insight is that consecutive frames are mostly the same. Codecs exploit this by storing most frames as differences, which creates a hidden structure inside every file that decides how it seeks, how it streams, and where you can cut it.
Three kinds of frames
- I-frames (keyframes) are complete pictures, decodable on their own: essentially a JPEG sitting in the stream. Expensive, but self-sufficient.
- P-frames are predicted from earlier frames: “like the last frame, but this region moved three pixels left.” A fraction of the cost of an I-frame.
- B-frames are predicted from both directions (earlier and later frames) and are the cheapest of all. Their existence is why decode order and display order differ inside a stream.
A decoder can only start from an I-frame. Everything between two keyframes depends, directly or through a chain, on the keyframe before it.
The GOP
The run from one keyframe up to the next is a Group of Pictures. Its length, the keyframe interval, is the lever you actually control:
- Long GOPs compress better. Keyframes are the expensive frames; the fewer you spend, the more bits remain for quality. For an upload destined for a normal player, long GOPs (say 5–10 seconds) are free money.
- Short GOPs respond faster. Every seek, stream join, and error recovery starts from a keyframe. A player asked to jump to 1:23:45 actually jumps to the nearest keyframe and either starts there or silently decodes forward to your target. With ten-second GOPs, that is up to ten seconds of work: the lag you have felt scrubbing some videos and not others.
Streaming forces the issue: HTTP streaming (HLS/DASH) cuts video into segments, every segment must begin on a keyframe, and adaptive quality switching can only happen at segment boundaries. This is why streaming pipelines pin the keyframe interval to short, exact values (2–4 seconds) and disable the encoder’s freedom to improvise.
Scene cuts and the “improvise” part
By default, x264 also inserts keyframes at scene changes (scenecut):
a hard cut compresses terribly as a P-frame, so promoting it to an I-frame is
usually smart. For streaming, that spontaneity breaks exact segment alignment,
which is why you will see -sc_threshold 0 in HLS recipes: it forces keyframes
to land only where scheduled.
# Web upload: quality-first, default GOP behavior is fine
ffmpeg -i input.mp4 -c:v libx264 -crf 20 -preset slow -c:a copy out.mp4
# Streaming-friendly: exact 2-second GOPs at 30fps, no surprise keyframes
ffmpeg -i input.mp4 -c:v libx264 -crf 20 -g 60 -keyint_min 60 -sc_threshold 0 \
-c:a aac -b:a 128k out.mp4
(-g counts frames, not seconds: 60 frames at 30 fps = one keyframe every
2 seconds.)
Where you feel this: cutting video
Trim a video with stream copy (-c copy) and the keyframe structure stops
being invisible. A copy can only begin at a keyframe: the frames after your
requested start point depend on it. Ask for a cut at 0:10 when the nearest
keyframe sits at 0:07, and your clip either starts early, or starts with
garbage/frozen frames until the next keyframe, depending on the player.
That is the entire trade in the trim builder: stream copy is instant but snaps to the GOP grid; re-encoding rebuilds the stream and can start on any frame you like.
Defaults worth knowing
x264’s default keyframe ceiling is 250 frames (~10 s at 25 fps) plus scene-cut insertion; broadcast encoders run much shorter; streaming ladders pin 2–4 s exactly. None of these is “correct”: the GOP is a dial between compression efficiency and responsiveness, and now you know which way to turn it.
The streaming case is the strictest, because every rendition has to put its keyframes in the same places or players cannot switch between them cleanly. Adaptive bitrate streaming covers why, and the flags that force it.