HLS contextualized manifests
Original manifests
broadpeak.io only contextualizes the manifest upon request when there is an active slot for the specified audience in the manifest DVR window. When this is not the case, the original master manifest and media manifests are returned.
Example of an original Media manifest:
#EXTM3U
#EXT-X-VERSION:5
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-TARGETDURATION:4
#EXT-X-PROGRAM-DATE-TIME:2021-01-01T00:00:00.000000+00:00
#EXTINF:4, no desc
audio=129117-video=633990-01.ts
#EXTINF:4, no desc
audio=129117-video=633990-02.ts
#EXTINF:4, no desc
audio=129117-video=633990-03.ts
#EXTINF:4, no desc
audio=129117-video=633990-04.ts
#EXTINF:4, no desc
audio=129117-video=633990-05.ts
#EXTINF:4, no desc
audio=129117-video=633990-06.ts
#EXTINF:4, no desc
audio=129117-video=633990-07.ts
#EXTINF:4, no desc
audio=129117-video=633990-08.ts
#EXTINF:4, no desc
audio=129117-video=633990-09.ts
#EXTINF:4, no desc
audio=129117-video=633990-10.ts
#EXTINF:4, no desc
audio=129117-video=633990-11.ts
#EXTINF:4, no desc
audio=129117-video=633990-12.ts
#EXTINF:4, no desc
audio=129117-video=633990-13.ts
#EXTINF:4, no desc
audio=129117-video=633990-14.ts
#EXTINF:4, no desc
audio=129117-video=633990-15.ts
#EXTINF:4, no desc
audio=129117-video=633990-16.ts
#EXTINF:4, no desc
audio=129117-video=633990-17.ts
#EXTINF:4, no desc
audio=129117-video=633990-18.ts
#EXTINF:4, no desc
audio=129117-video=633990-19.ts
#EXTINF:4, no desc
audio=129117-video=633990-20.ts
Contextualized manifests
broadpeak.io will adapt the media manifests to reflect the switch from the original source to the replacement source for the duration of the Blackout slot, and then the switch back from the replacement content to the original content at the end of the slot.
Let's take the following example with a manifest that has a DVR of 1min 20s, and a switch from an original source to a replacement content after 20s. The replacement content lasts for 40s, then there is a switch back to the source content. For the sake of simplicity, in this example, we will assume that transcoding and packaging parameters are similar on the original and replacement sources.
Each content switch is represented in the manifest by a discontinuity tag #EXT-X-DISCONTINUITY, from the original source to the replacement source, then back to the original source after 40s.
#EXTM3U
#EXT-X-VERSION:5
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-TARGETDURATION:4
#EXT-X-PROGRAM-DATE-TIME:2021-01-01T00:00:00.000000+00:00
#EXTINF:4, no desc
audio=129117-video=633990-01.ts
#EXTINF:4, no desc
audio=129117-video=633990-02.ts
#EXTINF:4, no desc
audio=129117-video=633990-03.ts
#EXTINF:4, no desc
audio=129117-video=633990-04.ts
#EXTINF:4, no desc
audio=129117-video=633990-05.ts
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2011-01-01T00:00:20.000000+00:00
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-190.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-191.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-192.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-193.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-194.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-195.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-196.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-197.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-198.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-199.ts
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2011-01-01T00:00:40.000000+00:00
#EXTINF:4, no desc
audio=129117-video=633990-16.ts
#EXTINF:4, no desc
audio=129117-video=633990-17.ts
#EXTINF:4, no desc
audio=129117-video=633990-18.ts
#EXTINF:4, no desc
audio=129117-video=633990-19.ts
#EXTINF:4, no desc
audio=129117-video=633990-20.ts
Media sequence value in media playlists
When a new streaming session is opened, broadpeak.io initializes the media sequence value of each delivered media manifest to the value 1, regardless of the existing value. The media sequence value is then updated accordingly by the platform throughout the streaming session.
#EXT-X-MEDIA-SEQUENCE:1
Therefore, even in the context where contextualization is applied, the original media manifests are still altered as broadpeak.io modifies the value of the M3U8 media sequence, even if no contextualization is applied.
Dealing with encryption
Depending on your use case, there is a good chance you are dealing with encrypted HLS sources, whether they are your original source or replacement sources. broadpeak.io allows you to switch between encrypted or unencrypted sources, whether you are using AES-128 or SAMPLE-AES encryption.
Example of an encrypted source with a clear replacement content
We re-use the previous example, but this time the original source is encrypted with AES-128. The switch is then from an encrypted source to a clear replacement content, then back to the encrypted source after 40s.
We retrieve the #EXT-X-DISCONTINUITY tag each time there is a content switch, as well as additional information relative to the encryption method:
- The source content is encrypted with AES-128, so we retrieve the #EXT-X-KEY:METHOD=AES-128 tag at the beginning of the media manifest.
- The replacement content is free-to-air, which is an information that should be shared with the player. After the discontinuity tag, we retrieve the #EXT-X-KEY:METHOD=NONE.
- Back to the original stream, the player must also be informed as well that the content is encrypted. After the discontinuity tag, we retrieve the #EXT-X-KEY:METHOD=AES-128.
#EXTM3U
#EXT-X-VERSION:5
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-TARGETDURATION:4
#EXT-X-PROGRAM-DATE-TIME:2021-01-01T00:00:00.000000+00:00
#EXT-X-KEY:METHOD=AES-128,URI="https://keygenerator.com/sourcecontent/dummydrm/HLS/aes128.key",IV=0x73fbe3277bdf0bfc5217125bde4ca589
#EXTINF:4, no desc
audio=129117-video=633990-01.ts
#EXTINF:4, no desc
audio=129117-video=633990-02.ts
#EXTINF:4, no desc
audio=129117-video=633990-03.ts
#EXTINF:4, no desc
audio=129117-video=633990-04.ts
#EXTINF:4, no desc
audio=129117-video=633990-05.ts
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2011-01-01T00:00:20.000000+00:00
#EXT-X-KEY:METHOD=NONE
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-190.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-191.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-192.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-193.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-194.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-195.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-196.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-197.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-198.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-199.ts
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2011-01-01T00:00:40.000000+00:00
#EXT-X-KEY:METHOD=AES-128,URI="https://keygenerator.com/sourcecontent/dummydrm/HLS/aes128.key",IV=0x73fbe3277bdf0bfc5217125bde4ca589
#EXTINF:4, no desc
audio=129117-video=633990-16.ts
#EXTINF:4, no desc
audio=129117-video=633990-17.ts
#EXTINF:4, no desc
audio=129117-video=633990-18.ts
#EXTINF:4, no desc
audio=129117-video=633990-19.ts
#EXTINF:4, no desc
audio=129117-video=633990-20.ts
Example of an encrypted source with an encrypted replacement content
Adapting the previous example, here is what a manifest reflecting a source switch from an AES-128 encrypted source content to an AES-128 encrypted replacement content would look like:
#EXTM3U
#EXT-X-VERSION:5
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-TARGETDURATION:4
#EXT-X-PROGRAM-DATE-TIME:2021-01-01T00:00:00.000000+00:00
#EXT-X-KEY:METHOD=AES-128,URI="https://keygenerator.com/sourcecontent/dummydrm/HLS/aes128.key",IV=0x73fbe3277bdf0bfc5217125bde4ca589
#EXTINF:4, no desc
audio=129117-video=633990-01.ts
#EXTINF:4, no desc
audio=129117-video=633990-02.ts
#EXTINF:4, no desc
audio=129117-video=633990-03.ts
#EXTINF:4, no desc
audio=129117-video=633990-04.ts
#EXTINF:4, no desc
audio=129117-video=633990-05.ts
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2011-01-01T00:00:20.000000+00:00
#EXT-X-KEY:METHOD=AES-128,URI="https://keygenerator.com/replacementcontent/dummydrm/HLS/aes128.key",IV=0xA30FE123ECBF1BE323A775A119C553BC
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-190.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-191.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-192.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-193.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-194.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-195.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-196.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-197.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-198.ts
#EXTINF:4, no desc
../../../../replacement_content/hls/audio=129117-video=633990-199.ts
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2011-01-01T00:00:40.000000+00:00
#EXT-X-KEY:METHOD=AES-128,URI="https://keygenerator.com/sourcecontent/dummydrm/HLS/aes128.key",IV=0x73fbe3277bdf0bfc5217125bde4ca589
#EXTINF:4, no desc
audio=129117-video=633990-16.ts
#EXTINF:4, no desc
audio=129117-video=633990-17.ts
#EXTINF:4, no desc
audio=129117-video=633990-18.ts
#EXTINF:4, no desc
audio=129117-video=633990-19.ts
#EXTINF:4, no desc
audio=129117-video=633990-20.ts
We retrieve the #EXT-X-DISCONTINUITY tag each time there is a content switch, as well as additional information relative to the encryption method:
- The source content is encrypted with AES-128, that is why we have the #EXT-X-KEY:METHOD=AES-128 tag at the beginning of the media manifest.
- Since the replacement content is also encrypted with AES-128, but with different encryption parameters, the information must be shared with the player. After the discontinuity tag, we retrieve the #EXT-X-KEY:METHOD=AES-128 tag with associated information related to the encryption of the replacement content.
- Back to the original stream, the player must also be informed that the content is encrypted. After the discontinuity tag, we retrieve the #EXT-X-KEY:METHOD=AES-128 tag with associated information related to the encryption of the source content.
Key takeaways
- The Media Sequence (MS) value in the media manifests is modified by broadpeak.io. Each new streaming session opened initialized the MS to 1.
- The beginning of the playlist always indicates the encryption method used for the first media segment of the playlist using #EXT-X-KEY:METHOD tag. Free-to-air media segments at the beginning of the playlist also needs to be indicated with #EXT-X-KEY:METHOD=NONE.
- Changes of content within the manifest are specified through the #EXT-X-DISCONTINUITY tag.
- When there is a switch from encrypted to free-to-air content or from free-to-air to encrypted content, the change in encryption is specified using the #EXT-X-KEY:METHOD after the #EXT-X-DISCONTINUITY tag. Respectively, it should be #EXT-X-KEY:METHOD=NONE and #EXT-X-KEY:METHOD=AES-128 (or #EXT-X-KEY:METHOD=SAMPLE-AES if the encryption method is different).
Updated 5 months ago