Results 1 to 5 of 5

Thread: VoD to Live stream (ServerListenerServerPublisher) module

  1. #1
    Join Date
    Mar 2012
    Posts
    14

    Post VoD to Live stream (ServerListenerServerPublisher) module

    Hi there,

    I currently have this addon installed on my test Wowza server.

    So I was thinking of implementing this in production for our customers (ServerListenerServerPublisher from wms-plugin-collection), however I have some issues and I hope you could provide some info:

    - Per-application configuration: Is there any plans to make this configurable on a per-application level same as you have already for lets say "LiveStreamRecord" module (which our company also uses), where the conf is added in Application.xml, rather than Server.xml globally. I would like to be able to make it so that each "Application" has it's own "streamschedule.smil" for it's own "StorageDir" where the VoD files are located.

    - No restart of Wowza for applying "streamschedule.smil" changes: Currently, since configuration is on a global level, I would need to restart Wowza (with 10's, 100's Applications) for each change of the playlist in the "streamschedule.smil", which is not viable at all for a production environment. I would like it to be on a per-application basis and potentially only require an Application shutdown/start via JMX "shutdownAppInstance" and "startAppInstance".


    Regards,

  2. #2
    Join Date
    Sep 2011
    Posts
    1,933

    Default

    Hi
    This can be done with some custom code,
    If you can't build this code yourself I'm sure a consultant will be happy to help, contact support@wowza.com asking for the independent consultants list and contact a consultant of your choosing.

    You can make a storage directory for each application via the Application.xml file
    Example :

    <StorageDir>${com.wowza.wms.context.VHostConfigHome}/content/app1</StorageDir>

    If you have an application called app1 and used this directory you could keep track off all the content for each application.

    Jason

  3. #3
    Join Date
    Mar 2012
    Posts
    14

    Default

    Quote Originally Posted by JasonH View Post
    Hi
    This can be done with some custom code,
    If you can't build this code yourself I'm sure a consultant will be happy to help, contact support@wowza.com asking for the independent consultants list and contact a consultant of your choosing.

    You can make a storage directory for each application via the Application.xml file
    Example :

    <StorageDir>${com.wowza.wms.context.VHostConfigHome}/content/app1</StorageDir>

    If you have an application called app1 and used this directory you could keep track off all the content for each application.

    Jason
    Hi Jason,

    Thank you for your reply, however, I am aware of how to change the "StorageDir" in the Application.xml and how it works. What I was asking about is, if it is possible to make this specific module customizable so it can be configured on a per-application level (through Application.xml) for each application specifically, so each application would have it's own streamschedule.smil, and also for reloading of streamschedule.smil to be done on a per-application level instead of globally by restarting Wowza.

    If I understood you correctly, all this can be done through the change of the code (per-application streamschedule.smil and per-application reloading of this smil) for this module which can be found here:
    http://www.wowza.com/forums/content....t-in-smil-file

    specifically this code:
    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<String, Stream> streamMap = new HashMap<String, Stream>();
        Map<String, Playlist> playlistMap = new HashMap<String, Playlist>();
        
        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<String, Stream> 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<String, Playlist> 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());
                }
            }
        }
    }
    We do have a Java developer in our company, which could probably modify some of it. I'm just asking to confirm if modification to this code can achieve my requirements?

    Regards,

  4. #4
    Join Date
    Sep 2011
    Posts
    1,933

    Default

    Hi
    To Achieve your requirements you would have to write some more code, the code above won't be able to do all the requirements that you're looking for.

    Jason

  5. #5
    Join Date
    Dec 2007
    Posts
    21,962

    Default

    The schedule approach could be adapted to a Wowza module that loaded the schedule in the onAppStart. In that case the application would have to be re-loaded for changes in the schedule file to reload, and of course that would reset everything include client playback sessions if there are any.

    This example shows how to modify Stream class streams dynamically:
    http://www.wowza.com/forums/content....eam-controller

    You can start with the existing scheduler, or modify application scheduler, then make changes dynamically.

    Richard

Similar Threads

  1. Help with RTMP VOD mid-roll module
    By eTiMaGo in forum Server-side Modules and Code Samples Discussion
    Replies: 1
    Last Post: 03-12-2013, 10:53 AM
  2. Live Stream Record Module Not Working With MP4
    By grantk in forum AddOn: Other AddOns
    Replies: 12
    Last Post: 07-13-2012, 04:22 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •