美文网首页
自定义SpeechService开发指导

自定义SpeechService开发指导

作者: 徐海波 | 来源:发表于2019-07-20 18:40 被阅读0次

    概述

    悟空机器人在语音识别这块官方只支持中文、英语和韩文,开发者们可能希望让悟空支持更多的语言,为此他们需要接入新的语音服务商(如Alexa, Google Assistant等),如果想让语音交互的体验达到悟空官方版本的效果,开发者需要做大量的开发工作。为此我们开发了一套开发框架SpeechFramework,方便快速接入。 该框架把麦克风阵列模块、唤醒模块、识别模块、TTS模块、交互模型整合在一起,并实现各阶段的自动切换。它实现了麦克风阵列的开关,录音数据的读取,声源定位,并实现与机器人中其他模块的通信,实现开机自动启动, 休眠时自动关闭麦克风阵列,激活时重新开启的功能。开发者只需要按照我们定义的接口,来实现唤醒、识别、TTS模块(可选),就可以实现完整的与悟空机器人内置语音模块一样的交互表现。

    基本框架如下:

    speechFramework (1).png

    核心模块说明

    MicArrayModule:从4-Mic中读取原始的音频数据,经过麦克风阵列前端算法处理后,输出16K HZ、 16bit、 单通道的音频数据。

    WakeupModule : 实现唤醒功能,通过不断从MicArrayModule读取麦克风数据输入到唤醒引擎中监测是否发生了语音唤醒,当发生了语音唤醒时通过发布唤醒事件来触发RecognizeModule进入到识别阶段。

    RecognizeModule:包含ASR、NLP、TTS过程,开发者即可以集成Amazon AVS和腾讯叮当这类端到端的完整语音服务,也可以通过分别接入ASR Api,NLP Api,TTS Api来实现语音交互功能。

    Interactive Model: 当机器人被语音唤醒时,当机器人处于识别状态时,当机器人处于等待识别结果阶段时,机器人都有不同的表现,为保证交互的一致性,我们已经实现了标准的交互模型,开发者不需额外开发。
    唤醒时:播报唤醒应答音频,眼睛播放微笑动画,转头声源定位;
    语音识别阶段:眼睛播放眨眼动画;
    NLP识别阶段:眼睛播放左右转动动画;

    Note:
    开发者可以通过传入音频资源的id来自定义唤醒应答,并允许传入多个;
    转头声源定位的时机可以自定义,支持在唤醒时或者语音识别结束时。

    编码实现

    如何获取访问麦克风阵列访问权限

    1.增加标签

    AndroidManifest.xml文件application标签里,加入如下代码,申请访问麦克风阵列

    <meta-data android:name="ubt-master-app" android:value="third_part_speechservice"/>
    

    2. 首次安装该apk后,需要重启机器人

    机器人在每次开机时会检查安装的apk里有没有third_part_speechservice标记,如果有的话,
    则disable系统内置的访问麦克风阵列的应用SpeechService,把麦克风阵列的访问权让给该apk。
    系统内置的SpeechService被disable后,用户将无法访问腾讯叮当语音服务。

    让出麦克风阵列访问权

    1.卸载app或去掉meta-data的标签

    2.重启机器人
    重启机器人后,系统内置的SpeechService将重新获取麦克风阵列访问权限, 用户可以继续使用叮当语音服务。

    SDK引入

    • 下载demo工程speechmoduledemo
      包含的sdk如下:
    micrecord-sdk-release-versionCode.aar
    mini-outer-sdk-versionCode.jar
    protobuf-java-versionCode.jar
    speechFramework-release-versionCode.jar
    
    • sdk引入:
      在app module的build.gradle文件里配置如下:
    android {
        repositories {
            flatDir {
                dirs 'libs'
            }
        }
    
    }
    
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
       implementation(name: 'speechFramework-release', ext: 'aar')
        implementation(name: 'micrecord-sdk-release', ext: 'aar')
        implementation 'org.greenrobot:eventbus:3.0.0'
    }
    
    • 初始化:
      在自定义的Application子类的onCreate()的方法中加入如下代码:
            //setting turn head timing and wakeup reply media file
            Config config = new Config.Builder().timing(TurnHeadApi.Timing.AfterRecord).
                    wakeupResList(new int[] {R.raw.wakeup_001,R.raw.wakeup_002}).build();
    
            IModuleManager.Builder builder = new IModuleManager.Builder().recognizeModuleFactory(new DemoRecognizeModuleFactory())
                    .ttsModuleFactory(new DemoTtsModuleFactory())
                    .wakeupModuleFactory(new DemoWakeupModuleFactory())
                    .config(config);
    
            //inject
            SpeechManager.get().setImpl(new DefaultSpeechServiceImpl(builder));
    

    Config可以设置声源定位转头的时机以及自定义唤醒响应音频,当设置多个音频时则会随机播放一个。音频资源建议放在app工程的res/raw/目录下,支持mp3,wav等格式。
    IModuleManager用于设置RecognizeModule的工厂类,WakeupModule的工厂类,TTSModule的工厂类以及设置Config.
    SpeechManager.get().setImpl(new DefaultSpeechServiceImpl(builder));用于把`IModuleManager注入到SpeechFramework,由SpeechFramework来实现各个Module的调用。

    • WakeupModule的实现
      1.实现IWakeupModule接口。
    public interface IWakeupModule {
    
        void init(IWakeuperListener listener);
        void destroy();
        void enable();
        void disable();
        boolean isEnable();
        /**
         * @param pcmData the record data after wakeup
         * @param dataLen the record data length
         */
        void writeAudio(byte[] pcmData, int dataLen);
    }
    

    所有的接口方法都由SpeechFramework调用,开发者必须要严格按照要求进行重写。
    init():
    在此方法中实现唤醒模块的初始化,当初始化成功时请调用IWakeuperListener.onInitSuccess()当初始化失败时请调用IWakeuperListener.onInitError(errMsg,errCode). 只有WakeupModule初始化成功,机器人开机时才会播报已经准备好了。

    enable():使唤醒模块可用
    disable():禁用唤醒模块
    isEnable():判断唤醒模块是否可用,只有isEnable() ==true时麦克风数据才会输入到WakeupModule。
    writeAudio():用于接收麦克风数据,麦克风数据为16K HZ, 16bit, 单通道。 开发者需要把麦克风数据持续写入到唤醒引擎。当唤醒引擎检测到唤醒时,需要调用IWakeuperListener.onWakeup(wakeword),当SpeechFramework收到onWakeup()回调时Interactive Model会播报唤醒响应音频,并播放唤醒眼睛表情,同时会启动RecognizeModule,进入到语音识别阶段。
    destory():模块退出时调用,可以在此释放资源。

    1. 实现WakeupModuleFactory接口来实例化WakeupModule对象。
    public interface WakeupModuleFactory {
        IWakeupModule factory();
    }
    
    • RecognizeModule的实现
      1.实现IRecognizeModule接口
    public interface IRecognizeModule {
        void init(IRecognizerListener listener);
        void destroy();
        void startListening();
        /**
         * stop recognize
         */
        void stopListening();
    
        /**
         * @param data byte[]
         * @param start start >= 0
         * @param end end < byte.length
         */
        int writeAudio(byte[] data, int start, int end);
    
        /**
         * @return boolean Is Listening
         */
        boolean isListening();
    }
    

    在该Module里可以去接入Amazon AVS、腾讯叮当这样的完整的语音服务,也可以去分别接入ASR、NLP、TTS API.
    init():进行初始化。
    startListening():启动识别过程,当采用云端识别时,应开始于服务器建立连接,并开始把麦克风数据传输到云端识别服务。
    stopListening():中断识别过程,当在识别过程中,用户再次唤醒会调用该方法来中断当前的识别,然后再调用startListening()来启动新一轮的识别。
    writeAudio():用于接收麦克风数据,开发者需要把收到的数据持续地传输到识别服务。当isListening()== false时将无法收到麦克风数据。
    isListening():判断当前是否在识别阶段。
    destory():模块退出时调用,可以在此释放资源。
    2.错误处理:
    在RecognizeModule可能存在多种错误,在Speech.ErrorCode里我们有定义常见的错误,开发者在回调IRecognizerListener.onError()需要传入正确的错误码。SpeechFramework会把Error Event发布出去,机器人其他模块会进行相应的错误播报。

    1. 实现RecognizeModuleFactory接口来实例化RecognizeModule对象。
    public interface RecognizeModuleFactory {
        IRecognizeModule factory();
    }
    
    • TTSModule的实现:
      当开发者在RecognizeModule里接入的是Amazon AVS或腾讯叮当这样的完整的语音服务平台时,NLP识别的结果会直接在云端进行tts合成,然后把合成的结果返回给机器人端。 这种情况可以不需要实现TTSModule,但机器人其他模块如果需要实现tts播报时就需要实现,比如在一个app里实现了人脸识别的功能,需要把识别的人名播报出来,在另外一个app里实现了开机播报天气预报的功能,都需要使用到tts功能,这时就需要实现TTSModule,在其他app里开发者可以通过我们提供的SpeechApi.playTTS()方法来把tts请求传递给TTSModule。
    1. 实现ITtsModule接口
    public interface ITtsModule {
    
        void init();
    
        boolean destroy();
    
        /**
         * 启动tts播报
         *
         * @param text 播报文本
         * @param listener 播报状态回调监听
         */
        void startSpeaking(String text, ITTsListener listener);
    
        /**
         * 停止tts播报
         */
        void stopSpeaking();
    }
    

    init():模块的初始化
    destory():退出该模块,可以释放资源
    startSpeaking():开发者需要在此实现tts合成功能,并把结果通过回调ITtsListener的方法传递给调用者。
    ``
    stopSpeaking():停止播报。

    1. 实现TtsModuleFactory接口,实例化TtsModule.
    public interface TtsModuleFactory {
        ITtsModule factory();
    }
    

    相关文章

      网友评论

          本文标题:自定义SpeechService开发指导

          本文链接:https://www.haomeiwen.com/subject/zptulctx.html