1. 程式人生 > >java MP3轉碼pcm 與 切割音訊

java MP3轉碼pcm 與 切割音訊

開發十年,就只剩下這套架構體系了! >>>   

需求1: 呼叫語音聽寫介面, 類似百度要pcm格式音訊, 但是發現百度給的mp3轉pcm的demo轉出的音訊識別錯誤, 不知道我是不是copy錯哪裡了...

需求2: 大量音訊需要切分成多個小句子(參看jdk11 HttpClient 爬蟲中, 爬了***網的音訊, 其中有個精聽練習, 音訊分為多個段落,我需要按照這個段落切分成一個個小音訊)

以上這兩個需求我最終都選擇了ffmpeg來實現.

下載並安裝ffmpeg

windows10配置

下載, 配置環境變數到Path, cmd測試ffmpeg命令

CentOS配置

略, 百度一下

mp3轉pcm

    /**
     * MP3轉換PCM檔案方法
     *
     * @param mp3filePath 原始檔案路徑
     * @param pcmFilePath 轉換檔案的儲存路徑
     */
    public static boolean mp32pcm(String mp3filePath, String pcmFilePath) {
//        String command = "ffmpeg -y -i mp3filePath -acodec pcm_s16le -f s16le -ac 1 -ar 16000 pcmFilePath";
        try {
            String command1 = "ffmpeg -y -i ";
            String command2 = " -acodec pcm_s16le -f s16le -ac 1 -ar 16000 ";


            Runtime runtime = Runtime.getRuntime();
            Process exec = runtime.exec(command1 + mp3filePath + command2 + pcmFilePath);
            exec.waitFor();

            exec.destroy();

            return true;
        } catch (Exception e) {
            System.out.println("MP3轉換PCM檔案 失敗");
        }
        return false;
    }

-y

允許覆蓋

-i test.mp3

原始檔

-acodec pcm_s16le

編碼器

-f s16le

強制檔案格式

-ac 2

雙聲道

-ar 16000

取樣率

 音訊分割

音訊分割先需要知道在哪裡分割, 看看下圖

有每句話的起始時間, 可以使用爬蟲爬一下, 我的方法是使用爬到每個頁面的資訊, 先存到一個excel裡(使用easypoi), 過程就不寫了, 爬蟲的部分可以看看我上一篇jdk11 HttpClient 爬蟲中的第二部分, 匯出的檔案如下

然後讀取並解析這個檔案(easypoi), 輪詢, 切割, 就這麼easy

class KmcJtPojo {
    @Excel(name = "名稱")
    private String name;
    @Excel(name = "父節點名稱")
    private String parentName;
    @Excel(name = "原文")
    private String enText;
    @Excel(name = "譯文")
    private String cnText;
    @Excel(name = "音訊檔案")
    private String filePath;
    @Excel(name = "開始表")
    private Double startSecond;
    @Excel(name = "結束秒")
    private Double endSecond;
    @Excel(name = "總秒")
    private Double allSecond;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getParentName() {
        return parentName;
    }

    public void setParentName(String parentName) {
        this.parentName = parentName;
    }

    public String getEnText() {
        return enText;
    }

    public void setEnText(String enText) {
        this.enText = enText;
    }

    public String getCnText() {
        return cnText;
    }

    public void setCnText(String cnText) {
        this.cnText = cnText;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public Double getStartSecond() {
        return startSecond;
    }

    public void setStartSecond(Double startSecond) {
        this.startSecond = startSecond;
    }

    public Double getEndSecond() {
        return endSecond;
    }

    public void setEndSecond(Double endSecond) {
        this.endSecond = endSecond;
    }

    public Double getAllSecond() {
        return allSecond;
    }

    public void setAllSecond(Double allSecond) {
        this.allSecond = allSecond;
    }
}

public class 本地音訊切割根據Excel {


    @Test
    public void cutAudio() {
        String excelFilePath = "H:\\精聽匯出檔案.xls";
        String audioFilePath= "H:\\jt_speak\\";

        List<KmcJtPojo> list = ExcelImportUtil.importExcel(new File(excelFilePath), KmcJtPojo.class, new ImportParams());

        List<KmcJtPojo> bigs = list.stream().filter(t -> StringUtils.isNotEmpty(t.getName())).collect(Collectors.toList());
        //建立資料夾
        bigs.forEach(t -> {
            File file = new File(audioFilePath + t.getName().trim().replace(" ", "_"));
            if (!file.exists()) {
                file.mkdir();
            }
        });


        //遍歷children節點 切割音訊
        List<KmcJtPojo> children = list.stream().filter(t -> StringUtils.isNotEmpty(t.getParentName())).collect(Collectors.toList());
        children.parallelStream().forEach(t -> {
            try {
//                String command1 = "ffmpeg -ss 00:00:00 -t 00:02:00 -i 輸入檔名.mp3輸出檔名_1.mp3 -y";
                String command0 = "ffmpeg -ss ";
                String command1 = " -t ";
                String command2 = " -i ";
                String command3 = " -c copy ";
                String command4 = " -y";


                Runtime runtime = Runtime.getRuntime();
                String replace = t.getParentName().trim().replace(" ", "_") + ".mp3";
                Process exec = runtime.exec(command0 + t.getStartSecond() + command1 + t.getAllSecond() +
                        command2 + audioFilePath+ replace + command3 + audioFilePath+ t.getFilePath() + command4);
                exec.waitFor();

                exec.destroy();

            } catch (Exception e) {
                System.out.println("MP3切割失敗" + t.getFilePath());
            }
        });
    }
}