I´ve run into problem. I want to convert video using ffmpeg but it gives me no output
public void convert(String inputFile, String outputFile, String ... optionalParams) {
ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-i", "\"" + inputFile.trim() +"\"", "\""+ outputFile.trim() + "\"");
DownloadRecord downloadRecord = table.getItems().get(0);
downloadRecord.setStatus("Downloading");
// Try to execute process
try {
// Set the working directory
processBuilder.directory(new File(workingDirectory));
//Start the process
Process process = processBuilder.start();
// Read the output from cmd
BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader ra = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
String errline;
while ((line = r.readLine()) != null) {
System.out.println(line);
}
while ((errline = ra.readLine()) != null) {
System.out.println(errline);
}
process.waitFor();
System.out.println("the end");
} catch(IOException | InterruptedException e) {
System.out.println(e.toString());
}
}
I've been searching on stackoverflow and find some solutions, none worked. What I tried and figured out so far
No output or error output
I tried to remove backslashes from ProcessBuilder, it
also gives me no output
I tried to let the program running, but it never finishes
I tried to use full path to the ffmpeg, no changes
I tried to run the video, no error
I am using
Netbeans IDE so I tried clean and rebuild project, no change
process also never finishes
I would like from it an output. Does someone know what I am doing wrong here ?
I fixed it by reinstalling the ffmpeg. Just went ffmpeg website downloaded newest version, replaced files in folder and it works
Edit:
It just works for files with less thatn 2 mins for some reason, more thatn 2 mins files are behaving like this
I start converting, it will not convert entirely until program runs. After I exit the program it will finish. It´s strange behaviour.
Related
I am trying to print the output of a shell script on the console using java. When I manually run the script, I get
C:/Users/user1/Desktop/shell.sh: line 78: /usr/ucb/ps: No such file or directory
<STATUS>: Probe [ devicename ] is not running!
But, when I try to run it on my Java program, the output is not being printed on the console.
My code is:
ProcessBuilder processBuilder = new ProcessBuilder("C:/Program Files/Git/git-bash.exe","C:/Users/user1/Desktop/shell.sh");
try {
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
System.out.println(line);
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
System.exit(0);
} else {
//abnormal...
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
The only output I am getting is "Success". When I debugged my code, I found that the code never enters the condition
while ((line = reader.readLine()) != null)
even though, in the bash terminal, there are lines of output. Why is this happening?
I am stuck at this point and I couldn't find any other explanations for this problem. Kindly help.
You are running git-bash.exe which opens as a windows application. Although Java has access to the stdout/stderr streams of git-bash.exe, these are not necessarily the same as the stdout/err of the internal launch of your shell script within git-bash.exe.
One way to see the stdout/err of your command would be to make a java friendly version of the .sh script which launches your original sh and redirects output to a specific files which you can then access within java afterwards.
ProcessBuilder pb = new ProcessBuilder("C:/Program Files/Git/GIT-BASH.EXE","/c/Users/blah/somescript.sh");
somescript.sh:
#!/bin/sh
runtheoriginalcommand > ~/somepath.out 2> ~/somepath.err
You could also add extra args to wrapper to pass the out/err files to be used so there is no contention with any other launches or hardcoded output files.
I've come across a strange issue. I've used process builder several times to call an executable from a program but have never encountered this before. For debug purposes I made a method which prints the output of the executable to System.out. Everything worked fine and my program nicely exported all of the test gifs I ran.
When it came time to run this program properly for 1000+ gifs I commented out the printout method to improve performance. Once the whole program had run I come back to find that the exportGif did not work. The program ran with no errors but the calling of the process simply did not export the gifs as expected.
After isolating lines in the printout method it seems that the deciding bit of code is the reader.readLine(). Why would this be the case? The executable should have already run, the debug method should only read the output stream after the fact, correct? I'd rather not loop through it's output stream every time as it causes the program to slow considerably.
private void printProcessOutput(Process process){
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
try{
while ( (line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
}catch(IOException e){
e.printStackTrace();
}
System.out.println(builder.toString());
}
private void exportGIF(String dirPath) throws IOException {
List<String> lines = Arrays.asList("/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/timMaster_4.1.png \"{200.0,467.0}\"");
Path headImageFile = Paths.get(System.getProperty("user.dir") + File.separator + "headImageInfo.txt");
Files.write(headImageFile, lines, Charset.forName("UTF-8"));
String templatePath = dirPath + File.separator + "template.mp4";
String outputPath = dirPath + File.separator;
String headImagePath = headImageFile.toString();
String gifExportExecPath = "/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/GIFExport";
Process process = new ProcessBuilder(gifExportExecPath, "-s", templatePath, "-o", outputPath, "-h", headImagePath).start();
printProcessOutput(process);
Files.delete(headImageFile);
}
EDIT
One thing I should add. I noticed that when I comment out the debug method it clocks through all 1000+ iterations in less than ten minutes, But, of course the gifs do not export (the executable doesn't run...? Not sure).
When I include the printout method it is a lot slower. I tried running it overnight but it got stuck after 183 iterations. I've tried profiling to see if it was causing some thrashing but the GC seems to run fine.
You need to consume the output of the Process or it may hang. So you can't comment out printProcessOutput(process);. Instead, comment out the lines that actually do the printing:
try{
while ( (line = reader.readLine()) != null) {
//builder.append(line);
//builder.append(System.getProperty("line.separator"));
}
} catch(IOException e){
e.printStackTrace();
}
//System.out.println(builder.toString());
I generally use this method, which also redirects the error stream:
public static void runProcess(ProcessBuilder pb) throws IOException {
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
//System.out.println(line);
}
}
I am trying to call the sccmap command from GraphViz using Java.
String command = "/usr/bin/sccmap -S /home/paperclip/Desktop/graph.dot > /home/paperclip/Desktop/scc.dot";
try {
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(command);
System.out.println("Process exited with code = " + p.waitFor());
java.io.InputStream is = p.getInputStream();
java.io.BufferedReader reader = new java.io.BufferedReader(new InputStreamReader(is));
String s = null;
while ((s = reader.readLine()) != null) {
System.out.println(s);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
The output for this snippet of code is:
Process exited with code = 0
The sccmap function is supposed to output a dot file in the location that I have specified. However, it doesn't work like I expected. Even though the exitValue was given as 0, the dot file was not created.
I tried using the command manually in Terminal and it works perfectly. I also tried using other commands such as "ls" and it works too. Why does this code not work for "sccmap"?
I also searched for some Java APIs for GraphViz such as the jGraphViz (http://jgraphviz.sourceforge.net/) and graphviz-java-api at (http://www.loria.fr/~szathmar/off/projects/java/GraphVizAPI/index.php), but they don't seem to work for me.
FYI I am on Ubuntu 11.10 and GraphViz is already installed.
Thanks!
> is interpreted by the shell (it's a stream redirect), it's not an argument to the application. There is no shell in this situation.
Try /usr/bin/sccmap -S -o /home/paperclip/Desktop/scc.dot /home/paperclip/Desktop/graph.dot instead.
I am hoping to leverage the unix sort command to sort a large text file in Java. I've tried executing sort with the process builder, but with no luck. However when I print the exact command it is going to execute and copy and paste it into the terminal, it works fine.
So far I've tried executing with /bin/sh -c "", making sure the directory the input file is and where the output file will be is fully permissioned (chmod 777) but with no luck.
Here is the code (if it looks funny, note is using some functions found in Guava)
File inputFile = new File(inputFileName);
//build the command (optional number of sort columns)
List<String> command = new LinkedList<String>();
command.addAll(ImmutableList.<String>of("sort","-t"+delimiter));
for (int i : sortFieldPositions) {
command.add("-k"+i+","+i);
}
command.addAll(ImmutableList.<String>of(inputFileName,">",outputFileName));
//for debugging: output the command that will be executed
System.out.println("Executing: "+Joiner.on(" ").join(command));
//construct and start the process
Process process = new ProcessBuilder(command).redirectErrorStream(true).directory(inputFile.getParentFile()).start();
//for debugging: save process output
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder outputStringBuilder = new StringBuilder();
for (String line; (line = bufferedReader.readLine()) != null; /*reading taking place in check */) {
System.out.println("FROM PROCESS: "+line);
outputStringBuilder.append(line);
}
bufferedReader.close();
if (process.exitValue() != 0) {
//something went wrong
throw new RuntimeException("Error code "+process.exitValue()+" executing command: "+Joiner.on(" ").join(command)+"\n"+outputStringBuilder.toString());
}
Unfortunately this does not work, with the following output:
Executing: sort -t, -k2,2 -k1,1 /tmp/java/TestDataSorterImporterInput.txt /tmp/java/TestDataSorterImporterOutput.txt
FROM PROCESS: sort: stat failed: >: No such file or directory
Edit: It may be helpful to note that if I remove saving the output (> outputfile) from the command, then the command executes without complaint and the sorted version appears in the output from the Processes' input stream)
It is the shell that knows how to perform output redirection. The sort program cannot do it on its own. So if you want redirection, you need to do /bin/sh -c ... to let she shell into the loop.
(You write that you have tried this, but something else must have gone wrong with that).
Try this:
String whatever = "filename";
Process p = Runtime.getRuntime().exec("sort -t -k2 2 -k1 1 " + whatever);
See this site.
Process process = new ProcessBuilder("/bin/bash", "-c", "sort -t'|' -k2").start();
I'm using this code to make my Java program open a (visible) CMD window:
try {
String line;
Process p = Runtime.getRuntime().exec("cmd /C start \"Render\" \"" + myPath + "\\punchRender.cmd\"");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
and I've been trying to do the same thing with the OSX terminal, this is where I'm at right now:
try {
String line;
Process p = Runtime.getRuntime().exec("sh " + myPath + "/punchRender.sh");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
So far, no luck :( Any suggestions? The .sh file isn't even running...
I would just make sure your shell script has the execute bits on and just pass in the shell script file name.
Process p = Runtime.getRuntime().exec(myPath + "/punchRender.sh")
Edit:
I don't know Java specifically if there is anyway to set file permissions for Unix/Linux with it to set the eXecute bit or how to escape quotes. But It would be something like this:
Process chmod = Runtime.getRuntime().exec("chmod u+x \"" + myPath + "/punchRenderer.sh\"")
This should work. Not only running the script, but opening a terminal also:
Process p = Runtime.getRuntime().exec("open -a /Applications/Utilities/Terminal.app \"" + myPath + " /punchRender.sh\"");
If you want a new visible Terminal window, you can't run the shell directly. You need to start Terminal and then run a .command file, not a shell script. I'm not sure how hard it would be to connect the stdout of that command to your Java process. You might have to figure out some other way of getting the output into the terminal.
By the way, I tried your code in a class on my own Mac at home, and it ran a .sh file just fine. I was running the java class from the command line. Maybe sh just isn't in your PATH.
I assume you've checked that the .sh file is executable, haven't you?
Can I suggest you capture the standard error as well as the standard output, and dump that. That should give you some idea as to what's going on (it's good practise generally).
You may need to gather standard output and standard error in different threads to avoid blocking issues. See here for a StreamGobbler