running ffmpeg command in java Process hangs in waitFor() - java

I'm running ffmpeg command to generate video for given images (img001.jpg, img002.jpg ...) it's creating slide.mp4, but it waits infinitely:
public class Ffmpeg {
public static void main(String[] args) throws IOException, InterruptedException {
String path = "E:\\pics\\Santhosh\\FadeOut\\testing";
String cmd = "ffmpeg -r 1/5 -i img%03d.jpg -c:v libx264 -r 30 -y -pix_fmt yuv420p slide.mp4";
runScript (path, cmd);
}
private static boolean runScript(String path, String cmd) throws IOException, InterruptedException {
List<String> commands = new ArrayList<String>();
commands.add("cmd");
commands.add("/c");
commands.add(cmd);
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File(path));
pb.redirectErrorStream(true);
Process process = pb.start();
flushInputStreamReader(process);
int exitCode = process.waitFor();
return exitCode == 0;
}
}
private static void flushInputStreamReader (Process process) throws IOException, InterruptedException {
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line=null;
StringBuilder s = new StringBuilder();
while((line=input.readLine()) != null) {
s.append(line);
}
}
Any suggestions?
After writing the function flushInputStreamReader, its working

Aside from reading the ErrorStream, there's a better way to handle this.
Add -loglevel quiet to the command, so that the ErrorStream won't overflow and blocking the process at the first place.

Here the working code for the live project:
public void executeHLS() throws IOException, InterruptedException {
String original_video_file = "C:\\xampp\\htdocs\\hls\\test.mp4";
String conversion = "cmd.exe /c F:\\java\\ffmpeg\\ffmpeg\\bin\\ffmpeg -i "+original_video_file+" -hls_time 10 -hls_playlist_type vod -hls_segment_filename \"C:\\xampp\\htdocs\\hls\\video_segments_%0d.ts\" C:\\xampp\\htdocs\\hls\\hls_master_for_test.m3u8";
//String conversion = "cmd.exe /c "+"dir";
String[] cmds={conversion};
for(int i=0;i<cmds.length;i++) {
try {
System.out.println(cmds[i]);
if(runScript(conversion)) {
System.out.println("Operation Successfull!!!!");
}else {
System.out.println("Operation Failed ####");
}
} catch (IOException e) {
e.printStackTrace();
}
//System.exit(0);
}
}
private static boolean runScript(String cmd) throws IOException, InterruptedException {
ArrayList<String> commands = new ArrayList<String>();
commands.add("cmd");
commands.add("/c");
commands.add(cmd);
ProcessBuilder pb = new ProcessBuilder(commands);
//pb.directory(new File(path));
pb.redirectErrorStream(true);
Process process = pb.start();
flushInputStreamReader(process);
int exitCode = process.waitFor();
return exitCode == 0;
}
private static void flushInputStreamReader (Process process) throws IOException, InterruptedException {
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line=null;
StringBuilder s = new StringBuilder();
while((line=input.readLine()) != null) {
s.append(line);
}
}

Related

Execute Java Program From Java Code using Process

I am trying to execute a java code by using Process class.
Here is my code.
Class file which is trying to execute is.
class Demo{
public static void main(String[] args) {
System.out.println("Hello World");
}
}
class Pro {
public static void main(String[] args) {
try {
ProcessBuilder builder = new ProcessBuilder("java Demo");
builder.redirectErrorStream(true);
Process process = builder.start();
InputStream is = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Both classes are in different file and in the same folder.
O/P
java.io.IOException: Cannot run program "java Demo": CreateProcess error=2, The system cannot find the file specified
at java.base/java.lang.ProcessBuilder.start(Unknown Source)
at java.base/java.lang.ProcessBuilder.start(Unknown Source)
at GFG.main(GFG.java:13)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.base/java.lang.ProcessImpl.create(Native Method)
at java.base/java.lang.ProcessImpl.<init>(Unknown Source)
at java.base/java.lang.ProcessImpl.start(Unknown Source)
... 3 more
Try like this:
private static final String LOCATION = "D:\\test.java";
public static void main(String args[]) throws InterruptedException,IOException{
ProcessBuilder processBuilder = new ProcessBuilder(command);
List<String> command = new ArrayList<String>();
command.add("javac"); //or command.add("javac -jar")
command.add(LOCATION);
ProcessBuilder builder = new ProcessBuilder(command);
Map<String, String> environ = builder.environment();
final Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Program terminated!");
}
}
Hope this helps,
Addendum (how to wait for process):
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
calling:
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String domainName = "https://wwww.google.com";
//in mac oxs
String command = "ping -c 3 " + domainName;
//in windows
//String command = "ping -n 3 " + domainName;
String output = obj.executeCommand(command);
System.out.println(output);
}
This is an example to ping some page, 3 times and wait for response.

Java Kill processes started with ProcessBuilder

I'm running my processes like this:
builder = new ProcessBuilder("/bin/bash", "-c", "./MessageGenerator | ./SimpleEchoServer");
process = builder.start();
Then process.destroy() or forciblyDestroy() doesn't work. Is it because I'm using a pipe? How can I kill these processes?
you should also split up the pipe command. I've written a little example:
package com.company;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder processBuilder;
String line;
processBuilder = new ProcessBuilder("/bin/bash", "-c", "ls -l", "|", "grep java");
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println ("Stdout: " + line);
}
Thread.sleep(10000);
process.destroy();
}
}

Java simple process builder issue

I just conducted simple test code for Java Process Builder.
There are 4 examples and everything is working smoothly excluding last one.
Here is my codes
public class bashProcessor {
public static void main(String args[]) {
try {
ProcessBuilder pb;
pb = new ProcessBuilder("/bin/bash", "-c", "touch Jin_1.sh");
pb.start();
pb = new ProcessBuilder("/bin/bash", "-c", "mkdir Jin_2");
pb.start();
pb = new ProcessBuilder("/bin/bash", "-c", "bash /home/Jin/test.sh");
pb.start();
//below is not working
pb = new ProcessBuilder("/bin/bash", "-c",
"bash /home/solr-tomcat/bin/shutdown.sh warm4 solr-instances");
pb.start();
System.out.println("pb job is done now");
Thread.sleep(3000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
When I type last example(bash /home/solr...) by hand-typing. It works without any error. I need your kind help. if you have any idea
please let me know it would be great help.
As pointed out by #ug_ try to remove bash from command and then execute your code. Following code works fine with multiple command.
cmd.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class cmd {
public static void main(String[] args) {
try {
String[] command = new String[3];
command[0] = "/bin/bash";
command[1] = "-c";
command[2] = "javac -verbose HelloWorld.java";
Process p = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String Error;
while ((Error = stdError.readLine()) != null) {
System.out.println(Error);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

how to run a java executable jar in another java program

I know this question has been asked before but those answers didn't provide me an answer.
I want to execute a exec jar file in my java program and get the output from executing jar into a string. Here below are the codes I have used so far without success.
cmdlink = "java -jar iwtest-mac.jar"+" "+cmd;
System.out.println(cmdlink);
Process process = Runtime.getRuntime().exec(cmdlink);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((reader.readLine()) != null) {
st = reader.readLine();
}
process.waitFor();
and another code I have tried is as follows:
String cmdlink = "iwtest-mac.jar "+cmd;
ProcessBuilder pb = new ProcessBuilder("java", "-jar", cmdlink); //cmd here is a string that contains inline arguments for jar.
pb.redirectErrorStream(true);
pb.directory(new File("C:\\Users\\Dharma"));
System.out.println("Directory: " + pb.directory().getAbsolutePath());
Process p = pb.start();
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for (String line = br.readLine(); line != null; line = br.readLine()) {
System.out.println( line );
p.waitFor();
Both of the above are not working for me. Any suggestions are appreciated.
This works For Me..
public class JarRunner {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "C:\\JCcc.jar");
pb.directory(new File("C:\\"));
try {
Process p = pb.start();
LogStreamReader lsr = new LogStreamReader(p.getInputStream());
Thread thread = new Thread(lsr, "LogStreamReader");
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class LogStreamReader implements Runnable {
private BufferedReader reader;
public LogStreamReader(InputStream is) {
this.reader = new BufferedReader(new InputStreamReader(is));
}
public void run() {
try {
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is what the Docs says-
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
You can pass any number of arguments in constructor.
Read more about process builder here.

Java program hangs when trying to invoke powershell script

I'm building a GUI with NetBeans, and one of the buttons in the GUI requires the use of a powershell script. I'm trying to get the script's output and put it into a JTextArea within the GUI. Here is what I have so far. I did a bit of debugging, and it seems to hang inside the while loop, but I'm confused as to why it's doing so.
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("cmd powershell C:/hello1.ps1");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
outputTextArea.setText(line);
}
reader.close();
proc.getOutputStream().close();
} catch (IOException ex) {
Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
And here is a simple powershell script I'm trying to get it to work with.
#Filename: hello1.ps1
Write-Host "Hello World!"
#End of Script
I did some researched, and I noticed that it was hanging for other people to, but only because they forgot to close the processes output stream.
I was having the same issue. I moved the proc.getOutputStream().close() before the while loop and everything worked
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
String allOutput = "";
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("cmd /c powershell C:/hello1.ps1");
BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
BufferedReader outReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = errorReader.readLine()) != null) {
allOutput += "\n" + line;
}
while ((line = outReader.readLine()) != null) {
allOutput += "\n" + line;
}
int retVal = proc.waitFor();
} catch (IOException ex) {
Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
}
outputTextArea.setText(allOutput);
}
Form the command line properly with CMD.EXE /c
Check the ErrorStream
Use Process.waitFor() read the java-docs for the Process class.
No need to close the OutputStream since you never use it and the program shouldn't expect user input (java switching the names of input and output is annoying)
NOTE the code above isn't tested, so there may be syntax errors etc etc.
Here is my tested code, note the choice to "hack" or close STDIN when done.
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Test
{
private static boolean hack=false;
public static void main(String[] args) throws IOException
{
Runtime rt = Runtime.getRuntime();
String cmd[];
if (hack)
cmd=new String[]{"cmd","/c","C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1", "<NUL"};
else
cmd=new String[]{"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1"};
final Process p = rt.exec(cmd);
Thread stdout = new Thread()
{
public void run()
{
InputStream out = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(out));
String line = null;
try
{
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
};
};
stdout.start();
Thread stderr = new Thread()
{
public void run()
{
InputStream err = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(err));
String line = null;
try
{
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
};
};
stderr.start();
if (hack)
;
else
p.getOutputStream().close();
}
}
This helped me: Do not read the InputStream if there are no errors.
e.g.
private void takeAction () throws IOException, InterruptedException
{
String action = getAction (); // A powershell-Command
Process p = Runtime.getRuntime ().exec ( action );
InputStream is = p.getErrorStream ();
if ( 0 < is.available () )
{
BufferedReader br = new BufferedReader (
new InputStreamReader ( is ) );
String err = br.readLine ();
while ( null != err )
{
System.out.println ( "takeAction() " + err );
err = br.readLine ();
}
p.getOutputStream ().close ();
}
}

Categories