command line JMX applet to start/stop recording via ModuleLiveStreamRecord

I want to use a command line JMX client to start/stop recording of a stream. I have successfully installed the module ModuleLiveStreamRecord. I can use a JMX GUI client to start and stop recording the stream. However, I am confused as to how I specify the correct parameters on the command line. I modified the code from here https://www.wowza.com/docs/how-to-set-up-a-command-line-interface-to-wowza-api-to-start-stop-vhost-using-jmx to add this capability.

I am using this command line:

./run.sh -jmx service:jmx:rmi://h264web.com:8084/jndi/rmi://h264web.com:8085/jmxrmi -user ****** -pass ******* startRecording defaultVHost:rtplive/definst rtplive 1.stream /root/foobar.mp4

I get this error when I do this:

“ERROR: doInvoke: javax.management.MBeanException: Cannot find operation recordStream”

Any ideas?

New code (added to code from here https://www.wowza.com/docs/how-to-set-up-a-command-line-interface-to-wowza-api-to-start-stop-vhost-using-jmx, and I’m omitting things like where I defined CMD_STARTRECORDING)

			else if (args[argOffset].equalsIgnoreCase(CMD_STARTRECORDING))
			{
				System.out.println("Record: #1) " + args[argOffset]+" #2) "+args[argOffset+1]+" #3) "+args[argOffset+2]+
							" #4) "+args[argOffset+3] );
				AppConextName context = new AppConextName(args[argOffset+1], true);
				String connectsName = MBEANNAME+":vHosts=VHosts,vHostName="+context.vhostName+",applications=Applications,applicationName="+context.appName+",applicationInstances=ApplicationInstances,applicationInstanceName="+context.appInstName+",name=ApplicationInstance";
				ObjectName connectsObjName = new ObjectName(connectsName);
				// pass 0 and true as second and third arguments
				Object[] arguments = {args[argOffset+2], "0", "true", args[argOffset+3]};
				String[] signature = {"java.lang.String", "int", "boolean", "java.lang.String"};
				[B]doInvoke(connection, connectsObjName, "recordStream", arguments, signature);[/B]
			}

Here is a screenshot of the GUI JMX client which shows the operations available and clearly one of them is marked as “recordStream”.

I’m really not sure, but I noticed your command line says “startRecording” but the screen shot shows an operation “recordStream”

Richard

The problem is that you are not going deep enough into the tree. you are stopping at appInstance instead of going to module/instance.

WowzaMediaServerPro:vHosts=VHosts,vHostName=defaultVHost,applications=Applications,applicationName=live,applicationInstances=ApplicationInstances,applicationInstanceName=definst,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

connectsName in your code should resolve to the same as the MBeanInfo / ObjectName value, in jconsole, for the MBean you are trying to work with.

The error is different. You are looking in the right place now but the method is wrong.

It looks like you are only passing 4 args to the recordStream method. If you haven’t modified ModuleLiveStreamRecord from the LiveStreamRecord package then it is expecting 7 args.

public void recordStream(String streamName, int format, boolean append, String outputPath, boolean versionFile, boolean startOnKeyFrame, boolean recordData)

The error is telling you that it cannot find a method with the signiture

public void recordStream(String, int, boolean, String)

final Object arguments = {args[argOffset+2], “0”, “true”, args[argOffset+3], true, true, true };

final String signature = {“java.lang.String”, “int”, “boolean”, “java.lang.String”, “boolean”, “boolean”, “boolean”};

arg 1 should be an int and arg 2 should be a boolean. You have them as Strings.

Latest version of the app:

import java.util.*;
import javax.management.*;
import javax.management.remote.*;
public class JMXCommandLine
{
	public static final String MBEANNAME = "WowzaMediaServerPro";
	public static final String CMD_STARTRECORDING = "recordStream";
	public static final String CMD_STOPRECORDING = "stopRecording";
	public static final String DEFAULT_VHOST = "_defaultVHost_";
	public static final String DEFAULT_APPLICATION = "_defapp_";
	public static final String DEFAULT_APPINSTANCE = "_definst_";
	public static class AppConextName
	{
		String vhostName = null;
		String appName = null;
		String appInstName = null;
		public AppConextName()
		{
		}
		public AppConextName(String fullname, final boolean startWithDefaults)
		{
			if (startWithDefaults)
			{
				vhostName = DEFAULT_VHOST;
				appName = DEFAULT_APPLICATION;
				appInstName = DEFAULT_APPINSTANCE;
			}
			final int qloc = fullname.indexOf(":");
			if (qloc >= 0)
			{
				vhostName = fullname.substring(0, qloc);
				fullname = fullname.substring(qloc+1);
			}
			else
				vhostName = DEFAULT_VHOST;
			if (fullname.length() > 0)
			{
				appName = fullname;
				final int sloc = fullname.indexOf("/");
				if (sloc >= 0)
				{
					appName = fullname.substring(0, sloc);
					appInstName = fullname.substring(sloc+1);
				}
			}
		}
		String getObjName()
		{
			String ret = "";
			while(true)
			{
				if (vhostName == null)
					break;
				ret += "vHosts=VHosts,vHostName="+vhostName;
				if (appName == null)
					break;
				ret += ",applications=Applications,applicationName="+appName;
				if (appInstName == null)
					break;
				ret += ",applicationInstances=ApplicationInstances,applicationInstanceName="+appInstName;
				break;
			}
			return ret;
		}
	}
	public static void printUsage()
	{
		System.out.println("");
		System.out.println("Usage:");
		System.out.println("");
		System.out.println("[command] -[switch [value]...] [command] [params...]");
		System.out.println("");
		System.out.println("Switches:");
		System.out.println("");
		System.out.println("  -jmx  [jmx-url]");
		System.out.println("  -user [jmx-username]");
		System.out.println("  -pass [jmx-password]");
		System.out.println("");
		System.out.println("Commands:");
		System.out.println("");
		System.out.println("  " + CMD_STARTRECORDING + " [vhost:application/appInstance] [stream-name] path");
		System.out.println("  " + CMD_STOPRECORDING + " [vhost:application/appInstance] [stream-name]");
		
		System.out.println("");
	}
	public static long objToLong(final Object valueObj)
	{
		long ret = 0;
		if (valueObj != null)
		{
			try
			{
				ret = Long.parseLong(valueObj.toString());
			}
			catch(final Exception e)
			{
			}
		}
		return ret;
	}
	public static Object doInvoke(final MBeanServerConnection connection, final ObjectName connectsObjName, final String cmdStr, final Object[] arguments, final String[] signature)
	{
		Object returnObj = null;
		try
		{
			returnObj = connection.invoke(connectsObjName, cmdStr, arguments, signature);
		}
		catch(final Exception e)
		{
			System.out.println("ERROR: doInvoke: "+e.toString());
		}
		return returnObj;
	}
	public static Object doGetAttribute(final MBeanServerConnection connection, final ObjectName connectsObjName, final String attributeName)
	{
		Object returnObj = null;
		try
		{
			returnObj = connection.getAttribute(connectsObjName, attributeName);
		}
		catch(final Exception e)
		{
		}
		return returnObj;
	}
	public static void main(final String[] args)
	{
		try
		{
			for(int i=0;i<args.length;i++)
				args[i] = args[i].trim();
			String host = "localhost";
			String username = null;
			String password = null;
			String jmxURL = "service:jmx:rmi://"+host+":8084/jndi/rmi://"+host+":8085/jmxrmi";
			int argOffset = 0;
			while(true)
			{
				if (argOffset >= args.length)
					break;
				if (!args[argOffset].startsWith("-"))
					break;
				if (args[argOffset].startsWith("-host"))
				{
					argOffset++;
					host = args[argOffset];
					jmxURL = "service:jmx:rmi://"+host+":8084/jndi/rmi://"+host+":8085/jmxrmi";
				}
				else if (args[argOffset].startsWith("-jmx"))
				{
					argOffset++;
					jmxURL = args[argOffset];
				}
				else if (args[argOffset].startsWith("-user"))
				{
					argOffset++;
					username = args[argOffset];
				}
				else if (args[argOffset].startsWith("-pass"))
				{
					argOffset++;
					password = args[argOffset];
				}
				argOffset++;
			}
			if (argOffset >= args.length)
			{
				printUsage();
				return;
			}
			// create a connection URL
			final JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
			final AppConextName context = new AppConextName(args[argOffset+1], true);
			final String connectsName = MBEANNAME+":vHosts=VHosts,vHostName="+context.vhostName+",applications=Applications,applicationName="+context.appName+",applicationInstances=ApplicationInstances,applicationInstanceName="+context.appInstName+",modules=Modules,module=ModuleLiveStreamRecord,name=Instance";
			System.out.println( "Using: " + connectsName );
			
			final ObjectName connectsObjName = new ObjectName(connectsName);
			
			// create a environment hash with username and password
			final Map<String, Object> env = new HashMap<String, Object>();
			if (username != null && password != null)
			{
				final String[] creds = {username, password};
				env.put(JMXConnector.CREDENTIALS, creds);
			}
			final JMXConnector connector = JMXConnectorFactory.connect(serviceURL, env);
			final MBeanServerConnection connection = connector.getMBeanServerConnection();
			if (connection == null)
			{
				System.out.println("ERROR: Cannot connect to JMX interface: "+jmxURL);
				return;
			}
			if (args[argOffset].equalsIgnoreCase(CMD_STARTRECORDING))
			{
				System.out.println("Record: #1) " + args[argOffset]+" #2) "+args[argOffset+1]+" #3) "+args[argOffset+2]+
							" #4) "+args[argOffset+3] );	
				// pass 0 and true as second and third arguments
				final Object[] arguments = {args[argOffset+2], "0", "true", args[argOffset+3], true, true, true };
				final String[] signature = {"java.lang.String", "int", "boolean", "java.lang.String", "boolean", "boolean", "boolean"};
				doInvoke(connection, connectsObjName, "recordStream", arguments, signature);
			}
			else if (args[argOffset].equalsIgnoreCase(CMD_STOPRECORDING))
			{
				System.out.println(args[argOffset]+" "+args[argOffset+1]);
				final Object[] arguments = {args[argOffset+2]};
				final String[] signature = {"java.lang.String"};
				doInvoke(connection, connectsObjName, "stopRecording", arguments, signature);
			}
			else
				System.out.println("ERROR: Command not recognized: "+args[argOffset]);
			}
		catch (final Exception e)
		{
			System.out.println("ERROR: "+e.toString());
		}
	}
}

With the following change

	if (args[argOffset].equalsIgnoreCase(CMD_STARTRECORDING))
	{
		System.out.println("Record: #1) " + args[argOffset]+" #2) "+args[argOffset+1]+" #3) "+args[argOffset+2]+
							" #4) "+args[argOffset+3] );	
		// pass 0 and true as second and third arguments
		[b]final Object[] arguments = {args[argOffset+2], 0, true, args[argOffset+3], true, true, true };[/b]
		final String[] signature = {"java.lang.String", "int", "boolean", "java.lang.String", "boolean", "boolean", "boolean"};
		doInvoke(connection, connectsObjName, "recordStream", arguments, signature);
	}

Before doing this you have to publish a live stream or start a MediaCaster stream in StreamManager. Then the stream, the application and tat application instance ( definst ) will exist.

Richard

The problem is that command by itself does not start the application instance. Run this command first:

java -cp . JMXCommandLine startAppInstance "live/_definst_"

That will start defaultVHost and the application/appInsance

Richard

Richard,

Yes, I named the switch for the command line that, but I do send the correct thing (“recordStream”), AFAICT, to the jmx server.

I think what I would like confirmation on more than anything is whether this is correct in my switches:

defaultVHost:rtplive/definst

In this code:


AppConextName context = new AppConextName(args[argOffset+1], true);
String connectsName = MBEANNAME+":vHosts=VHosts,vHostName="+context.vhostName+",applications=Applications,applicationName="+context.appName+",applicationInstances=ApplicationInstances,applicationInstanceName="+context.appInstName+",name=ApplicationInstance";
ObjectName connectsObjName = new ObjectName(connectsName);

I believe this is the correct way to address the module installed in the conf/rtplive/Application.xml file.

xrd@xrd:~$ grep -i record /usr/local/WowzaMediaServer/conf/rtplive/Application.xml

ModuleLiveStreamRecord

Can anyone confirm this?

I’m going to remove all the other functionality of this java program and then post the complete file to see if that provides more context for the problem.

Thanks,

Chris

I stripped the file down to what is below. If I run with this command line I get this:

./run.sh -jmx service:jmx:rmi://h264web.com:8084/jndi/rmi://h264web.com:8085/jmxrmi -user ***** -pass ***** recordStream _defaultVHost_:rtplive/_definst_ rtplive 1.stream /root/foobar.mp4
Record: #1) recordStream #2) _defaultVHost_:rtplive/_definst_ #3) rtplive #4) 1.stream
ERROR: doInvoke: javax.management.MBeanException: Cannot find operation recordStream

Here is the full program I am using:

import java.util.*;
import javax.management.*;
import javax.management.remote.*;
public class JMXCommandLine
{
	public static final String MBEANNAME = "WowzaMediaServerPro";
	public static final String CMD_STARTRECORDING = "recordStream";
	public static final String CMD_STOPRECORDING = "stopRecording";
	public static final String DEFAULT_VHOST = "_defaultVHost_";
	public static final String DEFAULT_APPLICATION = "_defapp_";
	public static final String DEFAULT_APPINSTANCE = "_definst_";
	public static class AppConextName
	{
		String vhostName = null;
		String appName = null;
		String appInstName = null;
		public AppConextName()
		{
		}
		public AppConextName(String fullname, boolean startWithDefaults)
		{
			if (startWithDefaults)
			{
				vhostName = DEFAULT_VHOST;
				appName = DEFAULT_APPLICATION;
				appInstName = DEFAULT_APPINSTANCE;
			}
			int qloc = fullname.indexOf(":");
			if (qloc >= 0)
			{
				vhostName = fullname.substring(0, qloc);
				fullname = fullname.substring(qloc+1);
			}
			else
				vhostName = DEFAULT_VHOST;
			if (fullname.length() > 0)
			{
				appName = fullname;
				int sloc = fullname.indexOf("/");
				if (sloc >= 0)
				{
					appName = fullname.substring(0, sloc);
					appInstName = fullname.substring(sloc+1);
				}
			}
		}
		String getObjName()
		{
			String ret = "";
			while(true)
			{
				if (vhostName == null)
					break;
				ret += "vHosts=VHosts,vHostName="+vhostName;
				if (appName == null)
					break;
				ret += ",applications=Applications,applicationName="+appName;
				if (appInstName == null)
					break;
				ret += ",applicationInstances=ApplicationInstances,applicationInstanceName="+appInstName;
				break;
			}
			return ret;
		}
	}
	public static void printUsage()
	{
		System.out.println("");
		System.out.println("Usage:");
		System.out.println("");
		System.out.println("[command] -[switch [value]...] [command] [params...]");
		System.out.println("");
		System.out.println("Switches:");
		System.out.println("");
		System.out.println("  -jmx  [jmx-url]");
		System.out.println("  -user [jmx-username]");
		System.out.println("  -pass [jmx-password]");
		System.out.println("");
		System.out.println("Commands:");
		System.out.println("");
		System.out.println("  " + CMD_STARTRECORDING + " [vhost:application/appInstance] [stream-name] path");
		System.out.println("  " + CMD_STOPRECORDING + " [vhost:application/appInstance] [stream-name]");
		
		System.out.println("");
	}
	public static long objToLong(Object valueObj)
	{
		long ret = 0;
		if (valueObj != null)
		{
			try
			{
				ret = Long.parseLong(valueObj.toString());
			}
			catch(Exception e)
			{
			}
		}
		return ret;
	}
	public static Object doInvoke(MBeanServerConnection connection, ObjectName connectsObjName, String cmdStr, Object[] arguments, String[] signature)
	{
		Object returnObj = null;
		try
		{
			returnObj = connection.invoke(connectsObjName, cmdStr, arguments, signature);
		}
		catch(Exception e)
		{
			System.out.println("ERROR: doInvoke: "+e.toString());
		}
		return returnObj;
	}
	public static Object doGetAttribute(MBeanServerConnection connection, ObjectName connectsObjName, String attributeName)
	{
		Object returnObj = null;
		try
		{
			returnObj = connection.getAttribute(connectsObjName, attributeName);
		}
		catch(Exception e)
		{
		}
		return returnObj;
	}
	public static void main(String[] args)
	{
		try
		{
			for(int i=0;i<args.length;i++)
				args[i] = args[i].trim();
			String host = "localhost";
			String username = null;
			String password = null;
			String jmxURL = "service:jmx:rmi://"+host+":8084/jndi/rmi://"+host+":8085/jmxrmi";
			int argOffset = 0;
			while(true)
			{
				if (argOffset >= args.length)
					break;
				if (!args[argOffset].startsWith("-"))
					break;
				if (args[argOffset].startsWith("-host"))
				{
					argOffset++;
					host = args[argOffset];
					jmxURL = "service:jmx:rmi://"+host+":8084/jndi/rmi://"+host+":8085/jmxrmi";
				}
				else if (args[argOffset].startsWith("-jmx"))
				{
					argOffset++;
					jmxURL = args[argOffset];
				}
				else if (args[argOffset].startsWith("-user"))
				{
					argOffset++;
					username = args[argOffset];
				}
				else if (args[argOffset].startsWith("-pass"))
				{
					argOffset++;
					password = args[argOffset];
				}
				argOffset++;
			}
			if (argOffset >= args.length)
			{
				printUsage();
				return;
			}
			// create a connection URL
			JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
			// create a environment hash with username and password
			Map<String, Object> env = new HashMap<String, Object>();
			if (username != null && password != null)
			{
				String[] creds = {username, password};
				env.put(JMXConnector.CREDENTIALS, creds);
			}
			JMXConnector connector = JMXConnectorFactory.connect(serviceURL, env);
			MBeanServerConnection connection = connector.getMBeanServerConnection();
			if (connection == null)
			{
				System.out.println("ERROR: Cannot connect to JMX interface: "+jmxURL);
				return;
			}
			if (args[argOffset].equalsIgnoreCase(CMD_STARTRECORDING))
			{
				System.out.println("Record: #1) " + args[argOffset]+" #2) "+args[argOffset+1]+" #3) "+args[argOffset+2]+
							" #4) "+args[argOffset+3] );
				AppConextName context = new AppConextName(args[argOffset+1], true);
				String connectsName = MBEANNAME+":vHosts=VHosts,vHostName="+context.vhostName+",applications=Applications,applicationName="+context.appName+",applicationInstances=ApplicationInstances,applicationInstanceName="+context.appInstName+",name=ApplicationInstance";
				ObjectName connectsObjName = new ObjectName(connectsName);
				// pass 0 and true as second and third arguments
				Object[] arguments = {args[argOffset+2], "0", "true", args[argOffset+3]};
				String[] signature = {"java.lang.String", "int", "boolean", "java.lang.String"};
				doInvoke(connection, connectsObjName, "recordStream", arguments, signature);
			}
			else if (args[argOffset].equalsIgnoreCase(CMD_STOPRECORDING))
			{
				System.out.println(args[argOffset]+" "+args[argOffset+1]);
				AppConextName context = new AppConextName(args[argOffset+1], true);
				String connectsName = MBEANNAME+":vHosts=VHosts,vHostName="+context.vhostName+",applications=Applications,applicationName="+context.appName+",applicationInstances=ApplicationInstances,applicationInstanceName="+context.appInstName+",name=ApplicationInstance";
				ObjectName connectsObjName = new ObjectName(connectsName);
				Object[] arguments = {args[argOffset+2]};
				String[] signature = {"java.lang.String"};
				doInvoke(connection, connectsObjName, "stopMediaCasterStream", arguments, signature);
			}
			else
				System.out.println("ERROR: Command not recognized: "+args[argOffset]);
			}
		catch (Exception e)
		{
			System.out.println("ERROR: "+e.toString());
		}
	}
}

Anyone interested in installing this module and seeing if it works for them using the parameters I specified? I am thinking there is something related to the parameter:

defaultVHost:rtplive/definst

Roger,

Thanks for your help.

I think I am closer. I put a line to print out the “Object Name” inside my code (on line 233). When I run it, I get this now:

Using: WowzaMediaServerPro:vHosts=VHosts,vHostName=_defaultVHost_,applications=Applications,applicationName=rtplive,applicationInstances=ApplicationInstances,applicationInstanceName=_definst_,modules=Modules,module=ModuleLiveStreamRecord,name=Instance
ERROR: doInvoke: javax.management.ReflectionException: Cannot find method recordStream with this signature

So, still have an issue. But, if I look at the JMX console and view the string inside Object Name, I see this:

WowzaMediaServerPro:vHosts=VHosts,vHostName=defaultVHost,applications=Applications,applicationName=rtplive,applicationInstances=ApplicationInstances,applicationInstanceName=definst,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

Which is exactly the same as what I get when I print it out inside my java app.

WowzaMediaServerPro:vHosts=VHosts,vHostName=defaultVHost,applications=Applications,applicationName=rtplive,applicationInstances=ApplicationInstances,applicationInstanceName=definst,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

Enclosed is the screenshot of where I am looking inside the JMX console. And, I can see that there is an operation “recordStream” exposed there, but the app says “Can’t find method…”

Chris

More specifically it says “cannot find method with signature.”

I’m thinking I am getting closer. If I run the stopRecording command (after correcting a typo…), no complaints.

I changed the signature line in the code so the code has a signature like exposed in the JMX console.

But, now I get:

“ERROR: doInvoke: javax.management.MBeanException: Exception invoking method recordStream”

Latest version of the app:

import java.util.*;
import javax.management.*;
import javax.management.remote.*;
public class JMXCommandLine
{
	public static final String MBEANNAME = "WowzaMediaServerPro";
	public static final String CMD_STARTRECORDING = "recordStream";
	public static final String CMD_STOPRECORDING = "stopRecording";
	public static final String DEFAULT_VHOST = "_defaultVHost_";
	public static final String DEFAULT_APPLICATION = "_defapp_";
	public static final String DEFAULT_APPINSTANCE = "_definst_";
	public static class AppConextName
	{
		String vhostName = null;
		String appName = null;
		String appInstName = null;
		public AppConextName()
		{
		}
		public AppConextName(String fullname, final boolean startWithDefaults)
		{
			if (startWithDefaults)
			{
				vhostName = DEFAULT_VHOST;
				appName = DEFAULT_APPLICATION;
				appInstName = DEFAULT_APPINSTANCE;
			}
			final int qloc = fullname.indexOf(":");
			if (qloc >= 0)
			{
				vhostName = fullname.substring(0, qloc);
				fullname = fullname.substring(qloc+1);
			}
			else
				vhostName = DEFAULT_VHOST;
			if (fullname.length() > 0)
			{
				appName = fullname;
				final int sloc = fullname.indexOf("/");
				if (sloc >= 0)
				{
					appName = fullname.substring(0, sloc);
					appInstName = fullname.substring(sloc+1);
				}
			}
		}
		String getObjName()
		{
			String ret = "";
			while(true)
			{
				if (vhostName == null)
					break;
				ret += "vHosts=VHosts,vHostName="+vhostName;
				if (appName == null)
					break;
				ret += ",applications=Applications,applicationName="+appName;
				if (appInstName == null)
					break;
				ret += ",applicationInstances=ApplicationInstances,applicationInstanceName="+appInstName;
				break;
			}
			return ret;
		}
	}
	public static void printUsage()
	{
		System.out.println("");
		System.out.println("Usage:");
		System.out.println("");
		System.out.println("[command] -[switch [value]...] [command] [params...]");
		System.out.println("");
		System.out.println("Switches:");
		System.out.println("");
		System.out.println("  -jmx  [jmx-url]");
		System.out.println("  -user [jmx-username]");
		System.out.println("  -pass [jmx-password]");
		System.out.println("");
		System.out.println("Commands:");
		System.out.println("");
		System.out.println("  " + CMD_STARTRECORDING + " [vhost:application/appInstance] [stream-name] path");
		System.out.println("  " + CMD_STOPRECORDING + " [vhost:application/appInstance] [stream-name]");
		
		System.out.println("");
	}
	public static long objToLong(final Object valueObj)
	{
		long ret = 0;
		if (valueObj != null)
		{
			try
			{
				ret = Long.parseLong(valueObj.toString());
			}
			catch(final Exception e)
			{
			}
		}
		return ret;
	}
	public static Object doInvoke(final MBeanServerConnection connection, final ObjectName connectsObjName, final String cmdStr, final Object[] arguments, final String[] signature)
	{
		Object returnObj = null;
		try
		{
			returnObj = connection.invoke(connectsObjName, cmdStr, arguments, signature);
		}
		catch(final Exception e)
		{
			System.out.println("ERROR: doInvoke: "+e.toString());
		}
		return returnObj;
	}
	public static Object doGetAttribute(final MBeanServerConnection connection, final ObjectName connectsObjName, final String attributeName)
	{
		Object returnObj = null;
		try
		{
			returnObj = connection.getAttribute(connectsObjName, attributeName);
		}
		catch(final Exception e)
		{
		}
		return returnObj;
	}
	public static void main(final String[] args)
	{
		try
		{
			for(int i=0;i<args.length;i++)
				args[i] = args[i].trim();
			String host = "localhost";
			String username = null;
			String password = null;
			String jmxURL = "service:jmx:rmi://"+host+":8084/jndi/rmi://"+host+":8085/jmxrmi";
			int argOffset = 0;
			while(true)
			{
				if (argOffset >= args.length)
					break;
				if (!args[argOffset].startsWith("-"))
					break;
				if (args[argOffset].startsWith("-host"))
				{
					argOffset++;
					host = args[argOffset];
					jmxURL = "service:jmx:rmi://"+host+":8084/jndi/rmi://"+host+":8085/jmxrmi";
				}
				else if (args[argOffset].startsWith("-jmx"))
				{
					argOffset++;
					jmxURL = args[argOffset];
				}
				else if (args[argOffset].startsWith("-user"))
				{
					argOffset++;
					username = args[argOffset];
				}
				else if (args[argOffset].startsWith("-pass"))
				{
					argOffset++;
					password = args[argOffset];
				}
				argOffset++;
			}
			if (argOffset >= args.length)
			{
				printUsage();
				return;
			}
			// create a connection URL
			final JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
			final AppConextName context = new AppConextName(args[argOffset+1], true);
			final String connectsName = MBEANNAME+":vHosts=VHosts,vHostName="+context.vhostName+",applications=Applications,applicationName="+context.appName+",applicationInstances=ApplicationInstances,applicationInstanceName="+context.appInstName+",modules=Modules,module=ModuleLiveStreamRecord,name=Instance";
			System.out.println( "Using: " + connectsName );
			
			final ObjectName connectsObjName = new ObjectName(connectsName);
			
			// create a environment hash with username and password
			final Map<String, Object> env = new HashMap<String, Object>();
			if (username != null && password != null)
			{
				final String[] creds = {username, password};
				env.put(JMXConnector.CREDENTIALS, creds);
			}
			final JMXConnector connector = JMXConnectorFactory.connect(serviceURL, env);
			final MBeanServerConnection connection = connector.getMBeanServerConnection();
			if (connection == null)
			{
				System.out.println("ERROR: Cannot connect to JMX interface: "+jmxURL);
				return;
			}
			if (args[argOffset].equalsIgnoreCase(CMD_STARTRECORDING))
			{
				System.out.println("Record: #1) " + args[argOffset]+" #2) "+args[argOffset+1]+" #3) "+args[argOffset+2]+
							" #4) "+args[argOffset+3] );	
				// pass 0 and true as second and third arguments
				final Object[] arguments = {args[argOffset+2], "0", "true", args[argOffset+3], true, true, true };
				final String[] signature = {"java.lang.String", "int", "boolean", "java.lang.String", "boolean", "boolean", "boolean"};
				doInvoke(connection, connectsObjName, "recordStream", arguments, signature);
			}
			else if (args[argOffset].equalsIgnoreCase(CMD_STOPRECORDING))
			{
				System.out.println(args[argOffset]+" "+args[argOffset+1]);
				final Object[] arguments = {args[argOffset+2]};
				final String[] signature = {"java.lang.String"};
				doInvoke(connection, connectsObjName, "stopRecording", arguments, signature);
			}
			else
				System.out.println("ERROR: Command not recognized: "+args[argOffset]);
			}
		catch (final Exception e)
		{
			System.out.println("ERROR: "+e.toString());
		}
	}
}

Roger,

Does it show that I have a background in Perl and Ruby, languages which do that for me? :slight_smile:

Thanks so much for your help. All is well now!

Chris

Nice write up,

however i get the error

Error: Could not find or load main class JMXCommandLine

when i schedule a cron job, but if i run the command at shell all it ok

and yes i have compile the files i get two files JMXCommandLine.class & JMXCommandLine$AppConextName.class that are placed in the /usr/ directory

command used

/usr/./jmxcl.sh -jmx service:jmx:rmi://localhost:8084/jndi/rmi://localhost:8085/jmxrmi -user admin -pass admin recordStream defaultVHost:test/definst test /usr/local/WowzaMediaServer/content/test.flv true true true

where am i going wrong?

figured it out thanks guys

Maybe you could be so gentle and share the final code of your application and command lines to control?

Now seems it’s working, but I guess this script is for Wowza 2.0. Can it work with Wowza 1.7 ?

I’m not able to configure the starting line.

LiveStreamRecord works

with

Server: rtmp://my-ip/test

Stream: udp://0.0.0.0:13707

I’m trying to start with:

jmxcl -jmx service:jmx:rmi://localhost:8084/jndi/

rmi://localhost:8085/jmxrmi -user admin -pass **** recordStream defaultVHost:

test/definst test 1.stream foobar.mp4

And I’m getting error

c:\Program Files\Java\jre6\bin>jmxcl -jmx service:jmx:rmi://localhost:8084/jndi/
rmi://localhost:8085/jmxrmi -user admin -pass admin recordStream _defaultVHost_:
test/_definst_ test 1.stream foobar.mp4
c:\Program Files\Java\jre6\bin>java -cp . JMXCommandLine -jmx service:jmx:rmi://
localhost:8084/jndi/rmi://localhost:8085/jmxrmi -user admin -pass **** recordSt
ream _defaultVHost_:test/_definst_ test 1.stream foobar.mp4
Using: WowzaMediaServerPro:vHosts=VHosts,vHostName=_defaultVHost_,applications=A
pplications,applicationName=test,applicationInstances=ApplicationInstances,appli
cationInstanceName=_definst_,modules=Modules,module=ModuleLiveStreamRecord,name=
Instance
Record: #1) recordStream #2) _defaultVHost_:test/_definst_ #3) test #4) 1.stream
ERROR: doInvoke: javax.management.InstanceNotFoundException: WowzaMediaServerPro
:vHosts=VHosts,vHostName=_defaultVHost_,applications=Applications,applicationNam
e=test,applicationInstances=ApplicationInstances,applicationInstanceName=_defins
t_,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

Hi everyone, I’ve tried this java class to record video-stream from my WowzaMediaServer

and I got the same error

Tried on Widows,Ubuntu ; used Wowsa 2.2.4 and 2.2.0 => problem is still not solved

ERROR: doInvoke: javax.management.InstanceNotFoundException: WowzaMediaServerPro

:vHosts=VHosts,vHostName=defaultVHost,applications=Applications,applicationNam

e=test,applicationInstances=ApplicationInstances,applicationInstanceName=_defins

t_,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

any ideas?

HI, I am trying it , bur getting below error:–

Using: WowzaMediaServerPro:vHosts=VHosts,vHostName=defaultVHost,applications=Applications,applicationName=nexgorigin,applicationInstances=ApplicationInstances,applicationInstanceName=definst,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

Record: #1) recordStream #2) defaultVHost:test/definst #3) test.sdp #4) abc.mp4

ERROR: doInvoke: javax.management.InstanceNotFoundException: WowzaMediaServerPro:vHosts=VHosts,vHostName=defaultVHost,applications=Applications,applicationName=nexgorigin,applicationInstances=ApplicationInstances,applicationInstanceName=definst,modules=Modules,module=ModuleLiveStreamRecord,name=Instance

Please note:-Stream already published from the streammanager.

Can some one please help in this regard.

Dsingh