Create adaptive bitrate CMAF streams using Wowza Streaming Engine

Using Wowza Streaming Engine™ media server software version 4.7.8 and later, you can create adaptive bitrate (ABR) live streams using CMAF, the open, extensible standard that allows streams to be played over both the HLS and MPEG-DASH protocols. CMAF is disabled by default. CMAF live streams must be enabled manually, by editing an application's configuration in XML or by using the Wowza Streaming Engine REST API. We recommend editing an application's configuration in XML as described in this article.

Before you start


You should complete the following tasks:

Set up adaptive bitrate CMAF streaming


Adaptive bitrate CMAF live streaming requires multiple bitrate renditions of the stream that have been encoded from the same source and that have properly aligned keyframes. When setting up ABR CMAF live streaming, however:

  • You need to create a Synchronized Multimedia Integration Language (SMIL) text file manually. Currently, you can’t create the required SMIL configuration in Wowza Streaming Engine Manager. 
  • For HLS playback, NGRP syntax is not supported. 
  • For HLS playback, the SMIL file must include specific information that supports ABR CMAF.

The procedures in this section describe how to set up ABR CMAF live streaming. They assume that you are using an external encoder to create the following three bitrate renditions of a live stream:

  • myStream_160 (160 kbps total bitrate)
  • myStream_360 (360 kbps total bitrate)
  • myStream_720 (720 kbps total bitrate)

Note: Optionally, instead of using an external encoder to create multiple bitrate renditions, you can connect a single live stream to Wowza Streaming Engine and configure the Wowza Streaming Engine Transcoder to create the multiple bitrate renditions. 

Set up adaptive bitrate streaming for HLS

Using a text editor, create a SMIL file named myStream.smil in the [install-dir]/content folder with the content shown below. 

This example assumes all bitrate renditions have the same audio encoding. Thus, you only need to specify one entry for the audio. All video entries then refer to that one audio entry using a <param> element containing the attributes name="cupertinoTag.AUDIO" and a value="aac", and the audio entry needs to contain a <param> element containing the attributes name="cupertinoTag.GROUP-ID" and value="aac". The audio entry also requires a title attribute. Note that the specific value aac in this example can be replaced with any value.

<smil>
  <head></head>
  <body>
    <switch>
      <video src="myStream_160" title="English" audio-bitrate="100000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac" valuetype="data"/>
      </video>
      <video src="myStream_720" width="1280" height="720" video-bitrate="1300000">
        <param name="videoCodecId" value="avc1.77.32" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="myStream_360" width="640" height="360" video-bitrate="850000">
        <param name="videoCodecId" value="avc1.77.31" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="myStream_160" width="284" height="160" video-bitrate="200000">
        <param name="videoCodecId" value="avc1.66.21" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
    </switch>
  </body>
</smil>

When creating a SMIL file for HLS streaming, each audio entry must have the following information:

  • audio-bitrate attribute – Defines the audio bitrate to report in the master playlist.
  • title attribute - Determines the value of the name attribute in the EXT-X-MEDIA tag in the resulting master playlist. If there are multiple audio renditions, the player uses the title tag value to display information about the audio track. If no title attribute is included, a default value is set.
  • audioOnly parameter – Tells Wowza Streaming Engine to list audio as having a separate media playlist from the video media playlist.
  • cupertinoTag parameter – This is set to EXT-X-MEDIA and tells Wowza Streaming Engine how to enter the information in the playlist.
  • cupertinoTag.GROUP-ID parameter – Defines the group ID of the audio entry. For a video entry to be paired with this audio entry, the value of the video entry's cupertinoTag.AUDIO parameter must match this value.

Each video entry must have the following information:

  • video-bitrate attribute – Defines the video bitrate to report in the master playlist.
  • videoOnly parameter – Tells Wowza Streaming Engine to list video as having a separate media playlist from the audio media playlist (if any).
  • cupertinoTag.AUDIO parameter – When set to the same value as the cupertinoTag.GROUP-ID of an audio entry, specifies that the video entry can be paired with that audio entry. This parameter can be used to differentiate separate audio groups if needed.
  • The video track tag provides the information for the EXT-X-STREAM-INF section in the playlist so the audioCodecId paramter should be included in the video track tag instead of on the audio track tags.

For additional CMAF ABR SMIL file examples, see Appendix: Additional ABR CMAF SMIL file examples for HLS.

For details on the tags, attributes, and parameters used in SMIL file definitions, see Understanding SMIL file syntax.

Set up adaptive bitrate streaming for MPEG-DASH

Using a text editor, create a SMIL file named myStream.smil in the [install-dir]/content folder with the following content:

Note: You can also use the SMIL file that was created for HLS playback, because MPEG-DASH playback ignores the cupertinoTag* entries.

<?xml version="1.0" encoding="UTF-8"?>
<smil title="SMIL file for live streaming">
  <head></head>
  <body>
    <switch>
      <video src="myStream_720" height="720" src="myStream_720" systemLanguage="eng" width="1280">
        <param name="videoBitrate" value="1300000" valuetype="data"></param>
        <param name="audioBitrate" value="100000" valuetype="data"></param>
      </video>
      <video src="myStream_360" height="360" src="myStream_360" systemLanguage="eng" width="640">
        <param name="videoBitrate" value="850000" valuetype="data"></param>
        <param name="audioBitrate" value="100000" valuetype="data"></param>
      </video>
      <video src="myStream_160" height="160" src="myStream_160" systemLanguage="eng" width="284">
        <param name="videoBitrate" value="200000" valuetype="data"></param>
        <param name="audioBitrate" value="100000" valuetype="data"></param>
      </video>
    </switch>
  </body>
</smil>

You can see that there's a <video> element in the <switch> container for each stream rendition. This syntax includes all aspects of the stream with videoBitrate and audioBitrate specified as parameters.


Test stream playback

When the camera or encoder is connected and the live stream is active, preview CMAF playback using a supported test player.

Test CMAF HLS stream playback

To test CMAF-packetized HLS live streams generated by Wowza Streaming Engine, use the Akamai HLS test player.

If only cmafstreamingpacketizer is enabled, specify the stream playback URL using the format: 

http://[address]/[application-name]/[application-instance]/smil:[stream-name]/playlist.m3u8

If cmafstreamingpacketizer and cupertinostreamingpacketizer use the format:

http://[address]/[application-name]/[application-instance]/smil:[stream-name]/playlist_sfm4s.m3u8

Where:

  • [address] is the IP address or domain and port of Wowza Streaming Engine (default port 1935)
  • [application-name] is the application name
  • [application-instance] is the name of the application instance (if omitted, defaults to _definst_)
  • [stream-name] is the name of the SMIL file (for example: myStream.smil)

For example, the playlist URL for a CMAF HLS stream that uses the address example.com, an application named myApplication, and the default stream name myStream is:

http://example.com:1935/myApplication/smil:myStream.smil/playlist.m3u8

or

http://example.com:1935/myApplication/smil:myStream.smil/playlist_sfm4s.m3u8

Test CMAF MPEG-DASH stream playback

To test CMAF-packetized MPEG-DASH live streams generated by Wowza Streaming Engine, you can use the MPEG-DASH test player on the Video Test Players webpage, which is based on the Shaka Player library.

Note: Alternatively, you can test CMAF DASH playback using the Akamai DASH.js test player

  1. On the Video Test Players webpage, click the MPEG-DASH tab.
  2. Enter the CMAF DASH playback URL for your stream using the format:

http://[address]/[application-name]/[application-instance]/smil:[stream-name]/manifest.mpd

Where:

  • [address] is the IP address or domain and port of Wowza Streaming Engine (default port 1935)
  • [application-name] is the application name
  • [application-instance] is the name of the application instance (if omitted, defaults to _definst_)
  • [stream-nameis the the name of the SMIL file (for example: myStream.smil)

For example, the playback URL for an MPEG-DASH stream that uses the address example.com, an application named myApplication, and the default stream name myStream is: 

http://example.com:1935/myApplication/smil:myStream.smil/manifest.mpd 

  1. Click Start.

Appendix: Additional adaptive bitrate CMAF SMIL file examples for HLS


Two audio renditions and two video renditions (single pairings)

In this example, the cupertinoTag.AUDIO parameter and the cupertinoTag.GROUP-ID parameter pair the myStream_720 video (1280 x 720) points with the myStream_720 audio (128000 bitrate) and the myStream_160 video (284 x 160) points with the myStream_160 audio (96000 bitrate).  This tells the player to only play with those pairings.

<smil>
  <head></head>
  <body>
    <switch>
      <video src="myStream_720" title="English" audio-bitrate="128000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-128" valuetype="data"/>
      </video>
      <video src="myStream_160" title="Commentary" audio-bitrate="96000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-96" valuetype="data"/>
      </video>
      <video src="myStream_720" width="1280" height="720" video-bitrate="1300000">
        <param name="videoCodecId" value="avc1.77.32" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac-128" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="myStream_160" width="284" height="160" video-bitrate="200000">
         <param name="videoCodecId" value="avc1.66.21" valuetype="data"/>
         <param name="videoOnly" value="TRUE" valuetype="data"/>
         <param name="cupertinoTag.AUDIO" value="aac-96" valuetype="data"/>
         <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
    </switch>
  </body>
</smil>

Two audio renditions and two video renditions (multiple pairings)

This example shows two entries for both of the video renditions, pointing to each of the two audio renditions. This tells the player that it can pair either video with either audio.

<smil>
  <head></head>
  <body>
    <switch>
      <video src="myStream_720" title="English" audio-bitrate="128000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-128" valuetype="data"/>
      </video>
      <video src="myStream_160" title="Commentary" audio-bitrate="96000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-96" valuetype="data"/>
      </video>
      <video src="myStream_720" width="1280" height="720" video-bitrate="1300000">
        <param name="videoCodecId" value="avc1.77.32" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac-128" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="myStream_720" width="1280" height="720" video-bitrate="1300000">
        <param name="videoCodecId" value="avc1.77.32" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac-96" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="myStream_160" width="284" height="160" video-bitrate="200000">
        <param name="videoCodecId" value="avc1.66.21" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac-128" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="myStream_160" width="284" height="160" video-bitrate="200000">
        <param name="videoCodecId" value="avc1.66.21" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac-96" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
    </switch>
  </body>
</smil>

Four audio renditions and two video renditions (multiple language pairings)

This example shows how to use the cupertinoTag.DEFAULT parameter and the cupertinoTag.AUTOSELECT parameter when multiple audio entries share the same cupertinoTag.GROUP-ID value. In this example, the cupertinoTag.DEFAULT parameter is set to YES for the English version of each pair of audio entries that share the same cupterinoTag.GROUP-ID, indicating which audio entry is the default audio stream. The cupertinoTag.AUTOSELECT parameter and the system-language attribute tell the player to attempt to automatically determine which language to use.

<smil>
  <head></head>
  <body>
    <switch>
      <video src="eng_audio_aac128.stream" system-language="en" title="English" audio-bitrate="128000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-128" valuetype="data"/>
        <param name="cupertinoTag.DEFAULT" value="YES" valuetype="data"/>
        <param name="cupertinoTag.AUTOSELECT" value="YES" valuetype="data"/>
      </video>
      <video src="spa_audio_aac128.stream" system-language="es" title="Spanish" audio-bitrate="128000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-128" valuetype="data"/>
        <param name="cupertinoTag.DEFAULT" value="NO" valuetype="data"/>
        <param name="cupertinoTag.AUTOSELECT" value="YES" valuetype="data"/>
      </video>
      <video src="eng_audio_aac96" system-language="en" title="English" audio-bitrate="96000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-96" valuetype="data"/>
        <param name="cupertinoTag.DEFAULT" value="YES" valuetype="data"/>
        <param name="cupertinoTag.AUTOSELECT" value="YES" valuetype="data"/>
      </video>
      <video src="spa_audio_aac96" system-language="es" title="Spanish" audio-bitrate="96000">
        <param name="audioOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag" value="EXT-X-MEDIA" valuetype="data"/>
        <param name="cupertinoTag.GROUP-ID" value="aac-96" valuetype="data"/>
        <param name="cupertinoTag.DEFAULT" value="NO" valuetype="data"/>
        <param name="cupertinoTag.AUTOSELECT" value="YES" valuetype="data"/>
      </video>
      <video src="main_video_720p.stream" width="1280" height="720" video-bitrate="1300000">
        <param name="videoCodecId" value="avc1.77.32" valuetype="data"/>
        <param name="videoOnly" value="TRUE" valuetype="data"/>
        <param name="cupertinoTag.AUDIO" value="aac-128" valuetype="data"/>
        <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
      <video src="main_video_160p.stream" width="284" height="160" video-bitrate="200000">
         <param name="videoCodecId" value="avc1.66.21" valuetype="data"/>
         <param name="videoOnly" value="TRUE" valuetype="data"/>
         <param name="cupertinoTag.AUDIO" value="aac-96" valuetype="data"/>
         <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
      </video>
    </switch>
  </body>
</smil>

More resources