This is a series of articles. Follow the link here to get an overview over all articles.


on Using FFmpeg as a HLS streaming server (Part 2) – Enhanced HLS Segmentation

The livestream with constant segment duration including x264 video encoding and aac audio encoding is working well.

./ffmpeg -listen 1 -i rtmp:// \
    -c:v libx264 -crf 21 -preset veryfast -g 25 -sc_threshold 0 \
    -c:a aac -b:a 128k -ac 2 \
    -f hls -hls_time 4 -hls_playlist_type event stream.m3u8

Now it’s time to support multiple quality versions. In my case it should be the full HD variant and a second SD variant. This article focuses on the video quality.

Multiple playlists

There will be a playlist with the segments for each quality level. All of this stream playlists are then listed in a master playlist. Since now, the master playlist will be used as video URL.


%v must be added in the output stream name. This is a number counting from 0 for the stream variant. In my case 0 will be the lower quality, 1 the higher quality.

-master_pl_name master.m3u8

This will create the new master playlist that contains the list of streams.


Again, Apple provides a list of recommendations for resolutions and the bitrates that should be used. I decided to use for full HD (1920×1080 6000kb/s) and for SD (960×540 2000kb/s). This replaces the -crf value, so this is no longer used and removed from our command.

-preset veryfast -g 25 -sc_threshold 0

This parameters stay as is and are used for all video variants.

-map v:0 -c:v:0 libx264 -b:v:0 2000k

-map v tells ffmpeg that a new video variant starts. x is the number of input video signal. Since I have only one video input, the index 0 is used here.

-c:v:x sets the codec for each variant. I will just use h264.

-b:v:0 sets the bitate for stream 0 (the lower quality).

Since I want to have two different bitrates, the following parameter sequence is used:

-map v:0 -c:v:0 libx264 -b:v:0 2000k
-map v:0 -c:v:1 libx264 -b:v:1 6000k

If you want to have more variants, just copy one of this lines and change the index.


Well, it’s possible to do the same as we have done with the video bitrates for the audio bitrate. But I want to have for both the same audio quality (since this is not using a lot of bandwidth).

-map a:0 -map a:0

Therefore, the map command must just be placed twice before the codec settings. If you have more streams, repeat this map command.

Bringing all together

-var_stream_map "v:0,a:0 v:1,a:1"

This tells FFmpeg what streams are combined together. A space separates each variant and everything that should be placed together is concatenated with a comma.

So the full command is now:

./ffmpeg -listen 1 -i rtmp:// \
    -preset veryfast -g 25 -sc_threshold 0 \
    -map v:0 -c:v:0 libx264 -b:v:0 2000k \
    -map v:0 -c:v:1 libx264 -b:v:1 6000k \
    -map a:0 -map a:0 -c:a aac -b:a 128k -ac 2 \
    -f hls -hls_time 4 -hls_playlist_type event \
    -master_pl_name master.m3u8 \
    -var_stream_map "v:0,a:0 v:1,a:1" stream_%v.m3u8