搜索
您的当前位置:首页ffmpeg转换通用音频格式为wav格式

ffmpeg转换通用音频格式为wav格式

来源:乌哈旅游
import com.jdd.ai.digital.human.live.common.exception.error.CommonErrorCode;
import com.jdd.ai.digital.human.live.constants.VideoMaterialTypeEnum;
import com.jdd.ai.digital.human.live.exception.BaseException;
import com.jdd.ai.robot.digital.human.service.system.oss.UuidUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jodd.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.MultimediaInfo;
import ws.schild.jave.MultimediaObject;

/**
 * @author ext.huishanyu1
 */
@Service
@Slf4j
public class AudioService {

  private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
  private final String ORIGIN_PATH = "/music/convert/";
  private static final String MUSIC_SUFFIX = ".wav";
  private final Pattern pattern = Pattern.compile("[\u4E00-\u9FA5|\\!|\\,|\\。|\\(|\\)|\\《|\\》|\\“|\\”|\\?|\\:|\\;|\\【|\\】]");
  
  /** 判断是否为music类型 */
  public boolean isMusicType(MultipartFile multipartFile) {
    return MaterialUtils.convert(Objects.requireNonNull(FilenameUtils.getExtension(multipartFile.getOriginalFilename()))).name().equals(VideoMaterialTypeEnum.music.name());
  }
  
  /** 判断是否为中文 */
  public boolean isChinese(String str) {
    if (StringUtils.isBlank(str)) {
      return false;
    }
    Matcher m = pattern.matcher(str);
    return m.find();
  }

  /** 判断是否为wav格式 */
  public boolean isWav(String suffix) {
    return MUSIC_SUFFIX.equalsIgnoreCase(suffix);
  }

  /** 获取新文件名 */
  public String getNewBaseName(String fileName) {
    return String.format("%s%s", FilenameUtils.getBaseName(fileName), MUSIC_SUFFIX);
  }

  /** 生成新文件名 */
  public String generateFileName(String suffix) {
    String newSuffix = StringUtils.isBlank(suffix) ? MUSIC_SUFFIX : String.format(".%s", suffix);
    return String.format("%s%s", UuidUtils.getUUID(), newSuffix);
  }

  /** 获取后缀 */
  public String getNewSuffix() {
    return MUSIC_SUFFIX;
  }

  /** 获取语音文件播放时长 */
  public String getDuration(MultipartFile multipartFile) {
    File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
    try {
      FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);

      MultimediaObject object = new MultimediaObject(file);
      MultimediaInfo info = object.getInfo();

      return DateUtils.convertMillisecond2(info.getDuration());
    } catch (Exception e) {
      e.printStackTrace();
      log.error("<AudioUtil>.getDuration, music get duration fail, message:{}", ExceptionUtils.getStackTrace(e));
      return "00:00";
    } finally {
      // 删除文件
      try {
        FileUtil.deleteFile(file);
      } catch (IOException e) {
        e.printStackTrace();
        log.error("<AudioUtil>.getDuration, file delete fail, message:{}", ExceptionUtils.getStackTrace(e));
      }
    }
  }

  /** 其他音乐类型转换为标准wav类型 */
  public InputStream toWav(MultipartFile multipartFile) throws BaseException{
    InputStream inputStream = null;
  
    // 录音文件下拉地址
    String sourceName = multipartFile.getOriginalFilename();
    String destName = String.format("%s%s", FilenameUtils.getBaseName(multipartFile.getOriginalFilename()), MUSIC_SUFFIX);
    // 文件中文检测
    if(isChinese(sourceName)){
      sourceName = generateFileName(FilenameUtils.getExtension(sourceName));
      destName = generateFileName(null);
    }
    String sourcePath = String.format("%s%s", ORIGIN_PATH, sourceName);
    String destPath = String.format("%s%s", ORIGIN_PATH, destName);
    try {
      if (save(ORIGIN_PATH, sourceName, multipartFile.getBytes())) {
        String command;
        // 将原音频文件转换为 双声道(-ac 2)/采样率22050Hz(-ar 22050) 16bit/音频码率128kbps(-ab 128k)/声音编解码器16kbs(-acodec pcm_s16le)的wav音频文件
        command = MessageFormat.format("ffmpeg -i {0} -ac 2 -ar 22050 -ab 128k -acodec pcm_s16le {1}", sourcePath, destPath);
//        command = MessageFormat.format("D:/software/ffmpeg/ffmpeg-5.0.1-essentials_build/bin/ffmpeg.exe -i {0} -ac 2 -ar 22050 -ab 128k -acodec pcm_s16le {1}", sourcePath, destPath);
        int n = execCommand(command, 30);
        // 获取文件流
        if (n == 0) {
          byte[] body = getFileBytes(destName);

          // byte[] convert InputStream
          inputStream = new ByteArrayInputStream(body);
        } else {
          throw new BaseException(CommonErrorCode.FILE_FFMPEG_CONVERT_TYPE_ERROR.getDesc());
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
      log.error("<AudioUtil>.toWav, source convert wav fail, message:{}", ExceptionUtils.getStackTrace(e));
    } finally {
      // 执行完毕,删除下拉音频文件
      try {
        FileUtil.deleteFile(sourcePath);
        FileUtil.deleteFile(destPath);
      } catch (IOException e) {
        e.printStackTrace();
        log.error("<AudioUtil>.toWav, delete file fail, message:{}", ExceptionUtils.getStackTrace(e));
      }
    }
    return inputStream;
  }

  /** 执行FFmpeg命令 */
  public int execCommand(String command, long timeout) {
    Process process = null;
    Future<Integer> executeFuture = null;
    try {
      process = Runtime.getRuntime().exec(command);
      final Process p = process;
      Callable<Integer> call = () -> {
          p.waitFor();
          return p.exitValue();
      };

      // 使用线程池防止Process阻塞
      executeFuture = executorService.submit(call);
      return executeFuture.get(timeout, TimeUnit.SECONDS);
    } catch (Exception e) {
      e.printStackTrace();
      log.error("<AudioUtil>.save, convert wav type error,execCommand fail, command:{}, message:{}", command, ExceptionUtils.getStackTrace(e));
      return 1;
    } finally {
      if (executeFuture != null) {
        try {
          executeFuture.cancel(true);
        } catch (Exception e) {
          e.printStackTrace();
          log.error("<AudioUtil>.save, convert wav type error,future cancel fail, message:{}", ExceptionUtils.getStackTrace(e));
        }
      }
      if (process != null) {
        process.destroy();
      }
    }
  }

  /** 保存文件 */
  private boolean save(String filePath, String fileName, byte[] content) {
    try {
      File fileDir = new File(filePath);
      if (!fileDir.exists()) {
        fileDir.mkdirs();
      }

      File file = new File(fileDir, fileName);
      OutputStream os = new FileOutputStream(file);
      os.write(content, 0, content.length);

      os.flush();
      os.close();
    } catch (IOException e) {
      e.printStackTrace();
      log.error("<AudioUtil>.save, file save error, fileName:{}, filePath:{}, message:{}", fileName, filePath, ExceptionUtils.getStackTrace(e));
      return false;
    }
    return true;
  }

  /** 获取文件byte[] */
  private byte[] getFileBytes(String fileName) {
    byte[] buffer = null;
    FileInputStream fis = null;
    ByteArrayOutputStream bos = null;
    try {
      File file = new File(ORIGIN_PATH, fileName);
      fis = new FileInputStream(file);
      bos = new ByteArrayOutputStream();
      byte[] b = new byte[1024 * 4];
      int n;
      while ((n = fis.read(b)) != -1) {
        bos.write(b, 0, n);
      }
      buffer = bos.toByteArray();
    } catch (Exception e) {
      e.printStackTrace();
      log.error("<AudioUtil>.getFile, get file bytes error, fileName:{}, filePath:{}, message:{}", fileName, ORIGIN_PATH, ExceptionUtils.getStackTrace(e));
    } finally {
      try {
        if (Objects.nonNull(bos)) {
          bos.close();
        }
        if (Objects.nonNull(fis)) {
          fis.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
        log.error("<AudioUtil>.getFile, close stream error, message:{}", ExceptionUtils.getStackTrace(e));
      }
    }
    return buffer;
  }
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Top