Results 1 to 9 of 9

Thread: wowza video recording question

  1. #1

    Default wowza video recording question

    Hello guys. I`m streaming from a webcam and saving via wowza to the content folder. I user adobe flash media live encoder. Each time i disconnect the encoder and start it again the currently saved file is deleted and it records a new file. How can i make wowza create a new flv file with other name so that the older files remain, and is there any way i can make wowza create new file hourly? Thanks

  2. #2

    Default

    ok, found out that i can use ModuleMediaWriterFileMover. Now the old file is moved into a folder, but the question remains how can i make it record new file every hour and save the file something like: date:hour_myStream.flv

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

    Default

    Take a look at this post:
    http://www.wowza.com/forums/showthre...3223#post53223

    And take a look at the IMediaWriterActionNotify API:
    http://www.wowza.com/forums/content....write-listener

    which you can use to re-name the file in that way as well as move.

    Richard

  4. #4

    Default

    i`m havin problems compiling this:


    package streamrecord.hourly.monthlyrollover;
    
    import java.io.File;
    import java.util.Calendar;
    import java.util.Collections;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.TimeZone;
    
    import com.wowza.wms.application.*;
    import com.wowza.wms.module.*;
    import com.wowza.wms.plugin.integration.liverecord.*;
    import com.wowza.wms.stream.IMediaStream;
    import com.wowza.wms.stream.IMediaStreamActionNotify;
    import com.wowza.wms.stream.IMediaStreamNotify;
    
    public class ModuleStreamRecord extends ModuleBase implements IMediaStreamNotify {
    	private IApplicationInstance appInstance;
    	private String timezone;
    	private StreamTimer streamTimer;
    	private int date;
    	private int startHour = 0;
    	private int endHour = 23;
    	private int hourOfDay = -1;
    	private boolean record = false;
    	private PublishNotifier publishNotifier;
    	private List<String> streams;
    	
    	public static final int FORMAT_UNKNOWN = 0;
    	public static final int FORMAT_FLV = 1;
    	public static final int FORMAT_MP4 = 2;
    	
    	private Map<String, ILiveStreamRecord> recorders = null;
    
    	private class StreamTimer extends Thread {
    		private boolean doQuit = false;
    
    		public synchronized void quit() {
    			doQuit = true;
    		}
    
    		public void run() {
    			while (true) {
    				try {
    					TimeZone tz = TimeZone.getTimeZone(timezone);
    					Calendar cal = Calendar.getInstance(tz);
    
    					date = cal.get(Calendar.DATE);
    					int prevHour = hourOfDay;
    					hourOfDay = cal.get(Calendar.HOUR_OF_DAY);
    					int start = startHour;
    					int end = endHour;
    					if (start > end && hourOfDay > start) {
    						end += 24;
    					}
    
    					if (end < start && hourOfDay < end) {
    						start -=24;
    					}
    
    					if (hourOfDay >= start && hourOfDay < end) {
    						record = true;
    					} else {
    						record = false;
    					}
    
    					streams = appInstance.getMediaCasterStreams().getMediaCasterNames();
    
    					if (prevHour != hourOfDay && record) {
    						for (String streamName : streams) {
    							IMediaStream stream = appInstance.getStreams().getStream(streamName);
    							appInstance.getVHost().getHandlerThreadPool().execute(new DoStartRecording(stream, streamName));
    						}
    					} else if(!record) {
    						for (String streamName : streams) {
    							ILiveStreamRecord recorder = recorders.remove(streamName);
    							if(recorder != null)
    								recorder.stopRecording();
    						}
    					}
    					
    					Thread.currentThread();
    					Thread.sleep(60000);
    					synchronized (this) {
    						if (doQuit) {
    							break;
    						}
    					}
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    
    	public void onAppStart(IApplicationInstance appInstance) {
    		this.appInstance = appInstance;
    		WMSProperties props = appInstance.getProperties();
    		startHour = props.getPropertyInt("startHour", 0);
    		endHour = props.getPropertyInt("endHour", 24);
    		timezone = props.getPropertyStr("timezone", "America/Chicago");
    
    		appInstance.addMediaStreamListener(this);
    		recorders = Collections.synchronizedMap(new HashMap<String, ILiveStreamRecord>());
    		publishNotifier = new PublishNotifier();
    		
    		streamTimer = new StreamTimer();
    		streamTimer.setName("RecordController-" + appInstance.getApplication().getName());
    		streamTimer.setDaemon(true);
    		streamTimer.start();
    	}
    
    	public void onAppStop(IApplicationInstance appInstance) {
    		streamTimer.quit();
    
    		// cleanup any recorders that are still running
    		synchronized (recorders) {
    			Iterator<String> iter = recorders.keySet().iterator();
    			while(iter.hasNext())
    			{
    				String streamName = iter.next();
    				ILiveStreamRecord recorder = recorders.get(streamName);
    				recorder.stopRecording();
    				getLogger().info("  stopRecording: "+streamName);
    			}
    			recorders.clear();
    		}
    		
    		recorders = null;
    		appInstance.removeMediaStreamListener(this);
    		publishNotifier = null;
    	}
    
    	private synchronized void startRecording(IMediaStream stream) {
    		String streamAlias = stream.getName().substring(0, stream.getName().indexOf(".stream"));
    		
    		if (!streamAlias.isEmpty()) {
    			String outputPath = appInstance.getStreamStorageDir()+"/"+String.format("%02d", date); //day;
    			boolean append = false;
    			File path = new File(outputPath);
    			if (path.exists()) {
    				File outputFile = new File(path.getPath()+File.separator+streamAlias+"_"+String.format("%02d", hourOfDay)+".mp4");
    				Date today = new Date();
    				if (!(outputFile.lastModified() < today.getTime() - 86400000)) {
    					append = true;
    				}
    				
    			} else {
    				path.mkdirs();
    			}
    			
    			recordStream(stream, FORMAT_MP4, append, outputPath+File.separator+streamAlias+"_"+String.format("%02d", hourOfDay)+".mp4", false, true, true);
    		}
    	}
    	
    	private void recordStream(IMediaStream stream, int format, boolean append, String outputPath, boolean versionFile, boolean startOnKeyFrame, boolean recordData)
    	{
    
    		String streamName = stream.getName();
    		
    		// if a format was not specified then check the stream prefix and choose accordingly
    		if (format == FORMAT_UNKNOWN)
    		{
    			format = FORMAT_FLV;
    			String extStr = stream.getExt();
    			if (extStr.equals("mp4"))
    				format = FORMAT_MP4;
    		}
    		
    		String params = "stream:"+streamName;
    		params += " format:"+(format==FORMAT_MP4?"mp4":"flv");
    		params += " append:"+append;
    		if (outputPath != null)
    			params += " outputPath:"+outputPath;
    		else
    		{
    			File writeFile = stream.getStreamFileForWrite();
    			params += " outputPath:"+writeFile.getAbsolutePath();
    		}
    		params += " versionFile:"+versionFile;
    		params += " startOnKeyFrame:"+startOnKeyFrame;
    		params += " recordData:"+recordData;
    		
    		getLogger().info("ModuleStreamRecord.startRecording: "+params);
    		
    		// create a stream recorder and save it in a map of recorders
    		ILiveStreamRecord recorder = null;
    		
    		// create the correct recorder based on format
    		if (format == FORMAT_MP4)
    			recorder = new LiveStreamRecorderMP4();
    		else
    			recorder = new LiveStreamRecorderFLV();
    		
    		// add it to the recorders list
    		ILiveStreamRecord prevRecorder = recorders.get(streamName);
    		if (prevRecorder != null)
    			prevRecorder.stopRecording();
    		recorders.put(streamName, recorder);
    		
    		// if you want to record data packets as well as video/audio
    		recorder.setRecordData(recordData);
    		
    		// Set to true if you want to version the previous file rather than overwrite it
    		recorder.setVersionFile(versionFile);
    		
    		// If recording only audio set this to false so the recording starts immediately
    		recorder.setStartOnKeyFrame(startOnKeyFrame);
    		
    		// start recording
    		recorder.startRecording(stream, outputPath, append);
    	}
    
    		@Override
    		public void onMediaStreamCreate(IMediaStream stream) {
    			stream.addClientListener(publishNotifier);
    		}
    
    		@Override
    		public void onMediaStreamDestroy(IMediaStream stream) {
    			stream.removeClientListener(publishNotifier);
    			if(!stream.isPlay()) {
    				ILiveStreamRecord recorder = recorders.remove(stream.getName());
    				if (recorder != null)
    					recorder.stopRecording();
    			}
    		}
    		
    	private class PublishNotifier implements IMediaStreamActionNotify {
    
    		@Override
    		public void onPause(IMediaStream stream, boolean isPause,
    				double location) {
    			// TODO Auto-generated method stub
    			
    		}
    
    		@Override
    		public void onPlay(IMediaStream stream, String streamName,
    				double playStart, double playLen, int playReset) {
    			// TODO Auto-generated method stub
    			
    		}
    
    		@Override
    		public void onPublish(IMediaStream stream, String streamName,
    				boolean isRecord, boolean isAppend) {
    			if(record)
    				appInstance.getVHost().getHandlerThreadPool().execute(new DoStartRecording(stream, streamName));
    		}
    
    		@Override
    		public void onSeek(IMediaStream stream, double location) {
    			// TODO Auto-generated method stub
    			
    		}
    
    		@Override
    		public void onStop(IMediaStream stream) {
    			// TODO Auto-generated method stub
    			
    		}
    
    		@Override
    		public void onUnPublish(IMediaStream stream, String streamName,
    				boolean isRecord, boolean isAppend) {
    			ILiveStreamRecord recorder = recorders.remove(streamName);
    
    			if (recorder != null)
    			{
    				// stop recording
    				recorder.stopRecording();
    			}
    		}
    	}
    	
    	private class DoStartRecording implements Runnable {
    		private IMediaStream stream;
    		private String streamName;
    		private DoStartRecording(IMediaStream stream, String streamName) {
    			this.stream = stream;
    			this.streamName = streamName;
    		}
    
    		public void run() {
    			List<String> mediaCasters = appInstance.getMediaCasterStreams().getMediaCasterNames();
    			if (mediaCasters.contains(streamName)) {
    				int lockCount = appInstance.getMediaCasterStreams().getMediaCaster(streamName).getLockCount();
    				if (lockCount > 0)
    					startRecording(stream);
    			}
    		}
    	}
    }
    is there any place where i can find a compiled version?
    This is the code from this post http://www.wowza.com/forums/showthre...e-name-control

  5. #5

    Default

    ok so i think i managed to compile this, wowza starts with no errors. But still the video files aren`t created hourly. I need to use this module for my recording app. Here is my videorecording Aplication.xml

    <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>record</StreamType>
    			<StorageDir>${com.wowza.wms.context.VHostConfigHome}/content</StorageDir>
    			<KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir>
    			<!-- LiveStreamPacketizers (separate with commas): cupertinostreamingpacketizer, smoothstreamingpacketizer, sanjosestreamingpacketizer, cupertinostreamingrepeater, smoothstreamingrepeater, sanjosestreamingrepeater, dvrstreamingpacketizer, dvrstreamingrepeater -->
    			<LiveStreamPacketizers></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></LiveStreamTranscoder>
    			<!-- [templatename].xml or ${SourceStreamName}.xml -->
    			<Templates>${SourceStreamName}.xml,transrate.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 -->
    
    			<!-- 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>
    
    			<!-- If this is a dvrstreamingrepeater, define ChunkOriginURL to point back to origin -->
    			<!-- And define Application/Repeater/OriginURL to point back to the origin -->
    			<Repeater>
    				<ChunkOriginURL></ChunkOriginURL>
    			</Repeater>
    
    			<!-- Properties for DVR -->
    			<Properties>
    			</Properties>
    		</DVR>
    
    		<!-- HTTPStreamers (separate with commas): cupertinostreaming, smoothstreaming, sanjosestreaming, dvrchunkstreaming -->
    		<HTTPStreamers>cupertinostreaming,smoothstreaming,sanjosestreaming</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>properties</Name>
    				<Description>Properties</Description>
    				<Class>com.wowza.wms.module.ModuleProperties</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>
     
    <Module>
    	<Name>ModuleMediaWriterFileMover</Name>
    	<Description>ModuleMediaWriterFileMover</Description>
    	<Class>com.wowza.wms.module.ModuleMediaWriterFileMover</Class>
    </Module> 
      <Module> 
                                    <Name>ModuleStreamRecord</Name> 
                                    <Description>File Management</Description> 
                                    <Class>streamrecord.hourly.monthlyrollover.ModuleStreamRecord</Class> 
                            </Module>
    
    		</Modules>
    		<!-- Properties defined here will be added to the IApplication.getProperties() and IApplicationInstance.getProperties() collections -->
    		<Properties>
    <Property>
    	<Name>fileMoverDestinationPath</Name>
    	<Value>${com.wowza.wms.context.VHostConfigHome}/content/acopy</Value>
    </Property>
    <Property>
    	<Name>fileMoverDeleteOriginal</Name>
    	<Value>false</Value>
    	<Type>Boolean</Type>
    </Property>
    <Property>
    	<Name>fileMoverVersionFile</Name>
    	<Value>true</Value>
    	<Type>Boolean</Type>
    </Property>
    <Property>
    				<Name>starHour</Name>
    				<Value>00</Value>
    				<Type>Integer</Type>
    			</Property>
    			<Property>
    				<Name>endHour</Name>
    				<Value>24</Value>
    				<Type>Integer</Type>
    			</Property>
    			<Property>
    				<Name>timezone</Name>
    				<Value>GMT-08:00</Value>
    				<Type>String</Type>
    			</Property>
    
    		</Properties>
    	</Application>
    </Root>
    Any ideas what i`m missing? Thanks!

  6. #6

    Default

    ok finally made it work. But there is one more problem i don`t understand.
    Right now i was recording from a webcam connected to a laptop in another location, but the power was cut off on the computer with the webcam. Now i have these 2 files in wowza content folder: file19.mp4 and file file19.mp4.tmp. If i want to see what happend in this recording i can`t because it says it`s corrupted. Is there any way wowza can close this file?
    Last edited by bizkit1; 04-05-2012 at 11:54 AM.

  7. #7

    Default

    There is not a way for Wowza to recover the file. There are some products that claim to recover corrupted .mp4 files, that you might try.

  8. #8

    Default

    I have a problem with this. I'm using it now to record a audio stream, Mp4 format hourly. All looks fine, but sometimes instead of 1 hour recording it records less (30 minutes, 8 minutes, 50 minutes...etc). In the wowza error log there is no error. Any ideea why?

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

    Default

    I don't.

    Richard

Posting Permissions

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