• olami sdk实现了把录音或者文字转化为用户可以理解的json字符串从而实现语义理解,用户可以定义自己的语义,是不是很强大?本文讲述怎么自定义语义,以及如何解析自定义语义。 本文使用olami sdk做了一个在线听书的...

    语音记账demo:http://blog.csdn.net/ls0609/article/details/72765789

    olami sdk实现了把录音或者文字转化为用户可以理解的json字符串从而实现语义理解,用户可以定义自己的语义,是不是很强大?本文讲述怎么自定义语义,以及如何解析自定义语义。
    本文使用olami sdk做了一个在线听书的demo,用户只需类似“我想听***”就能实现听书的在线查找并播放。用的是喜马拉雅的在线听书sdk.基于eclipse开发环境,libs目录下jar和so文件如下:
    
    olami-android-sdk.jar //olami sdk 的jar
    afinal_0.5.1_bin.jar
    litepal.jar
    gson-2.2.4.jar
    okhttp-2.4.0.jar
    okhttp-urlconnection-2.2.0.jar
    okio-1.4.0.jar
    opensdk.jar          //上面这几个都是喜马拉雅需要的jar
    libspeex.so          //olami sdk 需要用到speex压缩功能
    libxmediaplayer.so   // 喜马拉雅so
    libxmediaplayer_x.so // 喜马拉雅so
    

    概述: 
    VoiceSdkService中定义了OlamiVoiceRecognizer语音识别引擎,通过点击MusicActivity的开始button启动录音,录音结果在VoiceSdkService中的onResult()回调中拿到识别的Json字符串,在processServiceMessage()函数中处理后找到要听书的名称,然后进入BookUtil进行搜索,搜索到结果后通知VoiceSdkService进行播放,并通知MusicActivity更新播放进度等信息。

    1.AndroidManifest.xml配置

    <?xml version="1.0" encoding="utf-8"?>
         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.olami.musicdemo"
            android:versionCode="1"
            android:versionName="1.0" >
    
            <uses-sdk
                android:minSdkVersion="8"
                android:targetSdkVersion="21" />
    
            <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.READ_PHONE_STATE"/>
            <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
            <application
                android:name="com.olami.musicdemo.OlamiApplication"
                android:allowBackup="true"
                android:icon="@drawable/ic_launcher"
                android:label="@string/app_name"
                android:theme="@style/AppTheme" >
    
                <!--喜马拉雅听书测试账号app_key-->
                <meta-data
                    android:name="app_key"
                    android:value="b617866c20482d133d5de66fceb37da3" />
                <!--喜马拉雅听书测试账号包名-->
                <meta-data
                    android:name="pack_id"
                    android:value="com.app.test.android" />
    
                <activity
                    android:name=".MusicActivity"
                    android:label="@string/app_name" >
                    <intent-filter>
                        <action android:name="android.intent.action.MAIN" />
    
                        <category android:name="android.intent.category.LAUNCHER" />
                    </intent-filter>
                </activity>
    
                 <!--注册olami sdk service-->
                <service
                    android:name=".VoiceSdkService"
                    android:exported="true" >
                </service>
    
                <!--注册喜马拉雅听书service-->
                 <service                
                  android:name=
                 "com.ximalaya.ting.android.opensdk.player.service.XmPlayerService"
                />
            </application>
    
        </manifest>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    2.layout布局文件

    layout_musicview.xml

    TextView 有两个,tv_name显示听书的名称, tv_totoal_time显示听书的总时间。 
    ProgressBar 实时刷新显示听书的进度

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/transparent">
    
    
        <TextView
            android:text="name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:layout_centerHorizontal="true"
            android:id="@+id/tv_name"/>
    
        <ProgressBar
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_name"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:id="@+id/progressbar_music"/>
    
        <TextView
            android:text="total_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/progressbar_music"
            android:layout_marginTop="10dp"
            android:layout_centerHorizontal="true"
            android:id="@+id/tv_total_time"/>
    
    </RelativeLayout>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    activity_music.xml

    <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:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        tools:context="com.olami.musicdemo.MusicActivity" >
    
        <TextView
            android:id="@+id/tv_inputText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:text="输入:" />
    
        <TextView
            android:id="@+id/tv_volume"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/tv_inputText"
            android:layout_below="@+id/tv_inputText"
            android:layout_marginTop="40dp"
            android:text="音量:" />
    
        <TextView
            android:id="@+id/tv_result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_volume"
            android:layout_marginTop="20dp"
            android:maxLines="15"
            android:ellipsize="end"
            android:text="服务器返回sentence:"
            android:visibility="visible" />
    
        <com.olami.musicdemo.MusicView
            android:id="@+id/music_view"
            android:layout_width="fill_parent"
            android:layout_height="80dp"
            android:layout_centerInParent="true"
            >
        </com.olami.musicdemo.MusicView>
    
        <EditText
            android:id="@+id/et_content"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            android:layout_above="@+id/btn_stop"
            android:layout_alignLeft="@+id/tv_inputText"
            android:layout_marginBottom="10dp"
            android:layout_toLeftOf="@+id/btn_send"
            android:background="#E7E7E7"
            android:singleLine="true"
            android:text="上海的天气" />    
    
         <Button
            android:id="@+id/btn_send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/et_content"
            android:layout_alignBottom="@+id/et_content"
            android:layout_alignParentRight="true"
            android:text="提交" />
    
        <Button
            android:id="@+id/btn_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"  
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:text="开始" />
    
        <Button
            android:id="@+id/btn_stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/et_content"
            android:layout_alignParentBottom="true"
            android:text="停止" />
    
        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_toRightOf="@+id/et_content"
            android:text="取消" />
    
    </RelativeLayout>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    自定义MusicView比较简单,代码如下:

    public class MusicView extends RelativeLayout{
        private Context mContext;
        private Handler mHandler;
        private TextView mTextViewName;
        private TextView mTextViewTotalTime;
        private ProgressBar mProgressBar;
        public MusicView(Context context,AttributeSet attrs) {
            super(context,attrs);
            LayoutInflater inflater =(LayoutInflater) context.getSystemService(
                                                context.LAYOUT_INFLATER_SERVICE);
            RelativeLayout view = (RelativeLayout) inflater.inflate(R.layout.layout_musicview, this,true);
            mTextViewName = (TextView) view.findViewById(R.id.tv_name);
            mTextViewTotalTime = (TextView) view.findViewById(R.id.tv_total_time);
            mProgressBar = (ProgressBar)view.findViewById(R.id.progressbar_music);
    
        }
    
        public void initMusicView(Context context,Handler handler)
        {
            mContext = context;
            mHandler = handler;
        }
    
        public void setMusicName(String name)
        {//设置播放名称
            mTextViewName.setText(name);
        }
    
        public void setProgress(int progress)
        {//设置播放进度
            mProgressBar.setProgress(progress);
        }
    
        public void setTotalTime(String time)
        {//设置播放总时间
            mTextViewTotalTime.setText(time);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    布局效果图如下: 
    这里写图片描述

    3.MusicActivity和VoiceSdkService通信

    本文没有用bind service的方式实现activity和service的消息通信。 
    MusicAcitity 和 VoiceSdkService中分别实现了一个CommunicationAssist的接口

    public interface CommunicationAssist {
        public void callBack(int what, int arg1, int arg2,Bundle data, Object obj);
    }
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    然后把他们分别实现CommunicationAssist接口的变量注册到OlamiApplication,这样通过OlamiApplication实现了MusicAcitity 和 VoiceSdkService桥接。

    3.1OlamiApplication

    1) 注册MusicActivity到VoiceSdkService的回调

    public void setActivityToServiceListener(CommunicationAssist listener)
    {
       ActivityToServiceListener = listener;
    }
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    这个是在VoiceSdkService中调用setActivityToServiceListener(),把VoiceSdkService中的VoiceSdkComAssist注册到application中,MusicActivity中可以通过getActivityToServiceListener 
    这个函数回调向VoiceSdkService发送消息。

    2) 注册 VoiceSdkService到MusicActivity回调

    public void setServiceToActivityListener(CommunicationAssist listener)
    {
      mServiceToActivityListener = listener;
    }
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    这个是在MusicAcitivity中调用setServiceToActivityListener(),这样在VoiceSdkService中就可以通过getServiceToActivityListener()获得回调向MusciActivity发送消息。

    3.2 MusicActivity

    public class MusicActivity extends Activity {
        private Handler mHandler;
        private Handler mInComingHandler;
        private ActivityComAssist mActivityComAssist;
        private Button mBtnStart;
        private Button mBtnStop;
        private Button mBtnCancel;
        private Button mBtnSend;
        private EditText mEditText;
        private TextView mTextView;
        private TextView mInputTextView;
        private TextView mTextViewVolume;
        private BookUtil mBookUtil = null;
        private MusicView mMusicView = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_music);
            initHandler();//初始化handler用于内部消息处理
            initInComingHandler();//用于处理来自VoiceSdkService的消息
            initCommunicationAssist();//向application注册消息回调,VoiceSdkSerive可以
                    //通过getServiceToActivityListener()获得回调向MusicActivity发送消息
            initView();//初始化view控件
            Intent intent = new Intent();
            intent.setClass(MusicActivity.this, VoiceSdkService.class);
            startService(intent);//启动后台服务
    
        }
    
        private void initView()
        {
            mBtnStart = (Button) findViewById(R.id.btn_start);
            mBtnStop = (Button) findViewById(R.id.btn_stop);
            mBtnCancel = (Button) findViewById(R.id.btn_cancel);
            mBtnSend = (Button) findViewById(R.id.btn_send);
            mInputTextView = (TextView) findViewById(R.id.tv_inputText);
            mEditText = (EditText) findViewById(R.id.et_content);
            mTextView = (TextView) findViewById(R.id.tv_result);
            mTextViewVolume = (TextView) findViewById(R.id.tv_volume);
    
            mBtnStart.setOnClickListener(new OnClickListener(){
    
                @Override
                public void onClick(View v) {
                    sendMessageToService(MessageConst.CLIENT_ACTION_START_RECORED,0,0,null,null);
                }           
            });
    
            mBtnStop.setOnClickListener(new OnClickListener(){
    
                @Override
                public void onClick(View v) {
                    sendMessageToService(MessageConst.CLIENT_ACTION_STOP_RECORED,0,0,null,null);
                    mBtnStart.setText("开始");
                    Log.i("led","MusicActivity mBtnStop onclick 开始");
                }           
            });
    
            mBtnCancel.setOnClickListener(new OnClickListener(){
    
                @Override
                public void onClick(View v) {
                    sendMessageToService(MessageConst.CLIENT_ACTION_CANCEL_RECORED,0,0,null,null);
                }           
            });
    
            mBtnSend.setOnClickListener(new OnClickListener(){
    
                @Override
                    public void onClick(View v) {
                sendMessageToService(
                MessageConst.CLIENT_ACTION_SENT_TEXT,0,0,null,mEditText.getText());
                    mInputTextView.setText("文字: "+mEditText.getText());
                }           
            });
    
            mMusicView = (MusicView) findViewById(R.id.music_view);
            //if(mMusicView != null)
                //mMusicView.initMusicView(MusicActivity.this,mHandler);
    
        }
    
        private void initHandler()
        {
            mHandler = new Handler(){
                @Override
                public void handleMessage(Message msg)
                {
                    switch (msg.what){
                    case MessageConst.CLIENT_ACTION_START_RECORED:
                        break;
                    default:
                        break;  
                    }
                }
            };
        }
        //InComingHandler 收到来自VoiceSdkService的消息用于更新界面,
        //包括开始录音,结束录音,播放的书的名称和进度,音量等信息。
        private void initInComingHandler()
        {
            mInComingHandler = new Handler(){
                @Override
                public void handleMessage(Message msg)
                {
                    switch (msg.what){
                    case MessageConst.CLIENT_ACTION_START_RECORED:
                        mBtnStart.setText("录音中");
                        Log.i("led","MusicActivity 录音中");
                        break;
                    case MessageConst.CLIENT_ACTION_STOP_RECORED:
                        mBtnStart.setText("识别中");
                        Log.i("led","MusicActivity 识别中");
                        break;
                    case MessageConst.CLIENT_ACTION_CANCEL_RECORED:
                        mBtnStart.setText("开始");
                        mTextView.setText("已取消");
                        break;
                    case MessageConst.CLIENT_ACTION_ON_ERROR:
                        mTextView.setText("错误代码:"+msg.arg1);
                        mBtnStart.setText("开始");
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATA_VOLUME:
                        mTextViewVolume.setText("音量: "+msg.arg1);
                        break;
                    case MessageConst.SERVER_ACTION_RETURN_RESULT:
                        //mTextView.setText(msg.obj.toString());
                        mBtnStart.setText("开始");
                        break;
                    case MessageConst.CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH:
                        mBtnStart.setText("开始");
                        mBookUtil = BookUtil.getInstance();
                        mBookUtil.play(msg.arg1);
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATA_PLAYING_BOOK_NAME:
                        mMusicView.setMusicName(msg.obj.toString());
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATE_BOOK_PROGRESS:
                        int current = msg.arg1;
                        int duration = msg.arg2;
                        mMusicView.setProgress(current*100/duration);
                        float time = duration/1000/60;
                        mMusicView.setTotalTime("总时间:"+time);
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATA_INPUT_TEXT:
                        if(msg.obj != null)
                           mInputTextView.setText("文字: "+msg.obj.toString());
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATA_SERVER_MESSAGE:
                        if(msg.obj != null)
                            mTextView.setText("服务器返回sentence: "+msg.obj.toString());
                        break;
                    default:
                        break;
                    }
                }
            };
        }
    
        private void initCommunicationAssist()
        {//向Application注册VoiceSdkService到MusicActivity的回调
            mActivityComAssist = new ActivityComAssist();
            OlamiApplication.getInstance().setServiceToActivityListener(mActivityComAssist);
        }
    
        private void sendMessageToService(int what, int arg1, int arg2, Bundle data, Object obj)
        {//向VoiceSdkService发送消息
            if(OlamiApplication.getInstance().getActivityToServiceListener() != null)
                OlamiApplication.getInstance().getActivityToServiceListener().callBack
                (what, arg1, arg2, data, obj);
        }
    
        private class ActivityComAssist implements CommunicationAssist{
        //实现CommunicationAssist借口,用于回调VoiceSdkService发送过来的消息
            @Override
            public void callBack(int what, int arg1, int arg2, Bundle data,Object obj) {
                Message msg = Message.obtain(null, what);
                msg.arg1 = arg1;
                msg.arg2 = arg2;
                if (data != null)
                    msg.setData(data);
                if (obj != null)
                    msg.obj = obj;
                mInComingHandler.sendMessage(msg);
            }       
        }
    
        @Override
        public void onDestroy() {
            //退出应用,停止VoiceSdkService,会进行资源的释放
            super.onDestroy();
            Intent intent = new Intent();
            intent.setClass(MusicActivity.this, VoiceSdkService.class);
            stopService(intent);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198

    3.3 VoiceSdkService

    @Override
        public void onCreate() {
            initHandler();//用于内部消息处理
            initInComingHandler();//用于处理来自MusicActivity的消息
            initCommunicationAssist();//向application注册消息回调,这样MusicActivity可
            //以通过getActivityToServiceListener()回调向VoiceSdkService发送消息
            initViaVoiceRecognizerListener();//初始化录音识别回调listener
            init();//olami录音识别引擎初始化
            initXmly();//喜马拉雅初始化
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public void init()
    {
        initHandler();
        mOlamiVoiceRecognizer = new OlamiVoiceRecognizer(VoiceSdkService.this);
        TelephonyManager telephonyManager=(TelephonyManager) this.getSystemService(
        (this.getBaseContext().TELEPHONY_SERVICE);
        String imei=telephonyManager.getDeviceId();
        mOlamiVoiceRecognizer.init(imei);//设置身份标识,可以填null
    
        mOlamiVoiceRecognizer.setListener(mOlamiVoiceRecognizerListener);//设置识别结果回调listener
        mOlamiVoiceRecognizer.setLocalization(
        OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE);//设置支持的语音类型,优先选择中文简体
        mOlamiVoiceRecognizer.setAuthorization("51a4bb56ba954655a4fc834bfdc46af1",
                                "asr","68bff251789b426896e70e888f919a6d","nli");  
        //注册Appkey,在olami官网注册应用后生成的appkey
        //注册api,请直接填写“asr”,标识语音识别类型
        //注册secret,在olami官网注册应用后生成的secret
        //注册seq ,请填写“nli”
    
        mOlamiVoiceRecognizer.setVADTailTimeout(2000);//录音时尾音结束时间,建议填//2000ms
        //设置经纬度信息,不愿上传位置信息,可以填0 
        mOlamiVoiceRecognizer.setLatitudeAndLongitude(31.155364678184498,121.34882432933009); 
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    定义OlamiVoiceRecognizerListener

    onError(int errCode)//出错回调,可以对比官方文档错误码看是什么错误 
    onEndOfSpeech()//录音结束 
    onBeginningOfSpeech()//录音开始 
    onResult(String result, int type)//result是识别结果JSON字符串 
    onCancel()//取消识别,不会再返回识别结果 
    onUpdateVolume(int volume)//录音时的音量,1-12个级别大小音量

    下面是VoiceSdkService完整代码:

    public class VoiceSdkService extends Service{
    
        private Handler mHandler;
        private Handler mInComingHandler;
        private VoiceSdkComAssist mVoiceSdkComAssist;
        private OlamiVoiceRecognizer mOlamiVoiceRecognizer;
        private OlamiVoiceRecognizerListener mOlamiVoiceRecognizerListener;
        private BookUtil mBookUtil = null;
        private boolean mIsRecordPause = false;
    
        @Override
        public void onCreate() {
            initHandler();
            initInComingHandler();
            initCommunicationAssist();
            initViaVoiceRecognizerListener();
            init();
            initXmly();
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            // TODO Auto-generated method stub
            return null;
        }
    
        public void init()
        {
            initHandler();
            mOlamiVoiceRecognizer = new OlamiVoiceRecognizer(VoiceSdkService.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);
            mOlamiVoiceRecognizer.setLocalization(
                                             OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE);
            mOlamiVoiceRecognizer.setAuthorization(
                "51a4bb56ba954655a4fc834bfdc46af1",
                "asr","68bff251789b426896e70e888f919a6d","nli");        
            mOlamiVoiceRecognizer.setVADTailTimeout(2000);
            mOlamiVoiceRecognizer.setLatitudeAndLongitude(31.155364678184498,121.34882432933009); 
        }
    
        private void initHandler()
        {
            mHandler = new Handler(){
                @Override
                public void handleMessage(Message msg)
                {
                    switch (msg.what){
                    case MessageConst.CLIENT_ACTION_START_RECORED:
                        sendMessageToActivity(MessageConst.CLIENT_ACTION_START_RECORED,0,0,null,null);
                        break;
                    case MessageConst.CLIENT_ACTION_STOP_RECORED:
                        sendMessageToActivity(MessageConst.CLIENT_ACTION_STOP_RECORED,0,0,null,null);
                        break;
                    case MessageConst.CLIENT_ACTION_ON_ERROR:
                        sendMessageToActivity(MessageConst.CLIENT_ACTION_ON_ERROR,msg.arg1,0,null,null);
                        break;
                    case MessageConst.CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH:
                        sendMessageToActivity(MessageConst.
                        CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH, msg.arg1, 0, null, msg.obj);
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATA_PLAYING_BOOK_NAME:
                        sendMessageToActivity(MessageConst.
                        CLIENT_ACTION_UPDATA_PLAYING_BOOK_NAME, msg.arg1, 0, null, msg.obj);
                        break;
                    case MessageConst.CLIENT_ACTION_UPDATE_BOOK_PROGRESS:
                        sendMessageToActivity(MessageConst.
                        CLIENT_ACTION_UPDATE_BOOK_PROGRESS, msg.arg1, msg.arg2, null, null);
                        break;
                    case MessageConst.CLIENT_ACTION_CANCEL_RECORED:
                        sendMessageToActivity(MessageConst.
                        CLIENT_ACTION_CANCEL_RECORED, msg.arg1, msg.arg2, null, null);
                        break;
                    default:
                        break;
                    }
                }
            };
        }
    
        private void initInComingHandler()
        {
            mInComingHandler = new Handler(){
                @Override
                public void handleMessage(Message msg)
                {
                    switch (msg.what){
                    case MessageConst.CLIENT_ACTION_START_RECORED:
                        if(mOlamiVoiceRecognizer != null)
                            mOlamiVoiceRecognizer.start();  
                        break;
                    case MessageConst.CLIENT_ACTION_STOP_RECORED:
                        if(mOlamiVoiceRecognizer != null)
                            mOlamiVoiceRecognizer.stop();   
                        break;
                    case MessageConst.CLIENT_ACTION_CANCEL_RECORED:
                        if(mOlamiVoiceRecognizer != null)
                            mOlamiVoiceRecognizer.cancel(); 
                        break;
                    case MessageConst.CLIENT_ACTION_SENT_TEXT:
                        if(mOlamiVoiceRecognizer != null)
                            mOlamiVoiceRecognizer.sendText(msg.obj.toString());                 
                        break;
                    }
                }
            };
        }
    
        private void initViaVoiceRecognizerListener()
        {
            mOlamiVoiceRecognizerListener = new OlamiVoiceRecognizerListener();
        }
    
        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);
                if(mIsRecordPause)
                {
                    mIsRecordPause = false;
                    mBookUtil.resumePlay();
                }
    
            }
    
            @Override
            public void onBeginningOfSpeech() {
                if(mBookUtil.isPlaying())
                {
                    mBookUtil.pause();
                    mIsRecordPause = true;
                }
                mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_START_RECORED);
    
            }
    
            @Override
            public void onResult(String result, int type) {     
                sendMessageToActivity(MessageConst.SERVER_ACTION_RETURN_RESULT,type,0,null,result);
                processServiceMessage(result);
            }
    
            @Override
            public void onCancel() {
                mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_CANCEL_RECORED);
    
            }
    
            @Override
            public void onUpdateVolume(int volume) {
    
            sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_VOLUME,volume,0,null,null);
    
            }
    
        }
    
        private void initCommunicationAssist()
        {
            mVoiceSdkComAssist = new VoiceSdkComAssist();
            OlamiApplication.getInstance().setActivityToServiceListener(mVoiceSdkComAssist);
        }
    
        private void initXmly()
        {
            if(mBookUtil == null)
            {
                mBookUtil = BookUtil.getInstance();
                mBookUtil.init(VoiceSdkService.this);
                mBookUtil.setHandler(mHandler);
            }
        }
    
        private void processServiceMessage(String message)
        {
            String input = null;
            String serverMessage = null;
            try{
                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");
                else{
                    input = jsonObject.optJSONObject("data").optJSONObject("asr").
                    optString("result");
                    sendMessageToActivity(MessageConst.
                                         CLIENT_ACTION_UPDATA_INPUT_TEXT, 0, 0, null, input);
                    serverMessage = jObj.optJSONObject("desc_obj").opt("result").toString();
                    sendMessageToActivity(MessageConst.
                            CLIENT_ACTION_UPDATA_SERVER_MESSAGE, 0, 0, null, serverMessage);
                    return;
                }
                JSONObject jObjSemantic;
                JSONArray jArraySlots;
                JSONArray jArrayModifier;
                String type = null;
                String songName = null;
                String singer = null;
    
    
                if(jObj != null) {
                    type = jObj.optString("type");
                    if("musiccontrol".equals(type))
                    {
                        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) && ("play".equals(modifier)))
                        {
                            if(jArraySlots != null)
                               for(int i=0,k=jArraySlots.length(); i<k; i++)
                               {
                                   JSONObject obj = jArraySlots.getJSONObject(i);
                                   String name = obj.optString("name");
                                   if("singer".equals(name))
                                       singer = obj.optString("value");
                                   else if("songname".equals(name))
                                       songName = obj.optString("value");
    
                               }
                        }else if((modifier != null) && ("stop".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                if(mBookUtil.isPlaying())
                                    mBookUtil.stop();
                        }else if((modifier != null) && ("pause".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                if(mBookUtil.isPlaying())
                                    mBookUtil.pause();
                        }else if((modifier != null) && ("resume_play".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                mBookUtil.resumePlay();
                        }else if((modifier != null) && ("add_volume".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                mBookUtil.addVolume();
                        }else if((modifier != null) && ("del_volume".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                mBookUtil.delVolume();
                        }else if((modifier != null) && ("next".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                mBookUtil.next();
                        }else if((modifier != null) && ("previous".equals(modifier)))
                        {
                            if(mBookUtil != null)
                                mBookUtil.prev();
                        }else if((modifier != null) && ("play_index".equals(modifier)))
                        {
                            int position = 0;
                            if(jArraySlots != null)
                                   for(int i=0,k=jArraySlots.length(); i<k; i++)
                                   {
                                       JSONObject obj = jArraySlots.getJSONObject(i);
                                       JSONObject jNumDetial = obj.getJSONObject("num_detail");
                                       String index = jNumDetial.optString("recommend_value");
                                       position = Integer.parseInt(index) - 1;
                                   }
                            if(mBookUtil != null)
                                mBookUtil.skipTo(position);
                        }
                    }
                }
                if(songName != null)
                {
                    if(singer != null)
                    {
    
                    }else{
                        mBookUtil.searchBookAndPlay(songName,0,0);
                    }
                }else if(singer != null)
                {
                    mBookUtil.searchBookAndPlay(songName,0,0);
                }
                serverMessage = jObj.optJSONObject("desc_obj").opt("result").toString();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            //发送消息更新语音识别的文字
            sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_INPUT_TEXT, 0, 0, null, input);
            //发送消息更新服务器返回的结果字符串
            sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_SERVER_MESSAGE, 
                                                        0, 0, null, serverMessage);
    
        }
    
        private void sendMessageToActivity(int what, int arg1, int arg2, Bundle data, Object obj)
        {
            if(OlamiApplication.getInstance().getServiceToActivityListener() != null)
                OlamiApplication.getInstance().getServiceToActivityListener().
                                                 callBack(what, arg1, arg2, data, obj);
        }
    
        private class VoiceSdkComAssist implements CommunicationAssist{
    
            @Override
            public void callBack(int what, int arg1, int arg2, Bundle data,Object obj) {
                Message msg = Message.obtain(null, what);
                msg.arg1 = arg1;
                msg.arg2 = arg2;
                if (data != null)
                    msg.setData(data);
                if (obj != null)
                    msg.obj = obj;
                mInComingHandler.sendMessage(msg);
            }       
        }
    
        @Override
        public void onDestroy(){
            super.onDestroy();
            if(mOlamiVoiceRecognizer != null)
                mOlamiVoiceRecognizer.destroy();
            if(mBookUtil != null)
            {
                mBookUtil.destroy();
            }
    
        }
    
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344

    3.4 VoiceSdkService中onResult的回调处理

    在VoiceSdkService.java中processServiceMessage(String message)用于处理onResult的回调数据。例如“我要听三国演义”返回如下数据:
    
    {
        "data": {
            "asr": {
                "result": "我要听三国演义",
                "speech_status": 0,
                "final": true,
                "status": 0
            },
            "nli": [
                {
                    "desc_obj": {
                        "result": "正在努力搜索中,请稍等",
                        "status": 0
                    },
                    "semantic": [
                        {
                            "app": "musiccontrol",
                            "input": "我要听三国演义",
                            "slots": [
                                {
                                    "name": "songname",
                                    "value": "三国演义"
                                }
                            ],
                            "modifier": [
                                "play"
                            ],
                            "customer": "58df512384ae11f0bb7b487e"
                        }
                    ],
                    "type": "musiccontrol"
                }
            ]
        },
        "status": "ok"
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    1)解析出nli中type类型是musiccontrol,这是语法返回app的类型,而这个在线听书的demo只关心musiccontrol这 个app类型,其他的忽略。

    2)用户说的话转成文字是在asr中的result中获取 
    3)在nli中的semantic中,input值是用户说的话,同asr中的result。 
    modifier代表返回的行为动作,此处可以看到是play就是要求播放,slots中的数据表示歌曲名称是三国演义。 
    那么动作是play,内容是歌曲名称是三国演义,在这个demo中调用 
    mBookUtil.searchBookAndPlay(songName,0,0);会先查询,查询到结果会再发播放消息要求播放,我要听三国演义这个流程就走完了。

    4.BookUtil

    说一下搜索听书的实现过程
    public void searchBookInfo(String bookName,final int index,final boolean isNeedPlay)
    {
        mBookName = bookName;
        Map<String, String> param = new HashMap<String, String>();
        param.put(DTransferConstants.SEARCH_KEY, bookName);
        param.put(DTransferConstants.CATEGORY_ID, "" + 3);//此处3代表搜索的是听书
        //param.put(DTransferConstants.PAGE, "" + mPageId);
        param.put(DTransferConstants.SORT, "asc");//返回列表的排序是正序还是逆序
        param.put(DTransferConstants.PAGE_SIZE, "" + PAGE_SIZE);//每页能返回多少个查询结果
        mPage = (index/PAGE_SIZE)+1;//当前在第几页
    
        mPlayerManager = XmPlayerManager.getInstance(mContext);//喜马拉雅初始化部分
        mPlayerManager.init(mNotificationId, null);
        mPlayerManager.addPlayerStatusListener(mPlayerStatusListener);
        mPlayerManager.addAdsStatusListener(mAdsListener);
    
        CommonRequest.getSearchedAlbums(param, new IDataCallBack<SearchAlbumList>()
        {
    
            @Override
            public void onSuccess(SearchAlbumList object)   
            {                   
                if (object != null && object.getAlbums() != null
                        && object.getAlbums().size() != 0)
                {
                    if (mSearchAlbumList == null)
                    {
                        mSearchAlbumList = object;
                    }
                    else
                    {
                        mSearchAlbumList.getAlbums().addAll(object.getAlbums());
                    }
                    //mTrackAdapter.notifyDataSetChanged();
    
                    Map<String, String> map = new HashMap<String, String>();
    
                    map.put(
                    DTransferConstants.ALBUM_ID, ""+object.getAlbums().get(0).getId());
                    map.put(DTransferConstants.SORT, "asc");
                    map.put(DTransferConstants.PAGE, "" + mPage);
                    map.put(DTransferConstants.PAGE_SIZE,  "" + PAGE_SIZE);
    
                    CommonRequest.getTracks(map, new IDataCallBack<TrackList>()
                    {
    
                            @Override
                            public void onSuccess(TrackList object)
                            {
                                mTrackList = object;
                                mTotalCount = mTrackList.getTotalCount();
                                if(mTrackList.getTracks().size() <= 0)
                                    return;
                                String str = "专辑:"+mTrackList.getAlbumTitle()+
                                                get(0).getTrackTitle().toString();
                                if(isNeedPlay)
                                {
                                    mPosition = index % PAGE_SIZE;
                                    mHandler.sendMessage(mHandler.obtainMessage(
                                    MessageConst.CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH, 
                                    index % PAGE_SIZE,0));//此处mTrackList中已经查询出结果
                                    //向VoiceSdkService发送消息进行播放
                                }
                                else
                                    sendBookInfoToServer();                                 
                            }
                            @Override
                            public void onError(int code, String message)
                            {
                                Log.i("ppp","error: "+message);
                                sendBookInfoToServer();
                            }
                    });
    
                }
            }
    
            @Override
            public void onError(int code, String message)
            {
                  Log.i("ppp","error: "+message);
                  sendBookInfoToServer();
            }
        });
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    5.demo中支持的说法

    我想听西游记 
    我要听西游记 
    播放西游记 
    听西游记 
    我想听西游记这本书 
    上一首 
    上一回 
    下一首 
    下一回 
    暂停/暂停播放 
    继续/继续播放 
    声音大一点 
    声音小一点 
    关闭/关闭播放

    用的是喜马拉雅测试账号,只支持听书的功能,查找歌曲的结果返回为空。

    6.源码下载链接

    用olamisdk语音识别引擎做在线听书demo

    7.相关链接

    语音记账demo:http://blog.csdn.net/ls0609/article/details/72765789

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

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

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


    展开全文
  • olami开放平台sdk除了支持语音识别功能外,更强大的在于支持语义理解功能,在android平台和ios平台都有示例demo供大家下载。 语音在线听书demo:http://blog.csdn.net/ls0609/article/details/71519203 语音记账...

    转载请注明原文地址:http://blog.csdn.net/ls0609/article/details/73920229

    olami开放平台sdk除了支持语音识别功能外,更强大的在于支持语义理解功能,在android平台和ios平台都有示例demo供大家下载。

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

    语音记账demo:http://blog.csdn.net/ls0609/article/details/72765789

    在web端,基于javascript用olami开放平台sdk也可以实现语音识别语义理解。本文就实现了这样一个小程序,web客户端本地用麦克风录音,录音的数据用speex压缩,然后跨域向服务器发送请求,返回识别的语音和语义字符串并显示。

    先上图:

    如下图刚载入的时候,未录音前界面

    这里写图片描述

    点击开始录音button后

    这里写图片描述

    一句话说完自动检测尾音结束标志然后压缩上传给服务器进行识别

    这里写图片描述

    将从服务器获取的识别结果显示到界面上

    这里写图片描述

    本例中说的语音是:“我要听三国演义这本书”,用的是android平台听书app建立的语法。
    返回的json字串如下:

    {
    “data”: {
    “asr”: {
    “result”: “我要听三国演义这本书”,
    “speech_status”: 0,
    “final”: true,
    “status”: 0
    },
    “nli”: [
    {
    “desc_obj”: {
    “result”: “正在努力搜索中,请稍等”,
    “status”: 0
    },
    “semantic”: [
    {
    “app”: “musiccontrol”,
    “input”: “我要听三国演义这本书”,
    “slots”: [
    {
    “name”: “songname”,
    “value”: “三国演义”
    }
    ],
    “modifier”: [
    “play”
    ],
    “customer”: “58df512384ae11f0bb7b487e”
    }
    ],
    “type”: “musiccontrol”
    }
    ]
    },
    “status”: “ok”
    }
    通过解析这段json,可以得到app类型,songname(用于查询书名),modifier是play表示行为是播放。
    这段json的语法当然是用户自定义的,获得了json字串就可以解析得到程序需要的字段用于对应的操作,从而实现了语义理解功能。olami开放平台语法编写介绍http://blog.csdn.net/ls0609/article/details/71624340

    下面来看看实现的code,用eclipse建立J2EE工程WebVoiceRecognize
    初次搭建可以参考如下网站:
    http://jingyan.baidu.com/article/1709ad808caf9d4634c4f0f8.html

    下面是建立的工程目录结构,发布后,网页打开运行在chrome或者QQ浏览器均可。
    这里写图片描述

    下面讲述下voiceRecognize.html这个文件,其他都是min.js,只需知道如何调用就可以了。

    <!DOCTYPE HTML>
    <html>
        <head>
        <meta charset="utf-8">
        <title>voice recognize test</title> 
        <script type="text/javascript" src="jquery-1.10.1.min.js"></script>
        <script type="text/javascript" src="jQuery.md5.js"></script> 
        <script src="speex.min.js"></script>  
        <script src="pcmdata.min.js"></script>      
        </head> 
    
        <body onload= "load()">
            <fieldset style="width:50%;margin:10px auto">
            <p align="center" >点击开始button录音,点击停止button停止录音并进行识别</p>
            <p align="center">
            <input type="button" id="recordbutton" value="开始录音" onclick="StartRecording()"/>
            <input type="button" id="speexEncodebutton" value="停止录音" onclick="speexEncode()"/>
          </p>
          <p id ="result" style="margin-bottom:100px;margin-top:50px">result:</p>
          </p>
          <script src="recorder.min.js"></script>   
          <script src="uploaddata.min.js"></script> 
          <script>
    
    
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
    
            var audioContext = new AudioContext();
            var audioInput = null,
                realAudioInput = null,
                inputPoint = null,
                audioRecorder = null;
            var rafID = null;
            var analyserContext = null;
            var recIndex = 0;
    
            var recording = false;
            var bRecorded = false;
    
            function load(){
                initAudio();//初始化recorder
                setAuthorization("http://cn.olami.ai/cloudservice/api","51a4bb56ba954655a4fc834bfdc46af1","asr","68bff251789b426896e70e888f919a6d","nli");
                setCallBackFromServerResult(getResultFromServer);
            }
    
            function initAudio() {
                    if (!navigator.getUserMedia)
                        navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
                    if (!navigator.cancelAnimationFrame)
                        navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
                    if (!navigator.requestAnimationFrame)
                        navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;
    
                navigator.getUserMedia({audio:true}, gotStream, function(e) {
                        alert('Error getting audio');
                        console.log(e);
                    });
            }
    
            function gotStream(stream) {
                inputPoint = audioContext.createGain();
    
                // Create an AudioNode from the stream.
                realAudioInput = audioContext.createMediaStreamSource(stream);
                audioInput = realAudioInput;
                audioInput.connect(inputPoint);
                audioRecorder = new Recorder( inputPoint );
            }
    
            function StartRecording()
            {
                // start recording
                if (audioRecorder == null)
                {
                   initAudio(); 
                   alert("need initialize media");  
                }        
                audioRecorder.clear();
                audioRecorder.record();  
                recording = true;  
                bRecorded = false;
                ToggleLabels(); 
                RegisterCallBackToRecorder();           
            }
    
            function StopRecording()
            {
                audioRecorder.stop();
                audioRecorder.getBuffers( gotBuffers );     
            }
    
            function RegisterCallBackToRecorder()
            {//检测语音结束后回调
                audioRecorder.setCallBack(speexEncode);
            }
    
            function ToggleLabels()
            {
                if(recording)
                {
                    document .getElementById("recordbutton").value = "录音中ֹ";    
                    document .getElementById("speexEncodebutton").value = "停止录音";       
                    var btn = document .getElementById("recordbutton").value;   
    
                }else{
                    document .getElementById("speexEncodebutton").value = "识别中";    
                    document .getElementById("recordbutton").value = "停止录音ֹ";                               
                }   
    
            }
    
            window.record = function(e)
            {
                if(!recording)
                {
                    StartRecording();
                    recording = true;
                    bRecorded = false;
                }
                else
                {
                    StopRecording();
                    recording = false;
                    bRecorded = true;
                }
    
                ToggleLabels();
            };
    
          window.speexEncode =  function()
          {
                exportSpeex();      
          };
    
    
         function exportSpeex()
         {
            recording = false;
            bRecorded = true;
            ToggleLabels();
            audioRecorder.stop();               
            audioRecorder.exportPCM(uploadSpeexData);
         }           
    
         function getResultFromServer()
         {
             document .getElementById('result').innerText = JSON.stringify(result);
             document .getElementById("speexEncodebutton").value = "停止录音";  
             document .getElementById("recordbutton").value = "开始录音ֹ"
         }
          </script>
        </body> 
    
    </html> 

    浏览器载入的时候,先调用load()进行初始化

    function load(){
    setAuthorization(
                    "http://cn.olami.ai/cloudservice/api",//serverurl
                    "51a4bb56ba954655a4fc834bfdc46af1", //appkey             
                    "asr",//api类型
                    "68bff251789b426896e70e888f919a6d",//appSecret
                    "nli");//seq
    setCallBackFromServerResult(getResultFromServer);
            }

    initAudio()中初始化了recorder用于获取麦克风资源做录音使用。

    setAuthorization函数,参数分别是

    url 服务器地址
    appkey 开放平台注册应用后获得的appkey
    api api类型选asr为语音
    appSecret 开放平台注册应用后获得的appSecret
    nli 为seq表示包含语音语义返回,为stt表示只有语音返回

    setCallBackFromServerResult(getResultFromServer) 注册录音介绍并且识别出结果后的回调,在回调函数中可以把结果输出到界面上。

    当点击开始录音button后,调用

    function StartRecording()
    {
          // start recording
          if (audioRecorder == null)
          {
             initAudio();   
             alert("need initialize media");    
          }        
          audioRecorder.clear();
          audioRecorder.record();  
          recording = true;  
          bRecorded = false;
          ToggleLabels(); 
          RegisterCallBackToRecorder(); //注册recoder回调        
    }

    当在录音的js代码中,会自动检测尾音结束,然后回调注册的函数speexEncode (),点击停止录音button一样调用这个函数

     window.speexEncode =  function()
     {
        exportSpeex();      
     };
    
    
      function exportSpeex()
    {
        recording = false;
        bRecorded = true;
        ToggleLabels();//更新界面的button状态
        audioRecorder.stop();               
        audioRecorder.exportPCM(uploadSpeexData);
    }            

    audioRecorder.exportPCM(uploadSpeexData) 实现了将录好的16Kpcm语音压缩成speex格式并上传到服务器,从服务器取得结果后调用注册的setCallBackFromServerResult(getResultFromServer)函数,然后再函数getResultFromServer中进行结果的输出显示。

    代码下载地址:

    用olamisdk实现web端语音识别语音理解

    相关网站链接:

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

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

    展开全文
  • 转载请注明CSDN地址前言国内语音识别技术已有多家,而olami不仅在语音识别上准确率较高,更重要的是在语义理解上十分强大,本文用olami sdk做了一个记账demo(记账部分代码参考开源代码),这个demo可以语音添加不同...

    转载请注明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

    展开全文
  • 微信开发现在已经逐步向智能化的方向发展,像摇一摇和语义理解各种功能都是越来越高大上,也多亏了腾讯那些开发微信的程序员,不得不说他们很强大。

    微信功能可谓强大,最近学习了下它的智能接口,顿时觉得微信特别高大上,居然能识别语音而且准确度还是挺高且还能理解语义。这次打算针对这个智能接口演示下通过语音查询天气预报的例子。

    一 、 开启语音识别功能




    二   、处理语音消息

    请注意,开通语音识别后,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段(注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试)。开启语音识别后的语音XML数据包如下:

    <xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName>
    <CreateTime>1357290913</CreateTime>
    <MsgType><![CDATA[voice]]></MsgType>
    <MediaId><![CDATA[media_id]]></MediaId>
    <Format><![CDATA[Format]]></Format>
    <Recognition><![CDATA[腾讯微信团队]]></Recognition>
    <MsgId>1234567890123456</MsgId>
    </xml>
    

    多出的字段中,Format为语音格式,一般为amr,Recognition为语音识别结果,使用UTF8编码。


    以上是微信开发文档的说明,其实就是开启语音识别后多了一个参数


    String recognition=requestMap.get("Recognition");


    三 、 封装语义理解接口

    参照API:http://mp.weixin.qq.com/wiki/0/9b7e44d37062e3f014c0e05017eabf2c.html

    public static String getWeatherSemInfo(String accessToken,String reqJson){
    		String requestUrl="https://api.weixin.qq.com/semantic/semproxy/search?access_token=YOUR_ACCESS_TOKEN";
    		requestUrl=requestUrl.replace("YOUR_ACCESS_TOKEN", accessToken);
    		JSONObject json=CommonUtil.httpsRequest(requestUrl, "POST", reqJson);
    		
    		String city="上海";
    		int errcode=json.getInt("errcode");
    		if(0==errcode){
    			JSONObject semantic=json.getJSONObject("semantic");
    			JSONObject details=semantic.getJSONObject("details");
    			JSONObject location=details.getJSONObject("location");
    			city=location.getString("city");
    		}else{
    			System.out.println("语义理解失败");
    		}
    		
    		
    		return city;
    }

    四、   微信识别语音并回复消息

    String recognition=requestMap.get("Recognition");
                	
    //这里的token建议缓存起来或放数据库定期取最新的(这里就是掩饰下)
    String token=AdvancedUtil.getAccessToken("xxxxx","xxxxxx").getToken();
            
    SemParams p=new SemParams();
    p.setAppid("xxxxx");
    p.setCategory("weather");
    p.setCity("昆明");
    p.setQuery(recognition);
    p.setUid(fromUserName);
            		
    String city=AdvancedUtil.getWeatherSemInfo(token,JSONObject.fromObject(p).toString());
    String weatherInfo=WeatherUtil.getWeatherResult(city);
                    
    respContent = weatherInfo;  

    顺便贴下SemParams的代码出来

    package com.debug.weixin.pojo;
    
    public class SemParams {
    	
    	private String query;
    	private String city;
    	private String category;
    	private String appid;
    	private String uid;
    
    	public String getQuery() {
    		return query;
    	}
    
    	public void setQuery(String query) {
    		this.query = query;
    	}
    
    	public String getCity() {
    		return city;
    	}
    
    	public void setCity(String city) {
    		this.city = city;
    	}
    
    	public String getCategory() {
    		return category;
    	}
    
    	public void setCategory(String category) {
    		this.category = category;
    	}
    
    	public String getAppid() {
    		return appid;
    	}
    
    	public void setAppid(String appid) {
    		this.appid = appid;
    	}
    
    	public String getUid() {
    		return uid;
    	}
    
    	public void setUid(String uid) {
    		this.uid = uid;
    	}
    }
    

    来看下运行截图:



    如果对天气预报的获取有疑问请参考下面的文章:

    http://blog.csdn.net/walkcode/article/details/48947843


    以上程序只是简单的实现了功能,实际开发中情况会比这个复杂,例如要校验空值等各种逻辑判断,因此生产环境下的代码应该更加严谨,控制也应更加细腻。这样才能跻身于微信开发的高手行列。



    展开全文
  • 云知声“语音+语义”一站式解决方案(安卓版本),内含app key下载直接可用。可以实现语音转文字、文字转语音理解语言真实意思的功能,内含36个已优化好的生活类服务,
  • 阿里小蜜的语音识别语义理解技术用的是哪家公司的产品?有知道的不?
    阿里小蜜的语音识别、语义理解技术用的是哪家公司的产品?有知道的不?
    展开全文
  • 我想做这样一个在线听书应用,用语音输入,然后用...olami不仅支持语音识别,更强大的在于用户自定义语义实现语义理解功能。 详情请看CSDN博文:http://blog.csdn.net/ls0609/article/details/71519203   ...
  • 很多除接触AI的小伙伴, 不清楚语音识别和声纹识别的区别,经常混淆概念,以为语音识别、声纹识别、语义识别是同一回事,其实不然。这篇文章主要为小伙伴普及一下这三者的区别, 并且分别讲一讲如何测试。   语音...
  • 语音识别,刚才罗老师也分享了部分内容。语音合成是文字变成语音,这部分我们后面会详细展开。再往后看,声纹识别,在智能车里面有很多的功能需要人的发音媒介来控制命令的时候声纹就很重要。开一个车门,车上有一个...
  • 语音识别的流程

    2019-12-15 17:30:26
    语音合成是用语音方式输出用户想要的信息,用语音实现人与计算机之间的交互,主要包括语音识别、自然语言理解和语音合成。 相对于机器翻译,语音识别是更加困难的问题。机器翻译系统的输入通常是印刷文本,计算机能...
  • 在pc的浏览器上,基于JavaScript用olami开放平台sdk也可以实现语音识别语义理解。本文就实现了这样一个小程序,web客户端本地用麦克风录音,录音的数据用speex压缩,然后跨域向服务器发送请求,返回识别的语音和语义...
  • 一,语义识别和语音识别(在线语音识别语义)至于本地识别就是类型不同已备注,云知声语音识别语义识别是在一起的,这个大家使用时可注意了。语音识别我这边就直接转换成了String了,语义识别可能大家要根据自己...
  • 微信公众平台新增语义理解接口 微信公众平台语义理解接口正式对外开放。通过语义接口,接收用户发送的自然语言请求,让系统理解用户的说话内容。 微信语义理解接口提供从用户自然语言输入到结构化解析的技术实现...
  • 语音识别是十年来发展最快的技术之一,随着AI的不断发展,深度学习让语音识别技术得到了质的飞跃,开始从实验室走向市场,并逐步走到人们的生活中。 我们现在所用的语音输入法,以及以语音为智能交互入口的智能家居...
  • 介绍使用百度语音识别sdk时对JSON数据解析的使用方法
  • 这个语义理解类似中文分词技术,优于模糊匹配,拿查股票为例,你说“东风汽车”,“东风汽车股票”,“东风汽车价格”,“查一查东风汽车当前价”返回的内容是一样的,因此语义理解和微信语音识别的配合是最好的,...
  • 本文使用Kotlin开发android平台的一个语音识别方面的应用,用的是欧拉密开放平台olamisdk。1.Kotlin简介Kotlin是由JetBrains创建的基于JVM的编程语言,IntelliJ正是JetBrains的杰作,而android Studio是 基于...
  • 转载请注明CSDN博文地址:http://blog.csdn.net/ls0609/article/details/71519203olami sdk...前面写了两篇语音识别语义理解的博文,分别是语音在线听书和语音记帐软件,本篇是语音智能照相机。1.智能照相机的功能手
  • 从狭义上来说指语音语义理解识别,也称为自动语音识别(ASR)。其关键技术包括选择识别单元、语音端点检测、特征参数提取、声学模型及语音模型的建立。语音识别技术目前在桌面系统、智能手机、导航设备等嵌入式领域...
1 2 3 4 5 ... 20
收藏数 14,372
精华内容 5,748