一、概述和通过config接口注入权限验证配置
由于微信的
临时素材
(如:录音文件)上传到微信服务器上,微信后台保存时间为3天
。而我们需要长期保存,我们需要把资源从微信服务器转存到自己服务器,或者阿里云OSS/七牛云。
通过config接口注入权限验证配置:
/** * 微信JS-SDK权限验证配置 * * @return array */public function getSignPackage() { (new SignPackage())->goCheck(); $url = input('get.url'); $jsapiTicket = $this->getJsApiTicket(); $nonceStr = getRandChar(16); $timestamp = time(); $signature = $this->getSignature($jsapiTicket,$nonceStr,$timestamp,$url); $signPackage = array( "appId" => config('wx.g_app_id'), "nonceStr" => $nonceStr, "timestamp" => $timestamp, "signature" => $signature, 'expire_id' => config('setting.access_token_expire_in'), 'url' => $url ); return $signPackage;}/** * 获取签名 * * @param $jsapiTicket * @param $nonceStr * @param $timestamp * @param $url * @return string */private function getSignature($jsapiTicket,$nonceStr,$timestamp,$url){ // 这里参数的顺序要按照 key 值 ASCII 码升序排序 $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; $signature = sha1($string); return $signature;}/** * 获取临时票据 * { * "errcode": 0, * "errmsg": "ok", * "ticket": "kgt8ON7yVITDhtdwci0qeS9ULEKIkoU74AB_VMOQrWUhbW12MQht4FiX4qLA9Z5puKabs96SARo5f1bylEvwXw", * "expires_in": 7200 * } * @return mixed * @throws Exception * @throws ParameterException */private function getJsApiTicket() { $access_token = $this->getAccessToken(); $wxJSapiTicketUrl = sprintf(config('wx.jsapi_ticket'), $access_token); $result = curl_get($wxJSapiTicketUrl); $wxResult = json_decode($result, true); if (empty($wxResult)) { throw new Exception('微信内部错误'); }else if ($wxResult['errmsg'] != 'ok'){ throw new ParameterException([ 'errorCode' => $wxResult['errcode'], 'msg' => $wxResult['errmsg'] ]); }; return $wxResult['ticket'];}
二、获取media_id
三、根据media_id下载录音文件
/** * 获取访问微信接口的access_token * * @return mixed */public function getAccessToken(){ $redis = Cache::store('redis'); $wx_access_token = $redis->get('wx_access_token'); if (!$wx_access_token){ $access_token = $this->getWXAccessToken(); }else{ $access_token = $wx_access_token; } return $access_token;}
/** * 根据URL地址,下载文件 * * @param $url * @param $savePath */ public function downAndSaveFile($url,$savePath) { ob_start(); readfile($url); $img = ob_get_contents(); ob_end_clean(); $size = strlen($img); $fp = fopen($savePath, 'a'); fwrite($fp, $img); fclose($fp); }
四、FFmpeg将amr格式音频文件转换未mp3格式
/** * 将amr格式转换成mp3格式 * * @param $amr * @param $prefix_filename * @return mixed */public function amrTransCodingMp3($amr, $prefix_filename){ $msgId = $prefix_filename; $mp3 = $msgId.'.mp3'; $dir = $_SERVER['DOCUMENT_ROOT'].'/static/audio/'; exec("ffmpeg -y -i ".$dir.$amr." ".$dir.$mp3); return $mp3;}
五、将转码后MP3文件上传至OSS
/** * 上传指定的本地文件内容 * * @param OssClient $ossClient OSSClient实例 * @param string $bucket 存储空间名称 * @param string $object 名字 * @return mixed */function uploadFile($ossClient, $bucket, $object){ $filePath = $_SERVER['DOCUMENT_ROOT'].'/static/audio/'.$object; try{ $res = $ossClient->uploadFile($bucket, $object, $filePath); return $res; } catch(OssException $e) { return [ 'error' => 'FAILED', 'msg' => $e->getMessage() ]; }}
注:
坑一
:貌似服务端只有JAVA
的,其实通过PHP-SDK
也是可以通过上传文件来上传音频文件。 坑二
:
六、删除本地文件
由于我把微信音频文件存到阿里云OSS,所以将从微信服务器下载的amr和转码的mp3两个音频文件删除。
/** * 删除本地音频文件 * * @param $filename * @return bool * @throws ParameterException */public function deleteDownloadFile($filename){ $filename = $_SERVER['DOCUMENT_ROOT'].'/static/audio/'.$filename; if (!unlink($filename)) { throw new ParameterException([ 'msg' => "Error deleting $filename" ]); } else { return true; }}
七、测试样例
微信录音时长最多为60s
,经测试H5
端录音60s
语音后,后台下载,转码后如下图:
然后将mp3
文件上传OSS
后返回给客户端如下:
{ "server": "AliyunOSS", "date": "Mon, 09 Oct 2017 05:52:28 GMT", "content-length": "0", "connection": "keep-alive", "x-oss-request-id": "59DB0E9BE8DFE89CE466195A", "etag": "\"A6D50FD012FE2C6AA03EBF38CE23BEEB\"", "x-oss-hash-crc64ecma": "8903374940512099110", "content-md5": "ptUP0BL+LGqgPr84ziO+6w==", "x-oss-server-time": "243", "info": { "url": "http://xds-test.oss-cn-beijing.aliyuncs.com/wx_download_2017100913522559db0e99d3420.mp3", "content_type": null, "http_code": 200, "header_size": 335, "request_size": 472, "filetime": -1, "ssl_verify_result": 0, "redirect_count": 0, "total_time": 0.250512, "namelookup_time": 0.001418, "connect_time": 0.004533, "pretransfer_time": 0.004535, "size_upload": 60309, "size_download": 0, "speed_download": 0, "speed_upload": 240742, "download_content_length": 0, "upload_content_length": 60309, "starttransfer_time": 0.007707, "redirect_time": 0, "redirect_url": "", "primary_ip": "59.110.185.134", "certinfo": [], "method": "PUT" }, "oss-request-url": "http://xds-test.oss-cn-beijing.aliyuncs.com/wx_download_2017100913522559db0e99d3420.mp3", "oss-redirects": 0, "oss-stringtosign": "PUT\n\naudio/mpeg\nMon, 09 Oct 2017 05:52:27 GMT\n/xds-test/wx_download_2017100913522559db0e99d3420.mp3", "oss-requestheaders": { "Accept-Encoding": "", "Content-Type": "audio/mpeg", "Date": "Mon, 09 Oct 2017 05:52:27 GMT", "Host": "xds-test.oss-cn-beijing.aliyuncs.com", "Authorization": "OSS LTAIiKza8Qoz9q4A:PB8WBZp75iaN/pvpbIewFs3Rn08=" }, "body": false, "process_time": "2.2304130s"}
从返回process_time
来看,从客户端请求到最后返回给客户端,60s
音频后台大概需要处理2.3
秒左右(根据服务器配置而不同)。
完
参考资料如下: