Packager

Learning Outcomes

  • Understand what the packager is for
  • Know the packager use cases
  • Understand possible deployment scenarios

Diagram

../_images/packager.png

Schematically

@startditaa

  /------------+      /----------+      /-----------------------------+
  |(f)mp4 files| ---> | packager | ---> |hds,hls,hss,dash,cmaf (files)|
  +------------/      +----------/      +-----------------------------/
        |                                               |
        |                                               |
    +-------+                                       +-------+
    |{s}    |                                       |{s}    |
    |storage|                                       |storage|
    +-------+                                       +-------+

@endditaa

Use Cases

Unified Packager can be used independently of Unified Origin for setups that serve static content, or alongside as you prepare content for Origin’s dynamic packaging.

‘Packaging’ is the process of changing the file format or ‘container’ in which digital content is stored e.g. changing a progressive MP4 into a fragmented MP4. This process can also be called fragmenting. Encryption or DRM can also be applied as part of the process.

The packager (mp4split) has three different uses:

  • Package content (audio, video, subtitles and metadata)
  • Create manifests (both server and client)
  • Apply encryption or DRM

The packager supports the following formats (packaging to and from):

Format Input Output Notes
CMAF y y Input when creating playlists for HLS with fMP4
HDS n y  
HLS n y  
HSS y y  
MP4 y y Including ‘dref’ output (for progressive and download to own)
MPEG-DASH y y  
Metadata y y For instance Nielsen metadata

Selection of options

The generic command line for packaging:

mp4split -o output_file [options] <input_file(s)> [track-options]

A full list of options can be found in our online documentation. [1]

Package Content

Content can either be packaged for ‘standalone’ use, with a standard webserver, or for use with Unified Origin.

Be aware that only using packager has some limitations: IIS only delivers Smooth/HSS (when VOD), Adobe Media Server serves HDS (f4f/f4m) and HLS, but not MPEG-DASH.

The documentation contains a section listing specific possbilities for each of the formats e.g. the use of Dolby Vision with MPEG-DASH.

Input can be H.264/AAC, HEVC (including HDR, Dolby Vision or HLG), AV1 or VP9. For audio, Dolby Audio (AC-3 or EC-3), DTS or HE-AAC v2 and ‘plain’ AAC. An overview of supported formats can be found online. [2]

Subtitles / Captions

Generally subtitles have to be packaged in an fMP4 container(.ismt or .cmft) before they can be added to a stream (exceptions are embedded CE 608/708 or TTML/WebVTT sidecar in MPEG-DASH).

Adding a subtitle track, in an fMP4 container, to a stream is the same as adding an audio or video track: simply add the .ismt or .cmft to your mp4split input when generating the client manifest (.mpd or .m3u8). See the hands-on section for examples.

You can use TTML (Timed Text Markup Language), WebVTT (Web Video Text Tracks) or SRT (SubRip Text) as a source. Packager can convert between the above as well as packaging TTML and WebVTT in an fMP4 container.

For more information on these different formats read our blog on subtitles: Welcome to the jungle: caption and subtitle formats in video streaming. [3]

In summary, WebVTT and SRT are nearly identical plain-text formats, opposed to the XML-based TTML. (Note that SRT is ASCII, unless specified, and WebVTT is always UTF-8).

Source Output
TTML WebVTT, TTML in fMP4
WebVTT (or SRT) TTML, WebVTT in fMP4

Packager can package TTML subtitles following any of these profiles: DFXP, SMPTE-TT, EBU-TT-D, SDP-US, CFF-TT and the IMSC1 Text Profile.

Trick play

Trick play, or trick mode, is a feature giving viewers thumbnails while rewinding or fast-forwarding a stream. This feature is added to streams in numerous ways:

  • DASH requires a ‘sync-samples only’ track (reference: [1]). Alternatively, a track with tiled thumbnails in JPEG format can be added (reference: [2]).
  • HLS requires an I-frame Playlist which can reference either the original video track or a ‘sync-samples only’ track.
    • To reference the original video track an ‘iframe index file’ needs to be created and added to the master playlist (HLS TS only).
    • For HLS ‘sync-samples only’ tracks are supported for fMP4 HLS, not for HLS with Transport Streams (HLS TS).
    • Using a ‘sync-samples only’ track can make trick play’s visual feedback smoother, as it may offer a higher density of frames compared to an I-frame Playlist that references the original video track.

Adding or Changing Metadata

Using the --track_ options, specified after the content, manipulates metadata related to the MP4 tracks. This can be considered ‘advanced’ usage as most encoded content is good ‘as-is’.

One use case is signaling accessibility tracks, namely captions for the hard of hearing or audio description for the visually impaired, providing ‘–track_kind’ with the --track_kind="<SchemeIdUri>@<Value>" option adds the following to an (MPEG-DASH) client manifest:

<Accessibility
  schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007"
  value="1">
</Accessibility>
<Role
 schemeIdUri="urn:mpeg:dash:role:2011"
 value="alternate">
</Role>

For Nielsen, metadata is packaged into a (fragmented) MP4 track which is added to the server manifest so it can be applied through the origin, not through the --track_ option.

Creating Manifests

When not using Unified Origin both content and client manifests should be created (and in case of IIS a server manifest as well). This is needed for:

  • HDS: Adobe Media Server is used for delivery
  • HLS: a standard webserver is used for delivery
  • HSS: IIS is used for delivery
  • MPEG-DASH: a standard webserver is used for delivery

Note that with MPEG-DASH the webserver needs to be set up to handle range requests.

Apply Encryption/DRM

Each of the sections in the packaging documentation outline how to apply encryption/DRM for the format discussed:

Digital Rights Management DASH HDS HLS HSS
Microsoft PlayReady yes   yes yes
Adobe Primetime yes yes yes  
Marlin yes   yes  
Widevine Modular yes      
Apple FairPlay     yes  

There are also ‘cross-over’ variants supported e.g. PlayReady for HLS (Irdeto, Conax, ViaccesOrca/Discretix) or China DRM.

Multiple Key DRM

Encryption with multiple keys allows you to encrypt different tracks in a stream with different keys, instead of using one key to encrypt all audio and video tracks.

For example:

  • Encrypt audio with a different key than video
  • Encrypt some audio or video tracks, but not all of them
  • Encrypt premium features with a different key than standard features
  • Encrypt all tracks with separate keys for complete flexibility

Multiple keys can support a setup where different tracks are associated with DRM licenses that have different requirements. Such a setup is possible using only one encryption key, but becomes more secure when using multiple keys so that each key is only associated with a particular license. The latter approach is recommended by all major DRM systems.

Please note that the ‘Content Protection Information eXchange (CPIX)’ format is not used when packaging, individual tracks are encrypted with individual keys after which an .mpd or .m3u8 manifest is created (as this feature relates to MPEG-DASH and HLS (fMP4) only).

Deployment and Workflows

The most straightforward way to run Unified Packager, a commandline executable, is working from the (bash)shell.

However automation can also applied:

  • event based, a ‘watch folder’ triggering a package process
  • embed the packager in a job queue (Celery, Kue or other)
  • a third party CMS (which handles events)

There are so many approaches to building workflows we do not provide a single, mandatory approach but a building block that allows itself to be embedded.

Monitoring

Packager exits with a status code at the end of each process, a full list of which are listed in the documentation. [4]

While processing a file, Packager prints all actions to the console (stdout/stderr). This output can be used to register progress:

100%[==========================================================>]

For instance in Kue (Nodejs):

mp4split = spawn(cmd, spawnargs(args));
mp4split.stderr.on('data', function(data) {
  parse_progress_bar(data, function(point) {
    job.progress(point, 100);
  });
});

This snippet pushes mp4split progress output to the NodeJS library ‘Kue’ so it can be rendered in Kue’s UI. [5]

Hands-On

Below is a high-level workflow for preparing your content for streaming DASH or HLS, using static packaging. To augment this short overview links to the relevant parts of our online documentation are provided, where much more detailed information can be found.

Static packaging for streaming DASH

Package media content for DASH using --package_mpd, this will package your content in a fMP4 container that is compliant with the DASH specification:

#!/bin/bash

mp4split --package_mpd -o audio-dash.mp4 \
  /var/www/tears-of-steel/tears-of-steel-aac-64k.mp4

mp4split --package_mpd -o video-dash.mp4 \
  /var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4
  • Generate a DASH client manifest (MPD) based on DASH packaged content:
#!/bin/bash

mp4split --package_mpd -o client_manifest.mpd \
  audio-dash.mp4 \
  video-dash.mp4

Note

To stream the just created DASH content a different virtual host must be used. This is a ‘plain’ virtual host without Unified Origin enabled, simply serving DASH files. The same applies for the next step.

Static packaging for streaming HLS

Package media content for HLS in separate directories, using --package_hls. This will package your content in HLS compliant Transport Streams and generate the necessary Media Playlists:

#!/bin/bash

mp4split --package_hls -o stream1/audio.m3u8 \
  /var/www/tears-of-steel/tears-of-steel-aac-64k.mp4

mp4split --package_hls -o stream2/video.m3u8 \
  /var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4

Generate a HLS client manifest (Master Playlist) based on Media Playlists:

#!/bin/bash

mp4split --package_hls -o master_playlist.m3u8 \
  stream1/audio.m3u8 \
  stream2/video.m3u8

Note

Please refer to the online documentation for more details when packaging DASH, HLS, HDS or HSS.

Packaging CMAF

The process of packaging CMAF is similar to packaging ISMV. Depending on the extension of the output, mp4split will decide how to package the content. In the case of CMAF, you can choose between .cmfv for video, .cmfa for audio and .cmft for text streams:

#!/bin/bash

mp4split -o tears-of-steel-aac-128k.cmfa \
  /var/www/tears-of-steel/tears-of-steel-aac-128k.mp4

mp4split -o tears-of-steel-avc1-1500k.cmfv \
  /var/www/tears-of-steel/tears-of-steel-avc1-1500k.mp4

mp4split -o tears-of-steel-en.cmft \
  /var/www/tears-of-steel/tears-of-steel-en.srt

Hint

CMAF is also used as source for HLS with fMP4. Look up the chapter in docs.unified and created fMP4/HLS from the previous example. [6]

Packaging Subtitles

Packager follows ISO 14496-30 when packaging subtitles in a fMP4 container.

  • When using WebVTT (or SRT) as input, the resulting fMP4 will use the wvtt codec
  • When using TTML as input, the resulting fMP4 will use the stpp codec

The following options are worth noting for when packaging subtitles:

  • –track_language - When you need to add or overrule language signaling for WebVTT or SRT (if the source does not contain language signaling and you do not add any, English is the default):
  • –track_role and –track_kind - When you need to define a ‘role’ for the subtitles track, or want to add signaling for an accessibility feature
  • –fragment_duration - When you want to specify the duration of the fragments in which the subtitles are fragmented in the fMP4 (the default is 60000 milliseconds) to align it with the fragment duration of the other media in your stream

WebVTT or SRT in fMP4

#!/bin/bash

mp4split -o tears-of-steel-wvtt-de.ismt \
  /var/www/tears-of-steel/tears-of-steel-de.srt --track_language=de

TTML in fMP4

#!/bin/bash

mp4split -o tears-of-steel-de.ttml \
  /var/www/tears-of-steel/tears-of-steel-de.srt

mp4split -o tears-of-steel-ttml-de.ismt \
  tears-of-steel-de.ttml

Hint

Look up the two cases where ISO 14496-30 is not followed. [7]

Adding Trickplay

We’ll only look at the sync-samples option, DASH and HLS (and not at thumbnails or i-frame playlists).

How to package a sync-samples only MP4

Package a CMAF compliant MP4 that contains only sync-samples with proper signaling using mp4split with the --trickplay option:

#!/bin/bash

mp4split --trickplay -o tears-of-steel-1500k-sync-samples.cmfv \
  tears-of-steel-avc1-1500k.cmfv

MPEG-DASH

After you have created a sync-samples only file, add that file to the other media files making up your stream and, based on these files, create a MPD:

#!/bin/bash

mp4split --package_mpd \
  -o tears-of-steel-with-trickplay.mpd \
  tears-of-steel-avc1-1500k.cmfv \
  tears-of-steel-1500k-sync-samples.cmfv \
  tears-of-steel-aac-128k.cmfa

HLS/fMP4

When a track contains only sync-samples, mp4split automatically detects this and will create an I-frame Playlist for it, instead of a regular Media Playlist.

#!/bin/bash

mp4split -o iframe-sync-samples.m3u8 \
  tears-of-steel-1500k-sync-samples.cmfv

mp4split -o video.m3u8 \
  tears-of-steel-avc1-1500k.cmfv

mp4split -o audio.m3u8 \
  tears-of-steel-aac-128k.cmfa

mp4split -o master_playlist.m3u8 \
  iframe-sync-samples.m3u8 \
  video.m3u8 \
  audio.m3u8

Additional Hands-on

If you have extra time you can take a look at the following.

Using DRM with Multiple Keys

Our documentation discusses the following three possibilities in detail:

  • Multiple keys ‘cenc’ CENC encryption for DASH with Widevine and PlayReady
  • Multiple keys ‘cbcs’ CENC encryption for fMP4 HLS
  • Multiple keys encryption for HLS TS with SAMPLE-AES

We will only follow the first one here.

Encrypting your content according to the CENC ‘cenc’ encryption scheme and adding the necessary signaling for DRM is shown in the example below. Which type of DRM specific information you need to signal depends on the DRM system(s) you are using.

We recommend using the drm_specific_data option to specify the Protection Scheme Specific Header (PSSH) box. Unified Packager can synthesize this data but only for basic implementations, not for DRM with multiple keys or other more advanced use cases:

#!/bin/bash

KID1=c001de8e567b5fcfbc22c565ed5bda24
CEK1=533a583a843436a536fbe2a5821c4b6c

KID2=cbd1104bbc6f59ca91ac940b67032d80
CEK2=643d5329c8072509ae8003577b19d92f

#Add your PlayReady DRM specific PSSH data (same for all tracks)
PR_PSSH_STR=`cat <<END
6wMAAAEAAQDhAzxXUk1IRUFERVIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vRFJN
LzIwMDcvMDMvUGxheVJlYWR5SGVhZGVyIiB2ZXJzaW9uPSI0LjIuMC4wIj48REFUQT48UFJPVEVDVElO
Rk8+PEtJRFM+PEtJRCBBTEdJRD0iQUVTQ1RSIiBDSEVDS1NVTT0iSm9YZDRac0FoaDg9IiBWQUxVRT0i
anQ0QndIdFd6MSs4SXNWbDdWdmFKQT09Ij48L0tJRD48S0lEIEFMR0lEPSJBRVNDVFIiIENIRUNLU1VN
PSJvTUdjNlRsY0N6bz0iIFZBTFVFPSJTeERSeTIrOHlsbVJySlFMWndNdGdBPT0iPjwvS0lEPjxLSUQg
QUxHSUQ9IkFFU0NUUiIgQ0hFQ0tTVU09ImZlUjJLNVBBSmNVPSIgVkFMVUU9Imp1SG5CUUMvQ1ZLd3A4
bkF1dXpXMnc9PSI+PC9LSUQ+PEtJRCBBTEdJRD0iQUVTQ1RSIiBDSEVDS1NVTT0iSUhZd0ltUUJFeU09
IiBWQUxVRT0iTXJrazlaK08vVk9oSlhDdm5INHJkZz09Ij48L0tJRD48S0lEIEFMR0lEPSJBRVNDVFIi
IENIRUNLU1VNPSI3NEN5MGdiNjh4ND0iIFZBTFVFPSJBNVdsZ0YwbklsaTJ2Vnh2eEl4THF3PT0iPjwv
S0lEPjwvS0lEUz48L1BST1RFQ1RJTkZPPjxMQV9VUkw+aHR0cHM6Ly90ZXN0LnBsYXlyZWFkeS5taWNy
b3NvZnQuY29tL3NlcnZpY2UvcmlnaHRzbWFuYWdlci5hc214P2NmZz0oa2lkOmp0NEJ3SHRXejErOElz
Vmw3VnZhSkE9PSxjb250ZW50a2V5OlV6cFlPb1EwTnFVMisrS2xnaHhMYkE9PSksKGtpZDpTeERSeTIr
OHlsbVJySlFMWndNdGdBPT0sY29udGVudGtleTpaRDFUS2NnSEpRbXVnQU5YZXhuWkx3PT0pLChraWQ6
anVIbkJRQy9DVkt3cDhuQXV1elcydz09LGNvbnRlbnRrZXk6eHBnakZKelYyZGZXbGhmTjBkR211dz09
KSwoa2lkOk1ya2s5WitPL1ZPaEpYQ3ZuSDRyZGc9PSxjb250ZW50a2V5OlJicjgxWGRCNzRjWnJUeDUr
c29kN2c9PSksKGtpZDpBNVdsZ0YwbklsaTJ2Vnh2eEl4THF3PT0sY29udGVudGtleTpoSy9NUkNVN3Bu
dk5yTVA2ekZYS1l3PT0pPC9MQV9VUkw+PC9EQVRBPjwvV1JNSEVBREVSPg==
END
`
PR_PSSH="$(echo -e "${PR_PSSH_STR}" | tr -d '[:space:]')"

#Add your Widevine DRM specific PSSH data (same for all tracks)
WV_PSSH="AAAAKXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAkiAT1I49yVmwY="

mp4split --package_mpd -o tears-of-steel-aac-128k-dash-cenc.cmfa  \
  --cenc.key=${KID1}:${CEK1} \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  /var/www/tears-of-steel/tears-of-steel-aac-128k.mp4

mp4split --package_mpd -o tears-of-steel-avc1-400k-dash-cenc.cmfv \
  --iss.key=${KID2}:${CEK2} \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  /var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4

mp4split --package_mpd -o tears-of-steel-avc1-1500k-dash-cenc.cmfv \
  --iss.key=${KID2}:${CEK2} \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  /var/www/tears-of-steel/tears-of-steel-avc1-1500k.mp4

mp4split --package_mpd -o tears-of-steel-cenc.mpd \
  tears-of-steel-aac-128k-dash-cenc.cmfa \
  tears-of-steel-avc1-400k-dash-cenc.cmfv \
  tears-of-steel-avc1-1500k-dash-cenc.cmfv

Note

The above exercise only shows packaging DRM Streams, playout requires the set up of HTTPS which is outside the scope of this hands-on.

Footnotes

[1](1, 2) http://docs.unified-streaming.com/faqs/general/options.html
[2](1, 2) http://docs.unified-streaming.com/faqs/factsheet.html
[3]https://www.unified-streaming.com/blog/welcome-jungle-caption-and-subtitle-formats-video-streaming
[4]http://docs.unified-streaming.com/documentation/package/usage.html#option-status-codes
[5]https://github.com/Automattic/kue
[6]http://docs.unified-streaming.com/documentation/package/package.html#how-to-package-cmaf
[7]http://docs.unified-streaming.com/documentation/package/subtitles.html