Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

138.3. 语音唤醒

138.3.1. 范例

		
package cn.netkiller.album.religion.ai;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.iflytek.cloud.RequestListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.VoiceWakeuper;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;
import com.iflytek.cloud.util.ResourceUtil;

import java.nio.charset.StandardCharsets;

import cn.netkiller.album.religion.ContextHolder;
import cn.assets.album.religion.R;

public class Wakeup {
    private static final String TAG = Wakeup.class.getSimpleName();
    private final int curThresh = 1450;
    private final String threshStr = "门限值:";
    private final String keep_alive = "1";
    private final String ivwNetMode = "0";
    private final Context context;
    // 查询资源请求回调监听
    private final RequestListener requestListener = new RequestListener() {
        @Override
        public void onEvent(int eventType, Bundle params) {
            // 以下代码用于获取查询会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            //if(SpeechEvent.EVENT_SESSION_ID == eventType) {
            // 	Log.d(TAG, "sid:"+params.getString(SpeechEvent.KEY_EVENT_SESSION_ID));
            //}
        }

        @Override
        public void onCompleted(SpeechError error) {
            if (error != null) {
                Log.d(TAG, "error:" + error.getErrorCode());
                showTip(error.getPlainDescription(true));
            }
        }

        @Override
        public void onBufferReceived(byte[] buffer) {
            try {
                String resultInfo = new String(buffer, StandardCharsets.UTF_8);
                Log.d(TAG, "resultInfo:" + resultInfo);

//                JSONTokener tokener = new JSONTokener(resultInfo);
//                JSONObject object = new JSONObject(tokener);
//
//                int ret = object.getInt("ret");
//                if (ret == 0) {
//                    String uri = object.getString("dlurl");
//                    String md5 = object.getString("md5");
//                    Log.d(TAG, "uri:" + uri);
//                    Log.d(TAG, "md5:" + md5);
//                    showTip("请求成功");
//                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private VoiceWakeuper voiceWakeuper;
    // 唤醒结果内容
    private String resultString;
    private final WakeuperListener wakeuperListener = new WakeuperListener() {

        @Override
        public void onResult(WakeuperResult result) {
            Log.d(TAG, "onResult");

            try {
                String text = result.getResultString();
                Log.d(TAG, text);
//                JSONObject object;
//                object = new JSONObject(text);
//                StringBuffer buffer = new StringBuffer();
//                buffer.append("【RAW】 " + text);
//                buffer.append("\n");
//                buffer.append("【操作类型】" + object.optString("sst"));
//                buffer.append("\n");
//                buffer.append("【唤醒词id】" + object.optString("id"));
//                buffer.append("\n");
//                buffer.append("【得分】" + object.optString("score"));
//                buffer.append("\n");
//                buffer.append("【前端点】" + object.optString("bos"));
//                buffer.append("\n");
//                buffer.append("【尾端点】" + object.optString("eos"));
//                resultString = buffer.toString();
                showTip(text);
            } catch (Exception e) {
                resultString = "结果解析出错";
                e.printStackTrace();
            }

        }

        @Override
        public void onError(SpeechError error) {
            showTip(error.getPlainDescription(true));
        }

        @Override
        public void onBeginOfSpeech() {
        }

        @Override
        public void onEvent(int eventType, int isLast, int arg2, Bundle obj) {
            // EVENT_RECORD_DATA 事件仅在 NOTIFY_RECORD_DATA 参数值为 真 时返回
            if (eventType == SpeechEvent.EVENT_RECORD_DATA) {
                final byte[] audio = obj.getByteArray(SpeechEvent.KEY_EVENT_RECORD_DATA);
                Log.i(TAG, "ivw audio length: " + audio.length);
            }
        }

        @Override
        public void onVolumeChanged(int volume) {

        }
    };
    // 设置门限值 : 门限值越低越容易被唤醒


    public Wakeup() {
        this.context = ContextHolder.getContext();
//        String param = "appid=" + context.getString(R.string.app_id) + "," + SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC;
//        SpeechUtility.createUtility(context, param);

        voiceWakeuper = VoiceWakeuper.createWakeuper(context, null);
        if (null == voiceWakeuper) {
            // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
            Toast.makeText(context
                    , "创建对象失败,请确认 libmsc.so 放置正确,\n 且有调用 createUtility 进行初始化"
                    , Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(context, "准备唤醒", Toast.LENGTH_LONG).show();
            // 清空参数
            voiceWakeuper.setParameter(SpeechConstant.PARAMS, null);
            // 唤醒门限值,根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
            voiceWakeuper.setParameter(SpeechConstant.IVW_THRESHOLD, "0:1450");
            // 设置唤醒模式
            voiceWakeuper.setParameter(SpeechConstant.IVW_SST, "wakeup");
            // 设置持续进行唤醒
            voiceWakeuper.setParameter(SpeechConstant.KEEP_ALIVE, "1");
            // 设置闭环优化网络模式
            voiceWakeuper.setParameter(SpeechConstant.IVW_NET_MODE, "1");
            // 设置唤醒资源路径
            voiceWakeuper.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
            // 设置唤醒录音保存路径,保存最近一分钟的音频
            voiceWakeuper.setParameter(SpeechConstant.IVW_AUDIO_PATH,
                    context.getExternalFilesDir("msc").getAbsolutePath() + "/ivw.wav");
            voiceWakeuper.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
            // 如有需要,设置 NOTIFY_RECORD_DATA 以实时通过 onEvent 返回录音音频流字节
            //voiceWakeuper.setParameter( SpeechConstant.NOTIFY_RECORD_DATA, "1" );
            // 启动唤醒
            /*	voiceWakeuper.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");*/
        }
    }

    public void startListening(WakeuperListener wakeuperListener) {
        //非空判断,防止因空指针使程序崩溃
        voiceWakeuper = VoiceWakeuper.getWakeuper();
        if (voiceWakeuper != null) {
            resultString = "";
            voiceWakeuper.startListening(wakeuperListener);
        } else {
            showTip("唤醒未初始化");
        }
    }

    private void stopListening() {
        voiceWakeuper = VoiceWakeuper.getWakeuper();
        if (voiceWakeuper != null) {
            voiceWakeuper.stopListening();
        }
    }

    public void cancel() {
        // 销毁合成对象
        voiceWakeuper = VoiceWakeuper.getWakeuper();
        if (voiceWakeuper != null) {
            voiceWakeuper.cancel();
        }
    }

    public void destroy() {
        // 销毁合成对象
        voiceWakeuper = VoiceWakeuper.getWakeuper();
        if (voiceWakeuper != null) {
            voiceWakeuper.destroy();
        }
    }

    private String getResource() {
        final String resPath = ResourceUtil.generateResourcePath(context, ResourceUtil.RESOURCE_TYPE.assets, "ivw/" + context.getString(R.string.app_id) + ".jet");
        Log.d(TAG, "resPath: " + resPath);
        return resPath;
    }

    /**
     * 查询闭环优化唤醒资源
     * 请在闭环优化网络模式1或者模式2使用
     */
//    public void queryResource() {
//        int ret = voiceWakeuper.queryResource(getResource(), requestListener);
//        showTip("updateResource ret:" + ret);
//    }
    private void showTip(final String str) {
//        runOnUiThread(new Runnable() {
//            @Override
//            public void run() {

        Toast.makeText(context.getApplicationContext(), str, Toast.LENGTH_SHORT).show();

//            }
//        });
    }
}