Create Multi-Resolution DASH Ladder with FFmpeg
This article provides a complete, step-by-step guide to generating a
multi-resolution Dynamic Adaptive Streaming over HTTP (DASH) bitrate
ladder using FFmpeg. You will learn how to take a single source video,
transcode it into multiple resolutions and bitrates with aligned
keyframes, and package the output into a playback-ready DASH manifest
(.mpd) and media segments.
Step 1: Understand the Requirements for DASH
To ensure seamless switching between resolutions during playback, your adaptive bitrate (ABR) ladder must meet two strict criteria: 1. Identical Keyframe Intervals (GOP Size): Keyframes must occur at the exact same timestamps across all video streams. If a player switches from 1080p to 720p, it must do so at a keyframe boundary. 2. Segment Alignment: The audio and video segments must be cut at identical intervals (typically between 2 to 6 seconds).
Step 2: The FFmpeg Command
To create a three-tier DASH ladder (1080p, 720p, and 480p) from an
input file named input.mp4, run the following command in
your terminal:
ffmpeg -i input.mp4 \
-map 0:v:0 -map 0:v:0 -map 0:v:0 -map 0:a:0 \
-b:v:0 4500k -s:v:0 1920x1080 -profile:v:0 high \
-b:v:1 2500k -s:v:1 1280x720 -profile:v:1 main \
-b:v:2 1000k -s:v:2 854x480 -profile:v:2 main \
-b:a:0 128k \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac \
-keyint_min 48 -g 48 -sc_threshold 0 \
-bf 3 -b_strategy 1 \
-use_timeline 1 -use_template 1 \
-window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a" \
-f dash manifest.mpdStep 3: Command Breakdown
Here is what each part of the command does:
Stream Mapping
-map 0:v:0(repeated three times): Instructs FFmpeg to read the first video stream of the input file three separate times to create three independent output video streams.-map 0:a:0: Instructs FFmpeg to read the first audio stream once.
Video Representation Settings
-b:v:[index]: Sets the target bitrate for each video stream (e.g.,4500kfor 1080p,2500kfor 720p, and1000kfor 480p).-s:v:[index]: Sets the resolution scale for each stream (e.g.,1920x1080,1280x720,854x480).-profile:v:[index]: Sets the H.264 profile. Usehighfor 1080p for better compression, andmainfor lower resolutions to ensure compatibility with older devices.
Encoder and Keyframe Settings
-c:v libx264 -pix_fmt yuv420p: Encodes the video using the H.264 codec with a standard 8-bit YUV 4:2:0 color space.-c:a aac -b:a:0 128k: Encodes the audio to AAC format at a bitrate of 128 kbps.-g 48 -keyint_min 48: Forces a keyframe (I-frame) every 48 frames. Assuming a 24 fps source video, this guarantees a keyframe precisely every 2 seconds. Adjust this number based on your source framerate (e.g., use60for 30 fps video).-sc_threshold 0: Disables scene change detection. This prevents FFmpeg from inserting extra keyframes at scene transitions, keeping the GOP size strictly locked.
DASH Packaging Settings
-f dash: Specifies the output format as DASH.-use_timeline 1: Enables the Media Presentation Description (MPD) timeline, ensuring highly accurate playback synchronization.-use_template 1: Uses template-based URLs for segment naming (e.g.,chunk-stream0-00001.m4s), which reduces the size of the XML manifest file.-window_size 5: Retains only the 5 most recent segments in the manifest (highly useful for live streaming). For video-on-demand (VOD), you can omit this option to keep all segments.-adaptation_sets "id=0,streams=v id=1,streams=a": Groups all video streams into Adaptation Set 0 and the audio stream into Adaptation Set 1. This tells the video player that the video streams are alternative representations of the same content and can be swapped dynamically.manifest.mpd: The name of the output index file. FFmpeg will write this file alongside the video and audio segment files (.m4s) in your working directory.