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

时间:2017-07-26 20:56:33

标签: command-line ffmpeg java runtime

我在我的Java程序中调用java.lang.Runtime.exec(...)来运行一个命令(一些FFMPEG命令),只是传递给我的函数:

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

对于ffmpeg -i input.avi -c copy output.avi等简单的FFMPEG案例,它运行正常。

但是对于其中一个命令,显然它没有运行。当我在命令行中复制/粘贴确切的String时,我能够运行它并查看输出文件。

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

代码中的以下内容:

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

发生了什么事?有没有猜到它为什么不在代码中运行?如果"导致问题,为什么相应的字符串看起来不错?!

1 个答案:

答案 0 :(得分:3)

你写的命令:

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

在shell运行时有效。引号是shell语法的一部分,不是ffmpeg语法的一部分。引用是必要的,因为|字符会导致shell在没有引用的情况下构建管道。当它被引用时,它只是传递给ffmpeg。

您希望使用java Runtime exec函数完成相同的操作,但exec不像shell。它不执行管道,重定向,引用或$variable替换。它将字符串拆分为空格,并使用生成的字符串数组执行等效的unix execvp

由于exec不会对|字符做任何特殊处理,因此无需引用。您传递给exec以完成与上述shell命令相同的操作的字符串应该只是

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

根据文件名的不同,您可能遇到并发症。假设你的shell命令如下所示:

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

(差异:第一个文件名temp 10.avi中有一个空格。)现在引用有两个目的:阻止|创建管道,并防止空间拆分参数。如果你尝试将其传递给exec并删除了引号,那么它将无效,因为字符串将被拆分,生成这个参数数组:

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

这不是ffmpeg想要的;它需要在包含完整输入规范的-i之后的单个字符串。你必须自己完成拆分字符串的工作,所以你可以在参数中留下空格,如下所示:

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

以下评论中的示例如下所示

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"
  }
)

-filter_complex之后的大字符串是单个参数,因为它在命令的shell版本中引用。它没有在shell中""之间特殊的字符,也没有Java中""之间特殊的字符,因此无需修改即可使用。

相关问题