Java音频文件统一处理-源码分享

源于最近的项目接触到了音频文件的转换及相关操作,所以做个记录以供大家参考。

一.需求

由于当前的一批音频文件格式参差不齐,且采样率也不一致。在进行音频文件的统一处理前,需要将文件格式和采样率进行统一。
思路,将非wav格式的音频文件统一转换为wav格式,且将采样率统一为8k。

二.依赖

使用javazoom的Converter进行统一转换处理。

<dependency>
    <groupId>javazoom</groupId>
    <artifactId>jlayer</artifactId>
    <version>1.0.1</version>
</dependency>

三.源码(存在瑕疵,建议先看第四块的补充说明)

talk is cheap,show me the code.

import com.sun.media.sound.WaveFileReader;
import com.sun.media.sound.WaveFileWriter;
import javazoom.jl.converter.Converter;
import javazoom.jl.decoder.JavaLayerException;

import javax.sound.sampled.*;
import java.io.*;
import java.nio.file.Files;

/**
 * @author: Vainycos
 * @description 录音文件工具类
 * @date: 2023/4/17 17:14
 */
public class VoiceFileUtils {

    /**
     * 统一转换8k采样率。根据实际需求可进行调整,或者将此变量抽取至配置文件
     */
    public static final int TARGET_SAMPLE_RATE = 8000;


    /**
     * 转换wav格式
     * @param inputFilePath
     * @param outputFilePath
     * @return
     */
    public static boolean toWav(String inputFilePath, String outputFilePath){
        Converter converter = new Converter();
        try {
            converter.convert(inputFilePath, outputFilePath);
        } catch (JavaLayerException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 将wav转换为8k采样率
     * @param inputFilePath
     * @param outputFilePath
     */
    public static void toStandardWav(String inputFilePath, String outputFilePath){
        try {
            byte[] bytes = Files.readAllBytes(new File(inputFilePath).toPath());
            WaveFileReader reader = new WaveFileReader();
            AudioInputStream audioIn = reader.getAudioInputStream(new ByteArrayInputStream(bytes));
            AudioFormat srcFormat = audioIn.getFormat();
            AudioFormat dstFormat = new AudioFormat(srcFormat.getEncoding(),
                    TARGET_SAMPLE_RATE,
                    srcFormat.getSampleSizeInBits(),
                    srcFormat.getChannels(),
                    srcFormat.getFrameSize(),
                    srcFormat.getFrameRate(),
                    srcFormat.isBigEndian());
            AudioInputStream convertedIn = AudioSystem.getAudioInputStream(dstFormat, audioIn);
            File file = new File(outputFilePath);
            WaveFileWriter writer = new WaveFileWriter();
            writer.write(convertedIn, AudioFileFormat.Type.WAVE, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String filePath = "C:\\data\\test.mp3";
        String wavTargetPath = "C:\\data\\convert-wav-result.wav";
        String standardWavPath = "C:\\data\\standard-result.wav";
        toWav(filePath, wavTargetPath);
        toStandardWav(wavTargetPath, standardWavPath);
    }

唯一需要注意的是,如果调用toWav()传入的inputFilePath的源音频文件本来就是wav格式则会报异常,所以需要判断一下只有非wav格式才需要调用toWav()方法,否则直接调用toStandardWav()方法转换采样率即可。

四.补充

在mp3->wav的过程中,偶尔会遇到转换出错的情况。通过debug发现在convert()过程的源码javazoom.jl.converter.Converter读取Header会出现null的情况。
正常转换录音情况:
正常转换录音情况
异常转换录音文件的情况:
异常转换录音文件
目前暂时未做原理深究,初步推测是源文件音频文件头缺失。
在此补充另一种转换的方法,若上述转换失败则可以使用该方法作为替补方案,并可直接在mp3转换wav格式的过程中将采样率,比特率等参数进行统一设置:

public static void main(String[] args) throws IOException, IllegalArgumentException, InputFormatException, EncoderException {
    File source = new File("C:\\data\\test.mp3");
    File target = new File("C:\\data\\test.wav");
    trans(source,target);
}
public static void trans(File source, File target) throws IllegalArgumentException, InputFormatException, EncoderException  {
    AudioAttributes audio = new AudioAttributes();

    audio.setCodec("libmp3lame");
    // 设置比特率
    audio.setBitRate(new Integer(16000));
    // 设置音频通道数
    audio.setChannels(new Integer(2));
    // 设置采样率,此处设置为8k采样率
    audio.setSamplingRate(new Integer(8000));

    EncodingAttributes attrs = new EncodingAttributes();
    // 目标文件的格式
    attrs.setFormat("wav");
    // 将上述设置的参数设置到目标文件中
    attrs.setAudioAttributes(audio);
    Encoder encoder = new Encoder();
    MultimediaObject sourceObj = new MultimediaObject(source);
    encoder.encode(sourceObj, target, attrs);
}

五.补充2,使用java2

使用java实现格式转换:

<dependency>
 <groupId>ws.schild</groupId>
 <artifactId>jave-all-deps</artifactId>
 <version>3.3.1</version>
</dependency>
public boolean m4aToWav() {
        boolean succeeded = true;
        try {
            File source = new File("source.m4a");
            File target = new File("target.wav");

            //Audio Attributes
            AudioAttributes audio = new AudioAttributes();
            audio.setCodec("pcm_s16le");
            audio.setBitRate(16000);
            audio.setChannels(1);
            audio.setBitRate(16000);
            audio.setSamplingRate(16000);

            //Encoding attributes
            EncodingAttributes attrs = new EncodingAttributes();
            attrs.setFormat("wav");
            attrs.setAudioAttributes(audio);

            //Encode
            Encoder encoder = new Encoder();
            encoder.encode(new MultimediaObject(source), target, attrs);

           } catch (Exception ex) {
               ex.printStackTrace();
               succeeded = false;
           }
        return succeeded;
    }

参考资料:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值