【Recorder.js+百度語音識別】全棧方案技術細節

      網友投稿 796 2025-03-31

      一. 技術棧選擇


      需求:利用百度語音接口在Web端實現語音識別功能

      技術棧:React+recorder-tool.js?+recorder.js?+?Express?+?Baidu語音識別API

      recorder.js項目地址:https://github.com/mattdiamond/Recorderjs

      演示效果:

      二. 前端開發細節

      為recorder.js提供一個代理對象

      前端的主框架采用React,在基本結構和語法上并沒有太多問題,為了使用recorder.js,我們封裝了一個recorder-tool.js作為代理,其實現方法較為簡單,就是將官方示例中example示例中的html文件的腳本部分封裝成一個單例對象作為recorder.js的代理,然后暴露一組API供上層調用,大致的結構如下:

      解除exportWAV方法的回調地獄

      官方示例中輸出wav編碼格式的數據這個動作是通過webworker來完成的,也就是說二進制數據處理的開始和結束時間點是通過事件來觸發的,recorder.exportWAV( )接收一個回調函數作為入參,在得到wav格式的數據后會執行傳入的回調函數,如果要在react中實現,就需要寫成:

      你或許已經發現了這個【回調地獄】的現象,深度的嵌套會讓邏輯變的復雜且代碼高度耦合,想把一些方法從react中剝離出去非常困難,我們希望使用一些其他的方式來轉換代碼的控制權,而不是把一大堆后續的邏輯傳進exportData( )方法。

      方法一:使用HTML自定義事件

      我們在一個存在的DOM元素上添加一個自定義事件recorder.export的-,并在傳入recorder.exportWAV( )方法的回調函數中,手動初始化觸發一個自定義事件(暫不考慮兼容性問題),并把recorder.js導出的數據掛在這個event對象上,然后在指定元素上派發這個事件:

      這樣我們后續的處理邏輯就可以用常規的方式在React組件中繼續編寫后續的業務邏輯,這樣就實現了基本的職責分離和代碼分離。

      方法二:監聽WebWorker

      recorder.js中使用DOM0級事件模型來與webworker通訊,為了不覆蓋原功能,我們可以通過DOM2事件模型在recorder實例上綁定額外的-:

      這樣我們就可以在自己的邏輯代碼或二次封裝的代碼中實現對轉碼動作的監聽。

      方法三:Promise化

      使用Promise來實現異步的調用,將音頻處理的代碼剝離出去,最終的調用方式為:

      參考代碼如下:

      三. Recorder.js的功能擴展

      百度AI語音識別接口接收的語音文件需要滿足如下的要求:

      pcm格式或wav格式文件的二進制數據經過base64轉換后的編碼

      16000Hz采樣率

      16bit位深

      單聲道

      要利用recorder.js實現上述需求,需要對源碼進行一些功能擴展。編碼轉換可以在服務端進行,而recorder.js中的floatTo16BitPCM( )方法看名字應該是為了滿足16bit位深這個條件的,那么我們只需要考慮單聲道和16000采樣率這兩個條件了。

      源碼中Recorder構造函數是可以接受參數的,而這個參數會被合入實例的config屬性,其中numChannles就是聲道數,所以我們只需要在實例化是傳入自定義的聲道數目即可:

      new?Recorder({????numChannels:1//單聲道})

      再來看16000采樣率這個條件,查看源碼可以知道,源碼中對于sampleRate的使用,一律使用了音頻流數據源上下文的sampleRate,也就是對應著電腦聲卡的采樣率(48000Hz或44100Hz),那如何得到16000Hz采樣率的數據呢?比如一個48000Hz采樣率的聲卡采集的信號點,1秒采集了48000次,那么這48000個數據要變成16000個數據,最簡單的辦法就是每4個點取1個然后組成新的數據,也就是說實際上聲音采集設備傳過來的采樣率是固定的,我們需要多少的采樣率,只需要自己拿一個比例系數去換算一下,然后丟棄掉一部分數據點(當然也可以求平均值)就可以了,封裝后的調用方式為:

      new?Recorder({????numChannels:1,????sampleRate:16000});

      那么在源碼中需要做一些功能的擴展,關鍵的部分在下面這段代碼:

      【Recorder.js+百度語音識別】全棧方案技術細節

      //recorder.js部分源碼function?exportWAV(type)?{????var?buffers?=?[];????for?(var?channel?=?0;?channel?

      extractSingleChannel( )的具體實現參考interleave( )方法

      /** *sampleStep是系統的context.sampleRate/自定義sampleRate后取整的結果,這個方法實現了對單聲道的*采樣數據處理。 */function?extractSingleChannel(input)?{????//如果此處不按比例縮短,實際輸出的文件會包含sampleStep倍長度的空錄音 ????var?length?=?Math.ceil(input.length?/?sampleStep);????var?result?=?new?Float32Array(length);????var?index?=?0, ????????inputIndex?=?0;????while?(index?

      這樣處理后exportWAV( )方法輸出的Blob對象中存放的數據就滿足了百度語音的識別要求。

      四. 服務端開發細節

      在服務端我們使用Express框架來部署一個消息中轉服務,這里涉及的知識點相對較少,可以使用百度AI的nodejs-sdk來實現,也可以自行封裝,權限驗證的方法幾乎都是通用的,按照官方文檔來做就可以了。

      通過multipart/form-data方式提交的表單無法直接通過req.body或req.params進行處理,這里使用官方推薦的Multer中間件來處理,此處較為簡單,直接附上筆者的參考代碼:

      此處有一點需要注意的是:在實例化Multer時,傳參和不傳參時得到的轉換對象是不一樣的,如果涉及到相關場景可以直接在控制臺打印出來確保使用了正確的屬性。

      語音通話 JavaScript 一句話識別

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel怎么做表格(如何用excel做圖表)
      下一篇:智能業務流程管理,引領企業進入無縫高效的數字化時代
      相關文章
      亚洲日韩乱码中文无码蜜桃| 亚洲国产日韩在线视频| 亚洲AV无码国产丝袜在线观看| 亚洲精品成人a在线观看| 亚洲欧美日韩中文字幕一区二区三区 | 亚洲黄色三级视频| 亚洲第一视频网站| 久久久久久亚洲av成人无码国产| 久久亚洲欧洲国产综合| 国产国拍亚洲精品福利 | 伊人久久亚洲综合影院| 亚洲精品国产摄像头| 亚洲精品V天堂中文字幕| 噜噜综合亚洲AV中文无码| 亚洲AV成人精品一区二区三区| 亚洲JLZZJLZZ少妇| 欧美激情综合亚洲一二区| 亚洲AV伊人久久青青草原| 亚洲精品无码AV中文字幕电影网站| 亚洲国产成人精品91久久久| 亚洲精品和日本精品| 国产精品亚洲mnbav网站| 亚洲午夜福利精品无码| 国产AV无码专区亚洲AV漫画| 久久精品国产精品亚洲精品| 久久国产精品亚洲一区二区| 亚洲高清中文字幕| 亚洲六月丁香六月婷婷色伊人| 亚洲av片不卡无码久久| 国产亚洲中文日本不卡二区| 亚洲国产综合AV在线观看| 国产精品亚洲精品日韩动图| 亚洲精品97久久中文字幕无码| 亚洲精品视频久久久| 亚洲人成精品久久久久| 久久精品国产96精品亚洲| 亚洲欧洲在线播放| 中文日韩亚洲欧美制服| 国产成人精品亚洲一区| 国产亚洲精品不卡在线| 亚洲成a人片在线观看无码|