Packaging HTTP Live Streaming with fragmented MP4 (fMP4 HLS)

Note

This part of our documentation is specifically intended for packaging to deliver fMP4 over HLS, or, in short: fMP4 HLS. This is a new feature and other parts of our documentation that refer to HLS without explicitly mentioning compatibility with fMP4 HLS may not necessarily apply to it, as these parts were written when Transport Streams (TS) were the only output format supported for delivery of HLS.

New in version 1.8.3.

Packaging for delivery of fMP4 HLS does not differ much from packaging HLS using Transport Streams. The most significant differences are the following:

  • You package your content into a CMAF compatible container, instead of Transport Streams. See: How to package CMAF
  • You never use the --package_hls option (not for creating the Media Playlists, I-frame Playlists or Master Playlist)
  • A Media Playlist for fMP4 HLS uses byte ranges to index the CMAF packaged content. Therefore, no individual segments are generated
  • You add a different kind of encryption to your content and use different options to do so

Superficially, the resulting playlists look very similar. Do note though that regarding encryption, the exact meaning of SAMPLE-AES is different for fMP4 HLS than it is for HLS with Transport Streams.

The benefits of streaming fMP4 HLS

The first major benefit of fMP4 HLS is that it uses the same file container format as MPEG-DASH. You can read more about this convergence in our blog post about The promises of CMAF and its compatibility with the Unified Streaming Platform.

In addition, Apple added support for HEVC and HDR (Dolby Vision and HDR10) to the HLS specification, but restricted these features to fMP4 HLS only. Using Unified Packager, no additional configuration is needed when packaging HEVC and/or HDR for fMP4 HLS.

Overview of steps involved in packaging fMP4 HLS

Below you can find the necessary steps for packaging audio and video content. Overall, they are the following:

  • Make sure your content is packaged in a CMAF compatible container with the desired fragment duration (e.g., 6 seconds).
  • Create Media Playlists based on your CMAF packaged content
  • Create I-frame Playlists for your video content
  • Create a Master Playlist based on all the individual playlists that you created

Adding encryption is done at the first step (when packaging your content as CMAF) and adding the necessary signaling for the encryption is done at the second step (when creating the Media Playlists).

Creating HLS playlists with CMAF packaged content

As mentioned above, the notable difference when creating the necessary playlists for streaming HLS from statically packaged content is that the --package_hls should not be used.

Use tos-fmp4-hls-static.sh to package the Tears of Steel demo contents as CMAF and subsequently generate the necessary HLS playlists to set up a statically packaged fMP4 HLS stream.

Create Media Playlists

#!/bin/bash

mp4split -o tos-64k-fmp4.m3u8 \
  cmaf/tos-6000ms-64k.cmfa
mp4split -o tos-128k-fmp4.m3u8 \
  cmaf/tos-6000ms-128k.cmfa
mp4split -o tos-1-fmp4.m3u8 \
  cmaf/tos-6000ms-1.cmfv
mp4split -o tos-2-fmp4.m3u8 \
  cmaf/tos-6000ms-2.cmfv
mp4split -o tos-3-fmp4.m3u8 \
  cmaf/tos-6000ms-3.cmfv
mp4split -o tos-4-fmp4.m3u8 \
  cmaf/tos-6000ms-4.cmfv
mp4split-o tos-5-fmp4.m3u8 \
  cmaf/tos-6000ms-5.cmfv

Create I-frame Playlists

In addition to creating standard Media Playlists for each track, create I-frame Playlists for every track to enable trick play and allow viewers to fast forward and rewind playback of your stream. To do so, you can:

  • Create I-frame Playlists based on sync-samples only MP4s, as explained in Adding trick play to a DASH or HLS stream
  • Or you can create I-frame Playlists based on the regular video files, by using the --create_iframe_playlist option

The latter is explained below:

–create_iframe_playlist

#!/bin/bash

mp4split -o iframe-tos-1-fmp4.m3u8 \
  --create_iframe_playlist \
  cmaf/tos-6000ms-1.cmfv
mp4split -o iframe-tos-2-fmp4.m3u8 \
  --create_iframe_playlist \
  cmaf/tos-6000ms-2.cmfv
mp4split -o iframe-tos-3-fmp4.m3u8 \
  --create_iframe_playlist \
  cmaf/tos-6000ms-3.cmfv
mp4split -o iframe-tos-4-fmp4.m3u8 \
  --create_iframe_playlist \
  cmaf/tos-6000ms-4.cmfv
mp4split -o iframe-tos-5-fmp4.m3u8 \
  --create_iframe_playlist \
  cmaf/tos-6000ms.cmfv

Note

Also, the --create_iframe_playlist option is only available for fMP4 HLS and not supported for HLS with Transport Streams, as the necessary I-frame Playlists are generated automatically when packaging the latter.

Create Master Playlist

Packaging the media playlists into a Master Playlist is done the usual way.

#!/bin/bash

mp4split -o master_fmp4_clear.m3u8 \
  tos-64k-fmp4.m3u8 \
  tos-128k-fmp4.m3u8 \
  tos-1-fmp4.m3u8 \
  tos-2-fmp4.m3u8 \
  tos-3-fmp4.m3u8 \
  tos-4-fmp4.m3u8 \
  tos-5-fmp4.m3u8 \
  iframe-tos-1-fmp4.m3u8 \
  iframe-tos-2-fmp4.m3u8 \
  iframe-tos-3-fmp4.m3u8 \
  iframe-tos-4-fmp4.m3u8 \
  iframe-tos-5-fmp4.m3u8

Protecting a statically packaged fMP4 HLS stream

When streaming fMP4 HLS, Apple specifies that the CENC ‘cbcs’ encryption scheme must be used if you want to protect your content.

To do so, requires the following:

  • Add ‘cbcs’ encryption when packaging your content as CMAF
  • Add the required signaling of the keys when generating the Media Playlists

Adding CENC ‘cbcs’ encryption

To encrypt your content according to the CENC ‘cbcs’ encryption scheme you add the following parameters to your command-line when packaging your content to CMAF (with your own keys, of course).

--iss.key=10000000100010001000100000000001:3a2a1b68dd2bd9b2eeb25e84c4776668 \
--iss.key_iv=f9d9d5f5f3b5bc0372856df068f9f6a2 \
--scheme_type=cbcs

Note

The use of the iss prefix may seem confusing when you are setting up a HLS stream. This is so because the encryption is not HLS specific, but CENC.

Like so:

#!/bin/bash

CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
KID=10000000100010001000100000000001
KIV=f9d9d5f5f3b5bc0372856df068f9f6a2

mp4split -o tos-6000ms-128k-cbcs.cmfa \
  --fragment_duration=6000 \
  --iss.key=$KID:$CEK --iss.key_iv=$KIV \
  --scheme_type=cbcs \
  tears-of-steel-aac-128k.mp4

mp4split -o tos-6000ms-2200k-cbcs.cmfv \
  --fragment_duration=6000 \
  --iss.key=$KID:$CEK --iss.key_iv=$KIV \
  --scheme_type=cbcs \
  tears-of-steel-avc1-2200k.mp4

To add the necessary signaling of the key to your Media Playlists, make use of the --encrypt_key_url option when creating these playlists.

For example:

#!/bin/bash

# Store binary representation of CEK in cek.key file
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
echo ${CEK} | xxd -p -r > cek.key

mp4split -o tos-128k-fmp4-cbcs.m3u8 \
  --encrypt_key_url=cek.key \
  tos-6000ms-128k-cbcs.cmfa

mp4split -o tos-2200k-fmp4-cbcs.m3u8 \
  --encrypt_key_url=cek.key \
  tos-6000ms-2200k-cbcs.cmfv

Then, with all the Media Playlists in place, you generate the I-frame Playlists and Master Playlist as you normally would.

Use tos-fmp4-hls-cbcs-static.sh to package the Tears of Steel demo contents as CMAF with ‘cbcs’ encryption and subsequently generate the necessary HLS playlists to set up a statically packaged and encrypted fMP4 HLS stream.

Adding FairPlay DRM

When you want to use FairPlay DRM, you have to set the --encrypt_key_url to signal the URL of your FairPlay licensing server and you have to add the option --streaming-key-delivery when generating your Media Playlists.

#!/bin/bash

mp4split -o tos-128k-fmp4-fp.m3u8 \
  --encrypt_key_url=<fairplay-licensing-url> \
  --streaming-key-delivery \
  tos-6000ms-128k-cbcs.cmfa

mp4split -o tos-2200k-fmp4-fp.m3u8 \
  --encrypt_key_url=<fairplay-licensing-url> \
  --streaming-key-delivery \
  tos-6000ms-2200k-cbcs.cmfv

Then, with all the Media Playlists in place, you generate the I-frame Playlists and Master Playlist as you normally would.

Note

  • If you’re adding cbcs encryption to your content with FairPlay DRM as the only purpose, you can leave out the KID in the --iss.key parameter, i.e. --iss.key=:<CEK>. This is because FairPlay does not make use of a KID.
  • You can also specify a HDCP-LEVEL using the option –hdcp_level.