离线命令词识别

  • 效果图

  • 示例源码

地址:http://download.csdn.net/detail/q4878802/9023825

步骤:

1. 下载SDK

前面文章有,就不在复述了。这里要选择离线命令词的服务以后,重新加载,因为需要下载离线命令词识别的资源文件

地址:http://blog.csdn.net/q4878802/article/details/47762169

2. 集成方法

前面文章有,就不在复述了。

地址:http://blog.csdn.net/q4878802/article/details/47778629

3. 正题,开始集成

1. 添加权限

这里用到的唤醒功能不是所有的权限都用到的,具体用到了哪些权限,可以看上面的链接,用到哪写权限就加哪些权限,这个为了快速方便测试,把讯飞用到的权限都加上了。

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2. 初始化appid

我是将appid的初始化放在的Applicaiton下,具体可以下载源码

// 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null
// 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton
// 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true"
// 参数间使用“,”分隔。
// 设置你申请的应用appid
StringBuffer param = new StringBuffer();
param.append("appid=55d33f09");
param.append(",");
param.append(SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC);
// param.append(",");
// param.append(SpeechConstant.FORCE_LOGIN + "=true");
SpeechUtility.createUtility(InitKqwSpeech.this, param.toString()); 

3. 工具类

package com.example.kqwspeechdemo2.utils;import java.io.InputStream;
import android.content.Context;
import android.util.Log;/*** 功能性函数扩展类* * @author kongqw* */
public class FucUtil {// Log标签private static final String TAG = "FucUtil";/*** 读取asset目录下文件内容* * @return content*/public static String readFile(Context mContext, String file, String code) {int len = 0;byte[] buf = null;String result = "";try {InputStream in = mContext.getAssets().open(file);len = in.available();buf = new byte[len];in.read(buf, 0, len);result = new String(buf, code);} catch (Exception e) {Log.e(TAG, e.toString());e.printStackTrace();}return result;}}

4. 构建语法文件的工具类

package com.example.kqwspeechdemo2.engine;import com.example.kqwspeechdemo2.utils.FucUtil;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.GrammarListener;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;/*** 构建离线命令词语法* * @author kongqw* */
public abstract class BuildLocalGrammar {/*** 构建语法的回调* * @param errMsg*            null 构造成功*/public abstract void result(String errMsg, String grammarId);// Log标签private static final String TAG = "BuildLocalGrammar";public static final String GRAMMAR_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/msc/test";// 上下文private Context mContext;// 语音识别对象private SpeechRecognizer mAsr;public BuildLocalGrammar(Context context) {mContext = context;// 初始化识别对象mAsr = SpeechRecognizer.createRecognizer(context, new InitListener() {@Overridepublic void onInit(int code) {Log.d(TAG, "SpeechRecognizer init() code = " + code);if (code != ErrorCode.SUCCESS) {result(code + "", null);Log.d(TAG, "初始化失败,错误码:" + code);Toast.makeText(mContext, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();}}});};/*** 构建语法* * @return*/public void buildLocalGrammar() {try {/** TODO 如果你要在程序里维护bnf文件,可以在这里加上你维护的一些逻辑* 如果不嫌麻烦,要一直改bnf文件,这里的代码可以不用动,不过我个人不建议一直手动修改bnf文件* ,内容多了以后很容易出错,不好找Bug,建议每次改之前先备份。 建议用程序维护bnf文件。*//** 构建语法*/String mContent;// 语法、词典临时变量String mLocalGrammar = FucUtil.readFile(mContext, "kqw.bnf", "utf-8");mContent = new String(mLocalGrammar);mAsr.setParameter(SpeechConstant.PARAMS, null);// 设置文本编码格式mAsr.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");// 设置引擎类型mAsr.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);// 设置语法构建路径mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, GRAMMAR_PATH);// 使用8k音频的时候请解开注释// mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");// 设置资源路径mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());// 构建语法int ret = mAsr.buildGrammar("bnf", mContent, new GrammarListener() {@Overridepublic void onBuildFinish(String grammarId, SpeechError error) {if (error == null) {Log.d(TAG, "语法构建成功");result(null, grammarId);} else {Log.d(TAG, "语法构建失败,错误码:" + error.getErrorCode());result(error.getErrorCode() + "", grammarId);}}});if (ret != ErrorCode.SUCCESS) {Log.d(TAG, "语法构建失败,错误码:" + ret);result(ret + "", null);}} catch (Exception e) {e.printStackTrace();}}// 获取识别资源路径private String getResourcePath() {StringBuffer tempBuffer = new StringBuffer();// 识别通用资源tempBuffer.append(ResourceUtil.generateResourcePath(mContext, RESOURCE_TYPE.assets, "asr/common.jet"));// 识别8k资源-使用8k的时候请解开注释// tempBuffer.append(";");// tempBuffer.append(ResourceUtil.generateResourcePath(this,// RESOURCE_TYPE.assets, "asr/common_8k.jet"));return tempBuffer.toString();}}

5. 命令词识别工具类

package com.example.kqwspeechdemo2.engine;import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;/*** 命令词识别* * @author kongqw* */
public abstract class KqwSpeechRecognizer {/*** 初始化的回调* * @param flag*            true 初始化成功 false 初始化失败*/public abstract void initListener(boolean flag);public abstract void resultData(String data);public abstract void speechLog(String log);// Log标签private static final String TAG = "KqwLocalCommandRecognizer";public static final String GRAMMAR_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/msc/test";// 上下文private Context mContext;// 语音识别对象private SpeechRecognizer mAsr;public KqwSpeechRecognizer(Context context) {mContext = context;// 初始化识别对象mAsr = SpeechRecognizer.createRecognizer(context, new InitListener() {@Overridepublic void onInit(int code) {Log.d(TAG, "SpeechRecognizer init() code = " + code);if (code != ErrorCode.SUCCESS) {initListener(false);Toast.makeText(mContext, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();} else {initListener(true);}}});}/*** 参数设置*/public void setParam() {// 清空参数mAsr.setParameter(SpeechConstant.PARAMS, null);// 设置识别引擎 本地引擎mAsr.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);// mAsr.setParameter(SpeechConstant.ENGINE_TYPE,// SpeechConstant.TYPE_MIX);// mAsr.setParameter(SpeechConstant.ENGINE_TYPE, "mixed");// // 设置本地识别资源mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());// 设置语法构建路径mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, GRAMMAR_PATH);// 设置返回结果格式mAsr.setParameter(SpeechConstant.RESULT_TYPE, "json");// 设置本地识别使用语法idmAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "kqw");// 设置识别的门限值mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "60");// 使用8k音频的时候请解开注释// mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");mAsr.setParameter(SpeechConstant.DOMAIN, "iat");mAsr.setParameter(SpeechConstant.NLP_VERSION, "2.0");mAsr.setParameter("asr_sch", "1");// mAsr.setParameter(SpeechConstant.RESULT_TYPE, "json");}// 获取识别资源路径private String getResourcePath() {StringBuffer tempBuffer = new StringBuffer();// 识别通用资源tempBuffer.append(ResourceUtil.generateResourcePath(mContext, RESOURCE_TYPE.assets, "asr/common.jet"));// 识别8k资源-使用8k的时候请解开注释// tempBuffer.append(";");// tempBuffer.append(ResourceUtil.generateResourcePath(this,// RESOURCE_TYPE.assets, "asr/common_8k.jet"));return tempBuffer.toString();}int ret = 0;// 函数调用返回值/*** 开始识别*/public void startListening() {// 设置参数setParam();ret = mAsr.startListening(mRecognizerListener);if (ret != ErrorCode.SUCCESS) {Log.i(TAG, "识别失败,错误码: " + ret);}}/*** 识别监听器。*/private RecognizerListener mRecognizerListener = new RecognizerListener() {StringBuffer stringBuffer = new StringBuffer();public void onVolumeChanged(int volume) {Log.i(TAG, "当前正在说话,音量大小:" + volume);speechLog("当前正在说话,音量大小:" + volume);}@Overridepublic void onResult(final RecognizerResult result, boolean isLast) {/** TODO 拼接返回的数据* * 这里返回的是Json数据,具体返回的是离线名命令词返回的Json还是语义返回的Json,需要做判断以后在对数据数据进行拼接*/stringBuffer.append(result.getResultString()).append("\n\n");// isLast为true的时候,表示一句话说完,将拼接后的完整的一句话返回if (isLast) {// 数据回调resultData(stringBuffer.toString());}}@Overridepublic void onEndOfSpeech() {Log.i(TAG, "结束说话");speechLog("结束说话");}@Overridepublic void onBeginOfSpeech() {stringBuffer.delete(0, stringBuffer.length());Log.i(TAG, "开始说话");speechLog("开始说话");}@Overridepublic void onError(SpeechError error) {Log.i(TAG, "error = " + error.getErrorCode());if (error.getErrorCode() == 20005) {// 本地命令词没有识别,也没有请求到网络resultData("没有构建的语法");speechLog("没有构建的语法");/** TODO* 当网络正常的情况下是不会回调20005的错误,只有当本地命令词识别不匹配,网络请求也失败的情况下,会返回20005* 这里可以自己再做处理,例如回复“没有听清”等回复*/} else {/** TODO* 其他错误有很多,需要具体问题具体分析,正常在程序没有错误的情况下,只会回调一个没有检测到说话的错误,没记错的话错误码是10118*/}}@Overridepublic void onEvent(int eventType, int arg1, int arg2, Bundle obj) {Log.i(TAG, "eventType = " + eventType);}};}

这里的识别引擎设置的是SpeechConstant.TYPE_LOCAL,这种是本地识别引擎,只走本地识别,不走网络,如果换成SpeechConstant.TYPE_MIX,就是混合引擎,这种引擎方式,当本地没有识别到语法,返回20005错误码的时候,会直接请求语义接口,如果你语义开通了对应的场景,会走网络把你的语音转为语义,如果没有开通对应的场景,会把语音转为文字。

6. 测试类

package com.example.kqwspeechdemo2;import com.example.kqwspeechdemo2.engine.BuildLocalGrammar;
import com.example.kqwspeechdemo2.engine.KqwSpeechRecognizer;import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends Activity {private TextView mTvResult;private TextView mTvLog;private BuildLocalGrammar buildLocalGrammar;private KqwSpeechRecognizer kqwSpeechRecognizer;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTvResult = (TextView) findViewById(R.id.tv_result);mTvLog = (TextView) findViewById(R.id.tv_log);/*** 初始化本地语法构造器*/buildLocalGrammar = new BuildLocalGrammar(this) {@Overridepublic void result(String errMsg, String grammarId) {// errMsg为null 构造成功if (TextUtils.isEmpty(errMsg)) {Toast.makeText(MainActivity.this, "构造成功", Toast.LENGTH_SHORT).show();} else {Toast.makeText(MainActivity.this, "构造失败", Toast.LENGTH_SHORT).show();}}};/*** 初始化离线命令词识别器*/kqwSpeechRecognizer = new KqwSpeechRecognizer(this) {@Overridepublic void speechLog(String log) {// 录音Log信息的回调mTvLog.setText(log);}@Overridepublic void resultData(String data) {// 是识别结果的回调mTvResult.setText(data);}@Overridepublic void initListener(boolean flag) {// 初始化的回调if (flag) {Toast.makeText(MainActivity.this, "初始化成功", Toast.LENGTH_SHORT).show();} else {Toast.makeText(MainActivity.this, "初始化失败", Toast.LENGTH_SHORT).show();}}};/*** 构造本地语法文件,只有语法文件有变化的时候构造成功一次即可,不用每次都构造*/buildLocalGrammar.buildLocalGrammar();}/*** 开始识别按钮* * @param view*/public void start(View view) {mTvResult.setText(null);// 开始识别kqwSpeechRecognizer.startListening();}}

7. 界面布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.example.kqwspeechdemo2.MainActivity" ><Button
        android:id="@+id/bt_start"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:onClick="start"android:text="开始录音" /><TextView
        android:id="@+id/tv_log"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_above="@id/bt_start"android:gravity="center"android:text="录音信息" /><ScrollView
        android:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@id/tv_log" ><TextView
            android:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="返回结果" /></ScrollView></RelativeLayout>

8. BNF语法文件

#BNF+IAT 1.0 UTF-8;
!grammar kqw;
!slot <contact>;
!slot <callPre>;
!slot <callPhone>;
!slot <callTo>;
!slot <go>;
!slot <position>;!slot <move>;!start <callStart>;
<callStart>:
[<callPre>][<callTo>]<contact><callPhone>
|[<callPre>]<callPhone>[<callTo>]<contact>
|[<callPre>]<callPhone>|<move>|<go><position>;<contact>:庆威|小孔;
<callPre>:我要|我想|我想要;
<callPhone>:打电话;
<callTo>:给;<move>:前进|后退|左转|右转;<go>:去|到;
<position>:厨房|卧室|阳台|客厅;

在构建语法的时候,我们不是必要在assets目录下创建一个xxx.bnf文件,构建的时候我们只要能够拿到满足BNF语法文件的字符串就行,至于这个文件内容,你存在哪都无所谓,在程序里写死、存sp、数据库、自己程序维护都OK,只要满足BNF的语法就行。

BNF语法开发指南

下载地址:http://download.csdn.net/detail/q4878802/9023791

最后

  1. 如果你直接用我的Demo,我用的是测试版的离线包,只有35天的试用期,而且装机量只有3个,如果大家都用,很可能是不能正常运行的
  2. 如果是参考我的demo自己写一个,千万不要忘记替换appid和资源文件。

讯飞语音——离线命令词识别相关推荐

  1. 讯飞语音——离线命令词+语义识别

    讯飞语音--离线命令词+语义识别 意思就是先走离线命令词识别,如果离线命令词识别没有识别到结果,那么就再走语义接口,如果已开通对应场景,则转为语义,如果没有开通对应场景,则将语音转为文字 效果图 说的 ...

  2. 离线语音识别软件_6.语音板使用科大讯飞离线命令词识别

    0x00 离线命令词识别简介 语音识别技术(Auto Speech Recognize,简称ASR),就是把人的自然语言音频数据转换成文本数据的技术.理论上在线ASR是可以把所有的语音转换成对应的文本 ...

  3. 搜狗语音输入提示服务器繁忙,讯飞语音输入如何提高识别率 提高方法

    讯飞语音是一款语音输入软件,能够帮助用户进行通过语音说话,进行智能识别,帮助用户在繁忙的时候,直接语音输入,不过语言描述要清晰哦!小编在这里分享一下识别率提高方法,不要错过哦! 讯飞语音输入如何提高识 ...

  4. 科大讯飞离线命令词识别

    一.进入科大讯飞官网,下载自己所需要的SDK----以离线命令词识别为例: 二.分析代码-----主要有以下四大函数 const char *get_audio_file(void); //选择进行离 ...

  5. 【C++】QT调用VS封装的dll(以科大讯飞离线命令词识别SDK为例)

    QT调用VS封装的dll(以科大讯飞离线命令词识别SDK为例) 1.说明: 跨平台调用dll出现各种坑,谨以此文避坑. 参考博文:https://www.cnblogs.com/seer/p/4789 ...

  6. 离线命令词识别 (基于ASRT HTTP)

    文章目录 ASRT 环境配置 前端音频处理 音频文件格式标准 音频采集流程 命令关键字识别 主要有三部分 大概流程 示例demo asrt-vue-demo ASRT 环境配置 项目地址 https: ...

  7. 讯飞语音唤醒和语义识别同时使用,错误代码20006的解决方法

    今天测试了一下语音唤醒和语义识别,在我Android5.1的手机上用着好好的,换了一台Android6.0的设备就不能用了,报了一个20006的错误,这个错误的官方解释是"录音失败没有录音权 ...

  8. 讯飞离线语音命令词识别

    讯飞离线语音命令词识别 强烈推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来! 网址:http://www.captainbed.net/yancyang ...

  9. 科大讯飞离线语音命令词识别的使用说明

        最近因为项目的需求,需要在无网络的情况下实现语音识别的功能,因为之前在线识别一直用的科大的,所以经理就和我说,你花半天时间简单熟悉一下,然后出一个Demo,下午有人过来看:因为之前科大在线SR ...

最新文章

  1. JS实现复制到剪切板效果
  2. 字符串作为freemarker模板的简单实现例子
  3. 用PHP删除一条记录mysql,php – 如何使用jquery删除mysql记录
  4. 自适应设计与响应式设计
  5. leetcode 399. 除法求值(bfs)
  6. 生成html报告并整合自动发动邮件功能
  7. SpringCloud的Eureka客户端(解决自动退出问题)
  8. 子目录 makefile make和clean
  9. 苹果Mac出版物设计必备软件:​​​​Affinity Publisher
  10. 如何在苹果Mac上通过通知中心禁用通知?
  11. 改写自SqlHelper的SqliteHelper
  12. dbutilsjar包下载_commons dbutils 下载-commons dbutils.jar下载 v1.6官方版--pc6下载站
  13. 系统设计时要考虑哪些方面?
  14. matlab图像取样和量化,数字图像基础之图像取样和量化
  15. 删除 linux的ln文件夹,详解Linux ln 命令
  16. H5性能测试(优化建议)
  17. canvas中getContext(“2d“) 对象的属性和方法
  18. 利用CSS制作通栏,css6——通栏平均分布
  19. mysql 下一年_mysql时间增加一年
  20. 4k水面折射maya循环纹理支持arnold

热门文章

  1. QT::QBitArray
  2. 论文笔记:Parallel Tracking and Verifying: A Framework for Real-Time and High Accuracy Visual Tracking...
  3. 为什么你会被限制登录网页版微信?
  4. [hadoop那些事]hadoop及其组件资源 115/百度云
  5. 关于微信防撤回(文本、图片、语音、视频、名片等...)的Python学习教程
  6. 基金的估值原来这么简单,一文看懂
  7. QT OpenCV人脸考勤识别
  8. css使两个盒子并列_CSS常见面试题
  9. Navicata查看已经创建MySql的触发器
  10. 高斯消元法(高斯·约当消元法)(浮点)