目录:
- 一、背景
- 二、动手前
- 三、过程
-
- html代码
-
- js代码
-
- php代码
- 四、总结
一、背景:
商城的项目需要增加一个功能。输入文字的下单增加一个语音识别来下单,这样用户就能更加能缩短购物的时间了,而且也有个文字识别也更方便。
二、动手前:
老板说要加这个需求后,我就先去看了"微信JS-SDK说明文档",发现他们已经写有了接口,我截个大概图↓
三、过程:
之后我就百度搜了下,关于微信语音录音功能的相关文章↓ 我是根据这位博主来做参考写的:
然后下面是我自己的代码:
1、html:(多余的样式什么的我就不放了)
<div>我需要:</div>
<textarea name="goods_name" value="" placeholder="请输入商品内容(识别结果不要紧,跑哥能听到您的语音)" rows="3" id="goods_name"></textarea>
<span id="wxupload_route" hidden></span>
<div class="search-micro">
<button class="talk" id="talk" data-type="product">按住说话</button>
<input type="button" value="听听我说了什么" id="playId" "play_stop_record();">
</div>
<audio autoplay="autoplay" id="audio" controls="controls" preload hidden></audio>
2、js:(注意提交的ajax路径,要写成自己想要跳转的路径,我这里有两个url提交)
110行:%26(原本是并且这个符号: & ,这么写是因为没改之前提交的路径,后端php数据一直获取不到,之后var_dump输出才发现提交的路径不完全,被过滤掉了。我参考了这篇文章https://www.jb51.net/article/82340.htm)
<script>
window.onload = function() {
var friend = document.getElementById("talk");
var friendp = document.getElementById("playId");
// 触摸
friend.ontouchstart = function() {
// 背景变绿
this.style.backgroundColor = "#9E9E9E";
};
friendp.ontouchstart = function() {
// 背景变绿
this.style.backgroundColor = "#9E9E9E";
};
// 停止触摸
friend.ontouchend = function() {
// 还原白色
this.style.backgroundColor = "red";
};
friendp.ontouchend = function() {
// 还原白色
this.style.backgroundColor = "red";
};
};
post_url = location.href.split('#')[0];
$.ajax({
url: "这里写你自己要提交到后端的路径", type: 'POST', data:{ post_url : post_url } , dataType: 'json',
success: function (data) {
var resArr = data;
console.log(data);
wx.config({
debug: false,
appId: resArr.appId,
timestamp: resArr.timestamp,
nonceStr: resArr.nonceStr,
signature: resArr.signature,
jsApiList: ['startRecord', 'stopRecord', 'onVoiceRecordEnd', 'translateVoice','uploadVoice','downloadVoice'] // 必填,需要使用的JS接口列表
});
wx.ready(function () {
var localId;
//开始录音
$('#talk').on('touchstart', function (e) {
e.preventDefault();
var $this = $(this);
$this.addClass('red');
//开始录音
wx.startRecord();
});
//停止录音接口
$('#talk').on('touchend', function () {
var $this = $(this);
$this.removeClass('red');
//停止录音接口
wx.stopRecord({
success: function (res) {
//alert(res.localId);
localId = res.localId;
wx.translateVoice({ //语音识别
localId: localId, // 需要识别的音频的本地Id,由录音相关接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
//alert(res.translateResult);
result = res.translateResult;
//去掉最后一个句号
result = result.substring(0, result.length - 1);
$('#goods_name').val(result);
}
});
radio_file_upload(resArr.token,localId);
}
});
});
//监听录音自动停止接口
wx.onVoiceRecordEnd({
//录音时间超过一分钟没有停止的时候会执行 complete 回调
complete: function (res) {
localId = res.localId;
//alert(localId+"----");
$('#talk').removeClass('red');
wx.translateVoice({
localId: localId, // 需要识别的音频的本地Id,由录音相关接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
//alert(res.translateResult+1111111111);
result = res.translateResult;
//去掉最后一个句号
result = result.substring(0, result.length - 1);
}
});
}
});
});
},
error: function (err) {
console.log(err);
}
});
function radio_file_upload(a,b){
//上传语音接口
wx.uploadVoice({
localId: b, // 需要上传的音频的本地ID,由stopRecord接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
//alert(res.serverId); // 返回音频的服务器端ID
var give_url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token="+a+"%26media_id="+res.serverId;
$.post("这里写你自己要提交到后端的路径","give_url="+give_url,function(res){
//alert("上传成功"+res);
$('#audio').attr("src" , res);
$('#wxupload_route').text(res);
},"json");
}
});
}
function again_record(){
var audio = document.getElementById('audio');
audio.currentTime = 0;
}
function play_stop_record(){
var audio = document.getElementById('audio');
if(audio!==null){
//检测播放是否已暂停.audio.paused 在播放器播放时返回false.
//alert(audio.paused);
if(audio.paused){
audio.play();//audio.play();// 这个就是播放
}else{
audio.pause();// 这个就是暂停
}
}
}
</script>
3、php:(因为我们公众号的商城是用微擎弄的,所以下面主要是从第二行开始)
主要是看15行、17行、18行-->
15行:就是告诉我们如何通过得到的路径来下载对应的文件。
17行:
1、因为下载的微信音频文件是amr结尾的,在公众号网页不能直接播放,然后根据上面参考的文章来试一下(将amr文件在进行base64转码播放),发现播放出来的音频是有断层的,或者播放失败;
2、所以就改成从后端通过系统命令exec来进行转码成mp3格式(需要在系统上安装FFmpeg,我参考了这位博主 https://blog.csdn.net/p_function/article/details/80324406 )exec是php禁用的命令!!
18行:下面注释有解释。
if ($op == 'wxupload_ajax') {
mload()->classs('JSSDK');//引入JSSDK.class(这里我写了调用微信接口的公共方法,我会在文章的最后放出来,有三个文件)
$post_url = $_GPC['post_url'];
$jssdkObj = new JSSDK('自己的公众号appid', '自己的公众号appsecret', $post_url);
$res = $jssdkObj->getSignPackage();
$res['token'] = $jssdkObj->getAccessToken();
$give_url = trim($_GPC["give_url"]);
if (!empty($give_url)) {
$str = "wxupload" . time() . rand(1111, 9999);//微信录音文件名 扩展名为 .amr
$targetName = '你想要保存的路径' . $str . ".amr"; //保存目录
$targetName2 = '你想要保存的路径' . $str . '.mp3';
downAndSaveFile($give_url, $targetName); //保存
//$command = "ffmpeg -i $targetName $targetName2 2>&1";
$command = sprintf("ffmpeg -i %s %s 2>&1", escapeshellarg($targetName), escapeshellarg($targetName2));
exec($command);//escapeshellarg()给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的
echo json_encode($targetName2);
} else {
echo json_encode($res);
}
}
//根据URL地址,下载文件
function downAndSaveFile($url, $savePath)
{
ob_start();
readfile($url);
$radio = ob_get_contents();
ob_end_clean();
$size = strlen($radio);
$fp = fopen($savePath, 'a');
$res = fwrite($fp, $radio);
fclose($fp);
}
录音下载成功后,直接把转换成的mp3路径($targetName2)返回给ajax接收,这样在html那里就可以直接用audio标签播放了。
这是页面截图↓:
下面是微信JSSDK文件:
链接:https://pan.baidu.com/s/1TXRl_ARojsACn1j7evne4g
提取码:xzxn
四、总结:
参考的几篇文章后自己写出来,感觉很受益,所以就赶紧写完这篇文章来回忆一下。这次的需求,明白了我几个先前不懂的知识点:
1、微信音频接口的如何调用,哪一个接口需要在哪一个接口后才能使用;
2、js 的ajax提交url会有特殊符号的转义;
3、JSSDK.class里面顶部的还需要引入框架的路径;
4、微信音频可以通过一个链接中的一个access_token和media_id就能下载文件了;
5、php中如何调用系统命令,而且如果是php禁用的命令还需要把它解除,还需要有更安全的写法escapeshellarg()的使用;
6、还把php的sprintf()和系统命令结合写了一起。
多谢参考文章的几位博主。