首页 > 代码库 > 语音识别,语义理解一站式解决之二(android,olami)

语音识别,语义理解一站式解决之二(android,olami)

转载请注明CSDN地址:http://blog.csdn.net/ls0609/article/details/72765789

语音在线听书demo:http://blog.csdn.net/ls0609/article/details/71519203

前言

国内语音识别技术已有多家,而olami不仅在语音识别上准确率较高,更重要的是在语义理解上十分强大,本文用olami sdk做了一个记账demo(记账部分代码参考开源代码),这个demo可以语音添加不同消费记录,查询当天,当月消费情况,删除消费列表中的记录。让我们一起来感受下olami如何实现强大的语义理解。

1.demo支持的说法

demo中实现的说法主要有如下几种(同类说法可以很多,没有全部列举):

今天餐饮开销一百元 
今日交通出行五十元 
本月15号日常购物一百元 
这个月水电煤气两百元 
查询今天的账单 
查看今日的消费情况 
今天的账单 
今日消费 
查询这个月的消费情况 
查看本月消费 
本月的账单 
删除第一条 
删除第一个记录 
删除第五条消费记录

2. demo实现的效果图

技术分享

技术分享

3.olami的初始化和回调用法

初始化部分参考源码MainActivity.Java中init()函数

public void init()    {        initHandler();        mOlamiVoiceRecognizer = new OlamiVoiceRecognizer(MainActivity.this);        TelephonyManager telephonyManager=(TelephonyManager)this.getSystemService                                          (this.getBaseContext().TELEPHONY_SERVICE);        String imei=telephonyManager.getDeviceId();        mOlamiVoiceRecognizer.init(imei);//set null if you do not want to notify olami server.        mOlamiVoiceRecognizer.setListener(mOlamiVoiceRecognizerListener);//设置识别结果回listener        mOlamiVoiceRecognizer.setLocalization        (OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE);//设置支持的语音类型,优先选择中文简体        mOlamiVoiceRecognizer.setAuthorization(        "573031596fd746fca478e5cccf6ca9e2","asr","d5307ed38df64ab6a08e467c00c81d37","nli");        //注册Appkey,在olami官网注册应用后生成的appkey        //注册api,请直接填写“asr”,标识语音识别类型        //注册secret,在olami官网注册应用后生成的secret        //注册seq ,请填写“nli”              mOlamiVoiceRecognizer.setVADTailTimeout(2000);//录音时尾音结束时间,建议填//2000ms        mOlamiVoiceRecognizer.setLatitudeAndLongitude(31.155364678184498,121.34882432933009);        //设置经纬度信息,不愿上传位置信息,可以填0    }


注册一个回调,用于各种回调,可以更新界面和处理服务器返回数据。


private class OlamiVoiceRecognizerListener implements IOlamiVoiceRecognizerListener{        @Override        public void onError(int errCode) {//出错回调            mHandler.sendMessage(mHandler.obtainMessage(                                 MessageConst.CLIENT_ACTION_ON_ERROR,errCode,0));        }        @Override        public void onEndOfSpeech() {//录音结束回调            mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_STOP_RECORED);                }        @Override        public void onBeginningOfSpeech() {//录音开始回调            mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_START_RECORED);                    }        @Override        public void onResult(String result, int type) {//结果返回回调            mHandler.sendMessage(mHandler.obtainMessage(                           MessageConst.SERVER_ACTION_RETURN_RESULT, type, 0, result));        }        @Override        public void onCancel() {//取消录音回调            mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_CANCEL_RECORED);        }        @Override        public void onUpdateVolume(int volume) {//实时返回音量回调            mHandler.sendMessage(mHandler.obtainMessage(                           MessageConst.CLIENT_ACTION_UPDATA_VOLUME, volume, 0, null));        }    }

4.服务器返回结果及解析

本月15号日常购物200元,服务器返回数据如下:

[  {    "desc_obj": {      "result": "正在为您添加",      "status": 0    },    "semantic": [      {        "app": "account",        "input": "本月15号日常购物200元",        "slots": [          {            "num_detail": {              "recommend_value": "200",              "type": "number"            },            "name": "pay_number",            "value": "200"          },          {            "name": "pay_type",            "value": "日常购物"          },          {            "num_detail": {              "recommend_value": "15",              "type": "number"            },            "name": "day",            "value": "15"          }        ],        "modifier": [          "pay"        ],        "customer": "58df512384ae11f0bb7b487e"      }    ],    "type": "account"  } ]


删除第一个记录, 服务器返回数据如下:

[  {    "desc_obj": {      "result": "正在为您删除",      "status": 0    },    "semantic": [      {        "app": "account",        "input": "删除第一个记录",        "slots": [          {            "num_detail": {              "recommend_value": "1",              "type": "number"            },            "name": "index",            "value": "一"          }        ],        "modifier": [          "delete_today"        ],        "customer": "58df512384ae11f0bb7b487e"      }    ],    "type": "account"  } ]


来看一下代码是如何解析的:


private void processServerMessage(String message) {        try{            String input = null;            JSONObject jsonObject = new JSONObject(message);            JSONArray jArrayNli = jsonObject.optJSONObject("data").optJSONArray("nli");            JSONObject jObj = jArrayNli.optJSONObject(0);            JSONArray jArraySemantic = null;            if(message.contains("semantic"))            {              jArraySemantic = jObj.getJSONArray("semantic");              input = jArraySemantic.optJSONObject(0).optString("input");            }            else{                input = jsonObject.optJSONObject("data").                                    optJSONObject("asr").optString("result");            }            JSONObject jObjSemantic;            JSONArray jArraySlots;            JSONArray jArrayModifier;            String type = null;            String pay_number = null;            String pay_type = null;            String day = null;            if(jObj != null) {                type = jObj.optString("type");                if("account".equals(type))//应用的名称是account,代表记账应用                {                    jObjSemantic = jArraySemantic.optJSONObject(0);                    input = jObjSemantic.optString("input");                    jArraySlots = jObjSemantic.optJSONArray("slots");                    jArrayModifier = jObjSemantic.optJSONArray("modifier");                    String modifier = (String)jArrayModifier.opt(0);                    if((jArrayModifier != null) && ("pay".equals(modifier)))                    {//modifier为pay,代表行为是记账                        if(jArraySlots != null)                        {                           for(int i=0,k=jArraySlots.length(); i<k; i++)                           {                               JSONObject obj = jArraySlots.getJSONObject(i);                               String name = obj.optString("name");                               if("pay_type".equals(name))                                   pay_type = obj.optString("value");                               else if("pay_number".equals(name))                               {//找出记录的具体金额                                   pay_number = obj.getJSONObject("num_detail").                                                 getString("recommend_value");                               }                               else if("day".equals(name))                               {//找出某日发生消费的金额                                   day = obj.getJSONObject("num_detail").                                                 getString("recommend_value");                               }                           }                        }                        String date = null;                        Calendar localCalendar = Calendar.getInstance();                        int i_year = localCalendar.get(Calendar.YEAR);                        int i_month = localCalendar.get(Calendar.MONTH)+1;                        int i_day = localCalendar.get(Calendar.DAY_OF_MONTH);                         if(day == null)                         {                             date = i_year + "-" + i_month + "-" + i_day;                         }                         else                         {                             date = i_year + "-" + i_month + "-" + day;                         }                         consumeClass trade = new consumeClass(0,                                             Float.parseFloat("-"+pay_number),                                             date, "123", pay_type,  MainActivity.this);                                                                   trade.trade_add();                                             //添加到消费列表中                    }                    else if((jArrayModifier != null) && ("query_today".equals(modifier)))                    {                          QueryByTodayActivity.refreshListView(                                                 QueryByTodayActivity.QUERY_BY_DAY);                       //查询当天的消费情况,并更新列表                                              }                    else if((jArrayModifier != null) && ("query_month".equals(modifier)))                    {                          QueryByTodayActivity.refreshListView(                                                    QueryByTodayActivity.QUERY_BY_MONTH);                         //查询当月的消费情况,并更新列表                                                                          }else if((jArrayModifier != null) && ("delete_today".equals(modifier)))                    {//找出要删除的消费记录的索引,删除并更新界面                        String index = null;                        if(jArraySlots != null)                        {                                                   JSONObject obj = jArraySlots.getJSONObject(0);                                                       index = obj.getJSONObject("num_detail").                                          getString("recommend_value");                                                                          }                        if(index != null && !"".equals(index))                            QueryByTodayActivity. deleteTodayDataByIndex(                                                      Integer.parseInt(index));                                                                    }                }            }        }        catch(Exception e)        {            e.printStackTrace();        }                      }

5.源码下载链接

语音记账demo下载

6.相关链接

语音在线听书博客:http://blog.csdn.net/ls0609/article/details/71519203

olami开放平台语法编写简介:http://blog.csdn.net/ls0609/article/details/71624340

olami开放平台语法官方介绍:https://cn.olami.ai/wiki/?mp=nli&content=nli2.html


本文出自 “ls0609” 博客,请务必保留此出处http://ls0609.blog.51cto.com/12943469/1929868

语音识别,语义理解一站式解决之二(android,olami)