Wowza Community

Live streaming VOD concept using IP camera

I have been testing the WMS for several months and have finally figured out the best combination for my application. I am able to get the IP camera to re-stream fine to any type of player. Now I have a concept I would like to test but I am not sure if it is possible. The goal is to have an IP camera that streams live video 24/7 however I do not want the WMS to re-stream the camera unless the link to the WMS stream is clicked on by a client. Once that stream is started I would like it to time out after a set number of seconds and return to it’s “dormant” state until another client attempts to access the stream. Is my request possible to achieve and can someone point me to the proper code to make this happen? Thanks for your help.

Hi,

I haven’t tested this but it could possibly do the job. Set the stream type to live so that the mediacaster does’t start automatically when the stream is requested.

package test;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import com.wowza.wms.application.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.IMediaStreamNameAliasProvider;

public class OnDemandMediaCaster extends ModuleBase implements IMediaStreamNameAliasProvider {

	private Map<String, Timer> timers;
	
	public void onAppStart(IApplicationInstance appInstance) {
		appInstance.setStreamNameAliasProvider(this);
		timers = Collections.synchronizedMap(new HashMap<String, Timer>());
	}
	
	public void onAppStop(IApplicationInstance appInstance) {
		synchronized(timers.keySet()) {
			Iterator<String> iter = timers.keySet().iterator();
			while(iter.hasNext()) {
				String name = iter.next();
				if(appInstance.getMediaCasterStreams().getMediaCaster(name) != null)
					appInstance.stopMediaCasterStream(name);
			
				Timer t = timers.get(name);
				if(t != null)
					t.cancel();
				t = null;
			}
			timers.clear();
			timers = null;
		}
	}

	@Override
	public String resolvePlayAlias(IApplicationInstance appInstance, String name) {
		if(appInstance.getMediaCasterStreams().getMediaCaster(name) == null) {
			appInstance.startMediaCasterStream(name, "rtp");
			Timer t = new Timer();
			t.schedule(new ShutdownTask(appInstance, name), 30000);
			timers.put(name, t);
		}
		return name;
	}

	@Override
	public String resolveStreamAlias(IApplicationInstance appInstance, String name) {
		// startmediaCasterStream will call this method to resolve the mediaCaster name.
		return name;
	}

	private class ShutdownTask extends TimerTask {

		private IApplicationInstance appInstance;
		private String name;

		private ShutdownTask(IApplicationInstance appInstance, String name) {
			this.appInstance = appInstance;
			this.name = name;
		}
		
		@Override
		public void run() {
			if(appInstance.getMediaCasterStreams().getMediaCaster(name) != null)
				appInstance.stopMediaCasterStream(name);
			
			Timer t = timers.remove(name);
			if(t != null)
				t.cancel();
			t = null;
		}
		
	}
}

What you want to do, cannot be done without a custom module. The above is an example of what may work.

You will need to get WowzaIDE and then compile it into a new module to add to your server.

Hi Steve,

Did you try your stream normally to make sure it works. The mediacaster looks like it it is trying to connect to it continiously. Try starting it using the stream manager on another app which isnt running this module.

Did you try lengthening the duration of the timer. It is in milliseconds so in the example is 30 secs. I can confirm that this method does work with RTMP but I haven’t tested it using vlc as a client so I am not sure how vlc will handle it if the stream is not already running.

What is it that you actually want to achieve? There may be a better way to do it. The reason I used the resolve alias method is that it gets called by all stream connections.

Hi Steve,

I think your initial description threw me a bit and I took it that you wanted to kick the connection after a set time.

To do what you want to do, you just need to set the stream type to rtp-live. This will cause Wowza to start pulling the stream in from the camera when the first client connects and then drop it a few seconds after the last one disconnects.

I was just thinking that using your own StreamNameAliasProvider has probably stopped the normal functionality of the *.stream file. Normally if you don’t set the provider then it will default to the *.stream files as the alias provider. In the configuration you have, resolveStreamAlias is called after resolvePlayAlias and it needs to return the real address of the camera stream. At the moment, it is returning the *.stream file.

Thank you all for you assistance on this.

Roger,

We have an IP camera that is constantly streaming to a WMS. We are trying to avoid bandwidth usage both inbound and outbound between the camera/WMS and the WMS/client. What we would like to have happen is when a person attempts to view a live stream that is being restreamed from the WMS we want the WMS to open a connection to the camera and in turn restream the RTSP stream to the client but only for a short period of time (i.e. 10 secs). Once the stream times out we would like the session between the client and the WMS to close along with the session between the WMS and the camera to close so that there is no uneccesary usage of bandwidth. The camera will always be streaming but we do not want it to connect to the WMS stream manager until a client requests the stream. I hope this clarifies what we are trying to accomplish and if anyone can provide more assistance with this that would be great.

I didn’t realise that Steve had hijacked the thread and got a bit confused.

Did you manage to set up WowzaIDE and compile the code?

Also note what I said in my last post to Steve about how the aliasing system works with regard to if you use your own Alias provider, *.stream files will not work and you will need to also resolve the camera address in the resolveStreamAlias method.

From your latest description, I would also add to the ShutdownTask run method to disconnect any clients that are viewing the stream.

		@Override
		public void run() {
			List<IMediaStream> playStreams = appInstance.getPlayStreamsByName(name);
			for(IMediaStream playStream : playStreams) {
				playStream.getClient().setShutdownClient(true);
			}

			if(appInstance.getMediaCasterStreams().getMediaCaster(name) != null)
				appInstance.stopMediaCasterStream(name);
			
			Timer t = timers.remove(name);
			if(t != null)
				t.cancel();
			t = null;
		}

When you create a new Wowza Module Project, it should configure everything to output a jar file into your Wowza lib folder. To make your module work, you need to edit the Application.xml file for the app that will use the module and add your module to the Modules Section.

My apologies but I do not know exactly what to do with the code that you have sent over. I do not have much experience with code so I was hoping for the XML code that needed to be tweaked. Perhaps you could elaborate on the code above or at least point me in the right direction.

Thank you all for you assistance on this.

Roger,

We have an IP camera that is constantly streaming to a WMS. We are trying to avoid bandwidth usage both inbound and outbound between the camera/WMS and the WMS/client. What we would like to have happen is when a person attempts to view a live stream that is being restreamed from the WMS we want the WMS to open a connection to the camera and in turn restream the RTSP stream to the client but only for a short period of time (i.e. 10 secs). Once the stream times out we would like the session between the client and the WMS to close along with the session between the WMS and the camera to close so that there is no uneccesary usage of bandwidth. The camera will always be streaming but we do not want it to connect to the WMS stream manager until a client requests the stream. I hope this clarifies what we are trying to accomplish and if anyone can provide more assistance with this that would be great.

Hi Roger,

I have not had the opportunity to try the suggestion. This is a project I am pursuing outside my normal job so things have been busy. I will try the compiler later tonight. I do have some questions and I will try to teach myself but what does the compiler output and what do I do with it when it is compiled?

I can confirm this does not work. Wowza continuously starts and stops the stream

STARTING MEDIA CASTER: ponceinlet.stream
INFO server comment - onStreamCreate: 1
INFO server comment - onStreamCreate: 1
INFO stream create - -
INFO stream unpublish - -
INFO server comment - onStreamDestroy: 1
INFO server comment - onStreamDestroy: 1
INFO stream destroy - -
INFO server comment - onRTPSessionDestroy: 2139865102
INFO server comment - Application Name: _definst_
INFO server comment - RTP URI: rtsp://192.168.1.50:1935/dev/ponceinlet.stream
INFO server comment - onRTPSessionDestroy: 2139865102
INFO rtsp disconnect 2139865102 -
INFO server comment - RTPSessionDescriptionDataProviderBasic.getStreamInfo[dev/_definst_]: /Library/WowzaMediaServer/content/ponceinlet.stream
INFO server comment - onRTPSessionCreate: 448095884
INFO server comment - RTP URI: null
INFO server comment - onRTPSessionCreate: 448095884
INFO server comment - onStreamCreate: 2
INFO server comment - onStreamCreate: 2
INFO stream create - -
INFO stream publish ponceinlet.stream -
INFO server comment - RTPMediaCaster.Reconnector[490829456:dev/_definst_:ponceinlet.stream]: done: 1
INFO server comment - RTPMediaCaster.resetConnection[490829456:dev/_definst_:ponceinlet.stream]: 
INFO server comment - RTPMediaCaster.closeRTPSession[490829456:dev/_definst_:ponceinlet.stream]
INFO server comment - onRTPSessionDestroy: 448095884
INFO server comment - Application Name: _definst_
INFO server comment - RTP URI: null
INFO server comment - onRTPSessionDestroy: 448095884
INFO stream unpublish ponceinlet.stream -
INFO server comment - onStreamDestroy: 2
INFO server comment - onStreamDestroy: 2
INFO stream destroy ponceinlet.stream -
INFO server comment - RTPMediaCaster.Reconnector[490829456:dev/_definst_:ponceinlet.stream]: start: 2
INFO server comment - RTPSessionDescriptionDataProviderBasic.getStreamInfo[dev/_definst_]: /Library/WowzaMediaServer/content/ponceinlet.stream
INFO server comment - onRTPSessionCreate: 1942423646
INFO server comment - RTP URI: null
INFO server comment - onRTPSessionCreate: 1942423646
INFO server comment - onStreamCreate: 3
INFO server comment - onStreamCreate: 3
INFO stream create - -
INFO stream publish ponceinlet.stream -
INFO server comment - RTPMediaCaster.Reconnector[490829456:dev/_definst_:ponceinlet.stream]: done: 2

I only called into WMS once using VLC to get this process started.

If I remove the call to add this module as the alias provider and put the call to start up the stream in say onRTPSessionCreate then it works. In this case however the client RTPSession is closed. I assume this is due to the client RTPSession not being associated with the new stream. i.e. The RTPSession is too far down the pipeline to be connected to a newly created stream. I even tried putting a thread sleep in the initial onRTPSessionCreate, but the session is still closed out.

Is it possible to add a module to the RTP, RTMP and HTTP servers? I could just inspect the URLS and keep track of client counts there in order to start and stop the streams.

I tried implementing IMediaStreamNameAliasProvider2 instead, but the same thing occurs.

Thanks Roger,

I did confirm it was working under normal circumstances. I just tried your suggestion. While WMS was continually trying to start up the cam I used stream manager to add the cam to a different application. It starts up the stream properly. I used VLC to confirm the RTSP stream. I also tried the reverse. Same issue.

My implementation does not require a timer. I simply need to start the cams when a viewer tries to connect. I then need to shut them down when they disconnect. I have already written code to track stream counts. I just need a way to dynamically start and stop the streams, and it has to work with all client stream types.

I like the resolve alias method as well because it is called by all streams. I do notice in the logs that onRTPSessionCreate is called before the resolve alias handler. I suspect that I will run into the same issue in that the ‘first’ RTPSession will be ‘discarded’. I am using VLC to test as RTSP will be the method Android uses to stream.

I was thinking that pushing all this functionality up the call stack might solve the issue. I am not sure where in the ‘pipline’ the RTPSession gets connected to an actual stream. My current solution may work if I can manually tell the RTP client to reconnect, or I can manually connect it to the new stream.

It is strange that I can successfully get the stream started in one of the session handlers as long as my module is not the alias handler.

I do want to say while having this functionality would be nice, it is not terribly important for me. The bandwidth costs at EC2 are very affordable, and our cams only run during daylight. I was just looking to save a few bucks. And this will add up in the future when we have 15 to 20 axis cams. I have another idea to start the streams when the ‘commercial’ plays for that stream. By the time the commercial is done the stream should be ready to go. Then I will just run a timer, as in the origional posters solutions, to time out the cams when no one is connected.

I did hijack this thread a bit (I closed my original post about this). What I need to do and what ipvideosolutions needs are very similar.

Given that rtp-live disconnects the live ip camera stream if no one is connected to the application stream, then I think all ipvideosolutions needs is a timer object to force a disconnect of the client. WMS should stop the incoming stream as both of us want. Your code posting should work fine for ipvideosolutions as long as the stream type is rtp-live.

Thanks for the help. I did rtfm, but apparently I missed this. I have at least become familiar with the API. Lot’s of really cool stuff you can do with it.