You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java ProcessBuilder调用FFmpeg提取字幕时进程无法终止求助

解决ProcessBuilder调用FFmpeg进程无法终止的问题

问题原因

FFmpeg运行时会向标准输出(stdout)和标准错误(stderr)输出日志,Java子进程的默认缓冲区容量有限,当缓冲区被填满时,FFmpeg会暂停执行等待缓冲区被读取,导致waitFor()一直阻塞,直到Java进程终止、缓冲区释放后,FFmpeg才完成剩余操作。

解决方案

方案1:直接丢弃FFmpeg的输出流(简单快捷)

将FFmpeg的输出和错误流重定向到空设备,避免缓冲区阻塞:

List<String> command = new ArrayList<>();
command.add("ffmpeg");
command.add("-i");
command.add(fileName);
command.add("-c:s");
command.add("srt");
command.add(subfile);

ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(UPLOAD_MOVIE_DIR_disc + movie.getTitle()));

// Windows用"NUL",Linux/macOS用"/dev/null"
processBuilder.redirectOutput(new File("NUL"));
processBuilder.redirectError(new File("NUL"));

Process processConvert = processBuilder.start();
processConvert.waitFor(); // 现在会正常终止

如果是Java 9及以上版本,可使用更简洁的写法:

processBuilder.redirectOutput(ProcessBuilder.Redirect.toNull());
processBuilder.redirectError(ProcessBuilder.Redirect.toNull());

方案2:读取输出流(需要保留日志时使用)

启动独立线程分别读取标准输出和错误流,避免缓冲区被占满:

List<String> command = new ArrayList<>();
command.add("ffmpeg");
command.add("-i");
command.add(fileName);
command.add("-c:s");
command.add("srt");
command.add(subfile);

ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(UPLOAD_MOVIE_DIR_disc + movie.getTitle()));

Process processConvert = processBuilder.start();

// 读取标准输出线程
new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(processConvert.getInputStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            // 可根据需求处理日志,比如打印或写入文件
            System.out.println("[FFmpeg stdout] " + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

// 读取标准错误线程
new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(processConvert.getErrorStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.err.println("[FFmpeg stderr] " + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

processConvert.waitFor(); // 正常执行完毕后返回

额外注意事项

  • 确保FFmpeg路径正确:如果系统环境变量未配置FFmpeg,建议使用绝对路径(如Windows的"C:\\ffmpeg\\bin\\ffmpeg.exe",Linux的"/usr/bin/ffmpeg"),避免进程因找不到命令而异常。
  • 检查目标目录权限:确认程序对输出字幕文件的目录有写入权限,避免因权限问题导致隐性阻塞。

内容的提问来源于stack exchange,提问作者Mr12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:16:13