Packaging for MPEG-DASH

Unified Packager can generate fragmented MP4 audio/video and manifests required for MPEG-DASH streaming. We recommend packaging media as CMAF files, see: How to package CMAF, and then creating the media presentation description using the --package-mpd option. The following is a list of all options specific to MPEG-DASH packaging.

Note

Package MPEG-DASH compliant media files by either using --package-mpd or by specifying a CMAF file extension for the output (.cmfv, .cmfa or .cmft), but not both. Previously, we recommended packaging media as .mp4 files with --package-mpd option. This adds a fragment index as mfra to the end of a file. Going forward, we recommend using CMAF as output. CMAF files have a similar (but distinct) sidx index at the start of the file.

Packaging CMAF with the --package-mpd option (i.e. mp4split --package-mpd -o video.cmfv video.mp4) adds both sidx and mfra boxes. It is not recommended to package CMAF files this way (mfra is not used in ISO/IEC 23000-19).

In summary: use --package-mpd only to generate the Media Presentation Description (MPD).

Options for MPEG-DASH packaging

--package_mpd

Enable mp4split's MPEG-DASH packaging mode.

--fragment_duration

The duration of each fragment in milliseconds (e.g 8000) or as a fraction of seconds (e.g. 8000/1000, 192/24 or 8/1). Defaults to using the GOP size and if specified manually, it should be a multiple of the GOP size (if it is not, Packager will regard the specified duration as a minimum value).

--segment_list

List the all the segments in a SegmentList, instead of using SegmentBase.

MPEG-DASH profile

ISO BMFF On Demand

The default MPEG-DASH profile supported by Packager is the ISO Base media file format On Demand profile: urn:mpeg:dash:profile:isoff-on-demand:2011.

This is the most basic profile for On-Demand content and thus generates the best compatibility among DASH players and DASH capable devices.

The requirements imposed by this profile are:

  • A single segment for each representation (one audio or video track per file).

  • Subsegments are aligned across representations (GOP aligned fragments).

  • Subsegments must begin with a Stream Access Point (IDR/keyframe).

  • The segment is indexed using the Segment Index ('sidx').

In comparison to using a profile like urn:mpeg:dash:profile:isoff-live:2011 for statically packaged VOD, an important benefit of using the On Demand profile is that it does not segment the content on disk, but rather works with an MPD that specifies segments using byte ranges that point into a contiguous file. This leads to significantly less files and allows for better caching (if a cache preloads some byte range following the requested byte range).

ISO BMFF Main

When the above requirements are not met (for instance when having audio and video in one file), Packager switches to the Main profile: urn:mpeg:dash:profile:isoff-main:2011.

Note that not all DASH players support this profile.

ISO BMFF Live

New in version 1.10.5.

Both the On Demand and Main profile described above rely on HTTP byte range requests to work efficiently. For players or CDNs that do not support byte ranges, Packager can generate index-based media segment files alongside an MPD that uses a SegmentTemplate, as defined by the DASH Live profile urn:mpeg:dash:profile:isoff-live:2011.

When statically packaging DASH according to the Live profile, creating the MPD and packaging the content is done in only one step (instead of packaging the content in a separate step, before creating the MPD). In this one step, the media segments are written to the same directory as the MPD. Therefore, it is recommended to use an empty directory for the output.

To statically package DASH according to the Live profile, enable the package_mpd functionality, use your source content as input, specify an .mpd-file as output and use the mpd.profile option to specify urn:mpeg:dash:profile:isoff-live:2011:

#!/bin/bash

mkdir out
mp4split --package_mpd \
         -o out/presentation.mpd \
         --fragment_duration=8/1 \
         --mpd.profile="urn:mpeg:dash:profile:isoff-live:2011" \
         tears-of-steel-aac-128k.mp4 \
         tears-of-steel-avc1-400k.mp4

Note

When statically packaging content with Packager, the sole purpose of using the mpd.profile option is to enable packaging of DASH according to the Live profile. If you specify any other profile it will be ignored.

Creating the media files

First we have to package the audio and video tracks so that it fulfills the requirements listed above:

#!/bin/bash

mp4split -o tos-aac-128k-dash.cmfa   tears-of-steel-aac-128k.mp4
mp4split -o tos-avc1-1000k-dash.cmfv tears-of-steel-avc1-1000k.mp4
mp4split -o tos-avc1-400k-dash.cmfv  tears-of-steel-avc1-400k.mp4

Creating the media files with Common Encryption

Besides preparing content in-the-clear, you can use Common Encryption for the audio and video files. You can use either the DRM system specific command-line options that are available, or make use of CPIX. General info on CPIX can be found in our Content Protection Information eXchange (CPIX) documentation, and how to use if for static packaging is documented in Multi-DRM protected HLS and DASH from a shared CMAF source. Below you will find examples that demonstrate how to use the DRM system specific command-line options for DASH.

Note

In case your input is pre-encrypted, Packager and Origin will pick up on any DRM signaling present in the input and automatically pass it through in the output they generate. This means that for any DRM system for which signaling is present in the input, you do not need to specify DRM configuration options when preparing your stream. However, do note that there are DRM systems for which such signaling can't be present by design, like FairPlay, because signaling for these systems is never stored in the media. This means that to support such DRM systems, you will always need to add the necessary DRM configuration options.

Using 'cenc' Common Encryption

The following example encrypts the files with a single pair of Key ID (KID) and Content Encryption Key (CEK), using the 'cenc' scheme from the Common Encryption specification (i.e., 'CTR' or Counter mode). This encryption scheme is the default.

In this case, the signaling of the content protection is different depending on the DRM systems used. PlayReady signaling requires the License Acquisition URL (LAURL), while Widevine requires the Protection System Specific Header (PSSH) as drm_specific_data.

See also Common Encryption (CENC).

#!/bin/bash

KID=10000000100010001000100000000001
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
KID_UUID=10000000-1000-1000-1000-100000000001 #UUID representation of KID
CEK_B64="OiobaN0r2bLusl6ExHdmaA==" #Base64 byte array representation of CEK
LAURL="https://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(kid:${KID_UUID},contentkey:${CEK_B64},ckt:aesctr)"

PSSH=YOUR_PSSH #Add your Widevine DRM specific PSSH data

mp4split -o tos-aac-128k-dash-cenc.cmfa  \
  --iss.key=${KID}:${CEK} --iss.license_server_url=${LAURL} \
  --widevine.key=${KID}:${CEK} --widevine.drm_specific_data=${PSSH} \
  tears-of-steel-aac-128k.mp4

mp4split -o tos-avc1-400k-dash-cenc.cmfv \
  --iss.key=${KID}:${CEK} --iss.license_server_url=${LAURL} \
  --widevine.key=${KID}:${CEK} --widevine.drm_specific_data=${PSSH} \
  tears-of-steel-avc1-400k.mp4

mp4split -o tos-avc1-1000k-dash-cenc.cmfv \
  --iss.key=${KID}:${CEK} --iss.license_server_url=${LAURL} \
  --widevine.key=${KID}:${CEK} --widevine.drm_specific_data=${PSSH} \
  tears-of-steel-avc1-1000k.mp4

Using 'cbcs' Common Encryption

The following example encrypts the files with a single pair of Key ID (KID) and Content Encryption Key (CEK), using the 'cbcs' scheme from the Common Encryption specification (i.e., Cipher Block Chaining mode). This encryption scheme is specified using --scheme_type=cbcs.

In this case, the full Protection System Specific Header (PSSH) box must be added for each of the DRM systems that you want to use (except Marlin, which doesn't require such signaling):

#!/bin/bash

KID=10000000100010001000100000000001
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668

PR_PSSH=<PLAYREADY_PSSH> #Add your PlayReady DRM specific PSSH box
WV_PSSH=<WIDEVINE_PSSH> #Add your Widevine DRM specific PSSH box

mp4split -o tos-aac-128k-dash-cenc.cmfa  \
  --cenc.key=${KID}:${CEK} \
  --scheme_type=cbcs \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  tears-of-steel-aac-128k.mp4

mp4split -o tos-avc1-400k-dash-cenc.cmfv \
  --cenc.key=${KID}:${CEK} \
  --scheme_type=cbcs \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  tears-of-steel-avc1-400k.mp4

mp4split -o tos-avc1-1000k-dash-cenc.cmfv \
  --cenc.key=${KID}:${CEK} \
  --scheme_type=cbcs \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  tears-of-steel-avc1-1000k.mp4

Creating the Media Presentation Description file (.mpd)

After the content is properly packaged, step two is creating the Media Presentation Description (MPD) with the packaged media files as input:

#!/bin/bash

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

If the media is encrypted, content protection signaling is automatically added to the MPD using the protection information stored in the media files. When PlayReady and/or Widevine information is present, these schemes are added to the MPD. Marlin has no explicit signaling in the media files, and is always added to the MPD:

#!/bin/bash

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

Please download the mpeg-dash-cenc.sh sample script that creates the various server manifest as discussed above. The sample content is Tears of Steel.

Adding WebVTT or TTML subtitles

To add subtitles when statically packaging MPEG-DASH, you must first make sure that for each subtitles track you have packaged the WebVTT, SRT or TTML formatted source files in fMP4 (.ismt or .cmft), as explained in Packaging Subtitles.

When you have packaged your subtitles in fMP4, you simply add each fMP4 that contains a subtitles track that you want to add to your input when creating the MPEG-DASH client manifest (.mpd):

#!/bin/bash

mp4split -o tos-wvtt-en.cmft \
  tears-of-steel-en.srt --track_language=eng

mp4split --package_mpd -o tears-of-steel.mpd \
  tos-aac-128k-dash.cmfa \
  tos-avc1-400k-dash.cmfv \
  tos-avc1-1000k-dash.cmfv \
  tos-wvtt-en.cmft

Adding TTML or WebVTT sidecar subtitles for MPEG-DASH

New in version 1.7.12.

While fragmented MP4 is the format of choice for streaming subtitles, occasionally it may be desirable or necessary to expose raw unsegmented subtitles to the player. In these cases, a WebVTT or TTML sidecar file can be added to the MPD.

For instance, the following commands adds German subtitles as WebVTT:

#!/bin/bash

mp4split --package-mpd -o movie.mpd \
  [audio/video] \
  subtitles_deu.webvtt --track_language=ger

This adds an adaptation set with mime type text/vtt (or application/ttml+xml for TTML):

<AdaptationSet contentType="text" lang="de" mimeType="text/vtt">
  <Representation id="textstream_ger=0" bandwidth="0">
     <BaseURL>subtitles_deu.webvtt</BaseURL>
  </Representation>
</AdaptationSet>

Important

When you add sidecar subtitles, they are added as-is. That is, mp4split won't addd any metadata from the file. This means that metadata that is of importance for the file should be passed on the command-line (like the track's language, for example).

Dolby Vision Support

New in version 1.7.18.

Packaging MPEG-DASH with Dolby Vision Profile 5, aka Single Layer Non Backwards Compatible (NBC) is supported.

First take the input files containing Dolby Vision NBC to create a fragmented MP4. Then use the fragmented mp4 output to create an MPD:

#!/bin/bash

mp4split -o video-with-dolby-vision.cmfv \
  video-with-dolby-vision.mp4

mp4split --package_mpd -o video.mpd \
  video-with-dolby-vision.cmfv \
  example-audio.cmfa

Playback

Playback is supported by at least the following sample players:

See Which devices support DASH playback? and Which browsers support DASH playback? for more information.

Javascript / HTML5 based players

The Cross-Origin Resource Sharing (CORS) HTTP headers are necessary when the (javascript) player and content are hosted on different domains.

The are set like the following in the (Apache) virtual host configuration:

# Necessary for Media Source Extensions (MSE)
Header always set Access-Control-Allow-Headers "origin, range"
Header always set Access-Control-Allow-Methods "GET, HEAD, OPTIONS"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Expose-Headers "Server,range"

Action Script / Flash based players

For Action Script (Flash) based players the webserver needs to be setup to support Byte-Range requests through a query parameter. This is achieved by rewriting the byte range in the query parameter to the appropriate Range HTTP header in the request. The dash.as player appends '?bytes=' and the dash.js player appends '?range=' to the URL. The two rewrite rules are given in the configuration below.

  <IfModule headers_module>
    <IfModule rewrite_module>
      # dash.as
      # ^(.*) if .htaccess in a root; ^/(.*) otherwise
      RewriteEngine On
      RewriteCond %{QUERY_STRING} ^(.*)bytes=(.*)$
      RewriteRule ^(.*) - [L,E=range:%2]
      RequestHeader set Range "bytes=%{range}e" env=range

      # dash.js
      # ^(.*) if .htaccess in a root; ^/(.*) otherwise
      RewriteEngine On
      RewriteCond %{QUERY_STRING} ^(.*)range=(.*)$
      RewriteRule ^(.*) - [L,E=range:%2]
      RequestHeader set Range "bytes=%{range}e" env=range
  </IfModule>
</IfModule>

Important

When prepackaging files for MPEG-DASH playout, please make sure that the MP4 files are hosted on a location that doesn't have a running Unified Origin handling the MP4 files. Otherwise the progressive MP4 download feature will take over and it'll reformat the prepackaged MP4 files to progressive MP4 instead. This may prevent playout and cause SIDX errors to be displayed by the player.

Advanced recipes

Tuning Common Encryption

--disable_selective_nal_encryption

For NAL structured video samples, only video data in slice NALs should be encrypted with other NAL types kept in the clear.

Specifying this option overrides the (selective) encryption and encrypts all NAL units with a fixed number of bytes in the clear.