How to Force GOP Size in FFmpeg for Adaptive Streaming

Setting a fixed Group of Pictures (GOP) size in FFmpeg is crucial for adaptive bitrate streaming formats like HLS and DASH. This article explains how to force a specific GOP size and disable scene change detection using FFmpeg, ensuring that keyframes align perfectly across different video resolutions and bitrates for seamless quality switching.

Why Fixed GOP Size Matters for Adaptive Streaming

In adaptive streaming, a video is cut into small segments (usually 2 to 6 seconds long). Every segment must start with an IDR (Instantaneous Decoder Refresh) frame, which is a type of keyframe. If your different video renditions (e.g., 1080p, 720p, 360p) do not have keyframes at the exact same timestamps, the player will stutter or lag when switching between qualities.

To prevent this, you must force a fixed GOP size and disable the encoder’s default behavior of inserting extra keyframes at scene cuts.

How to Calculate GOP Size

GOP size is measured in frames, not seconds. To calculate your GOP size, multiply your video’s frame rate (FPS) by your desired keyframe interval in seconds.

FFmpeg Commands for Fixed GOP

To force a strict GOP size, you must set the minimum and maximum GOP size to the exact same value and disable scene change detection.

For H.264 (libx264)

Use the following FFmpeg arguments for the H.264 encoder:

ffmpeg -i input.mp4 -c:v libx264 -g 60 -keyint_min 60 -sc_threshold 0 output.mp4

Parameter Breakdown: * -g 60: Sets the maximum distance between keyframes to 60 frames. * -keyint_min 60: Sets the minimum distance between keyframes to 60 frames. Matching this with -g forces a constant interval. * -sc_threshold 0: Disables scene change detection. This prevents FFmpeg from inserting extra keyframes when a visual scene change is detected.

For H.265 / HEVC (libx265)

If you are encoding in HEVC, the scene change threshold option is handled differently through x265-params:

ffmpeg -i input.mp4 -c:v libx265 -g 60 -keyint_min 60 -x265-params no-scenecut=1 output.mp4

Parameter Breakdown: * -x265-params no-scenecut=1: Disables scene-cut detection in the libx265 encoder to ensure keyframes are only placed at the interval defined by -g.

Verifying the Keyframe Interval

After encoding, you can verify that your keyframes are strictly placed at the specified interval using ffprobe:

ffprobe -select_streams v:0 -show_entries frame=pict_type,pts_time -of csv=p=0 input.mp4 | grep -n I

This command lists all frames, their types, and timestamps. You should see “I” (keyframes) appearing at exact, predictable intervals (e.g., 0.0, 2.0, 4.0, 6.0 seconds).