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

Previously

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://martin-riedl.de/stream01 \
    -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.

stream_%v.m3u8

%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.

Video-Bitrates

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.

Audio-Bitrates

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://martin-riedl.de/stream01 \
    -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