View Source Membrane.MP4.Muxer.CMAF.SegmentDurationRange (Membrane MP4 plugin v0.17.0)

Structure specifying the minimal and target duration for a CMAF segment.

Each regular CMAF segment usually has to begin with a key frame. Sometimes the video stream can have irregularly occurring key frames which can influence the duration of a single segment.

It may happen that the segment duration significantly exceeds the target duration as the samples are aggregated until reaching a key frame which allows for finalizing the current segment and starting a new one.

irregular-key-frames

Irregular key frames

Let's study the following example:

  • we are streaming with an OBS on a mediocre machine
  • segment's target duration is set to 2 seconds, so we are expecting a key frame every 2 seconds
  • partial's segment target duration is set to 0.5 seconds so we want to create 4 partial segments for each segment

The broadcasting machine becomes overloaded and the OBS starts to drop the frame rate, as a result the key frames don't get produced regularly every 2 seconds but sometimes it may happen after 1.2 seconds or so and then it may get back to normal.

In this case we would produce 2 partial segments and a half. With a naive approach we could just try to gather 4 partial segments and with the 5 we just aggregate samples until reaching a key frame but in this case the last segments could be even 1.2 seconds long (as we are expecting to get the next key frame at around 3.2 seconds).

The idea is to have minimal and target durations. We just need to ensure that segments would have at least the minimal duration after which we can perform lookaheads for key frames so that we can end the partial segment early and start a new one. In our case we would produce 2 full partial segments and one with a duration of 0.2 seconds. Effectively, the third partial segment would start with a key frame.

Link to this section Summary

Link to this section Types

@type t() :: %Membrane.MP4.Muxer.CMAF.SegmentDurationRange{
  min: Membrane.Time.t(),
  target: Membrane.Time.t()
}

Link to this section Functions

@spec new(Membrane.Time.t()) :: t()
@spec new(Membrane.Time.t(), Membrane.Time.t()) :: t()
@spec validate(t()) :: :ok | {:error, :invalid_range}