I tried that still doesnt work...
Am I missing a step or putting the jar in the wrong spot?
Do I need to tell it to load the jar or something in other than the Application.xml?
Error:
Code:
ERROR server comment - loadModFunctions: java.lang.ClassNotFoundException: streamrecord.hourly.monthlyrollover.ModuleStreamRecord
java.lang.ClassNotFoundException: streamrecord.hourly.monthlyrollover.ModuleStreamRecord
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:323)
at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at com.wowza.wms.util.ModuleUtils.addModuleToApp(Unknown Source)
at com.wowza.wms.util.ApplicationUtils.loadModules(Unknown Source)
at com.wowza.wms.util.ApplicationUtils.loadConfigFile(Unknown Source)
at com.wowza.wms.application.ApplicationInstance.loadConfig(Unknown Source)
at com.wowza.wms.application.ApplicationInstance.<init>(Unknown Source)
at com.wowza.wms.application.Application.getAppInstance(Unknown Source)
at com.wowza.wms.vhost.VHost.startStartupStreams(Unknown Source)
at com.wowza.wms.server.Server.startVHost(Unknown Source)
at com.wowza.wms.server.Server.startVHosts(Unknown Source)
at com.wowza.wms.server.Server.start(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at com.wowza.wms.bootstrap.Bootstrap.startServer(Unknown Source)
at com.wowza.wms.bootstrap.Bootstrap.main(Unknown Source)
INFO server comment - ModuleStreamRecord.onAppStart
Application.xml:
Code:
<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>ModuleLiveStreamRecord</Name>
<Description>ModuleLiveStreamRecord</Description>
<Class>com.wowza.wms.plugin.livestreamrecord.ModuleLiveStreamRecord</Class>
</Module>
<Module>
<Name>ModuleStreamRecord</Name>
<Description>File Management</Description>
<Class>streamrecord.hourly.monthlyrollover.ModuleStreamRecord</Class>
</Module>
Code in IDE:
Code:
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 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;
}
boolean record = false;
if (hourOfDay >= start && hourOfDay < end) {
record = true;
}
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) {
TimeZone tz = TimeZone.getTimeZone(timezone);
Calendar cal = Calendar.getInstance(tz);
hourOfDay = cal.get(Calendar.HOUR_OF_DAY);
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) {
// 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);
}
}
}
}
Structure on left side of IDE:
Code:
ModuleStreamRecord
-> src
- -> streamrecord.hourly.monthlyrollover
- - -> ModuleStreamRecord
IDE Output:
Code:
Buildfile: C:\Documents and Settings\Administrator\Documents\workspace\ModuleStreamRecord\build.xml
jar:
[jar] Building jar: C:\Program Files\Wowza Media Systems\Wowza Media Server 2.1.2\lib\ModuleStreamRecord.jar
BUILD SUCCESSFUL
I copied that .jar to the /usr/local/WowzaMediaServer/lib folder on my linux box (the one im running, and is giving this error)
What am I missing??