讯飞语音命令词识别的SDK配置与运用

之前一直想开始写技术博客,倒不是说自己有多牛,只是觉得自己弄了点东西出来想和大家分享,而且听说有利于自己技术水平的提高,就权当是一次记录吧,这是第一篇。

之前因为一次比赛App要用到语音识别,做一个通过手机输入语音指令然后根据输入内容做出响应的功能,当时请教了一下别人决定采用科大讯飞的在线命令词识别工程集成的SDK,当时先申请Appid,再下载SDK。(这里推荐大家先到讯飞官方平台上下载资料,资料上写得很详细,我这里主要写一些自己遇到的问题)

第一步:配置jar包和.so文件,在这一步卡了一下,现在网上大部分资料还是关于eclipse软件上的配置,现在大部分都使用AS,在这里推荐一篇博客文章,当时就是靠大神的方法配置完的http://blog.csdn.net/yy1300326388/article/details/46422939#comments
我的配置完是这样的,具体以官方文档为准这里写图片描述

第二步:在工程AndroidManifest.xml文件中添加权限,参考官方下载的文件里的doc/MSC Develop Manual for Android文件这里写图片描述

第三步:初始化,同上。我是通过先创建一个类继承自Application 如图
忘记自己申请的appid可以上官网查这里写图片描述,接着在AndroidManifest.xml文件中配置新建的class为应用程序入口:主要是改变android:name这里写图片描述这里写图片描述

第四步:可以开始编写代码了,我所需要使用的功能是命令词识别功能,目前讯飞的离线语音识别功能需要收费,所以我使用的是在线的,但是两者代码相差不大。

(1)在线命令词识别需要先编写命令词语法文件,采用ABNF语法格式,官网上有详尽的资料,我们用记事本按照规定格式编写后上传到官网上就可以了,这里附上我的语法文件截图:主要修改 main command
这里写图片描述
(2)接下来直接贴代码,大部分都是官方demo:

//语音听写UI初始化
   // private RecognizerDialog mRecognizerDialog;
    //创建SpeechRecognizer,语音识别对象
    private SpeechRecognizer mSpeechRecognizer;

    //缓存
    private SharedPreferences mSharedPreferences;
    //云端语法文件
    private String mCloudGrammar = null;

    private static final String KEY_GRAMMAR_ABNF_ID = "grammar_abnf_id";
    private static final String GRAMMAR_TYPE_ABNF = "abnf";
    private static final String GRAMMAR_TYPE_BNF = "bnf";

    //引擎类型
    private String mEngineType = null;
    //语法,词典临时变量
    String mContent;
    //函数调用返回值
    int ret = 0 ;

接着在onCreate()中

button_voice = (Button)findViewById(R.id.button_voice);
        button_voice.setOnTouchListener(this);

        //语音识别引擎类型为云端
        mEngineType = SpeechConstant.TYPE_CLOUD;

        //创建SpeechRecognizedr对象,并初始化,注意不要导入错误的SpeechRecognizer
        mSpeechRecognizer = SpeechRecognizer.createRecognizer(RgbActivity.this,mInitListener);

        //初始化语法,命令词(FucUtil在下面)
        mCloudGrammar = FucUtil.readFile(this,"Command.abnf","utf-8");
        mContent = new String(mCloudGrammar);

        //设置指定引擎类型
        mSpeechRecognizer.setParameter(SpeechConstant.ENGINE_TYPE,"cloud");
        mSpeechRecognizer.setParameter(SpeechConstant.SUBJECT,"asr");
        ret = mSpeechRecognizer.buildGrammar(GRAMMAR_TYPE_ABNF,mContent,mCloudGrammarlistener);
        if (ret != ErrorCode.SUCCESS){
            LogUtil.e(TAG,"语音语法构建失败,错误码:"+ ret);

        }

语音识别的按钮的触碰监听:

 //语音识别按钮的触碰监听
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                //开始识别
                ret = mSpeechRecognizer.startListening(mRecognizerListener);
                //ToastUtils工具类,自定义Toast3500ms内显示时间
               ToastUtils.makeText(getApplicationContext(), "开始识别", 500);
                if(ret != ErrorCode.SUCCESS){
                    LogUtil.e(TAG,"识别失败,错误码:"+ret);
                }
                button_voice.setAlpha((float)0.5);
                break;
            case MotionEvent.ACTION_UP:
                //停止识别
                mSpeechRecognizer.stopListening();
               ToastUtils.makeText(getApplicationContext(), "停止识别", 500);
                button_voice.setAlpha((float) 1);
                break;
            case MotionEvent.ACTION_CANCEL:
            ToastUtils.makeText(getApplicationContext(),"识别取消",500);
                break;
            case MotionEvent.ACTION_BUTTON_PRESS:
                break;

        }
        return false;
    }

初始化监听器:

//初始化监听器
    private InitListener mInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            LogUtil.e(TAG, "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS){
                LogUtil.e(TAG,"mInitListener 初始化失败,错误码:"+code);
            }
        }
    };

云端构建语法监听器:

//云端构建语法监听器
    private GrammarListener mCloudGrammarlistener = new GrammarListener() {
        @Override
        public void onBuildFinish(String grammarId, SpeechError speechError) {
            if (speechError == null){
                String grammarID = new String(grammarId);
                Editor editor = mSharedPreferences.edit();
                if (!TextUtils.isEmpty(grammarId)){
                    editor.putString(KEY_GRAMMAR_ABNF_ID,grammarID);}
                editor.commit();
                LogUtil.e(TAG,"mCloudGrammarlistener 语法构建成功:"+grammarId);
            }else {
                LogUtil.e(TAG,"语法构建失败错误码:"+speechError.getErrorCode());
            }
        }
    };

识别监听器

//识别监听器
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
        //音量变化回调
        @Override
        public void onVolumeChanged(int i, byte[] bytes) {
            //在此添加动画
            LogUtil.e(TAG,"返回音频数据:"+ bytes.length);
        }
        //开始说话
        @Override
        public void onBeginOfSpeech() {}
        //结束说话
        @Override
        public void onEndOfSpeech() {}
        //返回结果
        @Override
        public void onResult(RecognizerResult recognizerResult, boolean b) {
            LogUtil.e(TAG, "调用了onResult....................");
            if (recognizerResult != null){
                LogUtil.e(TAG ,"recognizer Result:" + recognizerResult.getResultString());
                String text;
                //JsonParser:Json解析(代码在下方),text为解析出的命令词
                text = JsonParser.parseGramarResult(recognizerResult.getResultString());

                switch(text){
                    case "开灯":
                        break;
                    case "关灯":
                        break;
                     case "求救":
                        break;
                    case "安全":
                        break;
                    case "变亮":
                        break;
                    case "变暗":
                        break;
                    case "进餐":
                        break;
                    case "阅读":
                        break;
                    case "睡觉":
                        break;
                    case "复位":
                        break;
                    default:
                        Toast.makeText(getApplicationContext(),"无法匹配命令词,请重新发送命令",Toast.LENGTH_SHORT).show();
                }
            }else{
                LogUtil.e(TAG,"recognizerResult为null....................");
            }
        }
        //错误回调
        @Override
        public void onError(SpeechError speechError) {
            LogUtil.e("mRecognizerListener","出错,错误代码:"+speechError.getErrorCode());
            Toast.makeText(getApplicationContext(),"出错,错误代码:"+speechError.getErrorCode(),Toast.LENGTH_SHORT).show();
        }
        //事件回调
        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {}
    };

FucUtil:

public class 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){
            e.printStackTrace();
        }
        return result;

    }
}

JsonParser:

public class JsonParser {
    public static String TAG = "JsonParser";
    public static int index = 0;

    public static String parseGramarResult(String json){
        StringBuffer ret = new StringBuffer() ;

        try{
            JSONTokener mJSONTokener = new JSONTokener(json);
            JSONObject  mJSONObject = new JSONObject(mJSONTokener);

            JSONArray words = mJSONObject.getJSONArray("ws");
            for (int i = 0 ; i < words.length(); i++){
                JSONArray items = words.getJSONObject(i).getJSONArray("cw");
                for (int j = 0 ; j < items.length() ; j++){
                    JSONObject obj = items.getJSONObject(j);
                    if (obj.getString("w").contains("nomatch")){
                        ret.append("没有匹配结果");
                        return ret.toString();
                    }
                    //ret=命令词 置信度 命令词 置信度
                    ret.append(obj.getString("w"));
                    ret.append(obj.getInt("sc"));

                }
            }
        }catch (Exception e){
            e.printStackTrace();
            ret.append("没有匹配结果");
        }

        for (; index < ret.length();index++){
            //判断ret的内容,找到最接近的命令词,isDigit判断字符是否是数字,是数字则跳出循环
            if(Character.isDigit(ret.charAt(index)))
                break;
        }
        //retCommand = 最匹配的命令词
        String retCommand = ret.substring(0, index);

        LogUtil.e(TAG, "Json解析结果:    " + ret);
        LogUtil.e(TAG, "retComand:      " + retCommand);
        return retCommand;

    }
}

ToasrUtil(3500ms内自定义Toast显示时间)

public class ToastUtils{
    public static void makeText(Context mContext,String mString,final int time){

        final Toast mToast = Toast.makeText(mContext,mString,Toast.LENGTH_LONG);
        mToast.show();
        Handler mHandler = new Handler();
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (time <= 3500){
                    mToast.cancel();
                }
            }
        },time);

    }
}

LogUtil:类似于Log,设定规格,编写调试时开启,完成编译成apk时设置LEVEL为NOTHING,出自郭霖大神《第一行代码》

public class LogUtil {

    public static final int VERBOSE = 1;

    public static final int DEBUG = 2;

    public static final int INFO = 3;

    public static final int WARN = 4;

    public static final int ERROR = 5;

    public static final int NOTHING = 6;

    //测试时LEVEL=VERBOSE,上架后LEVEL=NOTHING
    public static final int LEVEL = VERBOSE;

    public static void v(String tag,String msg){
        if (LEVEL <= VERBOSE){
            Log.v(tag,msg);
        }
    }

    public static void d(String tag,String msg){
        if (LEVEL <= DEBUG){
            Log.d(tag, msg);
        }
    }

    public static void i(String tag,String msg){
        if (LEVEL <= INFO){
            Log.i(tag, msg);
        }
    }

    public static void w(String tag,String msg){
        if (LEVEL <= WARN){
            Log.w(tag, msg);
        }
    }

    public static void e(String tag,String msg){
        if (LEVEL <= ERROR){
            Log.e(tag,msg);
        }
    }


}

这次记录到此已经结束了,大家转载的话说明原址,有哪里做得不好或者不对也希望大家不吝赐教。。。万分感谢

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值