Runtime.getRuntime().exec() not working in a module

Hi,

I need to run a process using java’s Runtime.getRuntime().exec() when a stream gets unPublished. So I implemented IMediaStreamActionNotify3 on my Module and registered the notifier with the stream. In onUnPublish(), I tried to execute Runtime.getRuntime().exec(). As i can see, it starts the process, but execution of the created process just hangs(i can see process name in my taskmanager with 0% cpu and no change in memory). If I close the instance of the server, the created process executes and gives me desired output.

Note : Am running wowza in windows 8/64 bit. Behaviour is same if i run server instance from eclipse or as standalone application(startup.bat) . If i execute the same command through simple java class with a main() method, it just works fine.

Command i was executing was:

"ffmpeg -y -i in.mp4 -i in2.mp4 -filter_complex “[0] trim=start=40:end=70:duration=30, setpts=PTS-STARTPTS, scale=512:288 [v2] ;[0] trim=start=60:end=80:duration=20, setpts=PTS-STARTPTS, scale=512:288 [v1] ; [1] trim=start=0:end=30:duration=30, setpts=PTS-STARTPTS, scale=512:288 [v4] ; [1] trim=start=20:end=40:duration=20, setpts=PTS-STARTPTS, scale=512:288 [v3] ; [v2][v4][v1][v3] concat=n=4:v=1:a=0 [outv]; [0] atrim=start=40:end=70:duration=30, asetpts=PTS-STARTPTS [a2] ;[0] atrim=start=60:end=80:duration=20, asetpts=PTS-STARTPTS [a1] ; [1] atrim=start=0:end=30:duration=30, asetpts=PTS-STARTPTS [a4] ; [1] atrim=start=20:end=40:duration=20, asetpts=PTS-STARTPTS [a3]; [a2][a4][a1][a3] concat=n=4:v=0:a=1 [outa] " -map [outv] -map [outa] -profile:v main -level 3.1 -b:v 440k -ar 48000 -ab 128k -s 720x400 -vcodec h264 -acodec libvo_aacenc test.mp4”

ffmpeg with 2 input files(usage of -i twice): ffmpeg hangs till i close server instance and once i close server, works fine

Other command(works fine):

"ffmpeg -y -i in.mp4 -filter_complex “[0] trim=start=40:end=70:duration=30, setpts=PTS-STARTPTS, scale=512:288 [v2] ;[0] trim=start=60:end=80:duration=20, setpts=PTS-STARTPTS, scale=512:288 [v1] ; movie=in2.mp4, trim=start=0:end=30:duration=30, setpts=PTS-STARTPTS, scale=512:288 [v4] ; movie=in2.mp4, trim=start=20:end=40:duration=20, setpts=PTS-STARTPTS, scale=512:288 [v3] ; [v2][v4][v1][v3] concat=n=4:v=1:a=0 [outv]; [0] atrim=start=40:end=70:duration=30, asetpts=PTS-STARTPTS [a2] ;[0] atrim=start=60:end=80:duration=20, asetpts=PTS-STARTPTS [a1] ; amovie=in2.mp4, atrim=start=0:end=30:duration=30, asetpts=PTS-STARTPTS [a4] ; amovie=in2.mp4, atrim=start=20:end=40:duration=20, asetpts=PTS-STARTPTS [a3]; [a2][a4][a1][a3] concat=n=4:v=0:a=1 [outa] " -map [outv] -map [outa] -profile:v main -level 3.1 -b:v 440k -ar 48000 -ab 128k -s 720x400 -vcodec h264 -acodec libvo_aacenc test.mp4”

ffmpeg with 1 input file(usage of -i once. 2nd input is used with movie/amovie filter option, a work around to replace usage of -i option): ffmpeg executes normal

Both commands works fine from a simple java class with main() method(as module is java class too i expect both the commands to work on wowza module too). What difference it makes to execution if i supply ffmpeg 2 inputs(-i twice) through wowza module? Can there be any memory/cpu usage contrains on my newly created process by the instance of wowza server?

Krishna

Hi Krishna,

I’m not really sure why it is working in some cases but not others but this appropriately named article, When Runtime.exec() won’t, may indicate why.

In the past, I have used ProcessBuilder instead of Runtime.exec() in a separate thread to run external processes from within Wowza.

The following is a class that I have used previously to write a series of timestamped images out to an mp4 file. It was run every 24 hours on a timer thread to process the images. I know it is different to what you are doing but it does show how to invoke ffmpeg from within wowza using ProcessBuilder.

	private class TimeLapseWriter extends Thread {
		Calendar cal;
		File filePath;
		private TimeLapseWriter(File filePath) {
			cal = Calendar.getInstance();
			this.filePath = filePath;
			cal.add(Calendar.DATE, -1);
		}
		public void run() {
			String yesterday = dateFormat.format(cal.getTime());
			File yesterdaysFolder = new File(filePath.getAbsolutePath()
					+ File.separator + yesterday);
			if (yesterdaysFolder.exists()) {
				try {
					File outFolder = new File(appInstance
							.getStreamStoragePath()
							+ File.separator + yesterday);
					if (!outFolder.exists())
						outFolder.mkdirs();
					String[] parts = fileName.split("\\.");
					String ffmpegPath = props.getPropertyStr("ffmpegPath",
							"/usr/bin/ffmpeg");
					String[] execStr = {
							ffmpegPath,
							"-f",
							"image2",
							"-r",
							"10",
							"-i",
							yesterdaysFolder.getAbsolutePath() + File.separator
									+ parts[0] + "%04d." + parts[1],
							"-vcodec",
							"libx264",
							"-vpre",
							"default",
							"-vpre",
							"baseline",
							"-s",
							"512x288",
							outFolder.getAbsolutePath() + File.separator
									+ streamName + ".mp4" };
					for (String arg : execStr)
						System.out.println(arg);
					ProcessBuilder pb = new ProcessBuilder(execStr);
//					pb.environment().put("LD_LIBRARY_PATH",
//							"/usr/local/av/lib:/usr/lib:/lib");
//					pb
//							.environment()
//							.put("PATH",
//									"/usr/local/av/bin:/usr/kerberos/bin:/usr/bin:/bin:/usr/sbin:/sbin");
					pb.redirectErrorStream(true);
					Process p = pb.start();
					BufferedReader in = new BufferedReader(
							new InputStreamReader(p.getInputStream()));
					String line = null;
					while ((line = in.readLine()) != null) {
						System.out.println(line);
					}
					if (p.waitFor() == 0) {
						logger.info("File " + outFolder + File.separator
								+ streamName + ".mp4 Written Successfully.");
					} else {
						logger.error("File " + outFolder + File.separator
								+ streamName + ".mp4 Write Error.");
					}
				} catch (IOException e) {
					e.printStackTrace();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

Hope this helps.

Roger.

Hi,

Good to hear it is working. It’s a long time since I did anything with this and I do recall having similar issues with Runtime.exec.

Roger.

Hi Roger,

Appreciate ur reply. The link provided by u is very detailed. Applying the measures described(handling error and input streams of process) in that post helped me to fix my ‘process blocking’ problem. Thanx man.

Krishna