天天看點

基于React-Native0.55.4的語音識别項目全棧方案

移動端的

API

能力驗證方案與PC端不一樣!不一樣!!不一樣!!!

即使需要使用的

API

都存在,也不一定能用,這一點和PC端是有很大差別的,國内的手機系統雖然都是基于

Android

,但幾乎都會經過各大廠商的定制,功能與原版

Android

系統并不是完全一緻的,在考察技術方案的時候一定要确認用

demo

把功能跑起來才可以,别問我怎麼知道的。

一. 移動端直接通路Web應用?

PC端基于

Web API

的語音識别方案可參考《【Recorder.js+百度語音識别】全棧方案技術細節》一文。

1. 調用

Web API

的多媒體采集接口需要特定的域

Web API

的多媒體接口是WebRTC技術在PC端的實作,由于多媒體采集涉及到使用者隐私,是以在浏覽器端調用這個接口需要在安全的域下才能被調起,安全的域是指以下三類:

  • file:///

    本地域
  • http://localhost

    本地web伺服器
  • https://

    安全域

前兩類一般用于桌面應用和本地調試,實際網站上線部署需要以

https

方式部署,如何部署

https

及申請免費的CA憑證等網上有很多文章講解,本文不再贅述。

2. 手機浏覽器幾乎都不直接支援

WebRTC

接口

将PC端的Web應用以

https

方式部署好之後,從手機浏覽器直接通路時無法喚起錄音接口權限認證,

navigator.getUserMedia( )

方法一隻傳回

permissionDenied

錯誤,無論是在Android6.0以下通過編輯

manifest.xml

添加還是Android6.0以上通過動态擷取的方式取得

RECORD_AUDIO

權限,網站都可以正常通路,相關的

Web API

接口也都存在,但即使獲得使用者授權後也無法調起錄音功能。筆者測試了UC浏覽器,百度移動浏覽器和Android6.0(API23)自帶的浏覽器,Android8.0(API26)自帶的浏覽器,結果是都不支援。

二. 方案調研和新的坑

o( ̄▽ ̄)d 既然從移動端直接通路Web應用時無法調起錄音接口,至少是無法相容很多系統和機型,如果不考慮直接原生開發Android的話,隻有寄希望于Hybrid的方案了。

2.1 WebView

  • 方案:

    在一個app中單頁面全屏放置一個WebView元件,然後加載https方式部署的web應用。

  • 理由:

    手機浏覽器無法支援的情況下,隻能寄希望于

    WebView

    WebView

    是Android底層用于加載網頁的元件,Android4.4版本以後已将内置的浏覽器引擎更換為chromium,也就是chrome的核心,從Can I Use上查詢的支援度是Android5.0以上的版本的

    WebView

    都是支援

    WebRTC

    接口的

    getUserMedia( )

    方法的。
  • 測試結果:

    應用編譯目标版本為

    API23

    ,在支援

    API23

    (Android6.0)的虛拟機和真機中測試,均無法通過

    WebAPI

    接口調起麥克風進行錄音。在支援

    API26

    (Android8.0)版本的虛拟機中,功能均可實作。最終在Can I Use中對于

    getUserMedia( )

    方法支援度的統計資訊的備注中,發現已知問題中在寫明了:
基于React-Native0.55.4的語音識别項目全棧方案

簡單地說就是這個方法在

Android webview

iOS

PWA

基本都用不了。建議以後開發中可能用到一些不常用的API時完整地看一下相關資訊。

  • 結論:

    Android8.0支援,Android支援度不佳,不建議使用。

2.2 crosswalk

  • 官方網址:https://crosswalk-project.org/

    利用

    crosswalk

    ,在進行app打包時,将

    webview

    核心替換為

    xwalk

    (crosswalk開發的基于chromium的浏覽器核心),以擴充原生

    webview

    的能力。
  • 既然原生

    webview

    功能被閹割,那麼可以利用這個小型黑科技來把一個功能更強大的浏覽器核心跟自己的應用打包在一起,筆者3年前在

    cordova

    2.0-3.0版本流行的年代使用過這個技術,好處是的确可以擴充

    webview

    的能力無疑,不好的地方在于app項目會直接增大80-90Mb的體積,當然通過幾個版本的疊代,現在crosswalk可以針對手機核心類型生成不同的包,app體積增量大約在20Mb,基本屬于可接受範圍。
  • 遺憾地是這個項目一年前已經停止維護了,最後一版的官方腳手架工具也無法初始化新的工程,間接使用的方式分為兩種,第一,下載下傳

    crosswalk

    的包,手動在

    android

    工程中替換原生

    WebView

    ,對Hybrid開發者來說難度較大且與hybrid技術相容性不可控;另一種方案在下一小節說明。
  • 不建議使用,有那個精力真不如去研究一下可靠的hybrid方案。

2.3 Cordova/ionic

基于React-Native0.55.4的語音識别項目全棧方案
  • 官方網址:https://cordova.apache.org

    codova

    是一個很流行的hybrid方案,現在已經更新到8.0.0版本,它本身就是一個将web應用打包為app的解決方案。

    cordova

    的基本原理是将一般

    UI

    層操作和功能放在

    WebView

    裡實作,需要調用移動裝置硬體或原生接口時,均通過添加

    cordova

    插件的形式來實作,每一個

    cordova

    版本都會橫跨支援若幹個

    Android

    版本,例如新的

    cordova7.0.0

    在官方文檔的說明中是支援android從4.4到8.1版本的,筆者認為非常适合小型hybrid開發團隊使用。
  • 值得一提的是

    cordova

    擁有一個非常流行的移動端開發×××

    ionic

    ,現在已經疊代至

    4.0

    階段,這個技術筆者是有特殊感情的,當年

    ionic

    還在

    alpha

    版本的時候,筆者就在使用了,它是基于cordova+angular這個技術組合的,擁有清新且設計感極強的UI元件,非常值得嘗試。另外,

    cordova

    是擁有

    crosswalk

    插件的,可以直接以插件的形式,在

    cordova

    項目打包時加入

    crosswalk

    ,有相關需求的讀者可以以一試,尤其是團隊裡沒有Android開發人員也沒有專門的設計人員的時候,

    ionic

    出品的應用一定會讓别人對你另眼相看。
  • 筆者曾在使用

    cordova

    3.3的時候就融入過

    crosswalk

    ,也通過

    cordova

    插件成功調用過底層的

    GPS

    攝像頭

    及其他一些原生元件,當時是為了适配Android4.4版本。

    cordova7.0.0

    的腳手架經測試在國内是可以使用的,建立的工程無論是通過自帶指令行還是import進Android Studio來進行開發都可以打包為對應的工程,官方文檔有很詳細的調用各種底層接口的說明,網上也有

    cordova7.0.0+crosswalk

    方案對應的技術貼。

    筆者由于技術協定中指定技術棧的緣故,無法中途替換解決方案,故本次未進行測試。

  • 可考慮作為整體解決方案進行嘗試。

2.4 React-Native

基于React-Native0.55.4的語音識别項目全棧方案
  • 官方網址:https://reactnative.cn

    這是筆者本次使用的方案,由于web端采用

    React

    技術棧完成的緣故,為了不增加團隊小夥伴的學習成本,移動端就選用了

    React-Native

    的方案。這個方案既可以按照混合開發的方式來進行,也可以按照單個

    WebView

    的方式來進行(已驗證這種方案無法支援

    WebRTC

    )。

    可能很多人已經聽說去年

    Airbnb

    公開宣布不再繼續使用

    React-Native

    作為移動端解決方案并做了詳細的解釋,當時也是很多人鼓吹說

    React-Native

    要涼涼了。實際上

    Airbnb

    在聲明中說的很清楚,

    React-Native

    是非常好的hybrid解決方案,他們所遇到的問題是當性能和使用者體驗優化到一定程度時,在hybrid技術的維護和開發上投入的人力過多了,整個項目的前端人員不僅有Web前端,還有進階的

    Android

    IOS

    人員來保障hybrid項目的推進,他們認為這樣的人力成本相比于原生開發而言要高很多,是以更換了方案。聽明白了嗎?是以作為軟體技術比國外落後不知道多少年的天朝碼農,考慮實際的項目需求,盡管放心大膽地用就好了,跟風真的沒什麼價值。
  • 熱門的hybrid解決方案,和Web前端三駕馬車之一的

    React

    屬同門,文法群組件結構相似度高,社群活躍且周邊生态較好。
  • React-native

    已經釋出

    0.57.3

    版本,但經測試

    0.55.4

    在國内屬于可正常建立工程的版本(使用

    react-native init XXX

    指令建立的工程),

    0.56

    大版本中釋出的兩個小版本均在初始打包時報錯,指令行的提示連結到一個已知issue,但可惜照做以後也未能打包成功,

    0.57

    預設的Android-SDK是

    API27

    ,也就是Android8.1,對于經驗不足的開發者來說(比如我自己),太新的版本也不建議使用,除非你的項目是在指定機器上運作的。

    React-native

    也封裝了

    WebView

    元件,但很遺憾,直接加載web應用的方式經測試也無法調起

    getUserMedia( )

    這個方法,是以最終隻能通過混合開發的方案來實作(但回過頭來想,跟通過

    WebView

    來調用硬體接口相比,其實這種實作方式反而更符合邏輯)。
  • 建議未掌握多語言混合開發能力的hybrid開發者盡可能選用熱門方案,理由很簡單,所有的前端項目都有坑,但熱門項目出了問題可以找大牛咨詢。

WebRTC

技術錄音相關的

navigator.getUserMedia

,

navigator.mediaDevices.getUserMedia

AudioContext

這上面這幾個方案中都是存在的,但事實是都沒能在

webview

中調起麥克風進行錄音。

當然

WebRTC

作為獨立的标準和技術,也是可以融入Android工程的,但從前端開發者的角度來說這條路就有點跑偏了,執着于

WebRTC

或者團隊裡有原生開發者的小夥伴可以研究一下。

三. React-Native方案的整體架構

基于React-Native0.55.4的語音識别項目全棧方案

基本上隻要多複用現成的元件,加上适量的定制,盡可能不使用一些奇技淫巧,産品的流暢度基本區分不出來是否是Hybrid開發還是Native開發,當然跟筆者的項目體量不是很大也有一定關系。

四. 使用插件清單

  • react-native-audio

    位址:https://github.com/jsierles/react-native-audio

    調用麥克風采集音頻。

  • rn-fetch-blob

    位址:https://github.com/joltup/rn-fetch-blob

    在RN中從native層通過原生線程直接發送大體積二進制資料或檔案,通過Bridge對象從Web發請求會造成性能問題。

  • Multer

    子產品

    位址:https://github.com/expressjs/multer

    Express

    服務端中間件,用于接收用戶端發送的大體積二進制資料或檔案。
  • FFmpeg

    工具

    位址:http://ffmpeg.org/

    多媒體格式轉換庫。手機端采集編碼的格式無法被百度語音識别接口直接識别,需要先進行重編碼。

    node.js

    開發者通過

    child_process

    子產品直接從代碼中喚起指令行執行即可。

五. RN開發細節和遇到的坑

  1. 真機調試時,需要搖晃手機,在配置菜單中填寫内網IP+端口号,否則會直接紅屏報錯。
  2. 真機調試時,需要在設定中開啟應用的

    懸浮框

    權限,否則可能白屏什麼都不顯示。
  3. WebRTC

    Android WebView

    相容性不好,

    IOS

    内置浏覽器不支援。
  4. react-native-audio

    進行錄音時,每一次調用

    Stop

    之後,若要再次啟動錄音功能,必須先調用

    AudioRecorder.prepareRecordingAtPath( )

    方法重新初始化,否則會紅屏報錯。
  5. WebView

    元件必須設定

    ref={(webview)=>{this.webview = webview}}

    ,否則

    onMessage

    屬性無法監聽到來自

    WebView

    加載網頁通過

    window.postMessage

    發來的消息。
  6. TouchableHighlight

    元件必須先設定

    onPress

    屬性的回調函數(可以為空函數),否則觸摸變色的響應屬性

    UnderlayColor

    無法生效。
  7. Modal

    元件在一個自定義元件中隻能有一個(如果有多個必須通過條件判斷隻執行個體化一個),否則即使未顯示的

    Modal

    元件的

    Visible

    屬性設定為

    false

    ,其執行個體方法也會和另一個

    Modal

    元件發生重疊覆寫,可能出現的現象就是顯示了第一個

    Modal

    的界面,卻執行了第二個

    Modal

    的同名方法。