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.
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, configuration, and playback
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
Apple iOS device (Cupertino/Apple HTTP Live Streaming):
http://[wowza-ip-address]:1935/live/amlst:myStream/playlist.m3u8
Microsoft Silverlight (Smooth Streaming):
http://[wowza-ip-address]:1935/live/amlst:myStream/Manifest
Adobe Flash player (San Jose/Flash HTTP):
http://[wowza-ip-address]:1935/live/amlst:myStream/manifest.f4m
It will return a multi-bitrate description with two renditions using the stream name as the base name for the filename. This is equivelent 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, configuration, and playback
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:
Apple iOS device (Cupertino/Apple HTTP Live Streaming):
http://[wowza-ip-address]:1935/vod/amlst:sample/playlist.m3u8
Microsoft Silverlight (Smooth Streaming):
http://[wowza-ip-address]:1935/vod/amlst:sample/Manifest
Adobe Flash player (San Jose/Flash HTTP):
http://[wowza-ip-address]:1935/vod/amlst:sample/manifest.f4m
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.