总体逻辑就是,我们从微信的服务器端,把录制好的音频,放到本地,但放到本地的音频是amr格式的无法播放,所以我们要将录好的音频,上传到七牛转码成mp3格式,然后本地调用七牛的链接地址就可以了。
微信播放录制上传,仅支持https协议
首先,需要安装EasyWechat,七牛的php-sdk
安装EasyWechat,具体配置方法参照官方文档:https://www.easywechat.com/docs/5.x/installation
composer require overtrue/wechat:~5.0 -vvv
安装七牛php-sdk,配置方法参照官方文档:https://developer.qiniu.com/kodo/1241/php
php require qiniu/php-sdk
接下来
使用EasyWechat获取到微信的配置,遇到微信配置没过会显示什么signature invalid,可能是因为你没有在公众号配置域名白名单,也可能是因为你没有在公众号里把域名加入到JS安全名单里:
app/Http/Controllers/UserController.php
use EasyWechat;
...
public function voice_test(){
$app = EasyWeChat::officialAccount();
return view("voice.test")
->withApp($app);
}
resource/voice/test.blade.php
直接复制就可以了
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=640, user-scalable=no">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<meta name="apple-mobile-web-app-title" content="">
<title>录音test</title>
<style type="text/css">
@charset "utf-8";
*{ margin:0px; padding:0px; box-sizing:border-box; -webkit-tap-highlight-color:rgba(0,0,0,0);}
html{ max-width:640px; margin:0 auto;}
body{ font-family:"PingFangSC-Regular","sans-serif","STHeitiSC-Light","微软雅黑","Microsoft YaHei"; font-size:24px; line-height:1.5em; color:#000;
-webkit-user-select:none; user-select:none;
-webkit-touch-callout:none; touch-callout:none;
}
.start_btn , .play_btn , .send_btn{ width:250px; height:60px; line-height:60px; margin:20px auto; text-align:center; border:#eee solid 2px; cursor:pointer;}
.start_btn_in , .stop_btn{ color:#f00; border:#f00 solid 2px;}
</style>
</head>
<body>
<div class="start_btn">按住不放即可录音</div>
<div class="play_btn">点我播放</div>
<div class="send_btn">点我保存</div>
<script type="text/javascript" src="/plugins/jQuery/jQuery-2.1.4.min.js"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
wx.config(<?php echo $app->jssdk->buildConfig(array('onMenuShareTimeline','onMenuShareAppMessage','startRecord','stopRecord','onVoiceRecordEnd','playVoice','stopVoice','onVoicePlayEnd','uploadVoice'), true) ?>);
// wx.config({
// debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
// appId: '', // 必填,公众号的唯一标识
// timestamp: '', // 必填,生成签名的时间戳
// nonceStr: '', // 必填,生成签名的随机串
// signature: '',// 必填,签名,见附录1
// jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage','startRecord','stopRecord','onVoiceRecordEnd','playVoice','stopVoice','onVoicePlayEnd','uploadVoice'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
// });
wx.ready(function(){
//返回音频的本地ID
var localId;
//返回音频的服务器端ID
var serverId;
//录音计时,小于指定秒数(minTime = 10)则设置用户未录音
var startTime , endTime , minTime = 2;
//***********************************//
//开始录音
$('.start_btn').on('touchstart',function(e){
e.preventDefault();
var $this = $(this);
$this.addClass('start_btn_in');
startTime = new Date().getTime();
//开始录音
wx.startRecord();
});
//***********************************//
//停止录音接口
$('.start_btn').on('touchend', function(){
var $this = $(this);
$this.removeClass('start_btn_in');
//停止录音接口
wx.stopRecord({
success: function (res) {
localId = res.localId;
}
});
endTime = new Date().getTime();
alert((endTime - startTime) / 1000);
if((endTime - startTime) / 1000 < minTime){
localId = '';
alert('录音少于' + minTime + '秒,录音失败,请重新录音');
}
});
//监听录音自动停止接口
wx.onVoiceRecordEnd({
//录音时间超过一分钟没有停止的时候会执行 complete 回调
complete: function (res) {
localId = res.localId;
$('.start_btn').removeClass('start_btn_in');
}
});
//***********************************//
$('.play_btn').on('click',function(){
if(!localId){
alert('您还未录音,请录音后再点击播放');
return;
}
var $this = $(this);
if($this.hasClass('stop_btn')){
$(this).removeClass('stop_btn').text('点我播放');
// //暂停播放接口
// wx.pauseVoice({
// //需要暂停的音频的本地ID,由 stopRecord 或 onVoiceRecordEnd 接口获得
// localId: localId
// });
//停止播放接口
wx.stopVoice({
//需要停止的音频的本地ID,由 stopRecord 或 onVoiceRecordEnd 接口获得
localId: localId
});
}else{
$this.addClass('stop_btn').text('点我停止');
//播放语音接口
wx.playVoice({
//需要播放的音频的本地ID,由 stopRecord 或 onVoiceRecordEnd 接口获得
localId: localId
});
}
});
//监听语音播放完毕接口
wx.onVoicePlayEnd({
//需要下载的音频的服务器端ID,由uploadVoice接口获得
serverId: localId,
success: function (res) {
$('.play_btn').removeClass('stop_btn').text('点我播放');
//返回音频的本地ID
//localId = res.localId;
}
});
//***********************************//
//上传语音接口
$('.send_btn').on('click',function(){
if(!localId){
alert('您还未录音,请录音后再保存');
return;
}
// alert('上传语音,测试,并未提交保存');
// return;
//上传语音接口
wx.uploadVoice({
//需要上传的音频的本地ID,由 stopRecord 或 onVoiceRecordEnd 接口获得
localId: localId,
//默认为1,显示进度提示
isShowProgressTips: 1,
success: function (res) {
//返回音频的服务器端ID
serverId = res.serverId;
window.location.href = "/voice_save?serverId="+serverId;
}
});
});
});
</script>
</body>
</html>
注册路由:
routes/web.php
Route::get("/voice_test","[email protected]_test");
Route::get("/voice_save","[email protected]_save"); //这个方法我们最后会写
需要引入公共方法,Laravel公共方法怎么使用不再赘述,不想用公共方法的,可以把这些写到控制器里,方法前面加个public就行:
app/Functions/qiniu.php
<?php
require_once __DIR__.'/../../vendor/qiniu/php-sdk/autoload.php';
//qiniu上传的sdk文件夹放在vendor文件夹下
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use Qiniu\Storage\BucketManager;
// AK和SK,和上传空间要在该页面设置,AK和SK和bucket名字要上七牛才能看见
global $accessKey;
global $secretKey;
global $bucket;
$accessKey='去七牛找到你的AK';
$secretKey='去七牛找到你的SK';
$bucket='你的空间的名字';
function voiceUploads($media_id,$file_path){
global $accessKey;
global $secretKey;
global $bucket;
$auth = new Auth($accessKey,$secretKey);
$bucket = trim($bucket);
$savekey = \Qiniu\base64_urlSafeEncode($bucket.':speaker/'.$media_id.'.mp3'); //冒号后为七牛保存文件名,这个文件可以播放
//设置转码参数
$fops = "avthumb/mp3/ab/320k/ar/44100/acodec/libmp3lame";
$fops = $fops.'|saveas/'.$savekey;
$policy = array(
'persistentOps' => $fops
);
$up_token = $auth->uploadToken($bucket, null, 3600, $policy);
$key = 'speaker_del/'.$media_id.'.mp3'; //七牛云中保存的amr文件名,该文件无法播放,但最后ret返回的是这个文件名
$uploadMgr = new UploadManager();
list($ret, $err) = $uploadMgr->putFile($up_token, $key, $file_path);
if ($err !== null) {
return false;
}else {
//此时七牛云中同一段音频文件有amr和MP3两个格式的两个文件同时存在
$bucketMgr = new BucketManager($auth);
//为节省空间,删除本地amr格式文件
unlink($file_path);
return $ret;
// return $ret['key'];
}
}
?>
app/Functions/common.php
function httpGet($url){
$ch = curl_init($url);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_NOBODY,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$package = curl_exec($ch);
$http_info = curl_getinfo($ch);
curl_close($ch);
$res = array_merge(array_merge(array('header' => $http_info)),array('body' => $package));
return $res;
}
function saveWeixinFile($file_name,$file_content){
$local_file = fopen($file_name,'w');
if(false !== $local_file){
if(false !== fwrite($local_file,$file_content)){
fclose($local_file);
}else{
return false;
}
}else{
return false;
}
}
接下来,就可以继续写控制器了
app/Http/Controllers/UserController.php
public function voice_save(Request $request){
$serverId = $request->get("serverId");//微信语音的服务器ID
$app = EasyWeChat::officialAccount();
// 获取 access token 实例
$accessToken = $app->access_token; // EasyWeChat\Core\AccessToken 实例
$token = $accessToken->getToken(); // token 字符串
$access_token = $token["access_token"];
// dd($access_token);
$url = "https://file.api.weixin.qq.com/cgi-bin/media/get?access_token=$access_token&media_id=$serverId";
$res = httpGet($url); //common中的方法
//文件保存路径
$file_name = public_path('/uploads/audio/'.$serverId.'.mp3');
$save = saveWeixinFile($file_name,$res['body']); //common中的方法
if(false === $save){
exit('音频文件本地化失败');
}
$ret = voiceUploads($serverId,$file_name); //qiniu中的方法
dd($ret['key']);
}
最后打印出来的$ret['key'],就是我们上传到七牛的文件名,但是,这个文件是不能播放的!需要把speaker_del前缀,改成speaker才能播放(文件名更改在qiniu.php里,可根据需求更改),最后把$ret['key']得到的字符串,连接上你的域名就可以啦!
https://你的七牛域名/更换前缀后的$ret['key'] //最后生成的外链地址样式,可以直接播放
大功告成,如果各位有不懂的,可以联系QQ582874942,有偿。