Java实现音频添加自定义时长静音的示例代码

 更新时间:2022年01月27日 08:33:38   作者:剑客·阿良  
这篇文章主要介绍了一个Java工具类,可以实现给一个wav音频添加自定义时长静音。文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编学习一下

前言

本文提供一个可以给一个wav音频添加自定义时长静音的工具类。正好工作中用到,所以正好分享分享。

Maven依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.2</version>
        </dependency>

代码

package ai.guiji.csdn.tools;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.URLUtil;
import com.google.common.base.Joiner;
import com.google.common.primitives.Bytes;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.LongStream;

/** @Author 剑客阿良_ALiang @Date 2022/1/26 14:27 @Description: wav添加静音时长工具 */
public class WavAddSilenceUtils {
  /**
   * 根据PCM文件构建wav的header字段
   *
   * @param srate Sample rate - 8000, 16000, etc.
   * @param channel Number of channels - Mono = 1, Stereo = 2, etc..
   * @param format Number of bits per sample (16 here)
   * @throws IOException
   */
  public static byte[] buildWavHeader(int dataLength, int srate, int channel, int format)
      throws IOException {
    byte[] header = new byte[44];

    long totalDataLen = dataLength + 36;
    long bitrate = srate * channel * format;

    header[0] = 'R';
    header[1] = 'I';
    header[2] = 'F';
    header[3] = 'F';
    header[4] = (byte) (totalDataLen & 0xff);
    header[5] = (byte) ((totalDataLen >> 8) & 0xff);
    header[6] = (byte) ((totalDataLen >> 16) & 0xff);
    header[7] = (byte) ((totalDataLen >> 24) & 0xff);
    header[8] = 'W';
    header[9] = 'A';
    header[10] = 'V';
    header[11] = 'E';
    header[12] = 'f';
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';
    header[16] = (byte) format;
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    header[20] = 1;
    header[21] = 0;
    header[22] = (byte) channel;
    header[23] = 0;
    header[24] = (byte) (srate & 0xff);
    header[25] = (byte) ((srate >> 8) & 0xff);
    header[26] = (byte) ((srate >> 16) & 0xff);
    header[27] = (byte) ((srate >> 24) & 0xff);
    header[28] = (byte) ((bitrate / 8) & 0xff);
    header[29] = (byte) (((bitrate / 8) >> 8) & 0xff);
    header[30] = (byte) (((bitrate / 8) >> 16) & 0xff);
    header[31] = (byte) (((bitrate / 8) >> 24) & 0xff);
    header[32] = (byte) ((channel * format) / 8);
    header[33] = 0;
    header[34] = 16;
    header[35] = 0;
    header[36] = 'd';
    header[37] = 'a';
    header[38] = 't';
    header[39] = 'a';
    header[40] = (byte) (dataLength & 0xff);
    header[41] = (byte) ((dataLength >> 8) & 0xff);
    header[42] = (byte) ((dataLength >> 16) & 0xff);
    header[43] = (byte) ((dataLength >> 24) & 0xff);

    return header;
  }

  /**
   * 默认写入的pcm数据是16000采样率,16bit,可以按照需要修改
   *
   * @param filePath
   * @param pcmData
   */
  public static boolean writeToFile(String filePath, byte[] pcmData) {
    BufferedOutputStream bos = null;
    try {
      bos = new BufferedOutputStream(new FileOutputStream(filePath));
      byte[] header = buildWavHeader(pcmData.length, 16000, 1, 16);
      bos.write(header, 0, 44);
      bos.write(pcmData);
      bos.close();
      return true;
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (bos != null) {
        try {
          bos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

    return false;
  }

  /**
   * 增加延时静音
   *
   * @param filePath 音频地址
   * @param tmpDirPath 临时目录地址
   * @param delayTime 延时时长,单位毫秒
   * @return 最终文件地址
   * @throws Exception 异常
   */
  public static String delayWav(String filePath, String tmpDirPath, Long delayTime)
      throws Exception {
    byte[] bytes;
    if (filePath.startsWith("http")) {
      bytes = IoUtil.readBytes(URLUtil.getStream(new URL(filePath)));
    } else {
      bytes = FileUtil.readBytes(filePath);
    }
    List<Byte> resultByte =
        new ArrayList<>(Bytes.asList(Arrays.copyOfRange(bytes, 44, bytes.length)));
    LongStream.range(0, (long) (delayTime * 32)).forEach(x -> resultByte.add((byte) 0));
    String resultPath =
        Joiner.on(File.separator).join(Arrays.asList(tmpDirPath, IdUtil.simpleUUID() + ".wav"));
    writeToFile(resultPath, Bytes.toArray(resultByte));
    return resultPath;
  }

  public static void main(String[] args) throws Exception {
    System.out.println(delayWav("http://xxxx/xxx.wav", "C:\\Users\\huyi\\Desktop\\", 10000L));
  }
}

代码说明:

1、delayWav方法参数分别为wav音频文件地址(可以支持http的url地址)、临时文件目录地址、延时静音时长(单位毫秒)

2、对wav的要求默认为:采样率16K、单声道。可以参考:Java实现生成自定义时长的静音音频

对需要处理的音频参数调整。

3、生成uuid的随机文件名,避免重复。

验证一下

下面是准备的音频

file

执行结果

file

执行后音频

file

OK,加了10秒的静音。

到此这篇关于Java实现音频添加自定义时长静音的示例代码的文章就介绍到这了,更多相关Java音频添加静音内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现链表中元素的获取、查询和修改方法详解

    Java实现链表中元素的获取、查询和修改方法详解

    这篇文章主要介绍了Java实现链表中元素的获取、查询和修改方法,结合实例形式详细分析了Java针对链表中元素的获取、查询和修改相关原理、实现方法及操作注意事项,需要的朋友可以参考下
    2020-03-03
  • JAVA多线程实现生产者消费者的实例详解

    JAVA多线程实现生产者消费者的实例详解

    这篇文章主要介绍了JAVA多线程实现生产者消费者的实例详解的相关资料,需要的朋友可以参考下
    2017-06-06
  • 深入理解Spring bean加载顺序

    深入理解Spring bean加载顺序

    在默认配置下,SpringBean的加载顺序主要受到Bean定义顺序、依赖关系和生命周期回调方法的影响,本文就来了解一下Spring bean加载顺序,感兴趣的同学可以学习
    2024-10-10
  • springboot中EasyPoi实现自动新增序号的方法

    springboot中EasyPoi实现自动新增序号的方法

    本文主要介绍了EasyPoi实现自动新增序号,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 在SpringBoot环境中使用Mockito进行单元测试的示例详解

    在SpringBoot环境中使用Mockito进行单元测试的示例详解

    Mockito特别适用于在Spring Boot环境中进行单元测试,因为它能够轻松模拟Spring应用中的服务、存储库、客户端和其他组件,通过使用Mockito,开发者可以模拟外部依赖,从而使单元测试更加独立和可靠,本文给大家介绍了在Spring Boot环境中使用Mockito进行单元测试
    2024-01-01
  • SpringBoot集成redis与session实现分布式单点登录

    SpringBoot集成redis与session实现分布式单点登录

    这篇文章主要介绍了SpringBoot集成redis与session实现分布式单点登录,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • mybatis的ParamNameResolver参数名称解析

    mybatis的ParamNameResolver参数名称解析

    这篇文章主要为大家介绍了mybatis的ParamNameResolver参数名称解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Java全面细致讲解==和equals的使用

    Java全面细致讲解==和equals的使用

    这篇文章主要介绍了Java中==和equals()的区别,,==可以使用在基本数据类型变量和引用数据类型变量中,equals()是方法,只能用于引用数据类型,需要的朋友可以参考下
    2022-05-05
  • Junit单元测试关于@Transactional注解引起的事务回滚问题

    Junit单元测试关于@Transactional注解引起的事务回滚问题

    这篇文章主要介绍了Junit单元测试关于@Transactional注解引起的事务回滚问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 详解springMVC—三种控制器controller

    详解springMVC—三种控制器controller

    本篇文章主要介绍了springMVC—三种控制器controller,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论