你可以用LiveStreamRecordAPI和IMediaStreamActionNotify3接口写一个自定义的模块对一个直播流自动录制,当直播流进入wowza StreamEngine 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;
importcom.wowza.wms.livestreamrecord.model.ILiveStreamRecord;
importcom.wowza.wms.livestreamrecord.model.LiveStreamRecorderMP4;
importcom.wowza.wms.media.model.MediaCodecInfoAudio;
importcom.wowza.wms.media.model.MediaCodecInfoVideo;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.amf.AMFPacket;
importcom.wowza.wms.application.IApplicationInstance;
importcom.wowza.wms.application.WMSProperties;
public classModuleLiveStreamRecordAutoRecord extends ModuleBase implements IModuleOnStream
{
privateMap recorders = new HashMap();
privateIApplicationInstance appInstance;
publicvoid onAppStart(IApplicationInstance appInstance)
{
this.appInstance = appInstance;
}
classStreamListener implements IMediaStreamActionNotify3
{
publicvoid onMetaData(IMediaStream stream, AMFPacket metaDataPacket)
{
System.out.println("onMetaData["+ stream.getContextStr() + "]: " + metaDataPacket.toString());
}
publicvoid onPauseRaw(IMediaStream stream, boolean isPause, double location)
{
System.out.println("onPauseRaw["+ stream.getContextStr() + "]: isPause:" + isPause + "location:" + location);
}
publicvoid onPause(IMediaStream stream, boolean isPause, double location)
{
System.out.println("onPause["+ stream.getContextStr() + "]: isPause:" + isPause + "location:" + location);
}
publicvoid onPlay(IMediaStream stream, String streamName, double playStart, doubleplayLen, int playReset)
{
System.out.println("onPlay["+ stream.getContextStr() + "]: playStart:" + playStart + "playLen:" + playLen + " playReset:" + playReset);
}
publicvoid onPublish(IMediaStream stream, String streamName, boolean isRecord,boolean isAppend)
{
System.out.println("onPublish["+ stream.getContextStr() + "]: streamName:" + streamName + "isRecord:" + isRecord + " isAppend:" + isAppend);
//createa livestreamrecorder instance to create .mp4 files
ILiveStreamRecordrecorder = new LiveStreamRecorderMP4();
recorder.init(appInstance);
recorder.setRecordData(true);
recorder.setStartOnKeyFrame(true);
recorder.setVersionFile(true);
//add it to the recorders list
synchronized(recorders)
{
ILiveStreamRecordprevRecorder = 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 defaultcontent 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());
}
publicvoid onUnPublish(IMediaStream stream, String streamName, boolean isRecord,boolean isAppend)
{
System.out.println("onUnPublish["+ stream.getContextStr() + "]: streamName:" + streamName + "isRecord:" + isRecord + " isAppend:" + isAppend);
ILiveStreamRecordrecorder = null;
synchronized(recorders)
{
recorder= recorders.remove(streamName);
}
if(recorder != null)
{
//grab the current path to the recorded file
Stringfilepath = 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");
}
}
publicvoid onSeek(IMediaStream stream, double location)
{
System.out.println("onSeek["+ stream.getContextStr() + "]: location:" + location);
}
publicvoid onStop(IMediaStream stream)
{
System.out.println("onStop["+ stream.getContextStr() + "]: ");
}
publicvoid onCodecInfoAudio(IMediaStream stream,MediaCodecInfoAudio codecInfoAudio) {
System.out.println("onCodecInfoAudio["+ stream.getContextStr() + " Audio Codec" + codecInfoAudio.toCodecsStr()+ "]: ");
}
publicvoid onCodecInfoVideo(IMediaStream stream,MediaCodecInfoVideo codecInfoVideo) {
System.out.println("onCodecInfoVideo["+ stream.getContextStr() + " Video Codec" +codecInfoVideo.toCodecsStr() + "]: ");
}
}
publicvoid onStreamCreate(IMediaStream stream)
{
getLogger().info("onStreamCreate["+stream+"]:clientId:" + stream.getClientId());
IMediaStreamActionNotify3actionNotify = new StreamListener();
WMSPropertiesprops = stream.getProperties();
synchronized(props)
{
props.put("streamActionNotifier",actionNotify);
}
stream.addClientListener(actionNotify);
}
publicvoid onStreamDestroy(IMediaStream stream)
{
getLogger().info("onStreamDestroy["+stream+"]:clientId:" + stream.getClientId());
IMediaStreamActionNotify3actionNotify = null;
WMSPropertiesprops = stream.getProperties();
synchronized(props)
{
actionNotify= (IMediaStreamActionNotify3)stream.getProperties().get("streamActionNotifier");
}
if(actionNotify != null)
{
stream.removeClientListener(actionNotify);
getLogger().info("removeClientListener:" + stream.getSrc());
}
}
}
Wowza Streaming Engine 4是业界功能强大、API接口丰富的流媒体Server产品,采用它作为流媒体服务器产品的案例很多,直播、在线教育、IPTV都有它的用武之地。