package com.fuyuanshen.app.service; import com.fuyuanshen.equipment.utils.AlibabaTTSUtil; import com.fuyuanshen.equipment.utils.AudioProcessUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Arrays; import java.util.List; /** * 音频处理服务 */ @Slf4j @Service @RequiredArgsConstructor public class AudioProcessService { // 配置参数 private static final int MAX_AUDIO_SIZE = 5 * 1024 * 1024; // 5MB private static final List SUPPORTED_FORMATS = Arrays.asList( ".wav", ".mp3", ".aac", ".flac", ".m4a", ".ogg" ); private final AudioProcessUtil audioProcessUtil; private final AlibabaTTSUtil alibabaTTSUtil; /** * 处理上传的音频文件 */ public List processAudio(MultipartFile file) { // 1. 参数校验 validateAudioFile(file); File tempFile = null; try { // 2. 创建临时文件 tempFile = createTempAudioFile(file); // 3. 转码为标准PCM-WAV格式 byte[] pcmData = audioProcessUtil.convertToStandardWav(tempFile); log.info("音频处理成功,输出数据大小: {} bytes", pcmData.length); // 获取音频信息 // String audioInfo = audioProcessUtil.getAudioInfo(pcmData); // log.info("音频处理成功,音频信息: {}", audioInfo); // // // 保存测试文件(用于验证) // String savedPath = audioProcessUtil.saveWavToFile(pcmData, "test_output.wav"); // if (savedPath != null) { // log.info("测试文件已保存: {}", savedPath); // } // 将byte[]转换为16进制字符串列表 List hexList = audioProcessUtil.bytesToHexList(pcmData); log.info("音频处理完成,原始数据大小: {} bytes, 16进制数据长度: {}", pcmData.length, hexList.size()); return hexList; } catch (Exception e) { log.error("音频处理失败", e); throw new RuntimeException("音频处理失败", e); } finally { // 4. 清理临时文件 deleteTempFile(tempFile); } } /** * 生成标准PCM数据(单声道,16K采样率,16bit深度,包含44字节WAV头) * 数据总大小不超过2MB,如果超过将抛出异常 * @param text 要转换的文本内容 * @return 标准PCM数据字节数组(WAV格式) * @throws IOException 处理失败时抛出 * @throws IllegalArgumentException 如果生成的数据超过2MB */ public List generateStandardPcmData(String text) throws IOException { // 参数校验 if (text == null || text.trim().isEmpty()) { throw new IllegalArgumentException("文本内容不能为空"); } if (text.length() > 100) { throw new IllegalArgumentException("文本长度超过限制(最大100字符)"); } log.info("输入文本长度: {}", text.length()); try { byte[] rawPcmData = alibabaTTSUtil.generateStandardPcmData(text); // 使用AudioProcessUtil转换成带头44字节 PCM byte[] pcmData = audioProcessUtil.rawPcmToStandardWav(rawPcmData); // String savedPath = audioProcessUtil.saveWavToFile(pcmData, "test_output.wav"); // if (savedPath != null) { // log.info("测试文件已保存: {}", savedPath); // } // 将byte[]转换为16进制字符串列表 List hexList = audioProcessUtil.bytesToHexList(pcmData); log.info("generateStandardPcmData音频处理完成,原始数据大小: {} bytes, 16进制数据长度: {}", pcmData.length, hexList.size()); return hexList; } finally { // 4. 清理临时文件 } } /** * 验证音频文件 */ private void validateAudioFile(MultipartFile file) { if (file == null || file.isEmpty()) { throw new IllegalArgumentException("上传文件不能为空"); } if (!isAudioFile(file.getOriginalFilename())) { throw new IllegalArgumentException("只允许上传音频文件"); } if (file.getSize() > MAX_AUDIO_SIZE) { throw new IllegalArgumentException("音频大小不能超过5MB"); } } /** * 判断是否是支持的音频格式 */ private boolean isAudioFile(String filename) { if (filename == null || filename.lastIndexOf('.') == -1) { return false; } String ext = filename.substring(filename.lastIndexOf('.')).toLowerCase(); return SUPPORTED_FORMATS.contains(ext); } /** * 创建临时音频文件 */ private File createTempAudioFile(MultipartFile file) throws IOException { String originalFilename = file.getOriginalFilename(); String extension = ""; if (originalFilename != null && originalFilename.contains(".")) { extension = originalFilename.substring(originalFilename.lastIndexOf(".")); } File tempFile = File.createTempFile("audio-", extension); file.transferTo(tempFile); log.debug("创建临时音频文件: {}", tempFile.getAbsolutePath()); return tempFile; } /** * 删除临时文件 */ private void deleteTempFile(File file) { if (file != null && file.exists()) { if (file.delete()) { log.debug("删除临时文件成功: {}", file.getAbsolutePath()); } else { log.warn("无法删除临时文件: {}", file.getAbsolutePath()); } } } }