Android集成科大訊飛語音識別與語音喚醒簡易封裝

目錄

一、語音喚醒部分

1、首先在科大訊飛官網注冊開發者賬號

2、配置喚醒詞然后下載sdk

3、選擇對應功能下載

4、語音喚醒lib包全部復制到工程目錄下

5、把語音喚醒詞文件復制到工程的assets目錄

6、復制對應權限到AndroidManifest.xml中

7、喚醒工具類封裝

二、語音識別

1、工具類

2、使用


一、語音喚醒部分

1、首先在科大訊飛官網注冊開發者賬號

控制臺-訊飛開放平臺

2、配置喚醒詞然后下載sdk

3、選擇對應功能下載

4、語音喚醒lib包全部復制到工程目錄下

5、把語音喚醒詞文件復制到工程的assets目錄

6、復制對應權限到AndroidManifest.xml中

    <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- App 需要使用的部分權限 --><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- 科大訊飛 --><uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"tools:ignore="ProtectedPermissions" /><uses-permissionandroid:name="android.permission.READ_PRIVILEGED_PHONE_STATE"tools:ignore="ProtectedPermissions" /><uses-permissionandroid:name="android.permission.MANAGE_EXTERNAL_STORAGE"tools:ignore="ProtectedPermissions" /><uses-permissionandroid:name="android.permission.READ_PHONE_NUMBERS"tools:ignore="ProtectedPermissions" />

7、喚醒工具類封裝

?其中IflytekAPP_id為科大訊飛平臺的應用id


public abstract class WakeUpUtil {private static AutoTouch autoTouch = new AutoTouch();//自動點擊屏幕/*** 喚醒的回調*/public abstract void wakeUp(String resultString);// Log標簽private static final String TAG = "WakeUpUtil";// 上下文private static Context mContext;// 語音喚醒對象private VoiceWakeuper mIvw;//喚醒門限值//門限值越高,則要求匹配度越高,才能喚醒//值范圍:[0,3000]//默認值:1450private static int curThresh = 1450;public WakeUpUtil(Context context) {initKedaXun(context);mContext = context;// 初始化喚醒對象mIvw = VoiceWakeuper.createWakeuper(context, null);Log.d("initLogData", "===進入喚醒工具類====");}/*** 獲取喚醒詞功能** @return 返回文件位置*/private static String getResource() {final String resPath = ResourceUtil.generateResourcePath(mContext, RESOURCE_TYPE.assets, "ivw/" + "cf22564a" + ".jet");return resPath;}/*** 喚醒*/public void wake() {Log.d("initLogData", "===進入喚醒工具類====");// 非空判斷,防止因空指針使程序崩潰VoiceWakeuper mIvw = VoiceWakeuper.getWakeuper();if (mIvw != null) {// textView.setText(resultString);// 清空參數mIvw.setParameter(SpeechConstant.PARAMS, null);// 設置喚醒資源路徑mIvw.setParameter(SpeechConstant.IVW_RES_PATH, getResource());// 喚醒門限值,根據資源攜帶的喚醒詞個數按照“id:門限;id:門限”的格式傳入mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:" + curThresh);// 設置喚醒模式mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");// 設置持續進行喚醒mIvw.setParameter(SpeechConstant.KEEP_ALIVE, "1");mIvw.startListening(mWakeuperListener);Log.d("initLogData", "====喚醒====");} else {Log.d("initLogData", "===喚醒未初始化11====");
//            Toast.makeText(mContext, "喚醒未初始化1", Toast.LENGTH_SHORT).show();}}public void stopWake() {mIvw = VoiceWakeuper.getWakeuper();if (mIvw != null) {mIvw.stopListening();} else {Log.d("initLogData", "===喚醒未初始化222====");
//            Toast.makeText(mContext, "喚醒未初始化2", Toast.LENGTH_SHORT).show();}}String resultString = "";private WakeuperListener mWakeuperListener = new WakeuperListener() {@Overridepublic void onResult(WakeuperResult result) {try {String text = result.getResultString();JSONObject object;object = new JSONObject(text);StringBuffer buffer = new StringBuffer();buffer.append("【RAW】 " + text);buffer.append("\n");buffer.append("【操作類型】" + object.optString("sst"));buffer.append("\n");buffer.append("【喚醒詞id】" + object.optString("id"));buffer.append("\n");buffer.append("【得分】" + object.optString("score"));buffer.append("\n");buffer.append("【前端點】" + object.optString("bos"));buffer.append("\n");buffer.append("【尾端點】" + object.optString("eos"));resultString = buffer.toString();stopWake();autoTouch.autoClickPos( 0.1, 0.1);wakeUp(resultString);
//                MyEventManager.postMsg("" + resultString, "voicesWakeListener");} catch (JSONException e) {MyEventManager.postMsg("" + "結果解析出錯", "voicesWakeListener");resultString = "結果解析出錯";wakeUp(resultString);e.printStackTrace();}//            Logger.d("===開始說話==="+resultString);}@Overridepublic void onError(SpeechError error) {MyEventManager.postMsg("" + "喚醒出錯", "voicesWakeListener");}@Overridepublic void onBeginOfSpeech() {Log.d("initLogData", "===喚醒onBeginOfSpeech====");}@Overridepublic void onEvent(int eventType, int isLast, int arg2, Bundle obj) {
//            Log.d("initLogData", "===喚醒onEvent===" + eventType);}@Overridepublic void onVolumeChanged(int i) {
//            Log.d("initLogData", "===開始說話==="+i);}};/*** 科大訊飛* 語音sdk* 初始化*/public void initKedaXun(Context context) {// 初始化參數構建StringBuffer param = new StringBuffer();//IflytekAPP_id為我們申請的Appidparam.append("appid=" + context.getString(R.string.IflytekAPP_id));param.append(",");// 設置使用v5+param.append(SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC);SpeechUtility.createUtility(context, param.toString());Log.d("initLogData", "===在appacation中初始化=====");}}

使用直接調用即可

/*** 科大訊飛* 語音喚醒* 對象*/private WakeUpUtil wakeUpUtil;private void voiceWake() {Log.d("initLogData", "===執行喚醒服務====");wakeUpUtil = new WakeUpUtil(this) {@Overridepublic void wakeUp(String result) {MyEventManager.postMsg("" + "喚醒成功", "voicesWakeListener");Log.d("initLogData", "====喚醒成功===========" + result);// 開啟喚醒wakeUpUtil.wake();}};wakeUpUtil.wake();}

到此語音喚醒已經集成結束,接下來是語音識別。

二、語音識別

1、工具類


/*** 科大訊飛* 語音識別* 工具類*/
public class KDVoiceRegUtils {private SpeechRecognizer mIat;private RecognizerListener mRecognizerListener;private InitListener mInitListener;private StringBuilder result = new StringBuilder();// 函數調用返回值private int resultCode = 0;/*** 利用AtomicReference*/private static final AtomicReference<KDVoiceRegUtils> INSTANCE = new AtomicReference<KDVoiceRegUtils>();/*** 私有化*/private KDVoiceRegUtils() {}/*** 用CAS確保線程安全*/public static final KDVoiceRegUtils getInstance() {for (; ; ) {KDVoiceRegUtils current = INSTANCE.get();if (current != null) {return current;}current = new KDVoiceRegUtils();if (INSTANCE.compareAndSet(null, current)) {return current;}Log.d("initLogData", "===科大訊飛實例化===大哥大哥==");}}/*** 初始化* 監聽*/public void initVoiceRecorgnise(Context ct) {if (mInitListener != null || mRecognizerListener != null) {return;}mInitListener = new InitListener() {@Overridepublic void onInit(int code) {
//            Log.e(TAG, "SpeechRecognizer init() code = " + code);Log.d("initLogData", "===科大訊飛喚醒初始化===" + code);if (code != ErrorCode.SUCCESS) {
//                showToast("初始化失敗,錯誤碼:" + code + ",請點擊網址https://www.xfyun.cn/document/error-code查詢解決方案");}}};//識別監聽mRecognizerListener = new RecognizerListener() {@Overridepublic void onBeginOfSpeech() {// 此回調表示:sdk內部錄音機已經準備好了,用戶可以開始語音輸入Log.d("initLogData", "=====開始說話======");}@Overridepublic void onError(SpeechError error) {// Tips:// 錯誤碼:10118(您沒有說話),可能是錄音機權限被禁,需要提示用戶打開應用的錄音權限。
//                Log.d("initLogData", "====錯誤說話=====" + error.getPlainDescription(true));senVoicesMsg(300, "識別錯誤 ");//100啟動語音識別    200識別成功   300識別錯誤mIat.stopListening();hideDialog();}@Overridepublic void onEndOfSpeech() {// 此回調表示:檢測到了語音的尾端點,已經進入識別過程,不再接受語音輸入mIat.stopListening();
//                Log.d("initLogData", "=====結束說話======");hideDialog();}@Overridepublic void onResult(RecognizerResult results, boolean isLast) {String text = parseIatResult(results.getResultString());
//                Log.d("initLogData", "==說話==語音識別結果==initVoice==" + text);result.append(text);if (!text.trim().isEmpty() && boxDialog != null) {senVoicesMsg(200, "識別成功");//100啟動語音識別    200識別成功   300識別錯誤boxDialog.showTxtContent(result.toString());senVoicesMsg(200, "" + result.toString());}if (isLast) {result.setLength(0);}}@Overridepublic void onVolumeChanged(int volume, byte[] data) {//showToast("當前正在說話,音量大小:" + volume);if (volume > 0 && boxDialog != null) {boxDialog.showTxtContent("錄音中...");}Log.d("initLogData", "===說話==onVolumeChanged:====" + volume);}@Overridepublic void onEvent(int eventType, int arg1, int arg2, Bundle obj) {// 以下代碼用于獲取與云端的會話id,當業務出錯時將會話id提供給技術支持人員,可用于查詢會話日志,定位出錯原因// 若使用本地能力,會話id為nullif (SpeechEvent.EVENT_SESSION_ID == eventType) {String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);}}};// 初始化識別無UI識別對象// 使用SpeechRecognizer對象,可根據回調消息自定義界面;mIat = SpeechRecognizer.createRecognizer(ct, mInitListener);if (mIat != null) {setIatParam();//參數配置}}/*** 執行語音* 識別*/public void startVoice(Context context) {senVoicesMsg(100, "啟動語音識別");//100啟動語音識別    200識別成功   300識別錯誤if (mIat != null) {showDialog(context);mIat.startListening(mRecognizerListener);}}/*** 科大訊飛* 語音識別* 參數配置*/private void setIatParam() {// 清空參數mIat.setParameter(com.iflytek.cloud.SpeechConstant.PARAMS, null);// 設置聽寫引擎mIat.setParameter(com.iflytek.cloud.SpeechConstant.ENGINE_TYPE, com.iflytek.cloud.SpeechConstant.TYPE_CLOUD);// 設置返回結果格式mIat.setParameter(com.iflytek.cloud.SpeechConstant.RESULT_TYPE, "json");// 設置語言mIat.setParameter(com.iflytek.cloud.SpeechConstant.LANGUAGE, "zh_cn");// 設置語言區域mIat.setParameter(com.iflytek.cloud.SpeechConstant.ACCENT, "mandarin");// 設置語音前端點:靜音超時時間,即用戶多長時間不說話則當做超時處理mIat.setParameter(com.iflytek.cloud.SpeechConstant.VAD_BOS, "4000");// 設置語音后端點:后端點靜音檢測時間,即用戶停止說話多長時間內即認為不再輸入, 自動停止錄音mIat.setParameter(com.iflytek.cloud.SpeechConstant.VAD_EOS, "500");// 設置標點符號,設置為"0"返回結果無標點,設置為"1"返回結果有標點mIat.setParameter(com.iflytek.cloud.SpeechConstant.ASR_PTT, "0");Log.d("initLogData", "==語音是被==初始化成功:====");// 設置音頻保存路徑,保存音頻格式支持pcm、wav,設置路徑為sd卡請注意WRITE_EXTERNAL_STORAGE權限// 注:AUDIO_FORMAT參數語記需要更新版本才能生效
//        mIatDialog.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
//        mIatDialog.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/MyApplication/" + filename + ".wav");}/*** 語音* 識別* 解析*/public static String parseIatResult(String json) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);JSONArray words = joResult.getJSONArray("ws");for (int i = 0; i < words.length(); i++) {// 轉寫結果詞,默認使用第一個結果JSONArray items = words.getJSONObject(i).getJSONArray("cw");JSONObject obj = items.getJSONObject(0);ret.append(obj.getString("w"));}} catch (Exception e) {e.printStackTrace();}return ret.toString();}/*** 對話框* getApplicationContext()*/private VoiceDialog boxDialog;private void showDialog(Context context) {View inflate = LayoutInflater.from(context).inflate(R.layout.donghua_layout, null, false);boxDialog = new VoiceDialog(context, inflate, VoiceDialog.LocationView.BOTTOM);boxDialog.show();}/*** 隱藏* 對話框*/private void hideDialog() {if (boxDialog != null) {boxDialog.dismiss();}}/*** 發送語音* 識別消息** @param code* @param conn*/private void senVoicesMsg(int code, String conn) {VoiceRecognizeResult voiceRecognizeResult = new VoiceRecognizeResult();voiceRecognizeResult.setCode(code);//100啟動語音識別    200識別成功   300識別錯誤voiceRecognizeResult.setMsg("" + conn);String std = JSON.toJSONString(voiceRecognizeResult);MyEventManager.postMsg("" + std, "VoiceRecognizeResult");}/*** 科大訊飛* 語音sdk* 初始化*/public void initKedaXun(Context context) {// 初始化參數構建StringBuffer param = new StringBuffer();//IflytekAPP_id為我們申請的Appidparam.append("appid=" + context.getString(R.string.IflytekAPP_id));param.append(",");// 設置使用v5+param.append(SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC);SpeechUtility.createUtility(context, param.toString());Log.d("initLogData", "===在appacation中初始化=====");}}

2、使用

        KDVoiceRegUtils.getInstance().initKedaXun(mWXSDKInstance.getContext());KDVoiceRegUtils.getInstance().initVoiceRecorgnise(mUniSDKInstance.getContext());//語音識別初始化KDVoiceRegUtils.getInstance().startVoice(mUniSDKInstance.getContext());

注意其實代碼還可以優化,由于公司業務需要,封裝的不怎么徹底,使用者可在此基礎上進一步封裝。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/214144.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/214144.shtml
英文地址,請注明出處:http://en.pswp.cn/news/214144.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux學習第46天:Linux音頻驅動試驗:能不能?不行也得行。

Linux版本號4.1.15 芯片I.MX6ULL 大叔學Linux 品人間百味 思文短情長 CAN 是目前應用非常廣泛的現場總線之一&#xff0c;主要應用于汽車電子和工業領域&#xff0c;尤其是汽車 領域&#xff0c;汽車上大量的傳感器與模塊都是通過 C…

十二、MapReduce概述

1、MapReduce &#xff08;1&#xff09;采用框架 MapReduce是“分散——>匯總”模式的分布式計算框架&#xff0c;可供開發人員進行相應計算 &#xff08;2&#xff09;編程接口&#xff1a; ~Map ~Reduce 其中&#xff0c;Map功能接口提供了“分散”的功能&#xff…

【Java期末復習資料】(1)知識點總結

本文章主要是知識點&#xff0c;后續會出模擬卷 以下是選擇、填空可能考的知識點&#xff0c;多看幾遍&#xff0c;混個眼熟 面向對象程序設計的基本特征是&#xff1a;抽象、封裝、繼承、多態&#xff08;后三個是三大特性&#xff09;Java源文件的擴綴名是.java編譯Java App…

知識筆記(五十三)———MySQL 刪除數據表

MySQL中刪除數據表是非常容易操作的&#xff0c;但是你在進行刪除表操作時要非常小心&#xff0c;因為執行刪除命令后所有數據都會消失。 語法 以下為刪除 MySQL 數據表的通用語法&#xff1a; DROP TABLE table_name ; -- 直接刪除表&#xff0c;不檢查是否存在 或 DROP…

neuq-acm預備隊訓練week 8 P8794 [藍橋杯 2022 國 A] 環境治理

題目描述 輸入格式 輸出格式 輸出一行包含一個整數表示答案。 輸入輸出樣例 解題思路 最短路二分 AC代碼 #include<bits/stdc.h> using namespace std; long long temp,n, Q; long long f[105][105],min_f[105][105],cut[105],dis[105][105];//cut為減少多少&#x…

寶塔面板部署Apache服務器搭建本地站點發布到公網可訪問【內網穿透】

文章目錄 前言1. 環境安裝2. 安裝cpolar內網穿透3. 內網穿透4. 固定http地址5. 配置二級子域名6. 創建一個測試頁面 正文開始前給大家推薦個網站&#xff0c;前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家…

最短循環節問題 和 最短回文串(kmp , HASH )

給定一個字符串 s&#xff0c;你可以通過在字符串前面添加字符將其轉換為回文串。找到并返回可以用這種方式轉換的最短回文串。 示例 1&#xff1a; 輸入&#xff1a;s "aacecaaa" 輸出&#xff1a;"aaacecaaa"示例 2&#xff1a; 輸入&#xff1a;s &…

Java智慧校園-中小學校園管理系統源碼

智慧校園系統是通過信息化手段&#xff0c;實現對校園內各類資源的有效集成 整合和優化&#xff0c;實現資源的有效配置和充分利用&#xff0c;將校務管理過程的優化協調。為校園提供數字化教學、數字化學習、數字化科研和數字化管理。 致力于為家長和教師提供一個全方位、多層…

scripty妙用

在monorepo項目中&#xff0c;隨著子模塊增多&#xff0c; 每個子項目都需要配置各自的package.json,并且大同小異&#xff0c;為了進一步提高配置效率&#xff0c;引入了scripty&#xff0c;自己寫腳本&#xff0c;直接就可以用哦 1、安裝 npm install scripty --save-dev 2…

ARMday6作業

串口發送指令控制硬件工作 uart1.h #ifndef __UART1_H__ #define __UART1_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_uart.h" void all_led_init(); void led1_on(); void led2_on(); void led3_o…

代碼隨想錄二刷 | 二叉樹 | 110.平衡二叉樹

代碼隨想錄二刷 &#xff5c; 二叉樹 &#xff5c; 110.平衡二叉樹 題目描述解題思路遞歸迭代 代碼實現遞歸法迭代法 題目描述 110.平衡二叉樹 給定一個二叉樹&#xff0c;判斷它是否是高度平衡的二叉樹。 本題中&#xff0c;一棵高度平衡二叉樹定義為&#xff1a; 一個二叉…

EMNLP 2023 獲獎論文公布,大模型、NLP等領域火爆

EMNLP是計算語言學和自然語言處理領域頂級國際會議之一&#xff0c;屬于CCF B類&#xff0c;是由 ACL 下屬的SIGDAT小組主辦的NLP領域頂級國際會議&#xff0c;一年舉辦一次。相較于ACL&#xff0c;EMNLP更偏向于NLP在各個領域解決方案的學術探討。 今年的EMNLP 2023 已于2023…

table表格table/tr/td寬度和高度的設置

關于html中table表格tr,td的?度和寬度 做?頁的時候經常會遇到各種各樣的問題&#xff0c;經常遇到的?個就是會碰到表格被內容撐開的問題。 設置table樣式為 table-layout: fixed; 寬度可以了&#xff0c;但是高度會被撐高。怎么設置都不行&#xff0c;只能給這個td標簽單獨…

【Linux】 線程池

線程池 什么是線程池&#xff1f; 一次預先申請一批線程&#xff0c;讓這批線程有任務&#xff0c;就處理任務&#xff1b;沒任務&#xff0c;就處于等待狀態。 為什么要有線程池&#xff1f; 以空間換時間&#xff0c;預先申請一批線程&#xff0c;當有任務到來&#xff0c;可…

將rtsp視頻流發送到AWS Kinesis Video Streams的方案——使用Gstreamer(C++) Command Line

大綱 1 創建Kinesis Video Streams1.1 創建視頻流1.2 記錄Creation Time 2 創建策略2.1 賦予權限2.2 限制資源2.3 Json格式描述&#xff08;或上面手工設置&#xff09;2.4 注意事項 3 創建IAM用戶3.1 生成密鑰對3.2 附加策略3.3 記錄訪問密鑰對 4 編譯C 創建者庫5 發送6 檢查參…

JavaScript <關于逆向RSA非對稱加密算法的案例(代碼剖析篇)>--案例(五點一)

引用上文: CSDNhttps://mp.csdn.net/mp_blog/creation/editor/134857857 剖析: var bitsPerDigit16; // 每個數組元素可以表示的二進制位數// 數組復制函數&#xff0c;將源數組部分復制到目標數組的指定位置 function arrayCopy(src, srcStart, dest, destStart, n) {var m…

國內地址地區智能解析,無需完整地址也能正確匹配

頁面直接引入使用 已打包成單文件dist/bundle.js 可以直接通過標簽引用 <script src="./bundle.js"></script> <script>var results = AddressParse.parse(福建省福州市福清市石竹街道義明綜合樓3F,15000000000,asseek);console.log(results);…

OD機考真題搜集:服務失效判斷

題目 某系統中有眾多服務,每個服務用字符串(只包含字母和數字,長度<=10)唯一標識,服務間可能有依賴關系,如A依賴B,則當B故障時導致A也故障。 依賴具有傳遞性,如A依賴B,B依賴C,當C故障時導致B故障,也導致A故障。 給出所有依賴關系,以及當前已知故障服務,要求輸…

git提交代碼報錯Git: husky > pre-commit

目錄 git提交代碼報錯原因解決方法&#xff08;三種&#xff09;1、第一種2、第二種3、第三種 git提交代碼報錯原因 這個問題是因為當你在終端輸入git commit -m “XXX”,提交代碼的時候,pre-commit(客戶端)鉤子&#xff0c;它會在Git鍵入提交信息前運行做代碼風格檢查。如果代…

Kotlin 中密封類、枚舉類與密封接口的對比分析

在 Kotlin 編程語言中&#xff0c;密封類&#xff08;Sealed Classes&#xff09;、枚舉類&#xff08;Enum Classes&#xff09;和密封接口&#xff08;Sealed Interfaces&#xff09;是處理一組固定類型的強大工具。它們在 Kotlin 中扮演著特殊的角色&#xff0c;特別是在創建…