最近在做基於微信小程序【垃圾分類引導指南】的語音識別功能模塊時,遇到了一個比較頭疼得事情,由於騰訊AI開放平臺的接口只支持PCM、WAV、AMR和SILK四種音頻格式,而微信小程序錄音的音頻文件是mp3格式的(此處就是踩得第一大坑了,剛開始看到開發文檔是的時候心裏還暗喜了一波,因爲微信小程序錄音文件就可以設置爲SILK格式,這樣豈不是可以不費吹灰之力就搞定了想想有點頭疼的語音識別啦然而我們終究還是太年輕折騰了半天,在真機測試的時候發現木有半點反應,調試發現沒有生成錄音文件,真的是丈二和尚摸不着頭腦的趕腳,最後查了一番資料才知道微信小程序在真機上只能設置成acc和mp3格式的),那麼這裏就不得不進行音頻格式轉化了。
此次分享廢話不多說,直接上每一步的代碼,首先上一波流程圖
微信小程序端語音頁面代碼如下
<view class='serac_img' bindtap="startRecord" wx:if="{{hasRecord == false}}">
<image src='../../images/voice.png' mode="widthFix"></image>
<text>語音查詢</text>
</view>
<view class='serac_img' bindtap="stopRecord" wx:if="{{hasRecord == true}}">
<image src='../../images/stop.png' mode="widthFix"></image>
<text>錄音中</text>
</view>
Js部分的話,先引入wx.getRecorderManager()
const recorderManager = wx.getRecorderManager()
然後,在錄音開始事件中進行錄音參數設置及開啓錄音
startRecord() {
this.setData({
hasRecord: true
})
const options = {
duration: 10000,
sampleRate: 16000,
numberOfChannels: 1,
encodeBitRate: 48000,
format: 'mp3'
}
recorderManager.start(options);
}
最後,在停止錄音事件裏進行停止錄音操作,並監控停止錄音事件,獲取到錄音文件,使用wx.uploadFile()方法將錄音文件傳給後端,後端處理完成後返回最終處理信息並展示
stopRecord() {
this.setData({ hasRecord: false })
var that = this
recorderManager.stop()
recorderManager.onStop((res) => {
const { tempFilePath } = res;
wx.showLoading({
title: '語音檢索中',
})
//上傳錄製的音頻
wx.uploadFile({
url: requestUrl + 'Rubbish/VoiceSearch',
filePath: tempFilePath,
name: 'voices',
success: function (event) {
var datas = JSON.parse(event.data);
if (datas.status == 0) {
wx.hideLoading()
if (datas.result.list.length > 0) {
that.setData({
detail: datas.result
})
} else {
wx.showToast({
title: '如此聰明伶俐的我居然會詞窮,我要喊我父親大人送我去深造~',
icon: 'none',
duration: 2000
})
}
} else {
wx.showToast({
title: datas.msg,
icon: 'none',
duration: 2000
})
}
}
})
})
}
後端代碼採用avconv進行音頻轉化,這裏採用騰訊語音識別-echo版Api接口來進行語音識別,具體實現如下
接收錄音文件並進行轉碼
public function VoiceSearch(){
$typeArr = array("mp3");
$path = "Public/uploads/voice_search/"; //上傳路徑
$name = $_FILES['voices']['name'];
$size = $_FILES['voices']['size'];
$name_tmp =$_FILES['voices']['tmp_name'];
if (empty($name)) {
jsonReturn(20000,'小主,請開口說話~');
}
$type = strtolower(substr(strrchr($name, '.'), 1)); //獲取文件類型
if (!in_array($type, $typeArr)) {
jsonReturn(20002,'文件格式好像不對喲~');
}
if ($size > (5000 * 1024)) { //上傳大小
jsonReturn(20003,'小主,口才可是真真的好呢~');
}
$pic_name = date('YmdHis') . rand(10000, 99999) . "." . $type; //名稱
$pic_url = $path . $pic_name; //上傳後路徑+名稱
if (move_uploaded_file($name_tmp, $pic_url)) { //臨時文件轉移到目標文件夾
$r_path = $_SERVER['DOCUMENT_ROOT'];
$wavname = date('YmdHis') . rand(10000, 99999).".wav";
$newpath = "Public/uploads/voice_search/".$wavname;
//執行文件格式轉換
$exec1 = "avconv -i $r_path/$pic_url -vn -f wav $r_path/$newpath";
exec($exec1,$info,$status);
//轉換成功後進入識別階段
if ($status == 0){
//語音識別
$r = $this->voiceGeneral(SITE_URL.'/'.$newpath);
$resu = json_decode($r,true);
if ($resu['ret'] == 0 && $resu['msg'] == 'ok'){
jsonReturn(0,'獲取成功',$resu['data']['text']);
}else{
jsonReturn(-1,'哎呀,人潮擁擠,請稍後重試~');
}
}else{
jsonReturn(-1,'哎呀,人潮擁擠,請稍後重試~');
}
} else {
jsonReturn(-1,'哎呀,人潮擁擠,請稍後重試~');
}
}
對接騰訊語音識別Api接口進行語音識別
public function voiceGeneral($path){
$url = 'https://api.ai.qq.com/fcgi-bin/aai/aai_asr';
$data = file_get_contents($path);
$base64 = base64_encode($data);
// 設置請求數據
$appkey = 'WjjphPD0oqrPJSYm';
$params = array(
'app_id' => '2018656256',
'format' => '2',
'rate' => '16000',
'speech' => $base64,
'time_stamp' => strval(time()),
'nonce_str' => strval(rand()),
'sign' => '',
);
$params['sign'] = $this->getReqSign($params, $appkey);
// 執行API調用
$response = httpRequest($url, 'POST',$params);
return $response;
}
public function getReqSign($params , $appkey )
{
// 1. 字典升序排序
ksort($params);
// 2. 拼按URL鍵值對
$str = '';
foreach ($params as $key => $value)
{
if ($value !== '')
{
$str .= $key . '=' . urlencode($value) . '&';
}
}
// 3. 拼接app_key
$str .= 'app_key=' . $appkey;
// 4. MD5運算+轉換大寫,得到請求籤名
$sign = strtoupper(md5($str));
return $sign;
}
至此,微信小程序語音識別就結束了,又可以愉快的玩耍了~
最後再上一個小程序碼,歡迎大家掃碼體驗,有什麼意見可以給我留言喲~