科大讯飞AIUI功能简述

讯飞AIUI功能说明

首先看图

sdk-22.png

最初讯飞只有1→2→4,当AIUI开放后,形成当前的局面,即:

  1. 递交语音到xf-server
  2. 识别递交的语音
  3. 识别结果匹配语义
  4. 返回语音识别结果和匹配语义
    如果需要对匹配语义进行加工处理,那么就多了3-a和3-b步骤,详见
    AIUI后处理开放平台协议 (版本0.3)

概要

本文只对上面流程图1234流程进行测试,3-a和3-b流程再次不做测试。测试源码是通过服务来识别语音,你也可以直接在Activity执行语音识别。

接入指南

在清单中配置如下:
权限
<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" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在清单application中添加KEY
需要申请
<meta-data
android:name="IFLYTEK_APPKEY"
android:value="59a3f271" />

复制so库和jar包

功能组件添加
把从AIUI处下载的SDK解压,然后复制libs文件夹里的如下文件放到工程的libs里
armeabi
----libmsc.so
Msc.jar
Sunflower.jar
加载功能组件
打开model的build.gradle,在defaultConfig{}里添加
    ndk {
        abiFilters "armeabi"
    }
在android{}里添加
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

添加cfg、vad文件夹

在刚才解压的SDK文件夹里,找到assets文件夹复制cfg文件夹,回到android工程,在模块里新建asstes文件夹,把刚才复制的cfg粘贴到asstes里
同样的,把解压的res/vad文件夹复制到刚才提到的位置

文件结构如下:
main
    assets
        cfg
            aiui_phone.cfg
        vad
            meta_vad_16k.jet

Application中初始化

在onCreate中
SpeechUtility.createUtility(getApplicationContext(), SpeechConstant.APPID + "=59a3f271");

开始使用

构造识别代理
* 首先构造AIUI代理。(AIUI功能模块是在原语音识别基础上构造起来的,当识别语音时,返回识别结果,同时也返回讯飞的AI语义匹配结果)
    private boolean checkAIUIAgent() {
        if (null == mAIUIAgent) {
            Log.e(TAG, "create aiui agent");
            mAIUIAgent = AIUIAgent.createAgent(this, getAIUIParams(), mAIUIListener);
            AIUIMessage startMsg = new AIUIMessage(AIUIConstant.CMD_START, 0, 0, null, null);
            mAIUIAgent.sendMessage(startMsg);
            // updateLexicon();// 更新词典
        }

        if (null == mAIUIAgent) {
            Log.e("tag", "【AIRecognizeServer】类的方法:【checkAIUIAgent】: " + "创建 AIUI Agent 失败!");
        }

        return null != mAIUIAgent;
    }
    private String getAIUIParams() {
        String params = "";

        AssetManager assetManager = getResources().getAssets();
        try {
            InputStream ins = assetManager.open("cfg/aiui_phone.cfg");
            byte[] buffer = new byte[ins.available()];

            ins.read(buffer);
            ins.close();

            params = new String(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return params;
    }
  • 识别结果接听器
private AIUIListener mAIUIListener = new AIUIResultListener();

    /**
     * 语音识别和语义数据监听器
     */
    private class AIUIResultListener implements AIUIListener {
        @Override
        public void onEvent(AIUIEvent event) {
            switch (event.eventType) {
                case AIUIConstant.EVENT_WAKEUP:
                    Log.e(TAG, "on event: 进入识别状态" + event.eventType);
                    break;

                case AIUIConstant.EVENT_RESULT: {
                    Log.e(TAG, "on event: " + event.eventType);
                    try {

                        String info = event.info;
//                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "这是处理前内容:" + info);
                        JSONObject bizParamJson = new JSONObject(info);
                        JSONObject data = bizParamJson.getJSONArray("data").getJSONObject(0);
                        JSONObject params = data.getJSONObject("params");
                        JSONObject content = data.getJSONArray("content").getJSONObject(0);

                        if (content.has("cnt_id")) {
                            String cnt_id = content.getString("cnt_id");
                            JSONObject cntJson = new JSONObject(new String(event.data.getByteArray(cnt_id), "utf-8"));

                            Log.e("tag", "【AIUIResultListener】类的方法:【onEvent】: " + cntJson.toString());

                            String sub = params.optString("sub");
                            if ("nlp".equals(sub)) {
                                // 解析得到语义结果
                                String resultStr = cntJson.optString("intent");
                                Log.e("tag", "【AIUIResultListener】类的方法:【onEvent】解析得到语义结果: " + resultStr);
                                // todo 获取到识别后的意图,在这里做你想做的事
                            }
                        }
                    } catch (Throwable e) {
                        e.printStackTrace();
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】:Throwable " + e.getLocalizedMessage());
                    }

                }
                break;

                case AIUIConstant.EVENT_ERROR: {
                    Log.i(TAG, "on event: " + event.eventType + "\n" + "错误: " + event.arg1 + "\n" + event.info);
                }
                break;

                case AIUIConstant.EVENT_VAD: {
                    if (AIUIConstant.VAD_BOS == event.arg1) {
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "找到vad_bos");
                    } else if (AIUIConstant.VAD_EOS == event.arg1) {
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "找到vad_eos");

                    } else {
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + event.arg2);
                    }
                }
                break;

                case AIUIConstant.EVENT_START_RECORD: {
                    Log.e(TAG, "on event: " + event.eventType + " 开始录音");
                }
                break;

                case AIUIConstant.EVENT_STOP_RECORD: {
                    Log.i(TAG, "on event: " + event.eventType + " 停止录音");
                }
                break;

                case AIUIConstant.EVENT_STATE: {    // 状态事件
                    mAIUIState = event.arg1;

                    if (AIUIConstant.STATE_IDLE == mAIUIState) {
                        // 闲置状态,AIUI未开启
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "STATE_IDLE");
                    } else if (AIUIConstant.STATE_READY == mAIUIState) {
                        // AIUI已就绪,等待唤醒
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "STATE_READY");
                    } else if (AIUIConstant.STATE_WORKING == mAIUIState) {
                        // AIUI工作中,可进行交互
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "STATE_WORKING");
                    }
                }
                break;

                case AIUIConstant.EVENT_CMD_RETURN: {
                    if (AIUIConstant.CMD_UPLOAD_LEXICON == event.arg1) {
                        Log.e("tag", "【AIRecognizeServer】类的方法:【onEvent】: " + "上传" + (0 == event.arg2 ? "成功" : "失败"));
                    }
                }
                break;

                default:
                    break;
            }
        }
    }
开启识别功能
    /**
     * 开始识别,语音理解,通过麦克风输入语音,然后识别,识别结束后再调用语义理解
     * 此处开始后就不会主动结束收听,除非触发了语音识别或者主动关闭收听,关闭后需再调用该方法打开收听
     */
    private void startRecognizeNlp() {
        if (checkAIUIAgent()) {
            //
            Log.e(TAG, "start voice nlp");

            // 先发送唤醒消息,改变AIUI内部状态,只有唤醒状态才能接收语音输入
            if (AIUIConstant.STATE_WORKING != this.mAIUIState) {
                AIUIMessage wakeupMsg = new AIUIMessage(AIUIConstant.CMD_WAKEUP, 0, 0, "", null);
                mAIUIAgent.sendMessage(wakeupMsg);
            }

            // 打开AIUI内部录音机,开始录音
            String params = "sample_rate=16000,data_type=audio";
            AIUIMessage writeMsg = new AIUIMessage(AIUIConstant.CMD_START_RECORD, 0, 0, params, null);
            mAIUIAgent.sendMessage(writeMsg);
        }
    }
关闭语音识别功能(可再开启)
    /**
     * 停止语音理解:AIUI 是连续会话,一次 start 后,可以连续的录音并返回结果;要停止需要调用 stop
     */
    private void stopVoiceNlp() {
        Log.e(TAG, "stop voice nlp");
        // 停止录音
        String params = "sample_rate=16000,data_type=audio";
        AIUIMessage stopWriteMsg = new AIUIMessage(AIUIConstant.CMD_STOP_RECORD, 0, 0, params, null);

        mAIUIAgent.sendMessage(stopWriteMsg);
    }

到此,AIUI的功能配置完毕

TTS功能(Text To Speech)

如果你还需要朗读文字功能,可以尝试以下方法:

  • 初始化
mTts = SpeechSynthesizer.createSynthesizer(context, new InitListener() {
            @Override
            public void onInit(int error) {
                // 在API文档里未发现error的值注解。
            }
        });
当然,mTts也可以设置参数,如不设置,默认为机器人朗读,具体设置详见讯飞在/离线语音合成功能
    /**
     * 开始合成语音并播放
     */
    private void startSpeaking() {
        if (mTts != null && !TextUtils.isEmpty(speechText)) {
            mTts.startSpeaking(speechText, synthesizerListener);
        }
    }

    /**
     * 停止语音播放
     */
    private void stopSpeaking() {
        if (mTts != null && mTts.isSpeaking()) {
            mTts.stopSpeaking();
        }
    }

    /**
     * 恢复播放
     */
    private void resumeSpeaking() {
        if (mTts != null && !mTts.isSpeaking()) {
            mTts.resumeSpeaking();
        }
    }

    /**
     * 暂停语音播放
     */
    private void pauseSpeaking() {
        if (mTts != null && mTts.isSpeaking()) {
            mTts.pauseSpeaking();
        }
    }

    /**
     * 释放语音合成功能对象
     */

    private void destroyTTS() {
        if (null != mTts) {
            mTts.stopSpeaking();
            // 退出时释放连接
            mTts.destroy();
        }
    }

附件

源码地址
科大讯飞AIUI 帮助文档

参考文档

科大讯飞AIUI开放平台

目前国内还是有较多的语音识别大厂
讯飞、百度语音、搜狗语音、若琪语音开放平台、思必驰,阿里云语音识别,出门问问等

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容