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
相关产品推荐
相关产品推荐

