How to use ffmpeg cli in Java? - java

I have an application written in java that needs read videos from a directory and convert them using ffmpeg. I already have ffmpeg installed on my pc and i want use it in my program using "ProcessBuilder", here a sample code:
List<String> cmds = new ArrayList<>();
cmds.add("ffmpeg");
cmds.add("-i");
cmds.add("video1.avi");
cmds.add("video2.mp4");
cmds.add("-hide_banner");
ProcessBuilder pb = new ProcessBuilder(cmds);
Process p = pb.start();
p.waitFor();
The ffmpeg process is created and as expected my app is blocked until ffmpeg process finish its job, but the process never finish, it create a file with 2mb of size and then pause the convertion, and never finish, when i kill my java application the ffmpeg process continue the convertion, i need wait for the completion of the task and notify that the convertion is finished, any idea?, thanks

Related

How to make a java program wait for external script to complete?

I have run an octave script from Java using
ProcessBuilder pb = new ProcessBuilder("./ProcessImg");
Process p = pb.start();
But after executing these statements, the program isn't waiting for the process to finish and comeback.
How do I make the program wait for it? I want to use the file spit out by that script.
Currently I am running the program twice, so that first time it creates the files and also an exception,the second time the program uses the previously created file.

How to Terminate a Process Normally Created using ProcessBuilder

I am creating Processes using ProcessBuilder in my Java Application. The created process executes some FFMPEG commands which actually copy the RTSP streams in specified destination media file.
ProcessBuilder builder = new ProcessBuilder("ffmpeg", "-i", RTSP_URL, "-f", fileFormat, destFilePath);
Process processToExecute = builder.start();
I want to close the process before it completes its execution. So, If I run this FFMPEG command directly in windows CMD and then press 'CTRL+C' after 5 seconds then process get terminates with status '2'. And I can play the media file created so far.
So, If I do the same operation in my Java Application using:
process.destroy(); //I call this method after 5 sec
I get the status code '1' which means abnormal termination. I get the status by the following way:
processToExecute.destroy();
processToExecute.exitValue(); //This return me status '1'
And I can't play the media file and I think this is due to the abnormal termination of the process.
So how I can terminate the process created using ProcessBuilder in the same way we do in CMD with (CTRL+C) so that I may play the created media file ?
I want to terminate process (created using ProcessBuilder) in Java Application with status code of '2' that I get when I terminate process using CMD.
EDIT#01: --- Sharing Findings
So, when I try to delete that file once app terminates, I get the following error:
The Action Can't be Performed Because File is Opened in FFMPEG.exe
Which means that process is not terminating the command it is executing. That command still has occupied this file that's why I am not getting able to play it. Process gets terminate when I call:
processToExecute.destroy();
But, the task it is performing (that is execution of a command) is still active. Strange!!!!
EDIT#02: Sharing Ultimate Reason
Actually If I directly press 'CTRL+C' or 'q' in cmd when process is running then it terminates the process successfully and this process is no more visible in the currently executing processes lists.
And Programatically when I call method:
cmd> processToExecute.destroy();
It terminates the process but when I see the list of currently executing processes I can still see them over there.
And same scenario exists If I try to terminate this process using 'taskkill' or 'kill' command in another CMD by specifying their's name or pid that still process terminates abnormally.
P.S. I use the following command to see the running processes:
tasklist
So from this it proves that destroy() method from Application and 'taskkill or kill' command from another CMD is not terminating the process normally that pressing 'CTRL+C' and 'q' does.
Maybe try...
builder.inheritIO();
System.exit(2);
Or you could try to write to the stdin of the process...
process.getInputStream().write(exitCode);

Multiprocessing in Java Using ProcessBuilder

I working on a project that needs to run a shell file in MAC OS for many times. The shell file writes the result of each run on a separate log file. To speed up the process I have to use all the available cores in our machine. I tried to do this using BuildProcess in Java. It works fine for few seconds but the processes stop after few seconds. Each process takes about 18 hours when running on single core machine. For instance if run the followings it starts two processes and keeps them running for about 10 seconds but then they will be killed with no error!
ProcessBuilder pb1 = new ProcessBuilder("/bin/bash", "runFS.sh")
Process p1 = pb1.start()
ProcessBuilder pb2 = new ProcessBuilder("/bin/bash", "runFS.sh")
Process p2 = pb2.start();
Any help would be most appreciated.
If your example code is anything to go by, you're lacking p1.waitFor() and p2.waitFor() to actually keep the main process alive while the child processes are running. So when your JVM shuts down, it kills also the processes you started.

Java thread not running to completion, why?

I have a Runnable that transfers data(a few hundred files) from an android device to a PC by doing the following in its run method
Creates a process and executes a command using Runtime.exec(CMD)
The CMD is a command that transfers data from a device to the PC that runs this thread.
(This is an adb pull command for android )
I have a main program that creates a Thread and starts this runnable. The runnable starts running and it executes the "adb pull" command and starts transferring the data, BUT it seems to pause soon after before it completes the full transfer. IF I force quit the main program, the transfer runs to completion.
Also had I executed the command from the main program itself without using another thread, I face no issues.
Why am I facing this issue?
You need to consume the output of the command.
This question shows how to consume the output in shell scripts rather than your code: Java ProcessBuilder: Resultant Process Hangs .
If you want to consume the output in your Java code, basically you'll read from InputStream provided by Process.InputStream.
Process process = Runtime.exec(CMD);
InputStream in = process.getInputStream();
// Repeatedly read from the input stream until eof.
This blocks until the other process is complete. If you wanted concurrency, you could read the output in a another thread.

How to run ffmpeg command in background from java

I am running a ffmpeg command from java Runtime.getRuntime().exec.
ffmpeg command basically cut the images from live stream.
Actually when i run this command without & then it works fine for five minutes after that it stops cutting images.
but when i use "&" in ffmpeg command it does not work at all.
there is no problem in live stream as when i ran this ffmpeg command from linux its working fine.
My main question is how to run a ffmpeg command in background from java.
The '&' is a shell directive to drop the task into the background. Running from Process.exec() doesn't involve the shell.
If your process is stalling (i.e. running but just not working) then I suspect that it's blocked waiting for you to consume stdout/stderr. You have to do this using threads to prevent the process blocking waiting for you to consume its output. See this SO answer for more details.
To run it in the background (i.e. whilst your Java process does other stuff) you need to:
spawn a new thread
invoke the process via Process.exec in this thread
consume stdout/stderr (both in separate threads) and finally get the exit code
I know you ask for help for your command line problem in Java but you might be interest in an other solution.
Maybe you can give a try to this library:
http://code.google.com/p/jjmpeg/
It's a wrapper for ffmpeg.
Maybe you can try to create a java thread and run your command.
You wrote it stops working after minutes. Did you check the exit code (Process.exitValue()). Also, did you check output stream and error stream from the external process?
Are you passing the arguments in an array? If it works for a while are you giving it all the expected arguments? (print it out and check). Here is an example of my ffmpeg that I dug out for you.
String[] ffmpeg = new String[] {"ffmpeg", "-ss", Integer.toString(seconds),"-i", in, "-f", "image2", "-vframes", "1", out};
Process p = Runtime.getRuntime().exec(ffmpeg);
String livestream = "/Users/videos/video_10/video_1.mp4";
String folderpth = "/Users/videos/video_10/photos";
String cmd="/opt/local/bin/ffmpeg -i "+ livestream +" -r 10 "+folderpth+"/image%d.jpeg";
Process p = Runtime.getRuntime().exec(cmd);
The video was 10 sec. long and it created 100 jpeg's in photos folder. You have to provide the absolute path of the folder.
Also to find the path for ffmpeg binary use which ffmpeg in terminal. Mine was /opt/local/bin/ffmpeg.

Resources