Align HLS and DASH Segments with FFmpeg GOP
To deliver a seamless adaptive bitrate streaming experience via HLS
or DASH, video segments across different resolutions and bitrates must
be aligned precisely down to the frame. This article explains how to use
FFmpeg’s GOP (Group of Pictures) size (-g), keyframe
interval (-keyint_min), and scene-cut detection settings to
ensure perfectly synchronized segments for smooth player switching.
Why GOP Alignment Matters for HLS and DASH
HLS and DASH split video files into small segments (typically 2 to 10 seconds long). Players switch between different quality levels (representations) depending on the user’s network speed. This switch can only happen at a keyframe (specifically an IDR frame). If the keyframes in your 1080p stream do not occur at the exact same timestamps as the keyframes in your 720p stream, the player will lag, buffer, or drop frames when switching bitrates.
To prevent this, you must force FFmpeg to output keyframes at fixed, predictable intervals.
The Mathematical Formula for Segment Alignment
To achieve perfect alignment, your GOP size must be a direct multiple of your target segment duration and the video’s frame rate (FPS).
\[\text{GOP Size} = \text{Frame Rate (FPS)} \times \text{Desired Segment Duration (seconds)}\]
For example, if your video is 30 FPS and you want 4-second segments: \[30 \times 4 = 120 \text{ frames}\]
This means you must force a keyframe exactly every 120 frames.
The Critical FFmpeg Parameters
To enforce this GOP structure in FFmpeg, you must configure three key parameters together:
-g(GOP Size): Sets the maximum distance between keyframes.-keyint_min: Sets the minimum distance between keyframes. Keeping this identical to-gforces a fixed interval.-sc_threshold 0: Disables scene-change detection. By default, encoders likelibx264insert extra keyframes during scene transitions, which breaks segment alignment across different bitrates. Setting this to0prevents extra keyframes from being created.
FFmpeg Command Example
Here is how to apply these parameters in an FFmpeg command for a 30 FPS input video, targeting 4-second aligned segments (GOP of 120):
ffmpeg -i input.mp4 \
-c:v libx264 -r 30 \
-g 120 -keyint_min 120 -sc_threshold 0 \
-b:v 3000k -maxrate 3000k -bufsize 6000k \
-c:a aac -b:a 128k \
-f hls -hls_time 4 -hls_playlist_type vod output.m3u8Parameter Breakdown:
-r 30: Forces the output frame rate to 30 FPS.-g 120: Tells the encoder to put an I-frame every 120 frames.-keyint_min 120: Prevents the encoder from creating I-frames sooner than 120 frames.-sc_threshold 0: Ensures scene changes do not trigger accidental keyframes.-hls_time 4: Instructs the HLS muxer to split segments every 4 seconds, aligning perfectly with the 120-frame GOP.
By using this configuration across all your bitrate rungs, your HLS and DASH segments will align perfectly, ensuring a seamless playback experience.