流媒体技术世界——分享技术,增值服务
如何自动对直播流进行录制?
你可以用LiveStreamRecordAPI和IMediaStreamActionNotify3接口写一个自定义的模块对一个直播流自动录制,当直播流进入wowza Stream Engine 4时自动录制,当直播流停止时自动停止录制。

注意: 适用Wowza Media Server® 3.5.0及更高版本。

关于LiveStreamRecordAutoRecord 例子代码


LiveStreamRecordAutoRecord 例子代码使用了startRecordSegmentByDuration API按每隔60分钟的播放时长自动对直播流进行分割。下面的代码录制了一个应用的每一个直播流。
Code:
package com.wowza.wms.example.module;

import java.util.HashMap;
import java.util.Map;

import com.wowza.wms.livestreamrecord.model.ILiveStreamRecord;
import com.wowza.wms.livestreamrecord.model.LiveStreamRecorderMP4;
import com.wowza.wms.media.model.MediaCodecInfoAudio;
import com.wowza.wms.media.model.MediaCodecInfoVideo;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.amf.AMFPacket;
import com.wowza.wms.application.IApplicationInstance;
import com.wowza.wms.application.WMSProperties;

public class ModuleLiveStreamRecordAutoRecord extends ModuleBase implements IModuleOnStream
{
	private Map<String, ILiveStreamRecord> recorders = new HashMap<String, ILiveStreamRecord>();
	private IApplicationInstance appInstance;
	
	
	public void onAppStart(IApplicationInstance appInstance)
	{
     	this.appInstance = appInstance;
	}
	
	class StreamListener implements IMediaStreamActionNotify3
	{
		public void onMetaData(IMediaStream stream, AMFPacket metaDataPacket)
		{
			System.out.println("onMetaData[" + stream.getContextStr() + "]: " + metaDataPacket.toString());
		}

		public void onPauseRaw(IMediaStream stream, boolean isPause, double location)
		{
			System.out.println("onPauseRaw[" + stream.getContextStr() + "]: isPause:" + isPause + " location:" + location);
		}

		public void onPause(IMediaStream stream, boolean isPause, double location)
		{
			System.out.println("onPause[" + stream.getContextStr() + "]: isPause:" + isPause + " location:" + location);
		}

		public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset)
		{
			System.out.println("onPlay[" + stream.getContextStr() + "]: playStart:" + playStart + " playLen:" + playLen + " playReset:" + playReset);
		}

		public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend)
		{
			System.out.println("onPublish[" + stream.getContextStr() + "]: streamName:" + streamName + " isRecord:" + isRecord + " isAppend:" + isAppend);
			//create a livestreamrecorder instance to create .mp4 files
			ILiveStreamRecord recorder = new LiveStreamRecorderMP4();
		    recorder.init(appInstance);
		    recorder.setRecordData(true);
		    recorder.setStartOnKeyFrame(true);
		    recorder.setVersionFile(true);
		       
			// add it to the recorders list
			synchronized (recorders)
			{
				ILiveStreamRecord prevRecorder = recorders.get(streamName);
				if (prevRecorder != null)
					prevRecorder.stopRecording();
				recorders.put(streamName, recorder);
			}
			// start recording, create 1 minute segments using default content path
			System.out.println("--- startRecordingSegmentByDuration for 60 minutes");
			recorder.startRecordingSegmentByDuration(stream, null, null, 60*60*1000);
			// start recording, create 1MB segments using default content path
			//System.out.println("--- startRecordingSegmentBySize for 1MB");
			//recorder.startRecordingSegmentBySize(stream, null, null, 1024*1024);
			// start recording, create new segment at 1:00am each day.
			//System.out.println("--- startRecordingSegmentBySchedule every "0 1 * * * *");
			//recorder.startRecordingSegmentBySchedule(stream, null, null, "0 1 * * * *");
			
		    // start recording, using the default content path, do not append (i.e. overwrite if file exists)
			//System.out.println("--- startRecording");
		    //recorder.startRecording(stream, false);
		    
		    // log where the recording is being written
			System.out.println("onPublish[" + stream.getContextStr() + "]: new Recording started:" + recorder.getFilePath());
		}
        
		public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend)
		{
			System.out.println("onUnPublish[" + stream.getContextStr() + "]: streamName:" + streamName + " isRecord:" + isRecord + " isAppend:" + isAppend);
			
			ILiveStreamRecord recorder = null;
			synchronized (recorders)
			{
				recorder = recorders.remove(streamName);
			}
			
			if (recorder != null)
			{
				// grab the current path to the recorded file
				String filepath = recorder.getFilePath();
				
				// stop recording
				recorder.stopRecording();
				System.out.println("onUnPublish[" + stream.getContextStr() + "]: File Closed:" + filepath);
			}
			else
			{
				System.out.println("onUnPublish[" + stream.getContextStr() + "]: streamName:" + streamName + " stream recorder not found");
			}
		}
		
		public void onSeek(IMediaStream stream, double location)
		{
			System.out.println("onSeek[" + stream.getContextStr() + "]: location:" + location);
		}

		public void onStop(IMediaStream stream)
		{
			System.out.println("onStop[" + stream.getContextStr() + "]: ");
		}

		public void onCodecInfoAudio(IMediaStream stream,MediaCodecInfoAudio codecInfoAudio) {
			System.out.println("onCodecInfoAudio[" + stream.getContextStr() + " Audio Codec" + codecInfoAudio.toCodecsStr() + "]: ");
		}

		public void onCodecInfoVideo(IMediaStream stream,MediaCodecInfoVideo codecInfoVideo) {
			System.out.println("onCodecInfoVideo[" + stream.getContextStr() + " Video Codec" + codecInfoVideo.toCodecsStr() + "]: ");
		}
	}

	public void onStreamCreate(IMediaStream stream)
	{
		getLogger().info("onStreamCreate["+stream+"]: clientId:" + stream.getClientId());
		IMediaStreamActionNotify3 actionNotify = new StreamListener();

		WMSProperties props = stream.getProperties();
		synchronized (props)
		{
			props.put("streamActionNotifier", actionNotify);
		}
		stream.addClientListener(actionNotify);
	}

	public void onStreamDestroy(IMediaStream stream)
	{
		getLogger().info("onStreamDestroy["+stream+"]: clientId:" + stream.getClientId());

		IMediaStreamActionNotify3 actionNotify = null;
		WMSProperties props = stream.getProperties();
		synchronized (props)
		{
			actionNotify = (IMediaStreamActionNotify3) stream.getProperties().get("streamActionNotifier");
		}
		if (actionNotify != null)
		{
			stream.removeClientListener(actionNotify);
			getLogger().info("removeClientListener: " + stream.getSrc());
		}
	}
}     
www.ttstream.com
注意: When using this module, streams must have a unique name within the application. If a duplicate stream name is used, the existing recording associated with the current stream name will be stopped and a new recording will be started for the duplicate stream name.

Using the LiveStreamRecordAutoRecord module with the "live" application


To install and configure the module

  1. Compile the above code and then copy the .jar file to the [install-dir]/lib/ folder.
  2. Create an application folder named [install-dir]/applications/live.
  3. Create a configuration folder [install-dir]/conf/live and copy [install-dir]/conf/Application.xml to this new folder.
  4. Open [install-dir]/conf/live/Application.xml in a text editor then
    • change /Streams /StreamType to "live"
    • add the following module definition as the last entry in the <Modules> list:
      Code:
      <Module>
           <Name>ModuleLiveStreamRecordAutoRecord</Name>
           <Description>ModuleLiveStreamRecordAutoRecord</Description>
           <Class>com.wowza.wms.example.module.ModuleLiveStreamRecordAutoRecord</Class>
      </Module>
  5. If Wowza Media Server was running, restart the server.
  6. Live streams that are sent to the live application will be recorded automatically to [install-dir]/content.
匿名用户
评论

我们的地址


北京市朝阳区管庄西里建基商务楼423室


邮编:100024

关于我们


北京联方信科信息技术有限责任公司


官网:www.ttstream.com

联系我们


王经理:phone


柳经理:phone

京ICP备14033868号-2