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.mzph.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;特别是在创建…