java使用ffmpeg合并音频文件生成mp3

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);
    }
}


posted @ 2023-06-29 21:39  幸运刘  阅读(734)  评论(0)    收藏  举报