微信小程序的基礎庫升級到了 1.6.0 之后,提供了許多新的 API,其中新增了 錄音管理 的 API,不同于以前只有 wx.startRecord
和 wx.stopRecord
兩個簡單的錄音功能,新的 wx.getRecorderManager
接口提供了包括擴展時長、采樣率、錄音通道、碼率、格式等在內的許多配置項?;诖?,我們能更加輕松的控制錄音,新提供的 onFrameRecorded
的事件,甚至可以實現流式語音識別。
本文就介紹一下使用 Wafer Node.js SDK 提供的騰訊云智能語音識別接口來實現錄音轉文字的功能。請您先從 Github 下載 語音識別 Demo ,本文會根據 Demo 來介紹 SDK 中語音識別接口的使用。
使用語音識別需要開通騰訊云智能語音。
打開 server/config.js
,添加上 qcloudAppId
, qcloudSecretId
, qcloudSecretKey
三個配置項,并在代碼目錄中打開 CMD,運行如下代碼:
cd server && npm i
安裝完成依賴,選擇小程序開發(fā)者工具右上角的【騰訊云】按鈕,點擊【上傳測試環(huán)境】上傳代碼到測試環(huán)境中,一鍵部署程序。你也可以自行部署代碼,部署過程同 《自行部署 Node.js Demo》 ,這里不再介紹。
最終實現的效果如下:
具體是如何實現的呢?接下來我們來分析一下 Demo 里的有關代碼。
首先查閱 SDK API 文檔可知,SDK 提供的語音識別接口是分片識別接口,原理是將語音文件切分成一個個分片,將每個分片以 buffer
格式傳入接口,最后一個分片調用接口時需要將 isEnd
參數置為 true
,最后會返回完整的識別結果,以此來流式識別語音。
由于智能語音識別只支持以下幾種編碼格式的音頻文件:
所以小程序端通過 recorderManager
獲取到的錄音文件需要提前轉換為這幾種格式中的一種,然后才能識別。Demo 里選擇了將 mp3
格式轉換為 wav
格式文件的形式。
Demo 中采用了 ffmpeg
對語音文件進行轉碼,使用 ffmpeg
的前提是需要在環(huán)境中安裝 ffmpeg
,然后在 Node.js 中使用 fluent-ffmpeg
調用 ffmpeg
實現轉碼。
注意: ffmpeg
并沒有默認預裝在開發(fā)環(huán)境和生產環(huán)境中,如果您需要使用語音識別的轉碼功能,可以提交工單,我們會為您配置好環(huán)境。
打開 Demo 中的 server/controllers/recognize.js
文件,首先調用了 multiparty
從請求體中讀取出上傳上來的音頻數據,接著對語音的類型進行一些判斷。
...
const { files } = await resolveUploadFileFromRequest(ctx.req);
...
if (!resultType || !['audio/mpeg', 'audio/mp3'].includes(resultType.mime)) {
throw new Error('上傳的文件格式不是 mp3')
}
...
第 46 行開始對音頻文件進行處理,首先先生成了 voiceId
, voiceId
告訴了語音識別接口每個語音分片屬于哪個語音,每個語音的 voiceId
應當是唯一的。
接著調用了 convertMp3ToWav
函數對語音進行轉換, convertMp3ToWav
函數的實現如下:
/**
* mp3 轉 wav
* @param {string} srcPath 源文件地址
* @param {string} newPath 新文件地址
*/
function convertMp3ToWav (srcPath, newPath) {
return new Promise((resolve, reject) => {
ffmpeg(srcPath)
.format('wav')
.on('error', reject)
.on('end', function () {
resolve(newPath)
})
.save(newPath)
})
}
由于每次識別的文件大小最好不要超過 10K byte,所以需要對音頻文件進行切片,原理就是將音頻文件讀取為 buffer,然后按每 9K byte 大小切片識別。
// 將文件讀取為 Buffer
const voiceBuffer = fs.readFileSync(newVoicePath);
const taskList = [];
let leftBufferSize = 0;
let idx = 0;
// 按 9K 大小切分分片并識別
while (leftBufferSize < voiceBuffer.length) {
const newBufferSize = leftBufferSize + 9 * 1024;
// 切分分片
const chunk = voiceBuffer.slice(
leftBufferSize,
newBufferSize > voiceBuffer.length
? voiceBuffer.length
: newBufferSize
)
// 提交每個切片去識別,并將任務推入任務列表
taskList.push(
voice.recognize(
chunk,
newBufferSize > voiceBuffer.length,
voiceId,
idx
)
);
leftBufferSize = newBufferSize;
idx++;
}
以上就是語音識別 Demo 代碼的分析,您可以直接運行 Demo,在手機端 真機調試 體驗。
注意:開發(fā)者工具的錄音接口返回的數據不是 MP3 格式,與真機行為不完全相同,所以錄音相關的測試請直接使用真機調試。
原創(chuàng)聲明,本文系作者授權云+社區(qū)-專欄發(fā)表,未經許可,不得轉載。