首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 進程管理實戰:啟動 ffmpeg、等待結束、監控進度全流程

     編輯:程式設計綜合問答

業務場景

主程序 java.exe 啟動子進程 ffmpeg.exe 轉碼視頻,需:

  1. 異步啟動 ffmpeg,不阻塞主線程 UI。
  2. 實時讀取 ffmpeg stdout/stderr 解析進度。
  3. 轉碼結束後自動觸發後續業務(入庫、通知等)。

核心 API:ProcessBuilder + Process

List<String> cmd = Arrays.asList("ffmpeg", "-i", "input.mp4", "-c:v", "libx264", "output.mp4");
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true); // 合併 stderr 到 stdout,簡化讀取
Process process = pb.start();

// 異步讀取輸出流(生產環境建議用單獨線程或 CompletableFuture)
new Thread(() -> {
    try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
        String line;
        while ((line = br.readLine()) != null) {
            parseProgress(line); // 解析 "frame=123 fps=25 time=00:00:05.00 bitrate=..."
            pushToFrontend(progress); // WebSocket/HTTP 推送給前端
        }
    } catch (IOException e) { log.error("讀取 ffmpeg 輸出失敗", e); }
}).start();

// 等待結束(可設超時)
boolean finished = process.waitFor(30, TimeUnit.MINUTES);
int exitCode = process.exitValue();
if (exitCode == 0) { onSuccess(); } else { onFailure(exitCode); }

關鍵問題答疑

問題解答
能否設置子進程優先級?Java 無跨平台 API。Windows 可用 ProcessHandle (JDK 9+) 配合 JNA 調用 SetPriorityClass;Linux 用 nice 啟動腳本包裹。
如何獲取進程運行時間?ProcessHandle.of(process.pid()).info().startInstant() (JDK 9+) 或解析 ps -o etime= -p <pid>。
為何 java 結束前 ffmpeg 不執行?可能未正確調用 pb.start()、或主線程提前 System.exit(0) 導致 JVM 關閉銷毀子進程。確保主線程 waitFor 或註冊 ShutdownHook 清理。
Windows 默認調度算法?多級反饋隊列(優先級動態調整、時間片輪轉),非實時系統不建議依賴優先級控制。

生產級增強建議

  • 超時熔斷:process.waitFor(timeout, unit) + process.destroyForcibly()。
  • 流背壓:ffmpeg 輸出過快導致管道阻塞 → 使用非阻塞 I/O (NIO) 或限流讀取。
  • 資源隔離:Docker 容器限制 CPU/內存,避免 ffmpeg 佔滿宿主機資源。
  • 狀態持久化:將任務 ID、PID、進度寫入 DB/Redis,支撐重啟恢復與集群調度。

總結

Java 操作外部進程的標準範式是 ProcessBuilder → redirectErrorStream → 異步消費流 → waitFor。掌握此模式,配合 JDK 9+ ProcessHandle,即可覆蓋 95% 進程編排場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved