【发布时间】:2015-03-12 14:54:31
【问题描述】:
我正在我的 Java 应用程序中使用 ProcessBuilder 创建进程。创建的进程执行一些 FFMPEG 命令,这些命令实际上将 RTSP 流复制到指定的目标媒体文件中。
ProcessBuilder builder = new ProcessBuilder("ffmpeg", "-i", RTSP_URL, "-f", fileFormat, destFilePath);
Process processToExecute = builder.start();
我想在进程完成执行之前关闭它。因此,如果我直接在 Windows CMD 中运行此 FFMPEG 命令,然后在 5 秒后按“CTRL+C”,则进程会以状态“2”终止。我可以播放目前创建的媒体文件。
所以,如果我在我的 Java 应用程序中执行相同的操作:
process.destroy(); //I call this method after 5 sec
我得到状态码“1”,表示异常终止。我通过以下方式获取状态:
processToExecute.destroy();
processToExecute.exitValue(); //This return me status '1'
我无法播放媒体文件,我认为这是由于进程异常终止。
那么,如何像在 CMD 中使用 (CTRL+C) 一样终止使用 ProcessBuilder 创建的进程,以便播放创建的媒体文件?
我想终止 Java 应用程序中的进程(使用 ProcessBuilder 创建),状态码为“2”,当我使用 CMD 终止进程时得到。
EDIT#01: --- 分享发现
所以,当我在应用程序终止后尝试删除该文件时,我收到以下错误:
The Action Can't be Performed Because File is Opened in FFMPEG.exe
这意味着进程没有终止它正在执行的命令。该命令仍然占用了这个文件,这就是我无法播放它的原因。当我调用时进程终止:
processToExecute.destroy();
但是,它正在执行的任务(即执行命令)仍然处于活动状态。奇怪!!!!
EDIT#02:分享终极理由
实际上,如果我在进程运行时直接在 cmd 中按“CTRL+C”或“q”,则它会成功终止该进程,并且该进程在当前正在执行的进程列表中不再可见。
当我调用方法时以编程方式:
cmd> processToExecute.destroy();
它终止了进程,但是当我看到当前正在执行的进程列表时,我仍然可以在那里看到它们。
如果我尝试在另一个 CMD 中使用 'taskkill' 或 'kill' 命令通过指定它们的名称或 pid 来终止此进程,仍然会异常终止。
附:我使用以下命令查看正在运行的进程:
tasklist
由此证明,Application 中的 destroy() 方法和另一个 CMD 中的“taskkill 或 kill”命令不会像按“CTRL+C”和“q”那样正常终止进程。
【问题讨论】:
-
我不知道你是否可以在Java中做到这一点,但根据你的描述,你需要向FFMPEG发送一个control-C信号。执行此操作的 Win32 API 调用是 GenerateConsoleCtrlEvent。顺便说一句,问题不在于状态码本身,这只是另一个症状;使用状态码 2 终止进程与使用状态码 1 终止进程没有什么不同。您必须要求它终止(而不是强制它这样做),以便它可以运行其清理例程。
-
如果是 ffmpeg,也许给它发送一个 'q' 键告诉它退出...
-
是的,如果我通过 cmd 发送“q”,它会正常终止进程。但我想从我的应用程序内部终止它。
-
@BilalAhmedYaseen:你找到解决方案了吗?我遇到了同样的问题。
-
我创建了一个库来做视频导出 (github.com/hamoid/video_export_processing) 并在 Windows 上遇到了这个确切的问题。是否可以按照stackoverflow.com/questions/3240704/… 底部的建议向进程发送击键?
标签: java windows ffmpeg processbuilder kill-process