How to live-stream video-file on Wowza
This article is discussed about the way to configure Wowza Media Server to live-stream video-files for IPTV environment
Video File format Supported
-
Video and AudioFLV (Flash Video – .flv)
MP4 (QuickTime container – .mp4, .f4v, .mov, .m4v, .mp4a, .3gp, and .3g2)
MP3 (.mp3)
Download and extract the wowza media server plugin collection.
To click here to download the ZIP file (wms-plugin-collection.zip).
After the zip file extracted, please read “README.html” to install the plugins
This package contains one jar file that you can use to implement a number of extensions for Wowza Server To install 1. Copy the file jar file wms-plugin-collection.jar from [package]/lib/ into [install-dir]/lib/ For detailed description and implementation guide for each Module see this article on the Wowza Forum: Module Collection
All modules on this plugin package is described here.…
Setting the configuration on Wowza Media Server
After the installation of the plugin-modules, and then follow the instructions on “How to do scheduled streaming with Stream class streams”. particularly, the code listed as below:
package com.wowza.wms.plugin.collection.serverlistener; import com.wowza.wms.application.*; import com.wowza.wms.server.*; import com.wowza.wms.vhost.*; import com.wowza.wms.stream.publish.*; import com.wowza.wms.logging.*; import java.io.File; import java.text.SimpleDateFormat; import java.util.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class ServerListenerStreamPublisher implements IServerNotify { WMSLogger log = WMSLoggerFactory.getLogger(null); Map streamMap = new HashMap(); Map playlistMap = new HashMap(); public void onServerInit(IServer server) { log.info("ServerListenerStreamPublisher Started."); IVHost vhost = null; IApplication app = null; try { vhost = VHostSingleton.getInstance(server.getProperties().getPropertyStr("PublishToVHost", "_defaultVHost_")); } catch (Exception evhost) { log.info("ServerListenerStreamPublisher: Failed to get Vhost can not run."); return; } try { app = vhost.getApplication(server.getProperties().getPropertyStr("PublishToApplication", "live")); } catch (Exception eapp) { log.info("ServerListenerStreamPublisher: Failed to get Application can not run."); return; } // Belt and Braces check for VHost and App if ( vhost == null || app == null ) { log.info("ServerListenerStreamPublisher: VHost or Application failed, not running."); return; } Boolean passThruMetaData = server.getProperties().getPropertyBoolean("PassthruMetaData", true); String storageDir = app.getAppInstance("_definst_").getStreamStorageDir(); try { String smilLoc = storageDir + "/streamschedule.smil"; File playlistxml = new File(smilLoc); if (playlistxml.exists() == false){ log.info("ServerListenerStreamPublisher: Could not find playlist file: " + smilLoc); return; } DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; Document document = null; try { db = dbf.newDocumentBuilder(); document = db.parse("file:///" + smilLoc); } catch (Exception e ) { log.info("ServerListenerStreamPublisher: XML Parse failed"); return; } document.getDocumentElement().normalize(); NodeList streams = document.getElementsByTagName("stream"); for (int i = 0; i < streams.getLength(); i++) { Node streamItem = streams.item(i); if (streamItem.getNodeType() == Node.ELEMENT_NODE) { Element e = (Element) streamItem; String streamName = e.getAttribute("name"); log.info("ServerListenerStreamPublisher: Streame name is '"+streamName+"'"); Stream stream = Stream.createInstance(vhost, app.getName(), streamName); streamMap.put(streamName, stream); app.getAppInstance("_definst_").getProperties().setProperty(streamName, stream); } } NodeList playList = document.getElementsByTagName("playlist"); if (playList.getLength() == 0){ log.info("ServerListenerStreamPublisher: No playlists defined in smil file"); return; } for (int i = 0; i < playList.getLength(); i++) { Node scheduledPlayList = playList.item(i); if (scheduledPlayList.getNodeType() == Node.ELEMENT_NODE) { Element e = (Element) scheduledPlayList; NodeList videos = e.getElementsByTagName("video"); if (videos.getLength() == 0){ log.info("ServerListenerStreamPublisher: No videos defined in stream"); return; } String streamName = e.getAttribute("playOnStream"); if (streamName.length()==0) continue; Playlist playlist = new Playlist(streamName); playlist.setRepeat((e.getAttribute("repeat").equals("false"))?false:true); playlistMap.put(e.getAttribute("name"), playlist); for (int j = 0; j < videos.getLength(); j++) { Node video = videos.item(j); if (video.getNodeType() == Node.ELEMENT_NODE) { Element e2 = (Element) video; String src = e2.getAttribute("src"); Integer start = Integer.parseInt(e2.getAttribute("start")); Integer length = Integer.parseInt(e2.getAttribute("length")); playlist.addItem(src, start, length); } } String scheduled = e.getAttribute("scheduled"); SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date startTime = null; try { startTime = parser.parse(scheduled); } catch (Exception z ) { log.info("Parsing schedule time failed."); return ; } Stream stream = streamMap.get(streamName); stream.setSendOnMetadata(passThruMetaData); ScheduledItem item = new ScheduledItem(startTime, playlist, stream); item.start(); IStreamActionNotify actionNotify = new StreamListener(app.getAppInstance("_definst_")); stream.addListener(actionNotify); log.info("ServerListenerStreamPublisher Scheduled: " + stream.getName() + " for: " + scheduled); } } } catch(Exception ex) { log.info("ServerListenerStreamPublisher: Error from playlist manager is '"+ex.getMessage()+"'"); } } private class ScheduledItem { public Timer mTimer; public TimerTask mTask; public Date mStart; public Playlist mPL; public Stream mStream; public ScheduledItem(Date d, Playlist pl, Stream s){ mStart = d; mPL = pl; mStream = s; mTask = new TimerTask(){ public void run() { //synchronized(mStream.getLock()) //{ mPL.open(mStream); //} log.info("ServerListenerStreamPublisher Scheduled stream is now live: " + mStream.getName()); } }; mTimer = new Timer(); } public void start(){ if (mTimer==null) mTimer = new Timer(); mTimer.schedule(mTask, mStart); log.info("scheduled playlist: "+mPL.getName()+ " on stream: "+mStream.getName()+ " for:"+mStart.toString()); } public void stop(){ if (mTimer != null){ mTimer.cancel(); mTimer=null; log.info("cancelled playlist: "+mPL.getName()+ " on stream: "+mStream.getName()+ " for:"+mStart.toString()); } } } public void onServerCreate(IServer server) { } public void onServerShutdownComplete(IServer server) { log.info("ServerListenerStreamPublisher: Shutdown server start"); for (Map.Entry entry : streamMap.entrySet()) { try { Stream stream = entry.getValue(); stream.close(); stream = null; log.info("ServerListenerStreamPublisher Closed Stream: " + entry.getKey()); } catch(Exception ex) { log.error(ex.getMessage()); } } for (Map.Entry entry : playlistMap.entrySet()) { try { Playlist pl = entry.getValue(); pl = null; } catch(Exception ex) { log.error(ex.getMessage()); } } } public void onServerShutdownStart(IServer server) { } class StreamListener implements IStreamActionNotify { StreamListener(IApplicationInstance appInstance) { } public void onPlaylistItemStop(Stream stream, PlaylistItem item) { if (item.getIndex() == (stream.getPlaylist().size() - 1)) { if (! stream.getRepeat()) { stream.close(); WMSLoggerFactory.getLogger(null).info("ServerListenerStreamPublisher: closing stream: " + stream.getName()); } } } public void onPlaylistItemStart(Stream stream, PlaylistItem item) { try { String name = stream.getCurrentItem().getName(); stream.getPublisher().getAppInstance().broadcastMsg("PlaylistItemStart", name); WMSLoggerFactory.getLogger(null).info("ServerListenerStreamPublisher PlayList Item Start: " + name); } catch(Exception ex) { WMSLoggerFactory.getLogger(null).info("ServerListenerStreamPublisher Get Item error: " + ex.getMessage()); } } } }
is on the file at <<zip –> wms-plugin-collection -> src -> com -> wowza -> wms -> plugin -> collection -> serverlistener -> ServerListenerStreamPublisher.java >>. If you are interested in studying the code, may follow up the above instruction; otherwise, just followup the next instruction
Adding the following code to /conf/Server.xml below the section of /ServerListeners
<ServerListener> <BaseClass>com.wowza.wms.plugin.collection.serverlistener.ServerListenerStreamPublisher</BaseClass> </ServerListener>
EVENTUALLY, IT’S BEEN DONE ON SETTING of /conf/Server.xml AFTER THE ABOVE STEP IF YOU HAVE CONFIGURE LIVE CHANNEL ALREADY. Otherwise, still need to following the other 3 steps for furthermore settings.
**********************************************************
IMPORTANT: this server listener requires that there be an application named “live” where the Streams and Playlists are created. You can set another name for the application to be populated in /conf/Server.xml /Properties:
<Property> <Name>PublishToApplication</Name> <Value>MyLiveApp</Value> </Property>
And if you want to publish to another VHost, add this Property to /conf/Server.xml /Properties:
<Property> <Name>PublishToVHost</Name> <Value>CustomVHost</Value> </Property>
MetaData from media files are passed to the live stream by default, if you don’t want that to happen, add this Property to /conf/Server.xml /Properties:
<Property> <Name>PassthruMetaData</Name> <Value>false</Value> <Type>Boolean</Type> </Property>
The target application must have an Application.xml /StreamType “live” or “live-lowlatency”
*****************************************************
Create the smil file [install-dir]/content/streamschedule.smil
Create the smil file [install-dir]/content/streamschedule.smil
Create at least one stream, then create at least one playlist that plays on that stream. Set repeat to true or false for each playlist. Use start=”-2″ for live sources. Use length=”-1″ to play until media ends.
You can create an elaborate schedule with several streams and many playlists scheduled to play on a stream.
<smil> <head> </head> <body> <stream name="Stream1"></stream> <stream name="Stream2"></stream> <playlist name="pl1" playOnStream="Stream1" repeat="true" scheduled="2009-12-11 16:00:00"> <video src="mp4:sample.mp4" start="5" length="5"/> <video src="mp4:sample.mp4" start="50" length="5"/> <video src="mp4:sample.mp4" start="150" length="5"/> </playlist> <playlist name="pl2" playOnStream="Stream1" repeat="true" scheduled="2009-12-11 16:30:00"> <video src="mp4:sample.mp4" start="0" length="-1"/> </playlist> <playlist name="pl3" playOnStream="Stream2" repeat="true" scheduled="2009-12-11 16:00:00"> <video src="mp4:sample.mp4" start="30" length="5"/> </playlist> </body> </smil>
Brief Description of /content/streamschedule.smil
- all the playlist will be repeated when playing ended
- stream name = “stream1”: The stream1 means the stream to play
- “playlist name=”pl1″ playOnStream=”Stream1″ repeat=”true” scheduled=”2009-12-11 16:00:00″”: at 2009/12/11 16:00:00 starting to play the channel to stream1
- “video src=”mp4:sample.mp4″ start=”5″ length=”5″”: start the 5th second of the file sample.mp4, and playing 5 seconds only.
- “video src=”mp4:sample.mp4″ start=”50″ length=”5″”: continuing the same file at the 50th second, and playing 5 seconds
- “playlist name=”pl2″ playOnStream=”Stream1″ repeat=”true” scheduled=”2009-12-11 16:30:00″: at 2009/12/11 16:30:00 start to play this section to Stream1
- “video src=”mp4:sample.mp4″ start=”0″ length=”-1″”: start to play the file of sample.mp4 from the beginning to the end; when finished, to replay continually.
configuration a client site
Server: rtmp://[wowza-address]/live
Stream: Stream1 (or Stream2. As set in smil file).
Latest Comments