Android 訊飛語音聽寫SDK快速接入(附空指針解決和修改對話框文字方法)

来源:https://www.cnblogs.com/DMingO/archive/2020/05/05/12790055.html
-Advertisement-
Play Games

快速接入訊飛語音聽寫SDK(內附空指針解決和修改對話框文字方法) ...


 

1、賬號準備工作

首先要有一個訊飛的賬號啦,為後面申請APPID、APPKey等東西做準備。順帶一提:訊飛對不同認證類型用戶開

放的SDK的使用次數是有不同的,詳情如下圖。

不同用戶的套餐區別

賬號申請完成後,需要去你自己的控制台註冊你的應用,同時也可以看到你的應用對應的 APPID 等屬性,開通的功能,調用量剩餘次數等信息。

本文介紹的是Android SDK的接入,這是Android SDK的下載地址,可以根據項目的具體需求具體分析。

2、SDK集成準備工作

如果參照官方文檔中或者官方DEMO的做法,需要把對應架構的文件拷貝到 Android工程的libs目錄下 。

而官方提供的DEMO中,它只拷貝了armeabi-v7a架構。如下圖所示(我信了它的邪,在我第一次接入時,就因為參考了官方DEMO只導入了armeabi-v7a架構,導致出了一大堆毛病?)

官方DEMO

為了避免這個坑,我的建議是:把提供的架構都拷貝到工程里。(有特殊設備需求的除外)

然後在build.gradle文件中,添加SDK的依賴

    implementation files('libs/Msc.jar')

如果將SDK導入到lib文件夾後,可能還會有無法識別的錯誤。

可以試下在build.gradle(app)中註釋掉以下的代碼(玄學操作~~),再繼續排查。

//        ndk {
//            //選擇要添加的對應cpu類型的.so庫。
//            abiFilters 'armeabi-v7a', 'armeabi'
//        }

//    sourceSets {
//        main{
//            jniLibs.srcDirs = ['libs']
//        }
//    }

3、在 AndroidManifest.xml 文件 添加所需許可權

靜態添加許可權部分,參考了官方文檔的說法。

<!--連接網路許可權,用於執行雲端語音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--獲取手機錄音機使用許可權,聽寫、識別、語義理解需要用到此許可權 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--讀取網路信息狀態 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--獲取當前wifi狀態 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允許程式改變網路連接狀態 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--讀取手機信息許可權 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--讀取聯繫人許可權,上傳聯繫人需要用到此許可權 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存儲寫許可權,構建語法需要用到此許可權 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存儲讀許可權,構建語法需要用到此許可權 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置許可權,用來記錄應用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手機定位信息,用來為語義等功能提供定位,提供更精準的服務-->
<!--定位信息是敏感信息,可通過Setting.setLocationEnable(false)關閉定位請求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人臉識別,還要添加:攝相頭許可權,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />

不過,靜態申請了許可權,還不夠哦。對於現在的手機,很大部分都已經是Android版本678910的了,應用是需要動態申請許可權的,得讓用戶確認同意了,APP才可以使用這些許可權。

動態申請許可權的方法有很多,也有很多開源的項目,這裡就不做介紹了。

4、SDK初始化

SDK初始化建議放在程式入口處(如Application、Activity的onCreate方法),非常簡單,就一行語句。

初始化代碼如下:

//將“1234567”替換成您申請的APPID
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=1234567");

註意:SpeechConstant.APPID +"=1234567" 採用的是拼接的方式,所以不可以在“=”與appid之間添加任何空字元或者轉義符。

5、調用語音聽寫功能

最重要的來了,前面鋪墊這麼久,就是為了能調用它的語音聽寫啊。

離線聽寫方式,需要購買且下載特定的離線識別SDK,故這裡使用的是線上聽寫。

線上聽寫的SDK,提供了兩種識別方式,分別是帶語音對話框識別和無UI識別。

一.無UI識別

//初始化識別無UI識別對象
//使用SpeechRecognizer對象,可根據回調消息自定義界面--自己的語音識別UI
mIat = SpeechRecognizer.createRecognizer(IatDemo.this, mInitListener);

//設置語法ID和 SUBJECT 為空,以免因之前有語法調用而設置了此參數;或直接清空所有參數,具體可參考 DEMO 的示例。
mIat.setParameter( SpeechConstant.CLOUD_GRAMMAR, null );
mIat.setParameter( SpeechConstant.SUBJECT, null );
//設置返回結果格式,目前支持json,xml以及plain 三種格式,其中plain為純聽寫文本內容
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
//此處engineType為“cloud”
mIat.setParameter( SpeechConstant.ENGINE_TYPE, engineType );
//設置語音輸入語言,zh_cn為簡體中文
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//設置結果返回語言
mIat.setParameter(SpeechConstant.ACCENT, "mandarin");
// 設置語音前端點:靜音超時時間,單位ms,即用戶多長時間不說話則當做超時處理
//取值範圍{1000~10000}
mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
//設置語音後端點:後端點靜音檢測時間,單位ms,即用戶停止說話多長時間內即認為不再輸入, 
//自動停止錄音,範圍{0~10000}
mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
//設置標點符號,設置為"0"返回結果無標點,設置為"1"返回結果有標點
mIat.setParameter(SpeechConstant.ASR_PTT,"1");
//開始識別,並設置監聽器
mIat.startListening(mRecogListener);

二.帶語音對話框識別(SDK自帶)

// 初始化聽寫Dialog,如果只使用有UI聽寫功能,無需創建SpeechRecognizer
// 使用UI聽寫功能,請根據sdk文件目錄下的notice.txt,放置佈局文件和圖片資源
mIatDialog = new RecognizerDialog(IatDemo.this, mInitListener);

//以下為dialog設置聽寫參數
        mIatDialog.setParameter(SpeechConstant.RESULT_TYPE, "json");
        //設置語音輸入語言,zh_cn為簡體中文
        mIatDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        //設置結果返回語言
        mIatDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
        // 設置語音前端點:靜音超時時間,單位ms,即用戶多長時間不說話則當做超時處理
        //取值範圍{1000~10000}
        mIatDialog.setParameter(SpeechConstant.VAD_BOS, "4500");
        //設置語音後端點:後端點靜音檢測時間,單位ms,即用戶停止說話多長時間內即認為不再輸入,
        //自動停止錄音,範圍{0~10000}
        mIatDialog.setParameter(SpeechConstant.VAD_EOS, "1500");
        //開始識別並設置監聽器
        mIatDialog.setListener(mRecognizerDialogListener);

//開始識別並設置語音UI監聽器
mIatDialog.setListener(mRecognizerDialogListener);
//顯示聽寫對話框,show方法實際是內部調用無UI識別方式
mIatDialog.show();

重點來了,也是很多人很困擾的一步,官方文檔的說法是使用這個SDK自帶的語音識別對話框,需要把對應的佈局文件和圖片資源放入工程中。然而,很多人這樣做了之後, mIatDialog.show(); 調用了還是會出現空指針的異常。。例如:?

java.lang.NullPointerException
      at com.iflytek.cloud.ui.a.a(Unknown Source)
      at com.iflytek.cloud.ui.RecognizerDialog.setParameter(Unknown Source)
      atcom.example.mediaplayer.activity.SearchActivity.setParam(SearchActivity.java:111)
      at com.example.mediaplayer.activity.SearchActivity.onClick(SearchActivity.java:86)
      at android.view.View.performClick(View.java:4438)
      at android.view.View$PerformClick.run(View.java:18422)
      at android.os.Handler.handleCallback(Handler.java:733)
      at android.os.Handler.dispatchMessage(Handler.java:95)
      at android.os.Looper.loop(Looper.java:136)
      at android.app.ActivityThread.main(ActivityThread.java:5045)
      at java.lang.reflect.Method.invokeNative(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:515)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
      at dalvik.system.NativeStart.main(Native Method)

解決方法,如下:

首先,在asset文件內,放入所需的資源。註意:asset文件夾的位置,是要在src/main/ 的下一級,然後在與

asset文件夾同級的地方創建 jniLibs 文件夾,把 libs/文件夾的對應SDK文件拷貝到 jniLibs 中,如圖:

同時檢查下,SDK初始化的 APPId 有無出錯的可能。

獲取數據

解決了空指針的問題後,接下來調用 show 方法,就可以在自定義的監聽器里愉快地獲取到返回的聽寫數據了

 //創建語音識別UI對話框
 mIatDialog = new RecognizerDialog(getActivity(), searchViewModel.mInitListener);
 
 
 
 	/**
     * 初始化聽寫事件監聽器。
     */
    public InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {
            if (code != ErrorCode.SUCCESS) {
                //Todo
            }
        }
    };
    /**
     * 聽寫UI監聽器 訊飛
     */
    public RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {

        /**
         * 接收語音聽寫回調信息
         * @param recognizerResult 回調結果
         * @param b 是否翻譯
         */
        @Override
        public void onResult(com.iflytek.cloud.RecognizerResult recognizerResult, boolean b) {
        //返回的數據
		String data = recognizerResult.getResultString();
        }
        /**
         * 識別回調錯誤.
         */
        public void onError(SpeechError error) {
            if(error.getErrorCode() == 14002) {
               //Todo
            } else {
               //Todo
            }
        }

    };

修改預設對話框的文字

//動態更換了訊飛自帶對話框的底部文字,必須在dialog的show執行後更換,否則空指針報錯
TextView recorderDialogTextView = (TextView)  mIatDialog.getWindow().getDecorView().findViewWithTag("textlink");

recorderDialogTextView.setText(R.string.recorder_dialog_textview_text);

預設文本修改後

返回的聽寫數據實例,用於創建實體類:

{
    "sn": 1,
    "ls": true,
    "bg": 0,
    "ed": 0,
    "ws": [
        {
            "bg": 0,
            "cw": [
                {
                    "w": "今天",
                    "sc": 0
                }
            ]
        },
        {
            "bg": 0,
            "cw": [
                {
                    "w": "的",
                    "sc": 0
                }
            ]
        },
        {
            "bg": 0,
            "cw": [
                {
                    "w": "天氣",
                    "sc": 0
                }
            ]
        },
        {
            "bg": 0,
            "cw": [
                {
                    "w": "怎麼樣",
                    "sc": 0
                }
            ]
        },
        {
            "bg": 0,
            "cw": [
                {
                    "w": "。",
                    "sc": 0
                }
            ]
        }
    ]
}

註意:若在SDK中開通了 動態修正的功能,返回的數據會出現格式不一致的情況。官方的說法如下:

動態修正:
  • 未開啟動態修正:實時返回識別結果,每次返回的結果都是對之前結果的追加;
  • 開啟動態修正:實時返回識別結果,每次返回的結果有可能是對之前結果的的追加,也有可能是要替換之前某次返回的結果(即修正);
  • 開啟動態修正,相較於未開啟,返回結果的顆粒度更小,視覺衝擊效果更佳;
  • 使用動態修正功能需到控制台-流式聽寫-高級功能處點擊開通,並設置相應參數方可使用,參數設置方法:mIat.setParameter(“dwa”, “wpgs”); ;
  • 動態修正功能僅 中文 支持;
  • 未開啟與開啟返回的結果格式不同,詳見下方;

若開通了動態修正功能並設置了dwa=wpgs(僅中文支持),會有如下欄位返回:

參數類型描述
pgs string 開啟wpgs會有此欄位 取值為 “apd"時表示該片結果是追加到前面的最終結果;取值為"rpl” 時表示替換前面的部分結果,替換範圍為rg欄位
rg array 替換範圍,開啟wpgs會有此欄位 假設值為[2,5],則代表要替換的是第2次到第5次返回的結果

PS:一般項目中的語音聽寫需求,完全可以不使用動態修正功能,但若要使用同步顯示語音識別結果或者比較需要比較精準的結果,可以考慮使用此功能。

總結

訊飛語音聽寫SDK,坑點不少,但是都不是很難,還是適項目快速接入語音聽寫需求的。。?

如果要更多操作和功能,請參考訊飛語音聽寫SDK官方文檔


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 表結構 student(StuId,StuName,StuAge,StuSex) 學生表 teacher(TId,Tname) 教師表 course(CId,Cname,C_TId) 課程表 sc(SId,S_CId,Score) 成績表 問題三:查詢所有同學的學號、姓名、選課數、總成績 SELEC ...
  • 1、數據冗餘導致的問題:冗餘存儲、更新異常、插入異常、刪除異常。 2、函數依賴:一種完整性約束。 在關係模式r(R)中,α屬於R,β屬於R。 1)α函數確定β(β函數依賴於α):記作α→β,對於任意合法關係r及其中任兩個元組ti和tj,i≠j,若ti[α]=tj[α],則ti[β]=tj[β]。 2 ...
  • @2020.5.5 練習:賬號信息表,用戶組,主機表,主機組 ...
  • 【目錄】 一 系統資料庫 二 創建資料庫 三 資料庫相關操作 一 系統資料庫 information_schema: 虛擬庫,不占用磁碟空間,存儲的是資料庫啟動後的一些參數,如用戶表信息、列信息、許可權信息、字元信息等 performance_schema: MySQL 5.5開始新增一個資料庫,主要 ...
  • 伴隨著Redis6.0的發佈,作為最令人怦然心動的特性之一,Redis官方同時推出Redis集群的proxy了:redis-cluster-proxy,https://github.com/RedisLabs/redis-cluster-proxy 相比從前訪問Redis集群時需要制定集群中所有的I ...
  • mysql命令gruop by報錯this is incompatible with sql_mode=only_full_group_by 出現這個錯誤已導致在開發中mybatis的sql也運行不了 原因: 看一下group by的語法: select 選取分組中的列+聚合函數 from 表名稱 ...
  • 目錄:andorid jar/庫源碼解析 RxJava2: 作用: 通過提供一種,觀察者和訂閱者的模式,的架構,來優化邏輯流程。適用於複雜和需要多數據轉換和長流程。 慄子: 定義三個對象類 public class ResultInfo { public int code; public Strin ...
  • 目錄:andorid jar/庫源碼解析 Bolts: 作用: 用於鏈式執行跨線程代碼,且傳遞數據 慄子: Task.call(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return tr ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...