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., 8 seconds).
See this short overview that shows How to package CMAF
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 \
tos-8s-aac-64k.cmfa
mp4split -o tos-128k-fmp4.m3u8 \
tos-8s-aac-128k.cmfa
mp4split -o tos-400k-fmp4.m3u8 \
tos-8s-avc1-400k.cmfv
mp4split -o tos-750k-fmp4.m3u8 \
tos-8s-avc1-750k.cmfv
mp4split -o tos-1000k-fmp4.m3u8 \
tos-8s-avc1-1000k.cmfv
Note
It's also possible to create a HLS Media Playlist for subtitles that are
stored in a fMP4 container (i.e., a .cmft
-file). However, iOS and MacOS
devices only support the TTML based variant of ISO-14496-30 (IMSC1 Text) in
fMP4, not WebVTT. For WebVTT, only WebVTT Segments are supported. To generate
those WebVTT Segments and the necessary Media Playlist, follow the
instructions for Adding WebVTT subtitles when packaging HLS TS.
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-400k-fmp4.m3u8 \
--create_iframe_playlist \
tos-8s-avc1-400k.cmfv
mp4split -o iframe-tos-750k-fmp4.m3u8 \
--create_iframe_playlist \
tos-8s-avc1-750k.cmfv
mp4split -o iframe-tos-1000k-fmp4.m3u8 \
--create_iframe_playlist \
tos-8s-avc1-1000k.cmfv
Note
Also, the --create_iframe_playlist
option used for fMP4 HLS should not be
used 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-400k-fmp4.m3u8 \
tos-750k-fmp4.m3u8 \
tos-1000k-fmp4.m3u8 \
iframe-tos-400k-fmp4.m3u8 \
iframe-tos-750k-fmp4.m3u8 \
iframe-tos-1000k-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
Note
When generating a Media Playlist, you can specify a value for the advisory
HLS tag 'HDCP-LEVEL' using the option --hdcp_level
, for which none
,
type-0
and type-1
are valid values (e.g., --hdcp_level=type-1
).
If this tag is not specified, it will not be added.
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).
--cenc.key=10000000100010001000100000000001:3a2a1b68dd2bd9b2eeb25e84c4776668 \
--cenc.key_iv=f9d9d5f5f3b5bc0372856df068f9f6a2 \
--scheme_type=cbcs
Like so:
#!/bin/bash
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
KID=10000000100010001000100000000001
KIV=f9d9d5f5f3b5bc0372856df068f9f6a2
mp4split -o tos-8s-128k-cbcs.cmfa \
--fragment_duration=384000/48000 \
--cenc.key=${KID}:${CEK} \
--cenc.key_iv=${KIV} \
--scheme_type=cbcs \
tears-of-steel-aac-128k.mp4
mp4split -o tos-8s-2200k-cbcs.cmfv \
--fragment_duration=192/24 \
--cenc.key=${KID}:${CEK} \
--cenc.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
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
# Store binary representation of CEK in cek.key file
echo ${CEK} | xxd -p -r > cek.key
# URL that resolves to the cek.key file
LA_URL=https://license-server/cek.key
mp4split -o tos-128k-fmp4-cbcs.m3u8 \
--encrypt_key_url=${LA_URL} \
tos-8s-128k-cbcs.cmfa
mp4split -o tos-2200k-fmp4-cbcs.m3u8 \
--encrypt_key_url=${LA_URL} \
tos-8s-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. Additionally, you have to add
the option --key_format="com.apple.streamingkeydelivery"
when generating
your Media Playlists.
#!/bin/bash
KID=10000000100010001000100000000001
FP_URL=skd://${KID}
mp4split -o tos-128k-fmp4-fp.m3u8 \
--encrypt_key_url=${FP_URL} \
--key_format="com.apple.streamingkeydelivery" \
tos-8s-128k-cbcs.cmfa
mp4split -o tos-2200k-fmp4-fp.m3u8 \
--encrypt_key_url=${FP_URL} \
--key_format="com.apple.streamingkeydelivery" \
tos-8s-2200k-cbcs.cmfv
Then, with all the Media Playlists in place, you generate the I-frame Playlists and Master Playlist as you normally would.
Adding PlayReady DRM
To support PlayReady 4 for HLS, add the necessary signaling when generating the
Media Playlists with Unified Packager, by using the --iss.drm_specific_data
command-line option to specify the base64 encoded PlayReady Object containing
the PlayReady Header (or, even better, the complete PSSH box):
#!/bin/bash
PR_OBJECT=uAIAAAEAAQCuAjwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADMALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAOgAvAC8AZQB4AHAAZQByAGkAbQBlAG4AdABhAGwAMQAuAGEAegB1AHIAZQB3AGUAYgBzAGkAdABlAHMALgBuAGUAdAAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4AD8AYwBmAGcAPQAoAGMAawA6AFcAMwAxAGIAZgBWAHQAOQBXADMAMQBiAGYAVgB0ADkAVwAzADEAYgBmAFEAPQA9ACwAYwBrAHQAOgBBAEUAUwAxADIAOABCAGkAdABDAEIAQwApADwALwBMAEEAXwBVAFIATAA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARABTAD4APABLAEkARAAgAEEATABHAEkARAA9ACIAQQBFAFMAQwBCAEMAIgAgAFYAQQBMAFUARQA9ACIAQQBBAEEAQQBFAEEAQQBRAEEAQgBBAFEAQQBCAEEAQQBBAEEAQQBBAEEAUQA9AD0AIgA+ADwALwBLAEkARAA+ADwALwBLAEkARABTAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A
mp4split -o tos-128k-fmp4-pr.m3u8 \
--iss.drm_specific_data=${PR_OBJECT} \
tos-8s-128k-cbcs.cmfa
mp4split -o tos-2200k-fmp4-pr.m3u8 \
--iss.drm_specific_data=${PR_OBJECT} \
tos-8s-2200k-cbcs.cmfv
mp4split -o tos-master-pr.m3u8 \
tos-128k-fmp4-pr.m3u8 \
tos-2200k-fmp4-pr.m3u8
Adding Widevine DRM
To support Widevine DRM for HLS V2, add the necessary signaling when generating the
Media Playlists with Unified Packager, by using the --widevine.drm_specific_data
command-line option to specify the base64 encoded Widevine data (or, even better,
the complete PSSH box).
#!/bin/bash
WV_DATA=IhBma2ozbGphU2RmYWxrcjNqSOPclZsG
mp4split -o tos-128k-fmp4-wv.m3u8 \
--widevine.drm_specific_data=${WV_DATA} \
tos-8s-128k-cbcs.cmfa
mp4split -o tos-2200k-fmp4-wv.m3u8 \
--widevine.drm_specific_data=${WV_DATA} \
tos-8s-2200k-cbcs.cmfv
mp4split -o tos-master-wv.m3u8 \
tos-128k-fmp4-wv.m3u8 \
tos-2200k-fmp4-wv.m3u8