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 they 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 signficant 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.

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
  • 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 staticly packaged content is that the --package_hls should not be used.

See below for example command-lines for creating Media Playlists, I-frame Playlists and the Master Playlists. The --fragment_duration option is used to specify HLS’s recommended fragment length of 6 seconds (in milliseconds).

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 staticly packaged fMP4 HLS stream.

Create Media Playlists

#!/bin/bash

mp4split -o tos-64k-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-64k.cmfa
mp4split -o tos-128k-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-128k.cmfa
mp4split -o tos-1-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-1.cmfv
mp4split -o tos-2-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-2.cmfv
mp4split -o tos-3-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-3.cmfv
mp4split -o tos-4-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-4.cmfv
mp4split-o tos-5-fmp4.m3u8 \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-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, use the --create_iframe_playlist option:

–create_iframe_playlist

#!/bin/bash

mp4split -o iframe-tos-1-fmp4.m3u8 \
  --create_iframe_playlist \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-1.cmfv
mp4split -o iframe-tos-2-fmp4.m3u8 \
  --create_iframe_playlist \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-2.cmfv
mp4split -o iframe-tos-3-fmp4.m3u8 \
  --create_iframe_playlist \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-3.cmfv
mp4split -o iframe-tos-4-fmp4.m3u8 \
  --create_iframe_playlist \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-4.cmfv
mp4split -o iframe-tos-5-fmp4.m3u8 \
  --create_iframe_playlist \
  --fragment_duration=6000 \
  cmaf/tears-of-steel-5.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 staticly 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 tears-of-steel-128k-cbcs.cmfa \
  --iss.key=$KID:$CEK --iss.key_iv=$KIV \
  --scheme_type=cbcs \
  tears-of-steel-128k.mp4

mp4split -o tears-of-steel-5-cbcs.cmfv \
  --iss.key=$KID:$CEK --iss.key_iv=$KIV \
  --scheme_type=cbcs \
  tears-of-steel-5.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 \
  --fragment_duration=6000 \
  --encrypt_key_url=../cek.key \
  tears-of-steel-128k-cbcs.cmfa

mp4split -o tos-5-fmp4-cbcs.m3u8 \
  --fragment_duration=6000 \
  --encrypt_key_url=../cek.key \
  tears-of-steel-5-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 staticly 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 \
  --fragment_duration=6000 \
  --encrypt_key_url=<fairplay-licensing-url> \
  --streaming-key-delivery \
  tears-of-steel-128k-cbcs.cmfa

mp4split -o tos-5-fmp4-fp.m3u8 \
  --fragment_duration=6000 \
  --encrypt_key_url=<fairplay-licensing-url> \
  --streaming-key-delivery \
  tears-of-steel-5-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.