微信小程序的基礎(chǔ)庫(kù)升級(jí)到了 1.6.0 之后,提供了許多新的 API,其中新增了 錄音管理 的 API,不同于以前只有 wx.startRecord 和 wx.stopRecord 兩個(gè)簡(jiǎn)單的錄音功能,新的 wx.getRecorderManager 接口提供了包括擴(kuò)展時(shí)長(zhǎng)、采樣率、錄音通道、碼率、格式等在內(nèi)的許多配置項(xiàng)?;诖?,我們能更加輕松的控制錄音,新提供的 onFrameRecorded 的事件,甚至可以實(shí)現(xiàn)流式語(yǔ)音識(shí)別。
本文就介紹一下使用 Wafer Node.js SDK 提供的騰訊云智能語(yǔ)音識(shí)別接口來(lái)實(shí)現(xiàn)錄音轉(zhuǎn)文字的功能。請(qǐng)您先從 Github 下載 語(yǔ)音識(shí)別 Demo ,本文會(huì)根據(jù) Demo 來(lái)介紹 SDK 中語(yǔ)音識(shí)別接口的使用。
使用語(yǔ)音識(shí)別需要開通騰訊云智能語(yǔ)音。
打開 server/config.js ,添加上 qcloudAppId , qcloudSecretId , qcloudSecretKey 三個(gè)配置項(xiàng),并在代碼目錄中打開 CMD,運(yùn)行如下代碼:
cd server && npm i
安裝完成依賴,選擇小程序開發(fā)者工具右上角的【騰訊云】按鈕,點(diǎn)擊【上傳測(cè)試環(huán)境】上傳代碼到測(cè)試環(huán)境中,一鍵部署程序。你也可以自行部署代碼,部署過(guò)程同 《自行部署 Node.js Demo》 ,這里不再介紹。
最終實(shí)現(xiàn)的效果如下:

具體是如何實(shí)現(xiàn)的呢?接下來(lái)我們來(lái)分析一下 Demo 里的有關(guān)代碼。
首先查閱 SDK API 文檔可知,SDK 提供的語(yǔ)音識(shí)別接口是分片識(shí)別接口,原理是將語(yǔ)音文件切分成一個(gè)個(gè)分片,將每個(gè)分片以 buffer 格式傳入接口,最后一個(gè)分片調(diào)用接口時(shí)需要將 isEnd 參數(shù)置為 true ,最后會(huì)返回完整的識(shí)別結(jié)果,以此來(lái)流式識(shí)別語(yǔ)音。
由于智能語(yǔ)音識(shí)別只支持以下幾種編碼格式的音頻文件:
- pcm
- adpcm
- feature
- speex
- amr
- silk
- wav
所以小程序端通過(guò) recorderManager 獲取到的錄音文件需要提前轉(zhuǎn)換為這幾種格式中的一種,然后才能識(shí)別。Demo 里選擇了將 mp3 格式轉(zhuǎn)換為 wav 格式文件的形式。
Demo 中采用了 ffmpeg 對(duì)語(yǔ)音文件進(jìn)行轉(zhuǎn)碼,使用 ffmpeg 的前提是需要在環(huán)境中安裝 ffmpeg ,然后在 Node.js 中使用 fluent-ffmpeg 調(diào)用 ffmpeg 實(shí)現(xiàn)轉(zhuǎn)碼。
注意: ffmpeg 并沒(méi)有默認(rèn)預(yù)裝在開發(fā)環(huán)境和生產(chǎn)環(huán)境中,如果您需要使用語(yǔ)音識(shí)別的轉(zhuǎn)碼功能,可以提交工單,我們會(huì)為您配置好環(huán)境。
打開 Demo 中的 server/controllers/recognize.js 文件,首先調(diào)用了 multiparty 從請(qǐng)求體中讀取出上傳上來(lái)的音頻數(shù)據(jù),接著對(duì)語(yǔ)音的類型進(jìn)行一些判斷。
... const { files } = await resolveUploadFileFromRequest(ctx.req); ... if (!resultType || !['audio/mpeg', 'audio/mp3'].includes(resultType.mime)) { throw new Error('上傳的文件格式不是 mp3') } ...
第 46 行開始對(duì)音頻文件進(jìn)行處理,首先先生成了 voiceId , voiceId 告訴了語(yǔ)音識(shí)別接口每個(gè)語(yǔ)音分片屬于哪個(gè)語(yǔ)音,每個(gè)語(yǔ)音的 voiceId 應(yīng)當(dāng)是先進(jìn)。
接著調(diào)用了 convertMp3ToWav 函數(shù)對(duì)語(yǔ)音進(jìn)行轉(zhuǎn)換, convertMp3ToWav 函數(shù)的實(shí)現(xiàn)如下:
/** * mp3 轉(zhuǎn) 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) }) }
由于每次識(shí)別的文件大小較好不要超過(guò) 10K byte,所以需要對(duì)音頻文件進(jìn)行切片,原理就是將音頻文件讀取為 buffer,然后按每 9K byte 大小切片識(shí)別。
// 將文件讀取為 Buffer const voiceBuffer = fs.readFileSync(newVoicePath); const taskList = []; let leftBufferSize = 0; let idx = 0; // 按 9K 大小切分分片并識(shí)別 while (leftBufferSize < voiceBuffer.length) { const newBufferSize = leftBufferSize + 9 * 1024; // 切分分片 const chunk = voiceBuffer.slice( leftBufferSize, newBufferSize > voiceBuffer.length ? voiceBuffer.length : newBufferSize ) // 提交每個(gè)切片去識(shí)別,并將任務(wù)推入任務(wù)列表 taskList.push( voice.recognize( chunk, newBufferSize > voiceBuffer.length, voiceId, idx ) ); leftBufferSize = newBufferSize; idx++; }
以上就是語(yǔ)音識(shí)別 Demo 代碼的分析,您可以直接運(yùn)行 Demo,在手機(jī)端 真機(jī)調(diào)試 體驗(yàn)。
注意:開發(fā)者工具的錄音接口返回的數(shù)據(jù)不是 MP3 格式,與真機(jī)行為不完全相同,所以錄音相關(guān)的測(cè)試請(qǐng)直接使用真機(jī)調(diào)試。
原創(chuàng)聲明,本文系作者授權(quán)云+社區(qū)-專欄發(fā)表,未經(jīng)許可,不得轉(zhuǎn)載。
如有侵權(quán),請(qǐng)聯(lián)系z(mì)huanlan_guanli@qq.com刪除。
編輯于 15 小時(shí)前