1、需求简介
现在的需求是微信公众号内说一段话调用微信的上传接口上传至微信服务器,然后下载到我们本地,此时文件是amr格式,浏览器和很多播放器识别不了,需要转码成mp3格式,存储在我们的文件服务器上,现在在这里记录中间踩过的坑。
2、几个有用的调试技巧
微信上传语音文件的参考网址是:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#30
微信网页调试工具如下:https://mp.weixin.qq.com/debug/
amr文件下载地址:链接: https://pan.baidu.com/s/1bUohbqsF-1KV91g4Ra9Jsg 提取码: utpm
下载文件要调用的微信服务器地址:http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s
其它的生成accesstoken这些不是本文的重点,不再展开。
3、使用java代码将amr格式的文本转成mp3
3.1、使用jave的jar包转储
引入jar包:
<dependency>
<groupId>com.github.dadiyang</groupId>
<artifactId>jave</artifactId>
<version>1.0.4</version>
</dependency>
转码:
File source = new File(tempFilePath);
File target = new File(targetPath);
AudioUtils.amrToMp3(source, target);
参考文档:
https://blog.csdn.net/qllinhongyu/article/details/29817297
http://www.sauronsoftware.it/projects/jave/manual.php
3.2、使用jave-core转码
引入jar包:
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-core</artifactId>
<version>2.4.4</version>
</dependency>
转码:
public static void changeTemp() throws InputFormatException {
File source = new File("/Users/daji/Downloads/1.amr"); //源文件
File target = new File("/Users/daji/Downloads/1.mp3"); //目标文件
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("mp3");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder();
try {
MultimediaObject multimediaObject = new MultimediaObject(source);
encoder.encode(multimediaObject,target, attrs);
} catch (IllegalArgumentException | EncoderException e) {
e.printStackTrace();
}
}
参考文档:
https://www.jianshu.com/p/a9611651e95e
4、我的处理代码:
我是先把文件从微信服务器下载到本地服务器amr格式的,然后使用上面的工具转码成mp3格式的,之后将mp3文件上传到阿里oss上存储,并把本地的amr文件和mp3文件删除(防止占用磁盘)
4.1下载微信文件到本地:
public InputStream downloadFileFromWechat(String serviceId) {
log.info("desc:{},serviceId:{}", "准备连接微信服务器下载文件", serviceId);
try {
String accessToken = accessTokenUtil.getToken();
String urlStr = String.format(WXApiConstant.DOWNLOAD_MEDIA_URL, accessToken, serviceId);
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Charset", StandardCharsets.UTF_8.toString());
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
return inputStream;
} catch (Exception e) {
log.info("desc:{},errMsg:{}", "下载微信文件至本地服务器失败", ExceptionUtils.getStackTrace(e));
throw new BusinessException("下载微信文件至本地服务器失败:" + e.getMessage());
}
}
4.2生成文件名:
public String getFilePath(String fileNamePrefix) {
String baseFolder = "\\home\\comment"+ File.separator + "voice";
Date nowDate = new Date();
String fileFolder = baseFolder + File.separator + new DateTime(nowDate).toString("yyyy") + File.separator
+ new DateTime(nowDate).toString("MM") + File.separator + new DateTime(nowDate).toString("dd");
File file = new File(fileFolder);
if (!file.isDirectory()) {
// 如果目录不存在,则创建目录
file.mkdirs();
}
// 生成新的文件名--微信下载的文件格式为amr
String fileName = fileNamePrefix + "." + "amr";
return fileFolder + File.separator + fileName;
}
4.3将文件存储到硬盘:
public void saveToDisk(String mediaId,String filePath) {
InputStream inputStream = this.downloadFileFromWechat(mediaId);
try(FileOutputStream fileOutputStream = new FileOutputStream(filePath)) {
byte[] data = new byte[8192];
int len;
while ((len = inputStream.read(data)) != -1) {
fileOutputStream.write(data, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.4转码文件并上传到oss上,删除本地临时文件:
public String saveVoiceUrl(String serviceId) throws Exception {
String fileNamePrefix = String.valueOf(System.currentTimeMillis() + RandomUtils.nextInt(100, 9999));
String tempFilePath = getFilePath(fileNamePrefix);
String targetPath = tempFilePath.substring(0,tempFilePath.lastIndexOf('.'))+"."+"mp3";
//临时保存在硬盘,amr格式,转成mp3格式,存储到oss上
saveToDisk(serviceId,tempFilePath);
File source = new File(tempFilePath);
File target = new File(targetPath);
AudioUtils.amrToMp3(source, target);
//上传至oss,返回url
ossProxy.saveObject(WECHAT_COMMENT_PATH + fileNamePrefix+"."+"mp3", FileCopyUtils.copyToByteArray(target), 1);
String ossUrl = ossProxy.getUrl(WECHAT_COMMENT_PATH + fileNamePrefix+"."+"mp3", 1);
//删除文件
if (source.exists()) {
boolean deleted = source.delete();
if (!deleted) {
log.error("desc:{}, filePath:{}", "语音下载上传至OSS完成,删除本地文件失败", source.getPath());
}
}
if (target.exists()) {
boolean deleted = target.delete();
if (!deleted) {
log.error("desc:{}, filePath:{}", "语音下载上传至OSS完成,删除本地文件失败", source.getPath());
}
}
return ossUrl;
}
补充:如果你存储在oss的文件地址在浏览器打不开,可以检查本地文件和oss文件的md5是否一样,我当时就是粗心文件copy错了,在线比对地址:http://www.atool9.com/file_hash.php