I have problems executing this ffmpeg
command in my java code:
ffmpeg -i sample.mp4 -i ad.mp4 -filter_complex "[0:v]trim=0:15,setpts=PTS-STARTPTS[v0]; [1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; [0:v]trim=20:30,setpts=PTS-STARTPTS[v2]; [v0][v1][v2]concat=n=3:v=1:a=0[out]" -map "[out]" output.mp4
I used the getRuntime()
method below, but that doesn't work for me. Even if I simply remove the "
, still it doesn't work. When I simply copy-paste the equivalent string in terminal, it works.
String c1=" -i "+dir+"sample.mp4 "+"-i "+dir+"ad.mp4 -filter_complex [0:v]trim=0:15,setpts=PTS-STARTPTS[v0]; [1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; [0:v]trim=20:30,setpts=PTS-STARTPTS[v2]; [v0][v1][v2]concat=n=3:v=1:a=0[out] -map [out] "+dir+"output.mp4";
RunCommand("ffmpeg"+c1);
Using this method:
private static void RunCommand(String command) throws InterruptedException {
try {
// Execute command
Process proc = Runtime.getRuntime().exec(command);
System.out.println(proc.exitValue());
// Get output stream to write from it
// Read the output
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while((line = reader.readLine()) != null) {
System.out.print(line + "\n");
// System.out.println(ads.get(0));
}
proc.waitFor();
} catch (IOException e) {
}
}
This one doesn't work also, and printing the exit value shows this:
Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited
at java.lang.UNIXProcess.exitValue(UNIXProcess.java:423)
at parser.Parser.RunCommand(Parser.java:106)
at parser.Parser.commandGenerator2(Parser.java:79)
at parser.Parser.main(Parser.java:44)
If I move the proc.waitFor();
before printing the exit value, it is 1
.
What is the problem? Why it doesn't run in Java code?
It seems like you missed quotes around argument for
-filter_complex
parameter. Java will run something like this:It doesn't work since
;
means end of command in bash. Putting quotes back in java code should fix command (make sure to escape them properly).Several issues to fix (most are addressed by other answers individually, with various degrees of explanation, but you need to fix all):
ffmpeg
exactly as the shell would, that means you either need to build a command as string array with individual arguments, or, to make it easier (and identical to shell behavior), quote your arguments: add pair of\"
around the big filter argument. Then you should be able to pass command torunCommand
exactly as you write it in a shell.ffmpeg
, but/bin/sh
can do that for you: wrap your command with/bin/sh -c ...
(for that I will useProcessBuilder
below)ProcessBuilder
to the rescue: redirectstderr
tostdout
to only get a single stream to consume, then redirectstdout
wherever you want (below I inherit from parent process, so it goes to the output of yourjava
process itself.waitFor()
, which waits as long as necessary, but there are other options)-fi......lter_complex
(dots in hex aree2 80 8c e2 80 8b
), but there are more scattered in your command.Thus:
(*) In a shell, if you want to print
a b
you doecho "a b"
, but in java this does not work:What it does is naively split around the spaces, and it will pass 2 arguments instead of 1 to
echo
:"a
thenb"
. Not what you want.Alternative: pass arguments individually.
There is some issue on your code, First, use thread to stream in and err of inner process to the console
Create a pipe stream class like :
Then adapt the runtime part to:
It will show the command that will be run, the logs and potentially the error.
You will be able to copy paste the command to check on a terminal what is going on if needed.
EDIT: This is very funny. You code was missing some escape char AND there is not visible char in your code. I saw them when I copy paste the line of code. Copy paste the following line in your code, it will remove the error :