转自:http://www.cnblogs.com/liujunyang/p/4962423.html#undefined
0.需求描述
在微信浏览器内打开的页面,制作一个按钮,用户按住按钮后开始录音,松手后停止录音并将录音上传并长期保存。
1.开发流程
如果开发的是普通的展示性页面,就和开发普通的页面没有区别,不过这里要用到设备(手机)的录音功能,就需要调用微信app的录音接口,需要使用微信jssdk。
使用微信jssdk:微信JS-SDK说明文档
- 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。[需要有微信公众号]
- 引入JS文件
- 通过config接口注入权限验证配置
- 通过ready接口处理成功验证
- 通过error接口处理失败验证
//假设已引入微信jssdk。【支持使用 AMD/CMD 标准模块加载方法加载】 wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 }); wx.error(function(res){ // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 });
本次需求核心功能:录音并保存
//假设全局变量已经在外部定义 //按下开始录音 $('#talk_btn').on('touchstart', function(event){ event.preventDefault(); START = new Date().getTime(); recordTimer = setTimeout(function(){ wx.startRecord({ success: function(){ localStorage.rainAllowRecord = 'true'; }, cancel: function () { alert('用户拒绝授权录音'); } }); },300); }); //松手结束录音 $('#talk_btn').on('touchend', function(event){ event.preventDefault(); END = new Date().getTime(); if((END - START) < 300){ END = 0; START = 0; //小于300ms,不录音 clearTimeout(recordTimer); }else{ wx.stopRecord({ success: function (res) { voice.localId = res.localId; uploadVoice(); }, fail: function (res) { alert(JSON.stringify(res)); } }); } });
//上传录音
function uploadVoice(){
//调用微信的上传录音接口把本地录音先上传到微信的服务器
//不过,微信只保留3天,而我们需要长期保存,我们需要把资源从微信服务器下载到自己的服务器
wx.uploadVoice({
localId: voice.localId, // 需要上传的音频的本地ID,由stopRecord接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
//把录音在微信服务器上的id(res.serverId)发送到自己的服务器供下载。
$.ajax({
url: '后端处理上传录音的接口',
type: 'post',
data: JSON.stringify(res),
dataType: "json",
success: function (data) {
alert('文件已经保存到七牛的服务器');//这回,我使用七牛存储
},
error: function (xhr, errorType, error) {
console.log(error);
}
});
}
});
}
//注册微信播放录音结束事件【一定要放在wx.ready函数内】
wx.onVoicePlayEnd({
success: function (res) {
stopWave();
}
});
2.小麻烦
要防止用户误操作(如:反复点击、误触摸)导致的无效录音。
小于300ms不录音
防止用户长按导致的浏览器默认弹出微信浏览器默认的“复制对话框”。
使用css设置按钮 user-select:none;
微信播放录音接口事件回调函数无效
微信注册事件一定要放在wx.ready中。
阻止默认事件
touch 事件记得加 event.preventDefault(); 防火防爆
微信存储静态资源时间为3天,如何长期保存
要么存到自己服务器,要么利用其它资源,比如七牛,还可以帮我们自由转换amr格式到mp3等格式呢!
微信服务器默认资源格式为amr,这个格式在android机器可以使用audio标签播放,在ios机器使用audio标签无法播放。
微信录音功能授权引发的交互问题
使用微信jssdk接口录音,在同一个域只需要授权一次,即第一次使用录音的时候,微信自己会弹出对话框询问是否允许录音,用户点击允许后,之后再使用录音时,便不会再咨询用户是否允许。
在第一次按住录音后,由于用户未曾允许录音,微信会提示用户授权允许在本页面使用微信录音功能,这时用户会放开录音按钮转而去点击允许,在用户允许后,才真正会开始录音,而此时用户早已放开录音按钮,那么录音按钮上便不会再有touchend事件,录音便会一直进行。
解决策略:使用localStorage记录用户是否曾授权,并以此来判断是否需要在刚进入页面是自动录一段录音来触发用户授权
if(!localStorage.rainAllowRecord || localStorage.rainAllowRecord !== 'true'){ wx.startRecord({ success: function(){ localStorage.rainAllowRecord = 'true'; wx.stopRecord(); }, cancel: function () { alert('用户拒绝授权录音'); } }); }
3.难题
音量bug:在ios设备上,使用微信录音功能后,再播放audio标签的音频,音量极低。
但是使用微信接口(wx.playVoice)播放录音的音量是正常的,而且之后,audio标签的音量会有所增大(但是依然音量很低)。
该问题正在沟通微信相关技术人员。
暂时的解决策略为:对于刚刚录音的音频,使用wx.playVoice来播放,否则使用audio播放服务器资源。原因是不确定该音频本地是否存在,刚刚录音的音频肯定是存在的。