1、概(gai)述通(tong)過微信小(xiao)程序wx.startRecord()和wx.stopRecord()接口錄(lu)(lu)(lu)音并上(shang)傳(chuan)silk錄(lu)(lu)(lu)音文(wen)件至服務器,通(tong)過ffmpeg將silk錄(lu)(lu)(lu)音文(wen)件轉成wav錄(lu)(lu)(lu)音文(wen)件,再(zai)通(tong)過百(bai)度語(yu)音識(shi)別(bie) REST API 獲(huo)取語(yu)音識(shi) ...
//index.js
//開始錄(lu)音。當主動調用wx.stopRecord,
//或(huo)者錄(lu)音(yin)(yin)超過1分鐘時自(zi)動結束(shu)錄(lu)音(yin)(yin),返回錄(lu)音(yin)(yin)文件(jian)的臨時文件(jian)路徑(jing)。
//當用戶離(li)開小程序時,此接口無(wu)法調用。
wx.startRecord({
success: function (res) {
console.log('錄音(yin)成功(gong)' + JSON.stringify(res));
that.setData({
voiceButtonName: '語音識別',
voicePlayButtonName: '開始(shi)播放',
tempFilePath: res.tempFilePath
})
//上傳語(yu)音文件至服務器(qi)
wx.uploadFile({
url: '//你的域名/upload',
filePath: res.tempFilePath,
name: 'file',
// header: {}, // 設置請求的(de) header
formData: {
'msg': 'voice'
}, // HTTP 請求中其(qi)他額外的(de) form data
success: function (res) {
// success
console.log('begin');
console.log(res.data);
var json = JSON.parse(res.data);
console.log(json.msg);
var jsonMsg = JSON.parse(json.msg);
console.log(jsonMsg.result);
wx.navigateTo({
url: '../voicePage/voicePage?voiceData=' + jsonMsg.result.join('')
})
},
fail: function (err) {
// fail
console.log(err);
},
complete: function () {
// complete
}
})
},
fail: function (res) {
//錄音失敗
that.setData({
voiceButtonName: '語音識別'
})
console.log('錄音失(shi)敗' + JSON.stringify(res));
}
})
setTimeout(function () {
//結束錄音
wx.stopRecord()
}, 60000)
node.js服務(wu)端接(jie)收(shou)語音文件代(dai)碼
//upload.js
//使(shi)用koa-multer這個(ge)組件
var multer = require('koa-multer');
var router = require('koa-router')();
var path = require('path');
//存(cun)儲文件至path.resolve('./voice-file')路(lu)徑
var upload = multer({ dest: path.resolve('./voice-file')});
router.post('/', upload.single('file'), async function (ctx, next) {
//這是就(jiu)文(wen)件的具(ju)體信息
console.log(ctx.req.file);
});
silk文件轉wav文件
我使用的是silk-v3-decoder將(jiang)silk文(wen)件(jian)轉wav文(wen)件(jian)

//upload.js
var exec = require('child_process').exec;
function silkToWav(file){
return new Promise(function (resolve, reject) {
exec('sh converter.sh ' + file + ' wav', function(err,stdout,stderr){
if(err) {
resolve({
result : false,
msg : stderr
});
} else {
//var data = JSON.parse(stdout);
console.log(stdout);
console.log(stderr);
//console.log(err);
resolve({
result : true,
msg : ''
});
}
});
});
}
1、通過API Key和(he)Secret Key獲取的access_token

//speech.js
speech.getAccessToken = function(){
return new Promise(function (resolve, reject) {
request({
url: '//openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=(你自(zi)(zi)己的API key)&client_secret=(你自(zi)(zi)己的Secret Key)',
method: 'get',
headers: {
'content-type': 'application/json'
}
}, function (error, response, data) {
if (error){
resolve({
'result' : false,
'msg' : '出(chu)現錯誤: ' + JSON.stringify(error)
});
}else {
resolve({
'result' : true,
'msg' : data
});
}
});
});
}
2、通過(guo)token 調用(yong)百度語(yu)音識別 REST API識別接口
//speech.js
speech.recognize = function(base64String, size){
return new Promise(function (resolve, reject) {
request({
url: '//vop.baidu.com/server_api',
method: 'post',
headers: {
'content-type': 'application/json'
},
// len + speech方式(shi)
body: JSON.stringify({
"format":"wav",
"rate":16000,
"channel":1,
"token":'(你(ni)的token)',
"cuid":"9e:eb:e8:d4:67:00",
"len":size,
"speech":base64String
})
//url + callback方式(shi)
//body: JSON.stringify({
// "format":"wav",
// "rate":16000,
// "channel":1,
// "token":'(你的token)',
// "cuid":'9eebe8d46700',
// "url":'//ihealth-wx.s1.natapp.cc/download?name=123.wav',
// "callback":'//ihealth-wx.s1.natapp.cc/callback'
//})
}, function (error, response, data) {
if (error){
resolve({
result : false,
msg : '出(chu)現錯誤: ' + JSON.stringify(error)
});
}else {
resolve({
result : true,
msg : data
});
}
});
});
}
通過(guo)上述操作后,發(fa)現識別的內容和實際內容差(cha)別很大

查看文檔可知:采樣率:8000/16000 僅支持單通道
在ffmpeg里對應的設置方式分別是:
-ar rate 設置采樣率
-ac channels 設(she)置聲道數
修(xiu)改converter.sh文件,修(xiu)改為下圖所示(shi)
