问题
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