package com.dl.dml.common.voice;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author liuwenpu
* @version 1.0
* @Description 录音合成
* @date 2023/6/18 19:59
*/
public class RecordingSynthesis {
//音频处理器执行文件路径
public static final String FFMPEG_PATH = "D:\\tools\\ffmpeg\\bin\\ffmpeg.exe";
//音频处理器执行文件路径
public static final String FILE_TEXT_PATH = "D:\\tools\\ffmpeg\\fileList.txt";
public static void main(String[] args) throws Exception {
String fileText = "D:\\tmp\\voice\\fileList.txt";
String output = "D:\\tmp\\voice";
String fileName = "xixi";
String rootPath = "D:\\tmp\\voice\\测试音频样本";
generateMp3(1,fileText,output,fileName,rootPath);
}
/**
* 生成合并的mp3文件
* @param count 生成次数
* @param fileText 合并的文件路径
* @param outputPath 生成的mp3文件路径
* @param fileName 生成的mp3文件名称,多个按-1,-2计算
* @param rootPath 初始音频文件夹根目录
*/
public static boolean generateMp3(int count,String fileText,String outputPath,String fileName,String rootPath) throws Exception {
for (int i = 0; i < count; i++) {
String output = outputPath + File.separator + fileName + ".mp3";
if(i > 0) output = outputPath + File.separator + fileName + i + ".mp3";
List<String> randomFindFiles = randomFindFiles(rootPath);
//记录所有转换后音频的路径
List<String> tempPathList = new ArrayList<>();
for (String filePath : randomFindFiles) {
//生成临时文件用户转换mp3音频
String tempPath = filePath.substring(0,filePath.lastIndexOf(".mp3")) + "-1.mp3";
mp3Convert(filePath,tempPath);
tempPathList.add(tempPath);
}
//将需要合并的音频写入文件
fileTextCreate(fileText,tempPathList);
//音频文件合并
mp3Synthesis(fileText,output);
//清理临时生成的文件路径
FileUtil.del(fileText);
for (String tempPath : tempPathList) {
FileUtil.del(tempPath);
}
}
return true;
}
/**
* 根据根目录随机到子目录查找一个文件记录
* @param rootPath
*/
public static List<String> randomFindFiles(String rootPath) {
List<String> filePathList = new ArrayList<>();
File file = FileUtil.file(rootPath);
if(!file.isDirectory()) return null;
File[] childFiles = file.listFiles();
for (File childFile : childFiles) {
//如果是文件直接跳过
if(!childFile.isDirectory()) continue;
//得到子文件夹数组,根据随机数随机获取一个文件
File[] listFiles = childFile.listFiles();
filePathList.add(listFiles[getRandom(listFiles.length)].getAbsolutePath());
}
return filePathList;
}
/**
* 文件转换mp3格式
* @param mp3Path 需要转换的路径
* @param outputPath 输出路径
*/
public static void mp3Convert(String mp3Path,String outputPath) throws IOException {
String cmd = FFMPEG_PATH + " -i "+mp3Path+" -codec:a libmp3lame -qscale:a 2 " + outputPath + " -y";
execOutPutProcess(cmd);
}
/**
* mp3文件合并
* @param textPath 需要合并的文件路径
* @param outputPath 输出路径
*/
public static void mp3Synthesis(String textPath,String outputPath) throws IOException {
String cmd = FFMPEG_PATH + " -f concat -safe 0 -i "+textPath+" -acodec copy " + outputPath + " -y";;
execOutPutProcess(cmd);
}
/**
* 合并的文件生成
* @param textName 文件名称
* @param filePathList 需要合并的文件路径集合
* @throws IOException
*/
public static void fileTextCreate(String textName, List<String> filePathList) throws IOException {
// 创建临时文本文件来保存要合并的MP3文件列表
FileWriter fileWriter = new FileWriter(textName);
for (String filePath : filePathList) {
fileWriter.write("file '"+filePath+"'\n");
}
fileWriter.close();
}
/**
* cmd命令执行并输出结果
* @param cmd
* @throws IOException
*/
public static void execOutPutProcess(String cmd) throws IOException {
System.out.println(cmd);
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(cmd);
// 消费标准输出流(如果你需要)
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
// while ((line = reader.readLine()) != null) {
// // 处理标准输出信息
// System.out.println(line);
// }
// 消费错误输出流
InputStream errorStream = process.getErrorStream();
BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream));
while ((line = errorReader.readLine()) != null) {
// 处理错误输出信息
System.err.println(line);
}
}
/**
* 生成一个随机数
* @param max 上限值
* @return
*/
public static int getRandom(int max) {
return RandomUtil.randomInt(0, max);
}
}