1

I am calling java.lang.Runtime.exec(...) in my Java program to run a command (some FFMPEG commands) simply passed to my function:

    private static void RunCommand(String command) throws InterruptedException {
        try {
            // Execute command
            Process proc = Runtime.getRuntime().exec(command);
}
}

It runs OK for simple FFMPEG cases such as ffmpeg -i input.avi -c copy output.avi.

But for one of the commands, apparently it doesn't run. When I copy/paste the exact String in command line, I am able to run it and see the output file.

ffmpeg -i "concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi

Which is the following in code:

String c4="ffmpeg -i \"concat:"+dir+temp1+"|"+dir+ad+"|"+dir+temp3+"\" -c copy -y "+dir+output;

What is going on? Any guesses why it doesn't run in code? If the " is causing the problem, why the corresponding string looks good?!

3
  • 1
    It looks to me like this exec function doesn't do shell-style quoting, just a simple split on whitespace, so you should be able to fix it by removing the quotes. If the filenames might contain spaces, you'll have pass an array of String to exec instead. Commented Jul 26, 2017 at 21:19
  • Do you mean I should remove the quotes? Commented Jul 26, 2017 at 22:02
  • Wow! You were right. Just removing the " solved the problem. Maybe you want to describe it and I mark you as best answer? Commented Jul 26, 2017 at 22:05

1 Answer 1

3

The command as you have written it:

ffmpeg -i "concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi

works when run by a shell. The quotation marks are part of the shell syntax, not part of the ffmpeg syntax. Quoting is necessary because of the | character, which cause the shell to build a pipeline if it was unquoted. When it is quoted, it is simply passed along to ffmpeg.

You want to accomplish the same thing with the java Runtime exec function, but exec isn't like a shell. It doesn't do pipelines, or redirections, or quoting, or $variable substitutions. It splits the string on whitespace and does the equivalent of a unix execvp with the resulting array of strings.

Since exec won't do anything special with the | character, there is no need for quoting. The string you pass to exec to accomplish the same thing as the above shell command should just be

ffmpeg -i concat:/home/temp10.avi|/home/p2.avi|/home/temp15.avi -c copy -y /home/output.avi

There is a complication you may run into depending on the filenames. Suppose your shell command looked like this:

ffmpeg -i "concat:/home/temp 10.avi|/home/p2.avi|/home/temp15.avi" -c copy -y /home/output.avi

(Difference: the first filename temp 10.avi has a space in it.) Now the quoting is serving 2 purposes: prevent the | from creating a pipeline, and prevent the space from splitting the argument. If you try passing this to exec with the quotation marks removed, it won't work because the string will be split, generating this array of arguments:

-i
concat:/home/temp
10.avi|/home/p2.avi|/home/temp15.avi
-c
copy
-y
/home/output.avi

and that's not what ffmpeg wants; it wants a single string after the -i containing the full input specification. You would have to do the job of splitting the string yourself, so you can leave the space in the argument, like this:

Runtime.getRuntime().exec(
  new String[] {
    "ffmpeg",
    "-i",
    "concat:/home/temp 10.avi|/home/p2.avi|/home/temp15.avi",
    "-c",
    "copy",
    "-y",
    "/home/output.avi"
  }
)

The example in the comment below looks like

Runtime.getRuntime().exec(
  new String[] {
    "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"
  }
)

The large string after -filter_complex is a single argument because it's quoted in the shell version of the command. It has no characters in it that are special between "" in the shell, and no characters that are special between "" in Java, so it works without modification.

Sign up to request clarification or add additional context in comments.

1 Comment

I have difficulties running this command. Can you help me? 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.