我在我的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;
发生了什么事?有没有猜到它为什么不在代码中运行?如果"
导致问题,为什么相应的字符串看起来不错?!
答案 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中""
之间特殊的字符,因此无需修改即可使用。