原文是在我本身博客中,小夥伴也能夠點 閱讀原文進行跳轉查看,還有好聽的背景音樂噢~
一年的時間裏,前先後後都在搞微信開發的相關模塊,這不前一陣子,公司又開了個新項目,其中有一個就是相似於微信朋友圈的功能(我也不知道爲啥要開發微信已有的功能啊,淚奔...),其中包含上傳圖片、錄音、視頻等,因爲微信端上傳圖片和視頻這塊也是頭一遭作,圖片採用了微信的相關插件,視頻嘛用的是百度的webupload插件,感受也至關不錯,採用了分片上傳技術。今天這篇就主要介紹一下,錄音的相關功能。php
微信錄音這塊,其實面對這項功能的時候,不用我多說,都知道要先去看開發文檔,查閱相關資料等準備工做;我先貼個地址,省得看我這篇文檔的時候再去查找網頁:微信公衆號開發-微信JS-SDK說明文檔。進入到這個頁面找到第5小節,音頻接口這裏,就是本篇要說的東西了。html
微信錄音分爲以下幾個接口(這裏概括一下,文檔裏有,詳細內容本身去看吧):前端
看到以上,是否是以爲蠻多的,配合起來使用才提供了這麼一個完整(好像也並不怎麼完整,沒有提供方便的轉碼及下載本地機制)的錄音功能。好話說在前頭:你弄完了當你再去看這塊代碼的時候,發現還真他孃的亂啊。。。
因此,我寫這篇記錄的緣由就在這裏了,狗頭.pngweb
還有一個就是接口權限(一張圖片來表述,圖片來源微信文檔...):ajax
本章會以文字和代碼的形式進行梳理,過程應該會蠻多的,不過看完以後直接拿去使用,問題也應該不大,如是說道。數據庫
JS-SDK庫的使用步驟,這裏就不過多介紹了,文檔裏也有,也是簡單整理下幾個所需步驟吧:json
咱們直接從注入API列表提及,config接口有以下幾個屬性(不知道屬性是否合適,姑且叫爲屬性吧),segmentfault
/** * 微信jssdk調用接口初始化 */ wx.config({ debug: true, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。 appId: '', // 必填,公衆號的惟一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名 jsApiList: [ 'startRecord', // 錄音開始api 'stopRecord', // 錄音結束api 'uploadVoice', // 上傳錄音api 'onVoiceRecordEnd', // 超過一分鐘自動中止api 'playVoice', // 播放錄音api 'pauseVoice', // 暫停錄音api 'onVoicePlayEnd', // 監聽語音播放完畢api ] });
代碼中的jsApiList就是錄音功能所用到的全部接口了。其餘幾個屬性的值,就不介紹如何生成的了,調用jssdk的類庫,經過公衆號的appid和secret就能獲取到。嗯...仍是貼下這部分的代碼吧:後端
// 引入jssdk庫 require_once APPPATH . 'libraries/weixin/jssdk.php'; // 傳入appid和secret實例化jssdk類 $JsSdk = new JSSDK('wxa318c6979e231ffas', '301d8f04a0f2ba3098135a13165c9912'); // 獲得相關時間戳和隨機字符串 $data['signPackage'] = $JsSdk->getSignPackage(); // 獲取當前頁面url $data['signPackage']['url'] = explode('?', $data['signPackage']['url'])[0];
注意:調用JSSDK類的時候,會在項目根目錄下生成兩個文件access_token.php
和jsapi_ticket.php
,裏面放的是過時時間和token、ticket值。api
ready註冊錄音播放結束監聽事件:
wx.ready(function(){ // 監聽事件一開始就加載 wx.onVoicePlayEnd({ success: function (res) { layer.msg('播放完畢'); // 這裏用了layer彈框 } }); });
本小節主要是關於錄音事件的介紹,代碼行中的註釋應該寫的很清楚,不清楚的留言問吧:
// 聲明一個錄音數組 以存放錄音臨時ID var voice = { localId: [] }; // 手指按下錄音鍵 $('#micb').on('touchstart', function(event){ // 取消事件的默認動做 event.preventDefault(); // 賦值當前的錄音開始時間戳到全局變量 START = new Date().getTime(); recordTimer = setTimeout(function(){ // 錄音開始 wx.startRecord({ success: function(){ // 錄音不能超過一分鐘 超過一分鐘自動中止 並觸發該事件 wx.onVoiceRecordEnd({ // 錄音時間超過一分鐘沒有中止的時候會執行 complete 回調 complete: function (res) { // 給出提示 layer.msg('最多隻能錄製一分鐘', {icon:2, time:1000}); // 記錄錄音的臨時ID voice.localId = res.localId; uploadVoice(); } }); }, cancel: function () { alert('用戶拒絕受權錄音'); } }); },300); }); // 鬆手結束錄音 $('#micb').on('touchend', function(event){ event.preventDefault(); // 獲取錄音中止時間戳 END = new Date().getTime(); // 獲取錄音總時長 duration = END - START; // 若是小於300ms則視爲時間過短 拋出提示 if(duration < 300){ END = 0; START = 0; layer.msg('時間過短', {icon:2, time:1000}); //小於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: 'down_file.php', type: 'post', data: {serverId: res.serverId}, dataType: "json", success: function (data) { if(data.status == 200) { layer.msg('語音保存成功', {icon:1, time:2000}); } }, error: function (xhr, errorType, error) { console.log(error); } }); } }); } /** * 播放音頻 */ function playVoice() { wx.playVoice({ localId: voice.localId // 須要播放的音頻的本地ID,由stopRecord接口得到 }) }
以上就是微信錄音在前端的JS代碼,接下來講明服務器(PHP)端下載錄音到本地的代碼,下載代碼具體在download_media()
方法中,其餘都是一些輔助方法:
<?php class Wechat { /** * 獲取微信access_token * @return string access_token */ public function getWechatAccessToken() { $token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential'; $appid = 'appid'; $secret = 'secret'; $get_token_url = $token_url . '&appid=' . $appid . '&secret=' . $secret; $res = file_get_contents ( $get_token_url ); $res_arr = json_decode ( $res, true ); if($res_arr['access_token']) return $res_arr['access_token']; return false; } /** * 生成毫秒級時間戳 */ public function msectime() { list($msec, $sec) = explode(' ', microtime()); return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000); } /** * 隨機取出字符串 * @param int $strlen 字符串位數 * @return string */ public function salt($strlen) { $str = "abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789"; $salt = ''; $_len = strlen($str)-1; for ($i = 0; $i < $strlen; $i++) { $salt .= $str[mt_rand(0,$_len)]; } return $salt; } /** * 下載微信素材資源到本地 * @param url $url 素材地址 * @return json */ public function download_media() { // 獲取微信服務器的錄音ID $media_id = $this->input->post('serverId'); if ($media_id) { // 獲取access_token $access_tokens = $this->getWechatAccessToken(); // 下載素材接口 $down_media_url = 'https://api.weixin.qq.com/cgi-bin/media/get'; /** * 根據access_tokens獲取素材 */ $get_media_url = $down_media_url . '?access_token=' . $access_tokens . '&media_id=' . $media_id; // 獲取文件流 $file_flow = file_get_contents($get_media_url); // 本地保存目錄 $save_path = "resource/uploads/"; if( !is_dir($save_path) ) { mkdir(iconv('UTF-8', 'GBK', $save_path), 0777, TRUE); } // 生成文件名 $filename = $this->msectime() . $this->salt(6) . '.amr'; // 寫入文件流到本地 $flag = file_put_contents($save_path . '/' . $filename, $file_flow); unset($file_flow); if($flag !== FALSE) { return $save_path . '/' . $filename; }else { return FALSE; } } } }
因爲微信保存錄音的格式.amr,因此下載的時候只能下載amr格式的音頻,強行下載成MP3格式的話,播放可能會出現一些問題,接下來就說下轉碼的幾種方式;
FFmpeg是一套能夠用來記錄、轉換數字音頻、視頻,並能將其轉化爲流的開源計算機程序。FFmpeg在Linux平臺下開發,但它一樣也能夠在其它操做系統環境中編譯運行,包括Windows、Mac OS X等。———來自百度的介紹。
經過這個網址下載ffmpeg.exe程序 https://ffmpeg.zeranoe.com/bu...,選擇shared這個類型,以下圖:
下載完成後,解壓在bin目錄能夠看到ffmpeg.exe
cmd命令行轉碼:
直接切換到ffmpeg.exe的目錄,在命令行輸入
ffmpeg.exe -i E:\wode\ffmpeg\amr.amr E:\wode\ffmpeg\arm.mp3
便可,就能夠看到整個轉碼的過程。下圖所示:
php轉碼:
那麼如何利用php來調用exe軟件來進行轉碼呢?很方便的是php提供了相應的函數,exec
和system
,他們均可以調用cmd的命令,好比調用ffmpeg.exe來進行轉碼:
exec("E:\\wode\\ffmpeg\\bin\\ffmpeg.exe -i E:\\wode\\ffmpeg\\amr.amr E:\\wode\\ffmpeg\\exec.mp3");
就是這麼簡單了。固然ffmpeg也支持其餘格式的轉碼,音頻、視頻等均可以。
PS:會把測試的amr文件貼在下面的資源節裏,有須要的小夥伴能夠下載測試,由於如今的amr格式的文件都挺難找的,別問我怎麼知道的....
除了經過php外部命令調用軟件進行轉碼以外,還能夠經過第三方平臺實現轉碼操做,這裏就舉例七牛雲,首先貼兩個連接:
上面的的一個連接裏顯示的是七牛官方全部的SDK文檔列表,能夠根據後端語言的不一樣進行選擇查看;第二個連接就是本小節要說的利用七牛雲上傳文件。下面來瞧一下代碼,也一樣封裝成類的形式:
<?php use Qiniu\Auth; use Qiniu\Storage\UploadManager; use Qiniu\Storage\BucketManager; class uploadQiniu { public $qiniu = [ 'AccessKey' => '', // 配置七牛AccessKey 'SecretKey' => '', // 配置七牛SecretKey 'bucket' => 'cxiansheng', // 七牛的存儲空間名,個人是cxiansheng 'voice-pipeline' => 'cxiansheng', // 設置轉碼隊列名 'voice-domain' => 'http://***.com/' // 你的CDN加速域名 上傳文件成功後經過這個域名+文件名就能夠訪問到相應的資源 ]; /** * 上傳微信錄音文件到七牛並轉碼mp3 * @param string $trans_ext 本地文件路徑 */ public function upload_qiniu($file_path) { // 獲取七牛auth對象 $auth = new Auth($this->qiniu['AccessKey'], $this->qiniu['SecretKey']); // 定義轉碼後的mp3文件名 $qiniu_filename = 'qiniu' . $this->msectime() . $this->salt(6) . '.mp3'; // 指定上傳文件成功後的後續處理 這裏爲轉碼操做 $savekey = \Qiniu\base64_urlSafeEncode($this->qiniu['bucket'] . ":" . $qiniu_filename); $fops = 'avthumb/mp3/ab/128k/ar/44100/acodec/libmp3lame|saveas/' . $savekey; /** * 設置轉碼格式和轉碼隊列名 */ $policy = [ 'persistentOps' => $fops, 'persistentPipeline' => $this->qiniu['voice-pipeline'] ]; /** * 設置上傳到七牛的原始amr臨時文件名 * @var string */ $qiniu_tmp_filename = 'originamrtmp.amr'; // 獲取上傳token $uptoken = $auth->uploadToken($this->qiniu['bucket'], null, 3600, $policy); // 調用上傳類 $uploadMgr = new UploadManager(); // 調用 UploadManager 的 putFile 方法進行文件的上傳。 list($ret, $err) = $uploadMgr->putFile($uptoken, $qiniu_tmp_filename, $file_path); // 資源管理類 $bucketMgr = new BucketManager($auth); if($ret['key']) { // 刪除原始amr臨時文件 $err = $bucketMgr->delete($this->qiniu['bucket'], $ret['key']); unlink($file_path); //刪除服務器上的amr文件 // 返回在七牛上的資源路徑 return $this->qiniu['voice-domain'] . $qiniu_filename; }else { return FALSE; } } }
上面的代碼應該不用我作過多介紹,裏面的註釋每一步應該都寫得很清楚。
PS:在經過第三方轉碼的時候,調用api成功以後,因爲要待轉碼的文件通常都會處於轉碼隊列中,可能尚未當即轉碼成功咱們想要的文件。因此不能根據轉碼事後的文件名去下載,須要等待一下子,或者能夠先把轉碼後的文件名保存在數據庫中,用定時任務去下載到本地。具體請看我在SF提問裏的回答--下載七牛雲mp3文件間歇性失敗
至此,在微信開發中關於錄音這一起的功能,就已經介紹完畢。若是有寫錯的地方,歡迎拍磚。一樣看完還不是很理解的朋友,也能夠留言。
以上。
其餘另外兩篇本身關於微信開發的總結推薦: