项目中有个需求需要截取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 它是会自动在输出路径创建出来文件的 ,但是由于我上面这段代码创建过文件了,所以他会问我文件已存在是否覆盖 此时本来应该等待我的输入,但是我主进程也在等他结束,所以造成了死锁!
真是太坑了 其实终极原因还是怪自己不够仔细,竟然犯了这样的低级错误