Java execute command doesn't work in code

三世轮回 提交于 2021-02-18 19:06:49

问题


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?!


回答1:


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.



来源:https://stackoverflow.com/questions/45900006/java-execute-command-doesnt-work-in-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!