I am evaluating the Wowza server for our OTT service. We would like to use the Wowza server to transcode our source video into multiple .mp4 files, each with a different video profile and bit rate. We also need to transcode the source video into HLS chunks, also at multiple profiles and bit rates for ABR streaming over HLS.
Our video is not live but is pre-encoded into .mov files and stored in the content directory (at least that’s where we’re storing it for our evaluation purposes).
My problem is that I cannot work out how to make the Wowza server generate and deliver the HLS streams. I have followed the QuickStart guide and the AddOn_UserGuide to set up my application, but making any request for a HLS stream creates a “MediaList is empty” error on the server.
Here are the various details:
Running on CentOS, linux 2.6.32-279.el6.x86_64
INFO server server-start Wowza Media Server 3 Trial Edition (Expires: Nov 22, 2013) 3.6.2 build5334 -
INFO server comment - Server License Key: SVRT3-XXXXX-XXXXX-XXXXX-XXXXX-pFTcf
INFO server comment - Maximum Connections: Unlimited
INFO server comment - Transcoder Streams Available: Unlimited
INFO server comment - Transcoder Watermark: Yes
INFO server comment - nDVR Available: Yes
INFO server comment - DRM Available: Yes
INFO server comment - Hardware Available Processors: 12
INFO server comment - Hardware Physical Memory: 61173MB/64378MB
INFO server comment - Hardware Swap Space: 32255MB/32255MB
INFO server comment - Max File Descriptor Count: 20000
INFO server comment - Open File Descriptor Count: 51
INFO server comment - OS Name: Linux
INFO server comment - OS Version: 2.6.32-279.el6.x86_64
INFO server comment - OS Architecture: amd64
INFO server comment - Java Name: OpenJDK 64-Bit Server VM
INFO server comment - Java Vendor: Oracle Corporation
INFO server comment - Java Version: 1.7.0_45
INFO server comment - Java VM Version: 24.45-b08
INFO server comment - Java Spec Version: 1.7
INFO server comment - Java Home: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.45.x86_64/jre
INFO server comment - Java Max Heap Size: 1067MB
INFO server comment - Java Architecture: 64
INFO server comment - Java Locale[user.language]: en
INFO server comment - Java Locale[user.country]: US
INFO server comment - Java Locale[file.encoding]: UTF-8
INFO server comment - Java Timezone[user.timezone]: GMT-08:00
INFO server comment - Java Args[0]: -Xmx1200M
INFO server comment - Java Args[1]: -Djava.net.preferIPv4Stack=true
INFO server comment - Java Args[2]: -Dcom.sun.management.jmxremote=true
INFO server comment - Java Args[3]: -Dcom.wowza.wms.runmode=standalone
INFO server comment - Java Args[4]: -Dcom.wowza.wms.native.base=linux
INFO server comment - Java Args[5]: -Dcom.wowza.wms.AppHome=/usr/local/WowzaMediaServer
INFO server comment - Java Args[6]: -Dcom.wowza.wms.ConfigURL=
INFO server comment - Java Args[7]: -Dcom.wowza.wms.ConfigHome=/usr/local/WowzaMediaServer
INFO server comment - Server runmode: standalone
INFO server comment - Server native.platform: linux
INFO server comment - Server threads[h/t]: 10/10
INFO server comment - CMDInterface now listening: [any]:8083
INFO vhost vhost-start _defaultVHost_ -
INFO server comment - _defaultVHost_ threads[h/t]:120/80 home:/usr/local/WowzaMediaServer
INFO vhost comment _defaultVHost_ Bind attempt ([any]:1935:4)
INFO vhost comment _defaultVHost_ Bind successful ([any]:1935)
INFO vhost comment _defaultVHost_ Bind attempt ([any]:8086:1)
INFO vhost comment _defaultVHost_ Bind successful ([any]:8086)
INFO server comment - Server.startShutdownHook: Start server shutdown hook
INFO server comment - Wowza Media Server is started!
conf/p/Application.xml: Enabled Streams/StreamType = live, Transcoder/LiveStreamTranscoder = transcoder,
HTTPStreamers = cupertinostreaming, Transcoder/Templates = p.xml, Streams/LiveStreamPacketizers = cupertinostreamingpacketizer
<Root>
<Application>
<!-- Uncomment to set application level timeout values
<ApplicationTimeout>60000</ApplicationTimeout>
<PingTimeout>12000</PingTimeout>
<ValidationFrequency>8000</ValidationFrequency>
<MaximumPendingWriteBytes>0</MaximumPendingWriteBytes>
<MaximumSetBufferTime>60000</MaximumSetBufferTime>
<MaximumStorageDirDepth>25</MaximumStorageDirDepth>
-->
<Connections>
<AutoAccept>true</AutoAccept>
<AllowDomains></AllowDomains>
</Connections>
<!--
StorageDir path variables
${com.wowza.wms.AppHome} - Application home directory
${com.wowza.wms.ConfigHome} - Configuration home directory
${com.wowza.wms.context.VHost} - Virtual host name
${com.wowza.wms.context.VHostConfigHome} - Virtual host config directory
${com.wowza.wms.context.Application} - Application name
${com.wowza.wms.context.ApplicationInstance} - Application instance name
-->
<Streams>
<StreamType>live</StreamType>
<StorageDir>${com.wowza.wms.context.VHostConfigHome}/content</StorageDir>
<KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir>
<!-- LiveStreamPacketizers (separate with commas): cupertinostreamingpacketizer, smoothstreamingpacketizer, sanjosestreamingpacketizer, mpegdashstreamingpacketizer, cupertinostreamingrepeater, smoothstreamingrepeater, sanjosestreamingrepeater, dvrstreamingpacketizer, dvrstreamingrepeater -->
<LiveStreamPacketizers>cupertinostreamingpacketizer</LiveStreamPacketizers>
<!-- Properties defined here will override any properties defined in conf/Streams.xml for any streams types loaded by this application -->
<Properties>
</Properties>
</Streams>
<Transcoder>
<!-- To turn on transcoder set to: transcoder -->
<LiveStreamTranscoder>transcoder</LiveStreamTranscoder>
<!-- [templatename].xml or ${SourceStreamName}.xml -->
<Templates>p.xml</Templates>
<ProfileDir>${com.wowza.wms.context.VHostConfigHome}/transcoder/profiles</ProfileDir>
<TemplateDir>${com.wowza.wms.context.VHostConfigHome}/transcoder/templates</TemplateDir>
<Properties>
</Properties>
</Transcoder>
<DVR>
<!-- As a single server or as an origin, use dvrstreamingpacketizer in LiveStreamPacketizers above -->
<!-- Or, in an origin-edge configuration, edges use dvrstreamingrepeater in LiveStreamPacketizers above -->
<!-- As an origin, also add dvrchunkstreaming to HTTPStreamers below -->
<!-- If this is a dvrstreamingrepeater, define Application/Repeater/OriginURL to point back to the origin -->
<!-- To turn on DVR recording set Recorders to dvrrecorder. This works with dvrstreamingpacketizer -->
<Recorders></Recorders>
<!-- As a single server or as an origin, set the Store to dvrfilestorage-->
<!-- edges should have this empty -->
<Store></Store>
<!-- Window Duration is length of live DVR window in seconds. 0 means the window is never trimmed. -->
<WindowDuration>0</WindowDuration>
<!-- Storage Directory is top level location where dvr is stored. e.g. c:/temp/dvr -->
<StorageDir>${com.wowza.wms.context.VHostConfigHome}/dvr</StorageDir>
<!-- valid ArchiveStrategy values are append, version, delete -->
<ArchiveStrategy>append</ArchiveStrategy>
<!-- Properties for DVR -->
<Properties>
</Properties>
</DVR>
<TimedText>
<!-- VOD caption providers (separate with commas): vodcaptionprovidermp4_3gpp, vodcaptionproviderttml, vodcaptionproviderwebvtt, vodcaptionprovidersrt, vodcaptionproviderscc -->
<VODTimedTextProviders>vodcaptionprovidermp4_3gpp</VODTimedTextProviders>
<!-- Properties for TimedText -->
<Properties>
</Properties>
</TimedText>
<!-- HTTPStreamers (separate with commas): cupertinostreaming, smoothstreaming, sanjosestreaming, mpegdashstreaming, dvrchunkstreaming -->
<HTTPStreamers>cupertinostreaming</HTTPStreamers>
<SharedObjects>
<StorageDir></StorageDir>
</SharedObjects>
<Client>
<IdleFrequency>-1</IdleFrequency>
<Access>
<StreamReadAccess>*</StreamReadAccess>
<StreamWriteAccess>*</StreamWriteAccess>
<StreamAudioSampleAccess></StreamAudioSampleAccess>
<StreamVideoSampleAccess></StreamVideoSampleAccess>
<SharedObjectReadAccess>*</SharedObjectReadAccess>
<SharedObjectWriteAccess>*</SharedObjectWriteAccess>
</Access>
</Client>
<RTP>
<!-- RTP/Authentication/[type]Methods defined in Authentication.xml. Default setup includes; none, basic, digest -->
<Authentication>
<PublishMethod>digest</PublishMethod>
<PlayMethod>none</PlayMethod>
</Authentication>
<!-- RTP/AVSyncMethod. Valid values are: senderreport, systemclock, rtptimecode -->
<AVSyncMethod>senderreport</AVSyncMethod>
<MaxRTCPWaitTime>12000</MaxRTCPWaitTime>
<IdleFrequency>75</IdleFrequency>
<RTSPSessionTimeout>90000</RTSPSessionTimeout>
<RTSPMaximumPendingWriteBytes>0</RTSPMaximumPendingWriteBytes>
<RTSPBindIpAddress></RTSPBindIpAddress>
<RTSPConnectionIpAddress>0.0.0.0</RTSPConnectionIpAddress>
<RTSPOriginIpAddress>127.0.0.1</RTSPOriginIpAddress>
<IncomingDatagramPortRanges>*</IncomingDatagramPortRanges>
<!-- Properties defined here will override any properties defined in conf/RTP.xml for any depacketizers loaded by this application -->
<Properties>
</Properties>
</RTP>
<MediaCaster>
<RTP>
<RTSP>
<!-- udp, interleave -->
<RTPTransportMode>interleave</RTPTransportMode>
</RTSP>
</RTP>
<!-- Properties defined here will override any properties defined in conf/MediaCasters.xml for any MediaCasters loaded by this applications -->
<Properties>
</Properties>
</MediaCaster>
<MediaReader>
<!-- Properties defined here will override any properties defined in conf/MediaReaders.xml for any MediaReaders loaded by this applications -->
<Properties>
</Properties>
</MediaReader>
<MediaWriter>
<!-- Properties defined here will override any properties defined in conf/MediaWriter.xml for any MediaWriter loaded by this applications -->
<Properties>
</Properties>
</MediaWriter>
<LiveStreamPacketizer>
<!-- Properties defined here will override any properties defined in conf/LiveStreamPacketizers.xml for any LiveStreamPacketizers loaded by this applications -->
<Properties>
</Properties>
</LiveStreamPacketizer>
<HTTPStreamer>
<!-- Properties defined here will override any properties defined in conf/HTTPStreamers.xml for any HTTPStreamer loaded by this applications -->
<Properties>
</Properties>
</HTTPStreamer>
<Repeater>
<OriginURL></OriginURL>
<QueryString><![CDATA[]]></QueryString>
</Repeater>
<Modules>
<Module>
<Name>base</Name>
<Description>Base</Description>
<Class>com.wowza.wms.module.ModuleCore</Class>
</Module>
<Module>
<Name>logging</Name>
<Description>Client Logging</Description>
<Class>com.wowza.wms.module.ModuleClientLogging</Class>
</Module>
<Module>
<Name>flvplayback</Name>
<Description>FLVPlayback</Description>
<Class>com.wowza.wms.module.ModuleFLVPlayback</Class>
</Module>
</Modules>
<!-- Properties defined here will be added to the IApplication.getProperties() and IApplicationInstance.getProperties() collections -->
<Properties>
</Properties>
</Application>
</Root>
transcoder/templates/p.xml:
<Root>
<Transcode>
<Encodes>
<!-- Example Encode block for source, not required unless Member of StreamNameGroup. -->
<Encode>
<Enable>false</Enable>
<Name>source</Name>
<StreamName>mp4:${SourceStreamName}_source</StreamName>
<Video>
<!-- H.264, H.263, PassThru, Disable -->
<Codec>PassThru</Codec>
<Bitrate>${SourceVideoBitrate}</Bitrate>
<Parameters>
</Parameters>
</Video>
<Audio>
<!-- AAC, PassThru, Disable -->
<Codec>PassThru</Codec>
<Bitrate>${SourceAudioBitrate}</Bitrate>
<Parameters>
</Parameters>
</Audio>
<Properties>
</Properties>
</Encode>
<!-- Setup for 720p, high bandwith, main profile for desktop or set-top box -->
<Encode>
<Enable>true</Enable>
<Name>720p_2500</Name>
<StreamName>mp4:${SourceStreamName}_720p2500</StreamName>
<Video>
<!-- H.264, H.263, PassThru, Disable -->
<Codec>H.264</Codec>
<!-- default, CUDA, QuickSync, NVENC -->
<Transcoder>default</Transcoder>
<GPUID>-1</GPUID>
<FrameSize>
<!-- letterbox, fit-width, fit-height, crop, stretch, match-source -->
<FitMode>fit-height</FitMode>
<Width>1280</Width>
<Height>720</Height>
<!-- <Crop>0,0,0,0</Crop> -->
<!-- <SourceRectangle>0,0,320,240</SourceRectangle> -->
</FrameSize>
<!-- baseline, main, high -->
<Profile>main</Profile>
<Bitrate>2500000</Bitrate>
<KeyFrameInterval>
<FollowSource>true</FollowSource>
<Interval>60</Interval>
</KeyFrameInterval>
<Overlays>
<Overlay>
<Enable>false</Enable>
<Index>0</Index>
<ImagePath>${com.wowza.wms.context.VHostConfigHome}/content/wowzalogo.png</ImagePath>
<CheckForUpdates>false</CheckForUpdates>
<Opacity>100</Opacity>
<Location>
<X>4</X>
<Y>4</Y>
<Width>${ImageWidth}</Width>
<Height>${ImageHeight}</Height>
<!-- horiz: left, right, hcenter - vert: top, bottom, vcenter -->
<Align>left,top</Align>
</Location>
</Overlay>
</Overlays>
<Parameters>
</Parameters>
</Video>
<Audio>
<!-- AAC, PassThru, Disable -->
<Codec>PassThru</Codec>
<Bitrate>${SourceAudioBitrate}</Bitrate>
<Parameters>
</Parameters>
</Audio>
<Properties>
</Properties>
</Encode>
<!-- Setup for 480p, mid bandwith, main profile for desktop or set-top box -->
<Encode>
<Enable>true</Enable>
<Name>480p_1840</Name>
<StreamName>mp4:${SourceStreamName}_480p1840p</StreamName>
<Video>
<!-- H.264, H.263, PassThru, Disable -->
<Codec>H.264</Codec>
<!-- default, CUDA, QuickSync, NVENC -->
<Transcoder>default</Transcoder>
<GPUID>-1</GPUID>
<FrameSize>
<!-- letterbox, fit-width, fit-height, crop, stretch, match-source -->
<FitMode>fit-height</FitMode>
<Width>864</Width>
<Height>480</Height>
<!-- <Crop>0,0,0,0</Crop> -->
<!-- <SourceRectangle>0,0,320,240</SourceRectangle> -->
</FrameSize>
<!-- baseline, main, high -->
<Profile>main</Profile>
<Bitrate>1840000</Bitrate>
<KeyFrameInterval>
<FollowSource>true</FollowSource>
<Interval>60</Interval>
</KeyFrameInterval>
<Overlays>
<Overlay>
<Enable>false</Enable>
<Index>0</Index>
<ImagePath>${com.wowza.wms.context.VHostConfigHome}/content/wowzalogo.png</ImagePath>
<CheckForUpdates>false</CheckForUpdates>
<Opacity>100</Opacity>
<Location>
<X>4</X>
<Y>4</Y>
<Width>${ImageWidth}</Width>
<Height>${ImageHeight}</Height>
<!-- horiz: left, right, hcenter - vert: top, bottom, vcenter -->
<Align>left,top</Align>
</Location>
</Overlay>
</Overlays>
<Parameters>
</Parameters>
</Video>
<Audio>
<!-- AAC, PassThru, Disable -->
<Codec>PassThru</Codec>
<Bitrate>${SourceAudioBitrate}</Bitrate>
<Parameters>
</Parameters>
</Audio>
<Properties>
</Properties>
</Encode>
<Encode>
<Enable>true</Enable>
<Name>480p_1200</Name>
<StreamName>mp4:${SourceStreamName}_480p1200p</StreamName>
<Video>
<!-- H.264, H.263, PassThru, Disable -->
<Codec>H.264</Codec>
<!-- default, CUDA, QuickSync, NVENC -->
<Transcoder>default</Transcoder>
<GPUID>-1</GPUID>
<FrameSize>
<!-- letterbox, fit-width, fit-height, crop, stretch, match-source -->
<FitMode>fit-height</FitMode>
<Width>864</Width>
<Height>480</Height>
<!-- <Crop>0,0,0,0</Crop> -->
<!-- <SourceRectangle>0,0,320,240</SourceRectangle> -->
</FrameSize>
<!-- baseline, main, high -->
<Profile>main</Profile>
<Bitrate>1200000</Bitrate>
<KeyFrameInterval>
<FollowSource>true</FollowSource>
<Interval>60</Interval>
</KeyFrameInterval>
<Overlays>
<Overlay>
<Enable>false</Enable>
<Index>0</Index>
<ImagePath>${com.wowza.wms.context.VHostConfigHome}/content/wowzalogo.png</ImagePath>
<CheckForUpdates>false</CheckForUpdates>
<Opacity>100</Opacity>
<Location>
<X>4</X>
<Y>4</Y>
<Width>${ImageWidth}</Width>
<Height>${ImageHeight}</Height>
<!-- horiz: left, right, hcenter - vert: top, bottom, vcenter -->
<Align>left,top</Align>
</Location>
</Overlay>
</Overlays>
<Parameters>
</Parameters>
</Video>
<Audio>
<!-- AAC, PassThru, Disable -->
<Codec>PassThru</Codec>
<Bitrate>${SourceAudioBitrate}</Bitrate>
<Parameters>
</Parameters>
</Audio>
<Properties>
</Properties>
</Encode>
</Encodes>
<Decode>
<Video>
<Deinterlace>false</Deinterlace>
<Overlays>
<Overlay>
<Enable>false</Enable>
<Index>0</Index>
<ImagePath>${com.wowza.wms.context.VHostConfigHome}/content/wowzalogo.png</ImagePath>
<CheckForUpdates>false</CheckForUpdates>
<Opacity>100</Opacity>
<Location>
<X>4</X>
<Y>4</Y>
<Width>${ImageWidth}</Width>
<Height>${ImageHeight}</Height>
<!-- horiz: left, right, hcenter - vert: top, bottom, vcenter -->
<Align>left,top</Align>
</Location>
</Overlay>
</Overlays>
<Parameters>
</Parameters>
</Video>
<Properties>
</Properties>
</Decode>
<StreamNameGroups>
<!-- Note: Play stream using stream name ngrp:[stream-name] -->
<StreamNameGroup>
<Name>TV</Name>
<StreamName>${SourceStreamName}_tv</StreamName>
<Members>
<Member>
<EncodeName>source</EncodeName>
</Member>
<Member>
<EncodeName>720p_2500</EncodeName>
</Member>
<Member>
<EncodeName>480p_1840</EncodeName>
</Member>
<Member>
<EncodeName>480p_1200</EncodeName>
</Member>
</Members>
</StreamNameGroup>
</StreamNameGroups>
<Properties>
</Properties>
</Transcode>
</Root>
With these .xml file I start the server and then try to access a HLS stream. For first testing, I use wget
to get the top-level manifest file:
tmp >wget http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8
–12:33:39-- http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8
=> `playlist.m3u8’
Connecting to 192.168.10.124:1935… connected.
HTTP request sent, awaiting response… 200 OK
Length: 25 [application/vnd.apple.mpegurl]
100%[=========================================>] 25 --.–K/s
12:33:48 (189.26 KB/s) - `playlist.m3u8’ saved [25/25]
tmp >more playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
This is an empty .m3u8 file. I was expecting to see a list of profiles and URLs
to second level .m3u8 files
On the server, I see the following:
2013-10-23 11:35:06 GMT-08:00 connect cupertino INFO 200 1956111067 - defaultVHost p definst 111.611 192.168.10.124 1935 http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 192.168.10.45 http (cupertino) - Wget/1.9.1 1956111067 0 0 - sample.mp4_tv - - - - - http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 - http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 -
2013-10-23 11:35:06 GMT-08:00 create stream INFO 200 sample.mp4_tv - _defaultVHost_p definst 0.001 192.168.10.124 1935 http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 192.168.10.45 http (cupertino) - Wget/1.9.1 1956111067 0 0 3 0 sample.mp4_tv - - - - - http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 - http://192.168.10.124:1935/p/ngrp:sample.mp4_tv/playlist.m3u8 -
2013-10-23 11:35:06 GMT-08:00 comment server WARN 200 - HTTPStreamerCupertinoIndexPlaylist.indexFile[p/definst/ngrp:sample.mp4_tv]: MediaList is empty. - - - 111.613 - -
So what am I doing wrong here?