Wowza Streaming Engine Java API로 라이브 스트림 녹화를 시작하고 중지하십시오

Wowza Streaming Engine Java API로 라이브 스트림 녹화를 시작하고 중지하십시오

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

package io.github.sejoung;

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

import com.wowza.wms.amf.AMFPacket;
import com.wowza.wms.application.IApplicationInstance;
import com.wowza.wms.application.WMSProperties;
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.IModuleOnStream;
import com.wowza.wms.module.ModuleBase;
import com.wowza.wms.stream.IMediaStream;
import com.wowza.wms.stream.IMediaStreamActionNotify3;

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;
}

enum StreamType {
aac
}

class StreamListener implements IMediaStreamActionNotify3 {

@Override
public void onMetaData(IMediaStream stream, AMFPacket metaDataPacket) {
getLogger().info("onMetaData[" + stream.getContextStr() + "]: " + metaDataPacket.toString());
}

@Override
public void onPauseRaw(IMediaStream stream, boolean isPause, double location) {
getLogger()
.info("onPauseRaw[" + stream.getContextStr() + "]: isPause:" + isPause + " location:" + location);
}

@Override
public void onPause(IMediaStream stream, boolean isPause, double location) {
getLogger().info("onPause[" + stream.getContextStr() + "]: isPause:" + isPause + " location:" + location);
}

@Override
public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset) {
getLogger().info("onPlay[" + stream.getContextStr() + "]: playStart:" + playStart + " playLen:" + playLen
+ " playReset:" + playReset);
}

@Override
public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) {
getLogger().info("onPublish[" + stream.getContextStr() + "]: streamName:" + streamName + " isRecord:"
+ isRecord + " isAppend:" + isAppend + " StreamTranscoderList "
+ stream.getLiveStreamTranscoderList());

String type = streamName.substring(streamName.lastIndexOf("_") + 1);
getLogger().info("type: " + type);
// create a livestreamrecorder instance to create .mp4 files
if (StreamType.aac.toString().equals(type)) {
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
getLogger().info("--- startRecordingSegmentByDuration for 60 minutes");
// recorder.startRecordingSegmentByDuration(stream, null, null, 60 * 60 * 1000);
// start recording, create 1MB segments using default content path
// getLogger().info("--- startRecordingSegmentBySize for 1MB");
// recorder.startRecordingSegmentBySize(stream, null, null, 1024*1024);
// start recording, create new segment at 1:00am each day.
// getLogger().info("--- 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)
getLogger().info("--- startRecording");
recorder.startRecording(stream, false);

// log where the recording is being written
getLogger().info(
"onPublish[" + stream.getContextStr() + "]: new Recording started:" + recorder.getFilePath());
}

}

@Override
public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) {
getLogger().info("onUnPublish[" + stream.getContextStr() + "]: streamName:" + streamName + " isRecord:"
+ isRecord + " isAppend:" + isAppend);

String type = streamName.substring(streamName.lastIndexOf("_") + 1);

getLogger().info("type: " + type);

if (StreamType.aac.toString().equals(type)) {
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();
getLogger().info("onUnPublish[" + stream.getContextStr() + "]: File Closed:" + filepath);
}
} else {
getLogger().info("onUnPublish[" + stream.getContextStr() + "]: streamName:" + streamName
+ " stream recorder not found");
}
}

@Override
public void onSeek(IMediaStream stream, double location) {
getLogger().info("onSeek[" + stream.getContextStr() + "]: location:" + location);
}

@Override
public void onStop(IMediaStream stream) {
getLogger().info("onStop[" + stream.getContextStr() + "]: ");
}

@Override
public void onCodecInfoAudio(IMediaStream stream, MediaCodecInfoAudio codecInfoAudio) {
getLogger().info("onCodecInfoAudio[" + stream.getContextStr() + " Audio Codec"
+ codecInfoAudio.toCodecsStr() + "]: ");
}

@Override
public void onCodecInfoVideo(IMediaStream stream, MediaCodecInfoVideo codecInfoVideo) {
getLogger().info("onCodecInfoVideo[" + stream.getContextStr() + " Video Codec"
+ codecInfoVideo.toCodecsStr() + "]: ");
}
}

@Override
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);
}

@Override
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());
}
}
}

위에 코드를 작성한 후에 ant 빌드후 인스톨한 위치의 lib 아래 jar 파일을 업로드 하면 된다.

그 다음엔 서버를 완전 재기동 필요함

참조