简体   繁体   English

Java执行命令在代码中不起作用

[英]Java execute command doesn't work in code

I am calling java.lang.Runtime.exec(...) in my Java program to run a command (some FFMPEG commands) simply passed to my function: 我在我的Java程序中调用java.lang.Runtime.exec(...)来运行一个命令(一些FFMPEG命令),只是传递给我的函数:

    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 . 对于简单的FFMPEG情况,例如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. 当我在命令行中复制/粘贴确切的String时,我能够运行它并查看输出文件。

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?! 如果"导致问题,为什么相应的字符串看起来不错?!

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. 在shell运行时工作。 The quotation marks are part of the shell syntax, not part of the ffmpeg syntax. 引号是shell语法的一部分,不是ffmpeg语法的一部分。 Quoting is necessary because of the | 由于|引用是必要的 character, which cause the shell to build a pipeline if it was unquoted. character,如果没有引用shell,则会导致shell构建一个管道。 When it is quoted, it is simply passed along to ffmpeg. 当它被引用时,它只是传递给ffmpeg。

You want to accomplish the same thing with the java Runtime exec function, but exec isn't like a shell. 你想用java Runtime exec函数完成同样的事情,但是exec不像shell。 It doesn't do pipelines, or redirections, or quoting, or $variable substitutions. 它不执行管道,重定向,引用或$variable替换。 It splits the string on whitespace and does the equivalent of a unix execvp with the resulting array of strings. 它将字符串拆分为空格,并使用生成的字符串数组执行等效的unix execvp

Since exec won't do anything special with the | 因为exec不会对|做任何特殊的事情 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 您传递给exec以完成与上述shell命令相同的操作的字符串应该是

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: 假设你的shell命令看起来像这样:

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 | (差异:第一个文件名temp 10.avi有空格。)现在引用有2个目的:阻止| 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: 如果你尝试将它传递给删除引号的exec ,它将无法工作,因为字符串将被拆分,生成这个参数数组:

-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; 这不是ffmpeg想要的; it wants a single string after the -i containing the full input specification. 它需要在包含完整输入规范的-i之后的单个字符串。 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. -filter_complex之后的大字符串是单个参数,因为它在命令的shell版本中引用。 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. 它有一个不包含字符是特殊的之间""的外壳,并没有字符是特殊的之间""在Java中,因此它可以无需修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM