AudioOperationUtils.java 5.5 KB
package com.bsth.util;


import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.io.*;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;

public class AudioOperationUtils {
    public static void main(String[] args) throws Exception {
//        int duration = 450000;
//        double silenceThreshold = -40; // 声音阈值,可以根据需要调整,单位通常是分贝dB
//        splitBySilence("D:\\tts.mp3", "D:\\88814\\cn", duration, silenceThreshold);

        List<String> paths = new ArrayList<>();
        paths.add("D:/speech/803111/cn/000.mp3");
        paths.add("D:/speech/803111/cn/001.mp3");
        merge(paths, "D:/speech/803111/results.mp3");
    }

    public static void merge(List<String> inputPaths, String outputPath) throws Exception {
        File file = new File(outputPath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File(outputPath), 1);

        int i = 0;
        Frame frame = null;
        for (String inputPath : inputPaths) {
            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath);
            grabber.start();
            if (i == 0) {
                recorder.setAudioCodec(grabber.getAudioCodec());
                recorder.setFrameRate(grabber.getFrameRate());
                recorder.setFormat(grabber.getFormat());
                recorder.start();
            }
            while ((frame = grabber.grabSamples()) != null) {
                recorder.record(frame);
            }
            grabber.stop();
            grabber.close();
            i++;
        }
        recorder.stop();
        recorder.close();
    }

    public static void splitBySilence(String inputPath, String outputPath, int duration, double silenceThreshold) throws Exception {
        File file = new File(outputPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        boolean isSilent = false;
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath);
        grabber.start();
        Frame frame = null;
        List<SilenceInfo> silenceInfos = new ArrayList<>();
        long start = 0, end = 0;
        while((frame = grabber.grabSamples()) != null) {
            ShortBuffer buffer = (ShortBuffer) frame.samples[0];
            double energy = 0;
            while (buffer.hasRemaining()) {
                short sample = buffer.get();
                energy += sample * sample;
            }
            energy /= buffer.capacity();
            double db = 20 * Math.log10(Math.sqrt(energy));
            if (db < silenceThreshold) {
                if (!isSilent && start == 0) {
                    isSilent = true;
                    start = frame.timestamp;
                }
            } else {
                if (start != 0 && frame.timestamp - start >= duration) {
                    SilenceInfo info = new SilenceInfo(end, start);
                    silenceInfos.add(info);
                    end = frame.timestamp;
                }
                isSilent = false;
                start = 0;
            }
        }
        if (silenceInfos.size() > 0) {
            SilenceInfo info = new SilenceInfo(end, grabber.getLengthInTime());
            silenceInfos.add(info);
        }
        grabber.stop();
        grabber.close();
        grabber = new FFmpegFrameGrabber(inputPath);
        grabber.start();
        int idx = 0;
        boolean flag = false;
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File(String.format("%s%s%03d.mp3", outputPath, File.separator, idx)), 1);
        recorder.setAudioCodec(grabber.getAudioCodec());
        recorder.setFrameRate(grabber.getFrameRate());
        recorder.setFormat(grabber.getFormat());
        recorder.start();
        SilenceInfo info = silenceInfos.get(idx);
        while ((frame = grabber.grabSamples()) != null) {
            if (idx < silenceInfos.size()) {
                if (frame.timestamp >= info.start && frame.timestamp <= info.end) {
                    recorder.record(frame);
                    flag = false;
                } else {
                    if (!flag) {
                        flag = true;
                        recorder.stop();
                        recorder.close();
                        idx++;
                        info = silenceInfos.get(idx);
                        recorder = new FFmpegFrameRecorder(new File(String.format("%s%s%03d.mp3", outputPath, File.separator, idx)), 1);
                        recorder.start();
                        recorder.setAudioCodec(grabber.getAudioCodec());
                        recorder.setFrameRate(grabber.getFrameRate());
                        recorder.setFormat(grabber.getFormat());
                    }
                }
            }
        }
        if (recorder != null) {
            recorder.stop();
            recorder.close();
        }
    }

    public final static class SilenceInfo {

        private long start;

        private long end;

        public SilenceInfo() {}

        public SilenceInfo(long start, long end) {
            this.start = start;
            this.end = end;
        }

        public long getStart() {
            return start;
        }

        public void setStart(long start) {
            this.start = start;
        }

        public long getEnd() {
            return end;
        }

        public void setEnd(long end) {
            this.end = end;
        }
    }
}