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.

Configure a live application to deliver CMAF streams


You can use the default live application that installs with Wowza Streaming Engine, or create and use a custom live application.

(Optional) Create a custom live application

Although all of the new files and folders must be in place for your custom live application, to enable CMAF live streaming, all you'll need to edit is the application's XML configuration file.

Configure the live application's setup in XML

  1. Navigate to [install-dir]/conf/live or [install-dir]/conf/[custom live application] and open Application.xml file in a text editor.
  2. In the <Streams> container element, make sure the StreamType property is live. The XML looks like this:
<Streams>
    ...
    <StreamType>live</StreamType>
    ...
</Streams>
  1. Add cmafstreamingpacketizer to the LiveStreamPacketizers property. You can add it to the prepopulated comma-separated list, or it can be the only packetizer specified. For a workflow that only delivers only CMAF streams, the XML looks like this:
<Streams>
    ...
    <LiveStreamPacketizers>cmafstreamingpacketizer</LiveStreamPacketizers>
    ...
</Streams>
  1. For the HTTPStreamers property, make sure both HLS (cupertinostreaming) and MPEG-DASH (mpegdashstreaming) are specified. The XML looks like this:
<HTTPStreamers>cupertinostreaming, mpegdashstreaming</HTTPStreamers>
  1. Save your changes.

Your live application is configured to deliver CMAF streams to players. If desired, you can edit the packetization properties. For information, see Configure CMAF packetization in Wowza Streaming Engine. Otherwise, set up adaptive bitrate CMAF streaming.

Note: If you enable cupertinostreamingpacketizer and cmafstreamingpacketizer, Wowza Streaming Engine generates both MPEG-TS segments (using cupertinostreamingpacketizer) and fMP4 segments (using cmafstreamingpacketizer).

Enabling mepgdashstreamingpacketizer and cmafstreamingpacketizer is valid but redundant, as both create fMP4 segments. If both are defined in Application.xml, Wowza Streaming Engine ignores mepgdashstreamingpacketizer and produces one set of fMP4 segments using cmafstreamingpacketizer.

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 Apple HLS playback, NGRP syntax is not supported. 
  • For Apple 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 Apple 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". Note that the specific value aac in this example can be replaced with any value.

<smil>
  <head></head>
  <body>
    <switch>
      <video src="myStream_160" 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 Apple HLS streaming, each audio entry must have the following information:

  • audio-bitrate attribute – Defines the audio bitrate to report in the master playlist.
  • 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 Additional ABR CMAF SMIL file examples for Apple HLS.

For details on the tags, attributes, and parameters used in SMIL file definitions, see Appendix: 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.

Connect a live source to Wowza Streaming Engine


After your live application is configured to deliver CMAF streams, complete the stream setup by connecting a source encoder or IP camera to Wowza Streaming Engine and publishing the live source stream to the server. Although you enabled CMAF packetization in the Application.xml configuration file, your live application is available in Wowza Streaming Engine Manager, where you can establish a connection to a live source.

  1. In Wowza Streaming Engine Manager, click Applications in the menu bar and select your live application in the contents panel.
  2. Click Sources (Live) in the contents panel.
  3. Select the encoder or camera you want to use as your source. Click Learn more under any tile for detailed instructions on how to connect that encoder or camera, including how to configure source authentication.

If your encoder or camera isn't listed, click Other Encoders or use the Application Connection Settings in the Help panel to publish the stream to Wowza Streaming Engine. For more information about how to enter the connection settings in your source encoder or camera, consult that device or software's documentation. These articles may also help:

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

Test stream playback


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" 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" 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" 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" 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