SMIL files are used in Wowza Streaming Engine™ to describe multi-bitrate streams, both live and video-on-demand. You can use the Wowza Streaming Engine Java API to intercept requests for multi-bitrate streams and provide the stream grouping. To use this feature, you must use the stream name prefix amlst: (which stands for API-based MediaList). A MediaList is a set of Java objects that describe a multi-bitrate stream. When Wowza Streaming Engine reads a SMIL file, it creates a MediaList and passes it back to the streaming provider. The Java API provides a means to intercept these requests and create the MediaList dynamically in a Wowza Streaming Engine module.
Each ApplicationInstance has a IMediaListProvider provider interface. This interface is used to resolve stream names that are prefixed with the amlst: prefix to MediaList objects. In a module you can create your own IMediaListProvider implementation and replace the default implementation.
Note: For examples of intercepting requests for multi-bitrate streams that include captions, see Resolve SMIL file requests with captions with the Wowza Streaming Engine Java API.
MediaList object structure
A MediaList has the following object structure:
MediaList
|
--MediaListSegment
|
--MediaListRendition
[...]
A MediaList has a single MediaListSegment. The MediaListSegement can have multiple MediaListRenditions each representing a single multi-bitrate rendition.
Live streaming sample module
Here is a sample module that implements this interface for live streaming:
package com.wowza.wms.plugin.test.module;
import com.wowza.wms.medialist.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.application.*;
public class ModuleAMLSTTestLive extends ModuleBase
{
class MyMediaListProvider implements IMediaListProvider
{
public MediaList resolveMediaList(IMediaListReader mediaListReader, IMediaStream stream, String streamName)
{
MediaList mediaList = new MediaList();
MediaListSegment segment = new MediaListSegment();
mediaList.addSegment(segment);
MediaListRendition rendition1 = new MediaListRendition();
segment.addRendition(rendition1);
rendition1.setName(streamName+"_400");
rendition1.setBitrateAudio(128000);
rendition1.setBitrateVideo(400000);
rendition1.setWidth(320);
rendition1.setHeight(240);
rendition1.setAudioCodecId("mp4a.40.2");
rendition1.setVideoCodecId("avc1.66.12");
MediaListRendition rendition2 = new MediaListRendition();
segment.addRendition(rendition2);
rendition2.setName(streamName+"_800");
rendition2.setBitrateAudio(128000);
rendition2.setBitrateVideo(800000);
rendition2.setWidth(640);
rendition2.setHeight(480);
rendition2.setAudioCodecId("mp4a.40.2");
rendition2.setVideoCodecId("avc1.77.31");
return mediaList;
}
}
public void onAppStart(IApplicationInstance appInstance)
{
appInstance.setMediaListProvider(new MyMediaListProvider());
}
}
Add this module as the last entry in the <Modules> list in [install-dir]/conf/[application]/Application.xml:
<Module> <Name>ModuleAMLSTTestLive</Name> <Description>ModuleAMLSTTestLive</Description> <Class>com.wowza.wms.plugin.test.module.ModuleAMLSTTestLive</Class> </Module>
Quickly looking at the components of this module:
- Module extends the ModuleBase
- Internal class MyMediaListProvider implements the IMediaListProvider interface and returns a new MediaList based on the stream name.
- The onAppStart method is used to replace the application instance level IMediaListProvider with our implementation.
This module will intercept any request for stream names that start with amlst: such as
http://[wowza-ip-address]:1935/[application-name]/amlst:myStream/playlist.m3u8
It will return a multi-bitrate description with two renditions using the stream name as the base name for the filename. This is equivalent to the SMIL file:
<smil> <head> </head> <body> <switch> <video src="myStream_400" width="320" height="240" system-bitrate="528000"> <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/> <param name="videoCodecId" value="avc1.66.12" valuetype="data"/> <param name="audioBitrate" value="128000" valuetype="data"/> <param name="videoBitrate" value="400000" valuetype="data"/> </video> <video src="myStream_800" width="640" height="480" system-bitrate="928000"> <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/> <param name="videoCodecId" value="avc1.77.31" valuetype="data"/> <param name="audioBitrate" value="128000" valuetype="data"/> <param name="videoBitrate" value="800000" valuetype="data"/> </video> </switch> </body> </smil>
Video-on-demand streaming sample module
Here is a sample module that implements this interface for VOD streaming::
package com.wowza.wms.plugin.test.module;
import com.wowza.wms.medialist.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.application.*;
public class ModuleAMLSTTest extends ModuleBase
{
class MyMediaListProvider implements IMediaListProvider
{
public MediaList resolveMediaList(IMediaListReader mediaListReader, IMediaStream stream, String streamName)
{
MediaList mediaList = new MediaList();
MediaListSegment segment = new MediaListSegment();
mediaList.addSegment(segment);
MediaListRendition rendition1 = new MediaListRendition();
segment.addRendition(rendition1);
rendition1.setName("mp4:"+streamName+"_400k.mp4");
rendition1.setBitrateAudio(128000);
rendition1.setBitrateVideo(400000);
rendition1.setWidth(320);
rendition1.setHeight(240);
rendition1.setAudioCodecId("mp4a.40.2");
rendition1.setVideoCodecId("avc1.66.12");
MediaListRendition rendition2 = new MediaListRendition();
segment.addRendition(rendition2);
rendition2.setName("mp4:"+streamName+"_800k.mp4");
rendition2.setBitrateAudio(128000);
rendition2.setBitrateVideo(800000);
rendition2.setWidth(640);
rendition2.setHeight(480);
rendition2.setAudioCodecId("mp4a.40.2");
rendition2.setVideoCodecId("avc1.77.31");
return mediaList;
}
}
public void onAppStart(IApplicationInstance appInstance)
{
appInstance.setMediaListProvider(new MyMediaListProvider());
}
}
Add this module as the last entry in the <Modules> list in [install-dir]/conf/[application]/Application.xml:
<Module> <Name>ModuleAMLSTTest</Name> <Description>ModuleAMLSTTest</Description> <Class>com.wowza.wms.plugin.test.module.ModuleAMLSTTest</Class> </Module>
These are the components of this module:
- Module extends the ModuleBase
- Internal class MyMediaListProvider implements the IMediaListProvider interface and returns a new MediaList based on the stream name.
- The onAppStart method is used to replace the application instance level IMediaListProvider with our implementation.
This module will intercept any request for stream names that start with amlst: such as:
http://[wowza-ip-address]:1935/[application-name]/amlst:sample/playlist.m3u8
It will return a multi-bitrate description with two renditions using the stream name as the base name for the filename. This is equivalent to the SMIL file:
<smil> <head> </head> <body> <switch> <video src="mp4:sample_400.mp4" width="320" height="240" system-bitrate="528000"> <param name="videoCodecId" value="avc1.66.12" valuetype="data"/> <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/> <param name="audioBitrate" value="128000" valuetype="data"/> <param name="videoBitrate" value="400000" valuetype="data"/> </video> <video src="mp4:sample_800.mp4" width="640" height="480" system-bitrate="928000"> <param name="videoCodecId" value="avc1.77.31" valuetype="data"/> <param name="audioCodecId" value="mp4a.40.2" valuetype="data"/> <param name="audioBitrate" value="128000" valuetype="data"/> <param name="videoBitrate" value="800000" valuetype="data"/> </video> </switch> </body> </smil>
Note: The IMediaListReader interface does provide additional context information such as the IHTTPStreamerSession from which the stream is being requested.
Low-Latency HLS live streaming sample module
Here is a sample module that implements this interface for Low-Latency HLS live streaming:
package com.wowza.wms.plugin.test.module;
import com.wowza.wms.medialist.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.application.*;
public class CmafAmlst extends ModuleBase
{
class CmafAmlstProvider implements IMediaListProvider
{
public MediaList resolveMediaList(IMediaListReader mediaListReader, IMediaStream stream, String streamName)
{
MediaList mediaList = new MediaList();
MediaListSegment segment = new MediaListSegment();
mediaList.addSegment(segment);
MediaListRendition rendition1 = new MediaListRendition();
segment.addRendition(rendition1);
rendition1.setName(streamName+"_160p");
rendition1.setBitrateAudio(100000);
rendition1.setWowzaAudioOnly(true);
rendition1.setTitle("English");
rendition1.setLanguage("eng");
WMSProperties props1 = rendition1.getProperties(true);
props1.setProperty("cupertinoTag", "EXT-X-MEDIA");
props1.setProperty("cupertinoTag.GROUP-ID", "aac");
props1.setProperty("cupertinoTag.DEFAULT", "FALSE");
props1.setProperty("cupertinoTag.AUTOSELECT", "YES");
MediaListRendition rendition2 = new MediaListRendition();
segment.addRendition(rendition2);
rendition2.setName(streamName+"_source");
rendition2.setBitrateVideo(1300000);
rendition2.setWidth(960);
rendition2.setHeight(540);
rendition2.setAudioCodecId("mp4a.40.2");
rendition2.setVideoCodecId("avc1.77.32");
rendition2.setWowzaVideoOnly(true);
WMSProperties props2 = rendition2.getProperties(true);
props2.setProperty("cupertinoTag.AUDIO", "aac");
MediaListRendition rendition3 = new MediaListRendition();
segment.addRendition(rendition3);
rendition3.setName(streamName+"_360p");
rendition3.setBitrateVideo(850000);
rendition3.setWidth(640);
rendition3.setHeight(360);
rendition3.setAudioCodecId("mp4a.40.2");
rendition3.setVideoCodecId("avc1.77.31");
rendition3.setWowzaVideoOnly(true);
WMSProperties props3 = rendition3.getProperties(true);
props3.setProperty("cupertinoTag.AUDIO", "aac");
MediaListRendition rendition4 = new MediaListRendition();
segment.addRendition(rendition4);
rendition4.setName(streamName+"_160p");
rendition4.setBitrateVideo(200000);
rendition4.setWidth(284);
rendition4.setHeight(160);
rendition4.setAudioCodecId("mp4a.40.2");
rendition4.setVideoCodecId("avc1.66.21");
rendition4.setWowzaVideoOnly(true);
WMSProperties props4 = rendition4.getProperties(true);
props4.setProperty("cupertinoTag.AUDIO", "aac");
return mediaList;
}
}
public void onAppStart(IApplicationInstance appInstance)
{
appInstance.setMediaListProvider(new CmafAmlstProvider());
}
}
Note: SMIL files for Low-Latency HLS streaming require specific attributes and parameters. For more information, see Create adaptive bitrate CMAF streams using Wowza Streaming Engine.
Add this module as the last entry in the <Modules> list in [install-dir]/conf/[application]/Application.xml:
<Module> <Name>CmafAmlst</Name> <Description>CmafAmlst</Description> <Class>com.wowza.wms.plugin.test.module.CmafAmlst</Class> </Module>
Quickly looking at the components of this module:
- Module extends the ModuleBase
- Internal class CmafAmlstProvider implements the IMediaListProvider interface and returns a new MediaList based on the stream name.
- The onAppStart method is used to replace the application instance level IMediaListProvider with our implementation.
This module will intercept any request for stream names that start with amlst: such as
http://[wowza-ip-address]:1935/[application-name]/amlst:myStream/playlist.m3u8
It will return a multi-bitrate description with three video renditions and one audio rendition using the stream name as the base name for the filename. This is equivalent to the SMIL file:
<smil>
<head>
</head>
<body>
<switch>
<video src="mp4:myStream_160p" system-language="en" 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"/>
<param name="cupertinoTag.DEFAULT" value="YES" valuetype="data"/>
<param name="cupertinoTag.AUTOSELECT" value="YES" valuetype="data"/>
</video>
<video src="mp4:myStream_source" width="960" height="540" 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="mp4:myStream_360p" 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="mp4:myStream_160p" 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>




