当前位置: 首页 > news >正文

记一次极其坑爹的 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 它是会自动在输出路径创建出来文件的 ,但是由于我上面这段代码创建过文件了,所以他会问我文件已存在是否覆盖 此时本来应该等待我的输入,但是我主进程也在等他结束,所以造成了死锁!

真是太坑了 其实终极原因还是怪自己不够仔细,竟然犯了这样的低级错误

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【RAG入门教程04】Langchian的文档切分
  • 【代码随想录】【算法训练营】【第32天】 [122]买卖股票的最佳时机II [376]摆动序列 [53]最大子序和
  • string类的模拟实现的一些改进
  • R语言探索与分析18-基于时间序列的汇率预测
  • Spring Cloud Gateway CORS 跨域方案
  • 引入Springcloud--Sleuth-链路追踪中MDC是如何获取到traceid和何时放入traceid的
  • 用动态IP采集数据总是掉线是为什么?该怎么解决?
  • R语言探索与分析19-CPI的分析和研究
  • C++迈向精通:STL的Deque复现
  • 前端面试项目细节重难点(已工作|做分享)想(八)
  • Ubuntu22.04之解决:terminal使用alt+1/alt+2/alt+3失效问题(二百三十八)
  • 自然语言处理(NLP)—— 自动摘要
  • 【手推公式】如何求SDE的解(附录B)
  • 爬虫——有道云翻译
  • QTGUI编程入门:解锁图形用户界面设计的奥秘
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 3.7、@ResponseBody 和 @RestController
  • CentOS6 编译安装 redis-3.2.3
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • ES6系列(二)变量的解构赋值
  • Javascript设计模式学习之Observer(观察者)模式
  • JDK 6和JDK 7中的substring()方法
  • Logstash 参考指南(目录)
  • Node 版本管理
  • PaddlePaddle-GitHub的正确打开姿势
  • Puppeteer:浏览器控制器
  • Python学习之路16-使用API
  • Selenium实战教程系列(二)---元素定位
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 深度学习入门:10门免费线上课程推荐
  • 手机app有了短信验证码还有没必要有图片验证码?
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​MySQL主从复制一致性检测
  • #mysql 8.0 踩坑日记
  • #pragma预处理命令
  • #前后端分离# 头条发布系统
  • $(selector).each()和$.each()的区别
  • (02)Hive SQL编译成MapReduce任务的过程
  • (2024,Flag-DiT,文本引导的多模态生成,SR,统一的标记化,RoPE、RMSNorm 和流匹配)Lumina-T2X
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (四)模仿学习-完成后台管理页面查询
  • (译) 函数式 JS #1:简介
  • (转)Oracle 9i 数据库设计指引全集(1)
  • ****Linux下Mysql的安装和配置
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET C# 操作Neo4j图数据库
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • :class的用法及应用
  • ?.的用法
  • @Conditional注解详解
  • [04]Web前端进阶—JS伪数组
  • [C++初阶]list的模拟实现