9.【小萌伴Android】机器人陪聊--语音功能及其实现

前几篇都是介绍一些辅助功能,如新闻、H5游戏段子趣图、原生手电筒应用等,现在再来聊聊机器人陪聊主体功能--语音功能及其实现。

【小萌伴】语音

【小萌伴】中的语音功能使用的是百度语音sdk,包含语音输入、语音播放、语音转文字、文字转语音、声音变换、离线语音语义识别、语音唤醒等。

其中功能的主要可分为三部分:语音识别、语音合成、语音唤醒。(我用的sdk比较老了,下面代码也许已经不兼容新sdk,具体请参考 百度语音 官网

ChatActivity实现了RecognitionListener及SpeechSynthesizerListener接口,这两个接口是语音识别与合成的监听。

初始化

语音识别和语音合成需要在进入Activity后执行初始化,在销毁时进行销毁。初始化如下,语音识别初始化没有封装,语音合成则用TtsUtils封装了一下。

    mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(ChatActivity.this, new ComponentName(ChatActivity.this, VoiceRecognitionService.class));
    // 注册监听器
    mSpeechRecognizer.setRecognitionListener(ChatActivity.this);
    mSpeechSynthesizer = TtsUtils.getSpeechSynthesizer(ChatActivity.this, ChatActivity.this, getVoice(mRobot));

语音输入及识别

对这一块,通过BdVoiceUtil类进行了封装,通过调用如下方法即可开启语音识别:

    BdVoiceUtil.startASR(mSpeechRecognizer, mSpeechSynthesizer, true);

在RecognitionListener的回调中获取语音识别的结果,包括实时(部分)转换及全量(整句话)转换为文字,在onResults或者onPartialResults中将转换的文字发送到机器人api,之后逻辑与正常机器人陪聊一致。

语音合成

将机器人返回的语音转换为文字,这一块也在BdVoiceUtil进行了一下封装:

    BdVoiceUtil.startTTS(mSpeechSynthesizer, msg.getContent());

通过以上代码即可以开始转换,将msg.getContent()转换为语音,可以通过SpeechSynthesizerListener监听转换是否成功,语音播放的进度等。

语音合成后,也可以通过setParam控制声音(0 (普通女声), 1 (普通男声), 2 (特别男声), 3 (情感男声), 4 (童声))等

    mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, String.valueOf(getVoice(robot)));

语音唤醒

语音唤醒功能在这里没有用到,主要是在后续介绍的“找手机”功能用到;包括语音唤醒、通过语音识别达到唤醒的目的、与微信等的语音输入冲突问题等,这些留到后续介绍“找手机”时再说。

BdVoiceUtil

对语音相关的简单封装,其实还有TtsUtils等,总的代码太多,这里就不贴了...

public class BdVoiceUtil {

    /**
     * 开始识别(会先停止SpeechSynthesizer)
     * @param speechRecognizer
     * @param mSpeechSynthesizer
     * @param bindParams 是否需要提示音
     */
    public static void startASR(SpeechRecognizer speechRecognizer, SpeechSynthesizer mSpeechSynthesizer, boolean bindParams) {
        stopTTS(mSpeechSynthesizer);
        Intent intent = new Intent();
        bindParams(intent, bindParams);
        if(speechRecognizer != null) {
            speechRecognizer.startListening(intent);
        }
    }

    public static void stopASR(SpeechRecognizer speechRecognizer) {
        //  说完了
        if(speechRecognizer != null) {
            speechRecognizer.stopListening();
        }
    }

    public static void cancelASR(SpeechRecognizer speechRecognizer) {
        // 取消
        if(speechRecognizer != null) {
            speechRecognizer.cancel();
        }
    }

    public static void destroyASR(SpeechRecognizer speechRecognizer) {
        cancelASR(speechRecognizer);
        if(speechRecognizer != null) {
            speechRecognizer.destroy();
        }
    }

    public static void bindParams(Intent intent, boolean hintSound) {
        if(hintSound) {
            // 设置识别参数
            intent.putExtra(TtsUtils.EXTRA_SOUND_START, R.raw.bdspeech_recognition_start);
            intent.putExtra(TtsUtils.EXTRA_SOUND_END, R.raw.bdspeech_speech_end);
            intent.putExtra(TtsUtils.EXTRA_SOUND_SUCCESS, R.raw.bdspeech_recognition_success);
            intent.putExtra(TtsUtils.EXTRA_SOUND_ERROR, R.raw.bdspeech_recognition_error);
            intent.putExtra(TtsUtils.EXTRA_SOUND_CANCEL, R.raw.bdspeech_recognition_cancel);
        }
        intent.putExtra("sample", 16000); // 离线仅支持16000采样率
        intent.putExtra("language", "cmn-Hans-CN"); // 离线仅支持中文普通话
        intent.putExtra("prop", 20000); // 输入
        // 语音输入附加资源,value替换为资源文件实际路径
        // 离线包过大,暂不考虑支持 intent.putExtra("lm-res-file-path", "/path/to/s_2_InputMethod");
    }

    public static EventManager initEventWakeUp(final Activity context) {
        // 唤醒功能打开步骤
        // 1) 创建唤醒事件管理器
        EventManager mWpEventManager = EventManagerFactory.create(context, "wp");
        // 2) 注册唤醒事件监听器
        mWpEventManager.registerListener(new EventListener() {
            @Override
            public void onEvent(String name, String params, byte[] data, int offset, int length) {
                try {
                    if(params == null) {
                        return;
                    }
                    JSONObject json = new JSONObject(params);
                    if ("wp.data".equals(name)) { // 每次唤醒成功, 将会回调name=wp.data的时间, 被激活的唤醒词在params的word字段
                        String word = json.getString("word"); // 唤醒词
                        WpEventManagerUtil.doEvent(context, word);
                        if(Logs.isDebug()) {
                            Logs.logI(BdVoiceUtil.class.getSimpleName(), "百度语音唤醒" + word);
                        }
                    } else if ("wp.exit".equals(name)) {
                        // 唤醒已经停止
                    }
                } catch (JSONException e) {
                    throw new AndroidRuntimeException(e);
                }
            }
        });
        return mWpEventManager;
    }
    public static EventManager eventWakeUp(final Activity context, EventManager mWpEventManager) {
        if(mWpEventManager == null) {
            mWpEventManager = initEventWakeUp(context);
        }
        // 3) 通知唤醒管理器, 启动唤醒功能
        HashMap params = new HashMap();
        params.put("kws-file", "assets:///WakeUp.bin"); // 设置唤醒资源, 唤醒资源请到 http://yuyin.baidu.com/wake#m4 来评估和导出
        mWpEventManager.send("wp.start", new JSONObject(params).toString(), null, 0, 0);
        return mWpEventManager;
    }

    public static void eventWekeUpStop(EventManager mWpEventManager) {
        if(mWpEventManager != null) {
            // 停止唤醒监听
            mWpEventManager.send("wp.stop", null, null, 0, 0);
        }
    }


    public static void stopTTS(SpeechSynthesizer mSpeechSynthesizer) {
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.stop();
        }
    }

    public static void releaseTTS(SpeechSynthesizer mSpeechSynthesizer) {
        stopTTS(mSpeechSynthesizer);
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.release();
        }
    }

    public static void startTTS(SpeechSynthesizer mSpeechSynthesizer, String text) {
        stopTTS(mSpeechSynthesizer);
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.speak(text);
        }
    }
}

页面布局与一般输入框没大差别,这里就不多说了~~~

个人博客: IT老五
微信公众号:IT老五(it-lao5),一起源创,一起学习!

相关内容:
【小萌伴Android】相关文章目录
1.【小萌伴Android】思量再三,终于鼓起勇气开源~
2.【小萌伴Android】机器人陪聊模块分享
3.【小萌伴Android】新闻/H5游戏模块及广告过滤
4.【小萌伴Android】段子趣图模块及其实现段子趣图数据爬取
5.【小萌伴Android】原生小游戏及其实现(一)2048
6.【小萌伴Android】原生小游戏及其实现(二)小鸟
7.【小萌伴Android】原生小游戏及其实现(三)飞机
8.【小萌伴Android】手电筒功能及其实现
9.【小萌伴Android】机器人陪聊--语音功能及其实现

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

推荐阅读更多精彩内容