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:

  1. -g (GOP Size): Sets the maximum distance between keyframes.
  2. -keyint_min: Sets the minimum distance between keyframes. Keeping this identical to -g forces a fixed interval.
  3. -sc_threshold 0: Disables scene-change detection. By default, encoders like libx264 insert extra keyframes during scene transitions, which breaks segment alignment across different bitrates. Setting this to 0 prevents 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.m3u8

Parameter Breakdown:

By using this configuration across all your bitrate rungs, your HLS and DASH segments will align perfectly, ensuring a seamless playback experience.