记一次极其坑爹的 process.waitFor() 卡死问题
项目中有个需求需要截取wav的音频文件 ,网上找了找方法 用java调用ffmpeg 来截取
public static InputStream trimAudio(MultipartFile inputFile, Double startTime, Double endTime,Double volume) throws IOException {File file = new File(FileUtil.getTmpDirPath() + File.separator + System.currentTimeMillis() + ".wav");inputFile.transferTo(file);String outputFilePath =FileUtil.getTmpDirPath() + File.separator + System.currentTimeMillis() + 1 + ".wav";if(!FileUtil.exist(outputFilePath)) {new File(outputFilePath).createNewFile();}// 确保ffmpeg.exe在系统的PATH变量中或者提供完整路径String ffmpeg = "ffmpeg";// 构建FFmpeg命令String command = String.format("%s -i %s -ss %s -t %s -af volume=%s %s",ffmpeg, file.getAbsolutePath(),startTime, endTime - startTime, volume, outputFilePath);// 执行FFmpeg命令try {log.info("执行的cmd命令:{}", command);Process process = Runtime.getRuntime().exec(command);process.waitFor();return FileUtil.getInputStream(outputFilePath);} catch ( Exception e) {e.printStackTrace();} finally {FileUtil.del(file);FileUtil.del(outputFilePath);}return inputFile.getInputStream();}
代码比较简单 就是生成俩文件 使用ffmpeg对第一个文件进行截取处理 ,但是问题来了
每次执行到process.waitFor()就会卡死
在网上搜答案都说是要处理子线程的输出
那好 加上试试呗
ThreadUtil.execute(()->{log.info("处理FFMPEG音频截取进程错误信息");//防止ffmpeg进程塞满缓存造成死锁InputStream error = exec.getErrorStream();StringBuffer result = new StringBuffer();String line = null;try {BufferedReader br = new BufferedReader(new InputStreamReader(error,"GBK"));while((line = br.readLine()) != null){result.append(line+"\n");}log.info("FFMPEG音频截取进程错误信息:"+result.toString());}catch (IOException e2){e2.printStackTrace();}finally {try {error.close();} catch (IOException e) {throw new RuntimeException(e);}}});ThreadUtil.execute(()->{log.info("处理FFMPEG音频截取进程输出信息");InputStream is = exec.getInputStream();StringBuffer result = new StringBuffer();String line = null;try {BufferedReader br2 = new BufferedReader(new InputStreamReader(is,"GBK"));while((line = br2.readLine()) != null){result.append(line+"\n");}log.info("FFMPEG音频截取进程输出内容为:"+result.toString());}catch (IOException e2){e2.printStackTrace();}finally {try {is.close();} catch (IOException e) {throw new RuntimeException(e);}}});
但是问题依然没有得到解决 断点跟进 发现每次一读取InputStream就卡住了 日志也就到这里
在网上搜了大半天 基本全是这样处理的
cmd命令拷贝出来 也没问题啊
然后就陷入了循环,网上搜-> 试试 -> 不行 -> 网上搜
最后折腾了一整天 ,偶然间一次重启程序,发现程序一关闭的时候打印了点日志 但是立马重启了没看清,然后我等他卡住的时候关闭程序 发现报错信息上面有这样一条日志
我简直要吐血了
因为刚开始的时候 调试程序 一直提示我文件找不到 我就加了这样的代码 如果文件没有就创建(上面第一段代码的4 - 7行)
String outputFilePath =FileUtil.getTmpDirPath() + File.separator + System.currentTimeMillis() + 1 + ".wav";if(!FileUtil.exist(outputFilePath)) {new File(outputFilePath).createNewFile();}
本来调用ffmpeg 它是会自动在输出路径创建出来文件的 ,但是由于我上面这段代码创建过文件了,所以他会问我文件已存在是否覆盖 此时本来应该等待我的输入,但是我主进程也在等他结束,所以造成了死锁!
真是太坑了 其实终极原因还是怪自己不够仔细,竟然犯了这样的低级错误