springboot 实现base64格式wav转码并保存
问10系统需要安装 FFMPEG
win10环境安装
下载 FFmpeg:
访问官方构建:https://www.gyan.dev/ffmpeg/builds/
下载 "ffmpeg-git-full.7z"(最新完整版)
解压文件:
使用 7-Zip 解压到你想安装的目录,例如 C:\ffmpeg
设置环境变量:
右键"此电脑" → 属性 → 高级系统设置 → 环境变量
在"系统变量"中找到 Path → 编辑 → 新建
添加 FFmpeg 的 bin 目录路径,例如:C:\ffmpeg\bin
点击确定保存所有更改
复制命令行到指定路径,不然运行时报错
try {File javeDir = new File(System.getProperty("user.home") + "/AppData/Local/Temp/jave");javeDir.mkdirs();File target = new File(javeDir, "ffmpeg-amd64-3.3.1.exe");if (!target.exists()) {Files.copy(Paths.get("D:\\tool\\ffmpeg\\bin\\ffmpeg.exe"),target.toPath(),StandardCopyOption.REPLACE_EXISTING);}} catch (IOException e) {e.printStackTrace();}
转码服务
package com.race.APPControl.service;import com.race.APPControl.service.impl.LocalSysFileServiceImpl;
import com.race.system.api.domain.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.*;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.process.ProcessLocator;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.util.Base64;@Service
@Slf4j
public class WavToMp3Service {@Autowiredprivate LocalSysFileServiceImpl localSysFileService;// 自定义FFMPEG定位器private static final ProcessLocator CUSTOM_FFMPEG_LOCATOR = new DefaultFFMPEGLocator() {public String getExecutablePath() {return "D:\\tool\\ffmpeg\\bin\\ffmpeg.exe";}};public SysFile convertAndUpload(String base64Wav) {try {byte[] wavBytes = decodeBase64(base64Wav);byte[] mp3Bytes = convertWavToMp3(wavBytes);MultipartFile mp3File = createMultipartFile(mp3Bytes);String fileUrl = localSysFileService.uploadFile(mp3File);SysFile result = new SysFile();result.setName(fileUrl);return result;} catch (Exception e) {e.printStackTrace();throw new RuntimeException("WAV to MP3 conversion and upload failed", e);}}private byte[] decodeBase64(String base64) {String encodedData = base64.contains(",")? base64.split(",")[1]: base64;return Base64.getDecoder().decode(encodedData);}private byte[] convertWavToMp3(byte[] wavBytes) throws IOException {File tempWav = File.createTempFile("temp", ".wav");File tempMp3 = File.createTempFile("temp", ".mp3");try {Files.write(tempWav.toPath(), wavBytes);// 使用自定义的FFMPEG定位器创建编码器Encoder encoder = new Encoder(CUSTOM_FFMPEG_LOCATOR);AudioAttributes audio = new AudioAttributes();audio.setCodec("libmp3lame");audio.setBitRate(128000);audio.setChannels(2);audio.setSamplingRate(44100);EncodingAttributes attrs = new EncodingAttributes();attrs.setOutputFormat("mp3");attrs.setAudioAttributes(audio);encoder.encode(new MultimediaObject(tempWav), tempMp3, attrs);return Files.readAllBytes(tempMp3.toPath());} catch (EncoderException e) {throw new IOException("音频转换失败", e);} finally {tempWav.delete();tempMp3.delete();}}private MultipartFile createMultipartFile(byte[] fileContent) {return new MultipartFile() {@Overridepublic String getName() {return "audio.mp3";}@Overridepublic String getOriginalFilename() {return "audio.mp3";}@Overridepublic String getContentType() {return "audio/mpeg";}@Overridepublic boolean isEmpty() {return fileContent == null || fileContent.length == 0;}@Overridepublic long getSize() {return fileContent.length;}@Overridepublic byte[] getBytes() throws IOException {return fileContent;}@Overridepublic InputStream getInputStream() throws IOException {return new ByteArrayInputStream(fileContent);}@Overridepublic void transferTo(File dest) throws IOException, IllegalStateException {Files.write(dest.toPath(), fileContent);}// 修正这里 - 使用正确的Resource类型@Overridepublic org.springframework.core.io.Resource getResource() {return new ByteArrayResource(fileContent) {@Overridepublic String getFilename() {return getOriginalFilename();}@Overridepublic URL getURL() throws IOException {return null; // 明确返回null表示无URL}};}};}
}
文件上传service
package com.race.APPControl.service.impl;import com.race.APPControl.common.FileUploadUtils;
import com.race.APPControl.service.ISysFileService;
import com.race.system.api.domain.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;/*** 本地文件存储** @author race*/
@Slf4j
@Primary
@Servicepublic class LocalSysFileServiceImpl implements ISysFileService
{/*** 资源映射路径 前缀*/@Value("${file.prefix}")public String localFilePrefix;//private static final Logger log = LoggerFactory.getLogger(SysFileController.class);/*** 域名或本机访问地址*/@Value("${file.domain}")public String domain;/*** 上传文件存储在本地的根路径*/@Value("${file.path}")private String localFilePath;@Value("${file.pathSJY}")private String localFilePathSJY;@Value("${file.uploadFilePath}")private String uploadFilePath;/** 偏移纬度 */@Value("${file.uploadFileUrl}")private String uploadFileUrl;/*** 本地文件上传接口** @param file 上传的文件* @return 访问地址* @throws Exception*/@Overridepublic String uploadFile(MultipartFile file) throws Exception{String name = FileUploadUtils.upload(localFilePath, file);String url = domain + localFilePrefix + name;return url;}/*** 本地文件上传接口** @param file 上传的文件* @return 访问地址* @throws Exception*/@Overridepublic SysFile uploadSJY(MultipartFile file) throws Exception{SysFile filess= new SysFile();String name = FileUploadUtils.uploadSJY(localFilePathSJY, file);filess.setName(localFilePathSJY+name);
// String url = domain + localFilePrefix + name;return filess;}@Overridepublic SysFile uploadBase64(String base64) {log.info("uploadFilePath"+uploadFilePath);log.info("uploadFileUrl"+uploadFileUrl);
// log.info("图片图片"+base64);return FileUploadUtils.uploadBase64(base64,uploadFilePath,uploadFileUrl);}
}