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 1) - HLS Basics
We have set up our fist livestream that was already playable in safari. But we have seen, that the segmentation is not working as expected.
After a look in the stream.m3u8 we have a big surprise:
The given target duration of 4 seconds are not used.
Instead a TARGETDURATION of 10 is set and the segment length (value after #EXTINF:) is also not constant.
A constant value is required for a good buffering in the player.
We don’t want any interruptions.

Cause
The problem here is that the segmenter splits starts a new file only at keyframes (I-Frames).
This makes sense, because if you e.g. seek in the stream the player chooses the nearest new stream*.ts file and starts playing it.
How to solve (step 1)
-g 25 sets the group picture size to 25.
My video source has 25 FPS (25 pictures per second).
So each second will start with a new picture group.
This option forces a target size of 25 frames.
After that a new group will be created (starting with a new I-Frame).
Well, now it is much closer to what we want. But there are still some glitches above and also below 4 seconds.

How to solve (step 2)
The reason for this is that FFmpeg has a scene detection. This means that always when a new scene starts an I-Frame will be set. Since it’s FFmpeg we can easily disable this feature.
-sc_threshold 0
And the new playlist looks as we were expecting: Segments with the exact same duration.

The new command so far is:
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