前几天,公司让做一个微信用户上次语音,然后保存语音到本地服务器上做记录,前端按照微信的api就行,但是有一点大家注意:
//上传录音文件 获取微信录音标识
function uploadVoice(localIds){
//调用微信的上传录音接口把本地录音先上传到微信的服务器
//不过,微信只保留3天,而我们需要长期保存,我们需要把资源从微信服务器下载到自己的服务器
wx.uploadVoice({
localId: localIds, // 需要上传的音频的本地ID,由stopRecord接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
audio_serverId = res.serverId; // 录音文件的微信端唯一标识
}
});
}
微信返回的res,然后获取serviceId标识,传到后台,后台才可以下载微信服务器上的语音,千万不要完全复制网上的代码,将res.serverId转一下json,虽然看着是一样的,但是在微信服务器下载语音的时候,会一直是1k的文件,所以一定要直接返回res.serverId。
下面是下载微信服务器上的语音代码。
首先是ssl证书问题,下载可能会报sun的问题,所以工具类MyX509TrustManager解决这个问题。
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* @author
* @date 创建时间:2018年10月19日 上午10:05:39
* @version 1.0
* @Description: TODO
* @since 1.8
* @return
*/
public class MyX509TrustManager implements X509TrustManager{
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
然后是下载音频的工具:DloadVideoUtil
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.springframework.beans.factory.annotation.Value;
/**
* @author
* @date 创建时间:2018年10月18日 下午1:57:06
* @version 1.0
* @Description:
* @since 1.8
* @return
*/
public class DloadVideoUtil {
@Value("${TOKEN_KEY}")
private String TOKEN_KEY;
/* private final static String FFMPEG_PATH ;
//windows系统使用, FFmpeg文件和DloadImgUtil 同一目录下
static {
FFMPEG_PATH = DloadVideoUtil.class.getResource("ffmpeg.exe").getFile();
} */
// linux 系统使用
/*static {
FFMPEG_PATH =DloadVideoUtil.class.getResource("ffmpeg").getFile();
} */
public static String downloadMedia(String mediaId, String amrfile,String mp3File,String token,String FFMPEG_PATH) {
String filePath = null;
String requestUrl = "https://api.weixin.qq.com/cgi-bin/media/get?access_token="+token+"&media_id="+mediaId;
String returnstr="0";
BufferedInputStream bis = null;
FileOutputStream fos = null;
HttpsURLConnection conn = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod("GET");
filePath = amrfile;
File amrPath = new File(filePath);
if(amrPath.exists()){
}
bis = new BufferedInputStream(conn.getInputStream());
fos = new FileOutputStream(amrPath);
new File(mp3File);
byte[] buf = new byte[8096];
int size = 0;
while ((size = bis.read(buf)) != -1)
fos.write(buf, 0, size);
amr2mp31(filePath, mp3File,FFMPEG_PATH);
//删除amr文件
if(amrPath.isFile() && amrPath.exists()){
amrPath.delete();
}
} catch (Exception e) {
returnstr="-1";
e.printStackTrace();
} finally {
conn.disconnect();// 释放资源
try {
// 关闭流,释放资源
if (fos != null) { fos.close(); }
if (bis != null) { bis.close(); }
}catch (Exception e) {
e.getStackTrace();
}
}
return returnstr;
}
public static void amr2mp31(String amrFileName, String mp3FileName,String FFMPEG_PATH) throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(FFMPEG_PATH + " -i "+amrFileName+" -ar 8000 -ac 1 -y -ab 12.4k " + mp3FileName); //12.4
InputStream in = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
try {
String line = null;
while((line = br.readLine())!=null){
int exitValue = process.waitFor();
}
} finally {
in.close();
}
}
/**
* 判断多级路径是否存在,不存在就创建
*
* @param filePath 支持带文件名的Path:如:D:\news\2014\12\abc.text,和不带文件名的Path:如:D:\news\2014\12
*/
public static void isExistDir(String filePath) {
String paths[] = {""};
//切割路径
try {
String tempPath = new File(filePath).getCanonicalPath();//File对象转换为标准路径并进行切割,有两种windows和linux
paths = tempPath.split("\\\\");//windows
if(paths.length==1){paths = tempPath.split("/");}//linux
} catch (IOException e) {
System.out.println("切割路径错误");
e.printStackTrace();
}
//判断是否有后缀
boolean hasType = false;
if(paths.length>0){
String tempPath = paths[paths.length-1];
if(tempPath.length()>0){
if(tempPath.indexOf(".")>0){
hasType=true;
}
}
}
//创建文件夹
String dir = paths[0];
for (int i = 0; i < paths.length - (hasType?2:1); i++) {// 注意此处循环的长度,有后缀的就是文件路径,没有则文件夹路径
try {
dir = dir + "/" + paths[i + 1];//采用linux下的标准写法进行拼接,由于windows可以识别这样的路径,所以这里采用警容的写法
File dirFile = new File(dir);
if (!dirFile.exists()) {
dirFile.mkdir();
System.out.println("成功创建目录:" + dirFile.getCanonicalFile());
}
} catch (Exception e) {
System.err.println("文件夹创建发生异常");
e.printStackTrace();
}
}
}
}
因为微信下载的是.amr后缀的文件,所以需要转成MP3,用到了ffmpeg,大家可以自行去百度这个文件。就是在程序中调用ffmpeg,然后进行转码保存。大家注意,windows和linux是用到不一样的版本,所以要做好判断系统。
我用到的ffmpeg整理了一下,里面有windows和linux版本的https://download.csdn.net/download/zhaochao0037/10923578;