精华内容
下载资源
问答
  • 语音唤醒 SDK

    2018-07-19 15:52:47
    基于讯飞,语音唤醒 demo,appid=5af0ffe1,其中包括语音听写、语音合成等
  • Unity学习笔记通过接入百度语音sdk实现语音唤醒功能第一步第二步第三步第四步第五步第六步第八步 通过接入百度语音sdk实现语音唤醒功能 上次研究语音唤醒已经不知道是什么时候了,在这里感谢互联网,让基本对安卓完全...

    通过接入百度语音sdk实现语音唤醒功能

    上次研究语音唤醒已经不知道是什么时候了,在这里感谢互联网,让基本对安卓完全没基础的小白做到了这个功能
    具体的代码实现在下面的这个帖子里可以说是很完整了(大佬可能是忘了还是懒得看,甚至appid啥的忘了打码)

    https://blog.csdn.net/weixin_43271060/article/details/108381456

    就是这个帖子,把从百度开账号到安卓代码,打aar包,配置文件里面的依赖和unity如何调用都写的一清二楚明明白白
    小弟就是单纯的依葫芦画瓢,站在巨人的肩膀上而已,orz.只能说大佬们真的太强了
    这里我会说下自己在跟着帖子做的时候的心路历程和过程遇到问题是如何解决的

    第一步

    在百度智能云里开通账号,在语音技术里创建应用
    Tips在创建的时候记得勾选包名 Android以及写上自己的包名
    在这里插入图片描述
    如果你不需要用到语音唤醒那么可以不用加包名,如果要用到的话一定要有包名,这个在上图的右边有写上原因
    在实际的操作中我遇到的一个问题就是语音识别没问题,但是语音唤醒死活整不出来,看日志上面显示的是百度的错误码11002,查看官方文档是没有授权文件
    在这里插入图片描述
    也就是上图说的包名是一定要正确的.也就是在百度里设置的包名安卓里aar项目里的包名unity里真机打包出来时设置的包名
    只有这三个的包名都是一致的情况下,sdk才会在联网的时候去申请授权文件,唤醒的功能才能算是正式激活
    这是个巨坑,我卡在这个地方大概有一个多小时,全靠百度看大佬们的帖子才发现的这个问题,不过大佬们都没有提及到的就是unity里playersetting的包名也是要和百度里设置的一样的,不然就会有问题.为啥我会联想到unity的包名就是因为大佬们的帖子里都在说安卓和百度的包名一致,说明他们的环境不包括unity,但是我的项目就是unity的,所以才会想起来unity里也是需要保持包名一致的
    至于为啥上面提供的帖子里没有特别注明,现在想想是因为帖子里有一个关于签名的方法和aar打包的方法,这两个东东大佬是引用了另一个帖子来解决的,在那个帖子里我记得是有说明安卓和unity的包名必须一致的.所以可能大佬那个时候已经是在包名一致的情况下去做的这个项目,所以没有遇到这个问题,也才没有特别提出.

    其实第一步已经把我自己在实际操作中遇到的最难的问题解决了,所以这后面的我没啥好说太多的

    第二步

    新建一个as项目,这里大佬也没有特别说明,我就用了之前自己新建的模式去建了,没啥问题
    在这里插入图片描述
    这是新建的项目里的结构
    因为我们最终是从as 里打包出一个aar包到unity里,所以我们还需要在这个项目里面新建一个module
    这个有一点安卓基础的应该都不难
    在这里插入图片描述
    然后选Android library就可以了
    在这里插入图片描述
    这里新建了module之后的结构

    第三步

    解压下载的压缩包到任意目录下,然后把里面的一个jar包引入到刚才建的module中,记得添加引用(大佬的帖子里都有说,我就不多说了)在这里插入图片描述就这个包
    哦这个提一嘴,如果是新项目的话,还需要在这里面添加一个和unity关联的jar包,因为需要给unity发送消息需要用到这个包里的方法
    所以一共我们需要用的包是两个
    在这里插入图片描述

    unity的这个包百度一下会有很多告诉你在哪里拿这个包的,不过还得注意一下,不同的unity版本,这个包在所在的位置是不同的喔,记得留心
    我用的是2019的,在前面我写的安卓unity相互跳转的帖子里有说道具体的路径位置
    嘛,不过这个unity的jar包最后打包出来的时候是需要删掉的,不然在unity打包成最终的apk的时候会失败,因为unity自己就有这个jar包了,你又在这个aar里重复用,unity在打包项目上的时候会不知道到底用谁导致报错,无法打包

    第四步

    敲java代码,这里我完全是cv大法完成的,过程没有加入自己的一点灵魂
    照着帖子做就可以了,遇到引用报红的时候先不急,把所有代码都写进入之后再引用就可以了
    这里也有一个小地方需要注意的
    帖子里说的
    在这里插入图片描述
    这里编写的是新建的module里的这个文件,不是一开始新建项目自带的app里的同名文件
    然后可能有三个类的引用会有红波浪线,那个可以忽略它, 在实际的应用中是没有影响的

    第五步

    打aar包
    这个因为小弟之前打过好几次了,所以这个就相对比较熟练
    在这里插入图片描述
    找到module里的bulid.gradle,然后添加右面的那个代码,sync一下
    然后在右边点gradle会弹出下图的框,找到你的module名称,点击里面的other,然后找到刚才代码里敲的方法名,我这里写的和帖子大佬里写的一样,双击右边的那个方法就可以开始打包了
    在这里插入图片描述
    可能是之前打包过,所以没有遇到什么问题,如果在打包过程中遇到问题的话可以参考帖子大佬最后发的那个链接,里面有很多解决打包遇到的问题的方法

    第六步

    找到这个路径里-release后缀的aar包,这个就是我们需要的了
    注意前面说了需要删掉aar包里的unity-classesjar包,不然后面unity打包回报错
    怎么删很简单,先把这个包后缀改成zip,然后双击打开,找到libs,然后把里面的这个unity的jar包删掉,再把后缀改回aar就可以了

    #@ 第七步
    导入unity的路径,需要放置在下图的路径里,如果是新项目就自己创建文件夹就好了
    在这里插入图片描述

    第八步

    unity这里的代码我也是直接cv大法大佬的基本没有改过
    可能需要自己在类里声明一个AndroidJavaObject这个类其他的没啥
    不过确实有可以优化的地方.嘛这个问题不大
    不过这里帖子大佬没有说的一个就是这个类不是单纯的挂载到场景中的对象就可以了
    还需要在start或者awake里去调用唤醒的方法
    并且,如果前面安卓代码和我一样是直接复制粘贴没有注意看代码的话,等你在打包的时候一定是会出问题的,你会发现死活接受不到安卓回传的信息
    这里大佬是没有特别说要注意的
    我也是在自己之前和安卓工程师对接的时候知道的,就是as在代码里通过unity代码向我们发送消息的时候,是需要场景中某一个对象作为载体的,通过名称去找到这个载体,然后找到载体上挂载的方法去回传信息给unity
    在这里插入图片描述
    像这里,大佬写的对象就是叫NetLogic,然后调用的方法名叫WakeupResult
    所以在unity里你的场景里也必须要有这个对象名才可以实现消息的互通
    嘛,这个仔细想想的话自己在做安卓和unity消息互通的时候已经试过了,只是当时一次就成功了就没多留意

    到这里基本就结束了我在实现语音唤醒功能中的流程了
    希望能对大家有所帮助

    感谢以下帖子
    虽然没有实际解决我的问题,但给我的灵感和启发都是至关重要的

    https://blog.csdn.net/qq_45137584/article/details/115443437

    https://www.jianshu.com/p/a9ae5d3333d2

    2021.9.16更新
    需要注意一下
    如果需要让用户自定义是否开启语音唤醒的话,除了上面untiy里的stop唤醒的方法外
    还需要调用在as里写好的释放唤醒实例的那个方法才行
    举个例子,我是通过点击一个toggle调用脚本的enable去开启语音唤醒,disable去关闭语音唤醒
    在脚本的awake方法里先和aar包取得联系,然后在onenable方法里开启初始化语音唤醒和开始唤醒的方法
    如果是不需要语音唤醒的话,点击toggle,识别到ison = fales,会自动调用脚本的ondisable方法,然后在这个方法里调用关闭语音唤醒和释放语音实例的方法就可以了
    在这里插入图片描述
    就像这样

    场景中的toggle是这样设置的
    在这里插入图片描述

    展开全文
  • 这是科大讯飞的智能语音唤醒sdk,同学们想了解科大讯飞如何实现语音唤醒的话,可以下载此源码进行了解了解。了解整个语音唤醒的框架及其流程。 开发语言是Java,下载者需谨慎,不懂Java开发的不要下载哦
  • 在libs和jniLibs加入对应jar包... * 唤醒 */ public class WakeUpUtils { private final String TAG = this.getClass().getSimpleName(); private static WakeUpUtils utils = null; private EventManage...

    在libs和jniLibs加入对应jar包和so库

    /**
     * 唤醒
     */
    public class WakeUpUtils {
    
        private final String TAG = this.getClass().getSimpleName();
        private static WakeUpUtils utils = null;
        private EventManager eventManager;
        private EventListener listener;
        private boolean isInited = false;
        private static Handler handler;
        private final int WAKEUP = 1010;
        // 是否加载离线资源
        private boolean isOfflineEngineLoaded = false;
    
        public WakeUpUtils(){
            init();
        }
    
        public static WakeUpUtils getIntance(Handler mHandler){
            handler = mHandler;
            if (utils == null){
                synchronized (WakeUpUtils.class){
                    if (utils == null){
                        utils = new WakeUpUtils();
                    }
                }
            }
            return utils;
        }
    
        private void init(){
            if (isInited){
                LogUtils.log(TAG,"还未调用release(),请勿新建一个新类");
                return;
            }
            isInited = true;
            //创建唤醒事件管理器
            eventManager = EventManagerFactory.create(MyApplication.context,"wp");
            //注册唤醒事件监听器
            eventManager.registerListener(new EventListener() {
                @Override
                public void onEvent(String name, String params1, byte[] bytes, int i, int i1) {
                    try{
                        listener = this;
                        if ("wp.data".equals(name)){
                            LogUtils.log("唤醒", params1);
                            TTSUtils.getInstance().speak(MyApplication.context.getString(R.string.wakeup_yes), true);
    //                        handler.sendEmptyMessage(WAKEUP);
    //                        RecognizerUtils.getIntance(handler).start();
                        }else if ("wp.exit".equals(name)){
                            LogUtils.log("唤醒退出", params1);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            loadOfflineEngine(fetchOfflineParams());
        }
    
        /**
         * 离线命令词,在线不需要调用
         *
         * @param params 离线命令词加载参数,见文档“ASR_KWS_LOAD_ENGINE 输入事件参数”
         */
        private void loadOfflineEngine(Map<String, Object> params) {
            String json = new JSONObject(params).toString();
            // SDK集成步骤(可选)加载离线命令词(离线时使用)
            eventManager.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, json, null, 0, 0);
            isOfflineEngineLoaded = true;
            // 没有ASR_KWS_LOAD_ENGINE这个回调表试失败,如缺少第一次联网时下载的正式授权文件。
        }
    
        private Map<String, Object> fetchOfflineParams() {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(SpeechConstant.DECODER, 2);
            map.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets:///baidu_speech_grammar.bsg");
            map.putAll(fetchSlotDataParam());
            return map;
        }
    
        private Map<String, Object> fetchSlotDataParam() {
            Map<String, Object> map = new HashMap<String, Object>();
            try {
                JSONObject json = new JSONObject();
                json.put("name", new JSONArray().put("妈妈").put("老伍"))
                        .put("appname", new JSONArray().put("手百").put("度秘"));
                map.put(SpeechConstant.SLOT_DATA, json);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return map;
        }
    
        public void start() {
            if (eventManager != null){
                HashMap params = new HashMap();
                params.put("kws-file","assets:///WakeUp.bin");
                eventManager.send("wp.start",new JSONObject(params).toString(), null,0,0);
            }
        }
    
        public void stop() {
            if (eventManager != null){
                eventManager.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0);
            }
        }
    
        public void release() {
            isInited = false;
            stop();
            if (eventManager != null){
                if (isOfflineEngineLoaded) {
                    // SDK集成步骤 如果之前有调用过 加载离线命令词,这里要对应释放
                    eventManager.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0);
                    isOfflineEngineLoaded = false;
                }
                eventManager.unregisterListener(listener);
                eventManager = null;
                utils = null;
            }
        }
    
    }
    
    
    // 合成
    public class TTSUtils {
        private static TTSUtils utils = null;
        private SpeechSynthesizer mSpeechSynthesizer;
        private boolean isWakeUp = false;
    
        public TTSUtils(){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    init();
                }
            }).start();
        }
        public static TTSUtils getInstance(){
            if (utils == null){
                synchronized (TTSUtils.class){
                    if (utils == null){
                        utils = new TTSUtils();
                    }
                }
            }
            return utils;
        }
    
        /**
         * speak 实际上是调用 synthesize后,获取音频流,然后播放。
         * 获取音频流的方式见SaveFileActivity及FileSaveListener
         * 需要合成的文本text的长度不能超过1024个GBK字节。
         */
        public void speak(String text) {
            // 需要合成的文本text的长度不能超过1024个GBK字节。
            if (mSpeechSynthesizer != null){
                mSpeechSynthesizer.speak(text);
            }
        }
    
        /**
         * speak 实际上是调用 synthesize后,获取音频流,然后播放。
         * 获取音频流的方式见SaveFileActivity及FileSaveListener
         * 需要合成的文本text的长度不能超过1024个GBK字节。
         */
        public void speak(String text, boolean isWakeUp) {
            this.isWakeUp = isWakeUp;
            // 需要合成的文本text的长度不能超过1024个GBK字节。
            if (mSpeechSynthesizer != null){
                mSpeechSynthesizer.speak(text);
            }
        }
    
        public void pause() {
            // 需要合成的文本text的长度不能超过1024个GBK字节。
            if (mSpeechSynthesizer != null){
                mSpeechSynthesizer.pause();
            }
        }
    
        public void resume() {
            // 需要合成的文本text的长度不能超过1024个GBK字节。
            if (mSpeechSynthesizer != null){
                mSpeechSynthesizer.resume();
            }
        }
    
        public void stop() {
            // 需要合成的文本text的长度不能超过1024个GBK字节。
            if (mSpeechSynthesizer != null){
                mSpeechSynthesizer.stop();
            }
        }
    
        public void release() {
            // 需要合成的文本text的长度不能超过1024个GBK字节。
            if (mSpeechSynthesizer != null){
                mSpeechSynthesizer.release();
            }
        }
    
    
        private void init(){
            mSpeechSynthesizer = SpeechSynthesizer.getInstance();
            mSpeechSynthesizer.setContext(MyApplication.context.getApplicationContext());
            mSpeechSynthesizer.setSpeechSynthesizerListener(new SpeechSynthesizerListener() {
                @Override
                public void onSynthesizeStart(String s) {
    //                LogUtils.log("TTSUtils", "onSynthesizeStart" + "--" + s);
                }
    
                @Override
                public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {
    //                LogUtils.log("TTSUtils", "onSynthesizeDataArrived" + "--" + s);
                }
    
                @Override
                public void onSynthesizeFinish(String s) {
    //                LogUtils.log("TTSUtils", "onSynthesizeFinish" + "--" + s);
                }
    
                @Override
                public void onSpeechStart(String s) {
    //                LogUtils.log("TTSUtils", "onSpeechStart" + "--" + s);
                }
    
                @Override
                public void onSpeechProgressChanged(String s, int i) {
    //                LogUtils.log("TTSUtils", "onSpeechProgressChanged" + "--" + s);
                }
    
                @Override
                public void onSpeechFinish(String s) {
    //                LogUtils.log("TTSUtils", "onSpeechFinish" + "--" + s);
                    if (isWakeUp){
                        isWakeUp = false;
                        RecognizerUtils.getIntance().start();
                    }
                }
    
                @Override
                public void onError(String s, SpeechError speechError) {
    //                LogUtils.log("TTSUtils", "onError" + "--" + s + "--" +speechError.description);
                }
            });
            /*这里只是为了让Demo运行使用的APPID,请替换成自己的id。*/
            mSpeechSynthesizer.setAppId("15692915");
            /*这里只是为了让Demo正常运行使用APIKey,请替换成自己的APIKey*/
            mSpeechSynthesizer.setApiKey("R2XiXKorcR75HyIejnBROSMm",
                    "Co85H7ZXROB0DEM4WfLgAlEojUd5GXFi");
    
            // 授权检测接口(只是通过AuthInfo进行检验授权是否成功。选择纯在线可以不必调用auth方法。
            AuthInfo authInfo = mSpeechSynthesizer.auth(TtsMode.MIX);
            if (!authInfo.isSuccess()) {
                // 离线授权需要网站上的应用填写包名。本demo的包名是com.baidu.tts.sample,定义在build.gradle中
                String errorMsg = authInfo.getTtsError().getDetailMessage();
                LogUtils.log("TTSUtils","鉴权失败 =" + errorMsg);
            } else {
                LogUtils.log("TTSUtils","验证通过,离线正式授权文件存在。");
            }
    
            getParams();
            // 初始化tts
            int result = mSpeechSynthesizer.initTts(TtsMode.MIX);
            if (result != 0) {
                LogUtils.log("TTSUtils","【error】initTts 初始化失败 + errorCode:" + result);
                return;
            }
            // 此时可以调用 speak和synthesize方法
            LogUtils.log("TTSUtils", "合成引擎初始化成功");
        }
    
        /**
         * 合成的参数,可以初始化时填写,也可以在合成前设置。
         *
         * @return
         */
        protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            // 离线资源文件,从assets目录中复制到临时目录,需要在initTTs方法前完成
            setOfflineVoiceType(VOICE_FEMALE);
            // 文本模型文件路径 (离线引擎使用), 注意TEXT_FILENAME必须存在并且可读
            mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, textFilename);
            // 声学模型文件路径 (离线引擎使用), 注意TEXT_FILENAME必须存在并且可读
            mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, modelFilename);
            // 以下参数均为选填
            // 设置在线发声音人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
            params.put(SpeechSynthesizer.PARAM_SPEAKER, "0");
            // 设置合成的音量,0-9 ,默认 5
            params.put(SpeechSynthesizer.PARAM_VOLUME, "9");
            // 设置合成的语速,0-9 ,默认 5
            params.put(SpeechSynthesizer.PARAM_SPEED, "5");
            // 设置合成的语调,0-9 ,默认 5
            params.put(SpeechSynthesizer.PARAM_PITCH, "5");
    
            params.put(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_HIGH_SPEED_SYNTHESIZE);
            // 该参数设置为TtsMode.MIX生效。即纯在线模式不生效。
            // MIX_MODE_DEFAULT 默认 ,wifi状态下使用在线,非wifi离线。在线状态下,请求超时6s自动转离线
            // MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI wifi状态下使用在线,非wifi离线。在线状态下, 请求超时1.2s自动转离线
            // MIX_MODE_HIGH_SPEED_NETWORK , 3G 4G wifi状态下使用在线,其它状态离线。在线状态下,请求超时1.2s自动转离线
            // MIX_MODE_HIGH_SPEED_SYNTHESIZE, 2G 3G 4G wifi状态下使用在线,其它状态离线。在线状态下,请求超时1.2s自动转离线
    
            // 声学模型文件路径 (离线引擎使用), 请确认下面两个文件存在
            params.put(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, textFilename);
            params.put(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, modelFilename);
            return params;
        }
    
        private static HashMap<String, Boolean> mapInitied = new HashMap<String, Boolean>();
        private final String VOICE_FEMALE = "F";//离线女声
        private final String VOICE_MALE = "M";//离线男声
        private final String VOICE_DUYY = "Y";//离线度逍遥
        private final String VOICE_DUXY = "X";//离线度丫丫
        private String textFilename = "";
        private String modelFilename = "";
        private void setOfflineVoiceType(String voiceType) {
            String text = "bd_etts_text.dat";
            String model;
            if (VOICE_MALE.equals(voiceType)) {
                model = "bd_etts_common_speech_m15_mand_eng_high_am-mix_v3.0.0_20170505.dat";
            } else if (VOICE_FEMALE.equals(voiceType)) {
                model = "bd_etts_common_speech_f7_mand_eng_high_am-mix_v3.0.0_20170512.dat";
            } else if (VOICE_DUXY.equals(voiceType)) {
                model = "bd_etts_common_speech_yyjw_mand_eng_high_am-mix_v3.0.0_20170512.dat";
            } else if (VOICE_DUYY.equals(voiceType)) {
                model = "bd_etts_common_speech_as_mand_eng_high_am_v3.0.0_20170516.dat";
            } else {
                throw new RuntimeException("voice type is not in list");
            }
            textFilename = copyAssetsFile(text);
            modelFilename = copyAssetsFile(model);
        }
    
        private String copyAssetsFile(String sourceFilename) {
            String destFilename = FileUtil.createTmpDir(MyApplication.context) + "/" + sourceFilename;
            try {
                File file = new File(destFilename);
                if (file.exists()){
                    return destFilename;
                }
                boolean recover = false;
                Boolean existed = mapInitied.get(sourceFilename); // 启动时完全覆盖一次
                if (existed == null || !existed) {
                    recover = true;
                }
                FileUtil.copyFromAssets(MyApplication.context.getApplicationContext().getAssets(),
                        sourceFilename, destFilename, recover);
                return destFilename;
            }catch (Exception e){
                e.printStackTrace();
            }
            return destFilename;
        }
    
    展开全文
  • 讯飞语音唤醒SDK集成流程

    千次阅读 2018-09-03 09:20:00
    唤醒功能,顾名思义,通过语音唤醒服务,做我们想做的事情。 效果图(开启应用后说讯飞语音或者讯飞语点唤醒) 源码下载 地址:http://download.csdn.net/detail/q4878802/9023213 步骤 1. 创建应用,开通...

    唤醒功能,顾名思义,通过语音,唤醒服务,做我们想做的事情。

    • 效果图(开启应用后说讯飞语音或者讯飞语点唤醒)

    技术分享

    • 源码下载

    地址:http://download.csdn.net/detail/q4878802/9023213

    步骤

    1. 创建应用,开通服务

    地址:http://blog.csdn.net/q4878802/article/details/47762169

    2. 下载SDK

    我们要使用的是讯飞的付费功能,选择唤醒服务,点击下载以后,会提示没有购买。点击“购买服务” 
    技术分享

    点击购买一会看到付费情况,有项目需要,就必须购买,我们写Demo,讯飞给提供了体验版的SDK,和正式版的没有功能上的区别,但是只能试用35天,装机量只有3个,唤醒词不能改,只有“讯飞语音”和“讯飞语点”两个唤醒词。 
    技术分享

    3. 解压SDK

    assets目录下是一些图片资源文件

    doc目录下是一些开发文档

    libs目录下是一些jar包和so库

    res目录下是语音的资源文件,非常重要

    sample目录下是Demo

    技术分享

    4. 集成语音唤醒

    可以按照开发文档的介绍,一步一步跟着做,实现唤醒功能

    地址:http://www.xfyun.cn/doccenter/awd

    我个人的习惯是看Demo,开发文档只是做一个参考,我个人感觉这样更直接,开发效率更高。

    步骤

    1. 将Demo导入IDE,跑起来。
    2. 在手机上找到功能的入口,根据一些界面上显示的关键字,找到控件。
    3. 根据控件ID,在代码找到对应功能的的代码。
    4. 找到功能的核心代码以后,看看当前的方法或者类在哪里有用到,怎么用的,是如何初始化的然后集成到自己的工程里,就OK了。
    5. 下载的SDK里给的一些资源不是白给的,是和你的appid对应的,你要将demo的appid换成你自己的appid,资源文件也要拷贝到的你的工程里,才能正常使用。

    开发步骤

    1. 添加权限

    这里用到的唤醒功能不是所有的权限都用到的,具体用到了哪些权限,可以看上面的链接,用到哪写权限就加哪些权限,这个为了快速方便测试,把讯飞用到的权限都加上了。 

    <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.CHANGE_NETWORK_STATE" />
     
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     
    <uses-permission android:name="android.permission.READ_CONTACTS" />
     
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

     

    2. 初始化appid

    我是将appid的初始化放在的Applicaiton下,具体可以下载源码

     

     
    // 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null
     
    // 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton
     
    // 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true"
     
    // 参数间使用“,”分隔。
     
    // 设置你申请的应用appid
     
    StringBuffer param = new StringBuffer();
     
    param.append("appid=55d33f09");
     
    param.append(",");
     
    param.append(SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC);
     
    // param.append(",");
     
    // param.append(SpeechConstant.FORCE_LOGIN + "=true");
     
    SpeechUtility.createUtility(InitKqwSpeech.this, param.toString());
     

     

    3. 工具类

    初始化好了以后直接复制工具类就可以用了

     

     
    package com.example.kqwspeechdemo.engine;
     
    import org.json.JSONException;
     
    import org.json.JSONObject;
     
    import com.iflytek.cloud.SpeechConstant;
     
    import com.iflytek.cloud.SpeechError;
     
    import com.iflytek.cloud.SpeechUtility;
     
    import com.iflytek.cloud.VoiceWakeuper;
     
    import com.iflytek.cloud.WakeuperListener;
     
    import com.iflytek.cloud.WakeuperResult;
     
    import com.iflytek.cloud.util.ResourceUtil;
     
    import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
     
    import android.content.Context;
     
    import android.os.Bundle;
     
    import android.util.Log;
     
    import android.widget.Toast;
     
     
     
    /**
     
    * 语音唤醒
     
    *
     
    * @author kongqw
     
    *
     
    */
     
    public abstract class KqwWake {
     
     
     
    /**
     
    * 唤醒的回调
     
    */
     
    public abstract void kqwWake();
     
     
     
    // Log标签
     
    private static final String TAG = "KqwWake";
     
     
     
    // 上下文
     
    private Context mContext;
     
    // 语音唤醒对象
     
    private VoiceWakeuper mIvw;
     
     
     
    /*
     
    * TODO 设置门限值 : 门限值越低越容易被唤醒,需要自己反复测试,根据不同的使用场景,设置一个比较合适的唤醒门限
     
    */
     
    // private final static int MAX = 60;
     
    // private final static int MIN = -20;
     
    private int curThresh = 40;
     
     
     
    public KqwWake(Context context) {
     
    mContext = context;
     
     
     
    // 加载识唤醒地资源,resPath为本地识别资源路径
     
    StringBuffer param = new StringBuffer();
     
    String resPath = ResourceUtil.generateResourcePath(context, RESOURCE_TYPE.assets, "ivw/55d33f09.jet");
     
    param.append(ResourceUtil.IVW_RES_PATH + "=" + resPath);
     
    param.append("," + ResourceUtil.ENGINE_START + "=" + SpeechConstant.ENG_IVW);
     
    boolean ret = SpeechUtility.getUtility().setParameter(ResourceUtil.ENGINE_START, param.toString());
     
    if (!ret) {
     
    Log.d(TAG, "启动本地引擎失败!");
     
    }
     
    // 初始化唤醒对象
     
    mIvw = VoiceWakeuper.createWakeuper(context, null);
     
     
     
    };
     
     
     
    /**
     
    * 唤醒
     
    */
     
    public void wake() {
     
    // 非空判断,防止因空指针使程序崩溃
     
    mIvw = VoiceWakeuper.getWakeuper();
     
    if (mIvw != null) {
     
    // textView.setText(resultString);
     
    // 清空参数
     
    mIvw.setParameter(SpeechConstant.PARAMS, null);
     
    // 唤醒门限值,根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
     
    mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:" + curThresh);
     
    // 设置唤醒模式
     
    mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");
     
    // 设置持续进行唤醒
     
    mIvw.setParameter(SpeechConstant.KEEP_ALIVE, "1");
     
    mIvw.startListening(mWakeuperListener);
     
    } else {
     
    Toast.makeText(mContext, "唤醒未初始化", Toast.LENGTH_SHORT).show();
     
    }
     
    }
     
     
     
    public void stopWake() {
     
    mIvw = VoiceWakeuper.getWakeuper();
     
    if (mIvw != null) {
     
    mIvw.stopListening();
     
    } else {
     
    Toast.makeText(mContext, "唤醒未初始化", Toast.LENGTH_SHORT).show();
     
    }
     
    }
     
     
     
    String resultString = "";
     
    private WakeuperListener mWakeuperListener = new WakeuperListener() {
     
     
     
    @Override
     
    public void onResult(WakeuperResult result) {
     
    try {
     
    String text = result.getResultString();
     
    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();
     
    stopWake();
     
    kqwWake();
     
    } catch (JSONException e) {
     
    resultString = "结果解析出错";
     
    e.printStackTrace();
     
    }
     
    }
     
     
     
    @Override
     
    public void onError(SpeechError error) {
     
    Log.i(TAG, error.getPlainDescription(true));
     
    }
     
     
     
    @Override
     
    public void onBeginOfSpeech() {
     
    Log.i(TAG, "开始说话");
     
    }
     
     
     
    @Override
     
    public void onEvent(int eventType, int isLast, int arg2, Bundle obj) {
     
     
     
    }
     
    };
     
     
     
    }
    测试类
     
    package com.example.kqwspeechdemo;
     
     
     
    import com.example.kqwspeechdemo.engine.KqwWake;
     
     
     
    import android.app.Activity;
     
    import android.os.Bundle;
     
    import android.widget.TextView;
     
    import android.widget.Toast;
     
     
     
    public class MainActivity extends Activity {
     
     
     
    private TextView mTvLog;
     
    private TextView mTvResult;
     
    private KqwWake kqwWake;
     
     
     
    @Override
     
    protected void onCreate(Bundle savedInstanceState) {
     
    super.onCreate(savedInstanceState);
     
    setContentView(R.layout.activity_main);
     
     
     
    mTvLog = (TextView) findViewById(R.id.tv_log);
     
    mTvResult = (TextView) findViewById(R.id.tv_result);
     
     
     
    kqwWake = new KqwWake(this) {
     
    @Override
     
    public void kqwWake() {
     
    Toast.makeText(MainActivity.this, "Debug:\n唤醒成功", Toast.LENGTH_SHORT).show();
     
    // 开启唤醒
     
    kqwWake.wake();
     
    }
     
    };
     
    // 开启唤醒
     
    kqwWake.wake();
     
    }
     
    }

     

     

     

    页面布局

     
    <LinearLayout 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:orientation="vertical"
     
    tools:context="com.example.kqwspeechdemo.MainActivity" >
     
     
     
    <TextView
     
    android:layout_width="match_parent"
     
    android:layout_height="wrap_content"
     
    android:background="#FF000000"
     
    android:gravity="center"
     
    android:padding="10dp"
     
    android:text="唤醒词:讯飞语音、讯飞语点"
     
    android:textColor="#FFFFFFFF"
     
    android:textSize="20dp" />
     
     
     
    <View
     
    android:layout_width="match_parent"
     
    android:layout_height="1dp"
     
    android:background="#FFFFFFFF" />
     
     
     
    <TextView
     
    android:id="@+id/tv_log"
     
    android:layout_width="match_parent"
     
    android:layout_height="wrap_content"
     
    android:background="#FF000000"
     
    android:gravity="center"
     
    android:padding="10dp"
     
    android:text="录音信息"
     
    android:textColor="#FFFFFFFF"
     
    android:textSize="10dp" />
     
     
     
    <View
     
    android:layout_width="match_parent"
     
    android:layout_height="1dp"
     
    android:background="#FFFFFFFF" />
     
     
     
    <TextView
     
    android:id="@+id/tv_result"
     
    android:layout_width="match_parent"
     
    android:layout_height="match_parent"
     
    android:background="#FF000000"
     
    android:padding="10dp"
     
    android:text="返回结果"
     
    android:textColor="#FFFFFFFF"
     
    android:textSize="10dp" />
     
     
     
    </LinearLayout>

     

    注意

      1. 如果你直接用的Demo,demo用的是测试版的离线包,只有35天的试用期,而且装机量只有3个,如果大家都用,很可能是不能正常运行的
      2. 如果是参考demo自己写一个,千万不要忘记替换appid和资源文件。
    展开全文
  • 时代拓灵离线自定义语音唤醒SDK集成调试过程 离线自定义唤醒词顾名思义,省去上传语音到云端在处理返回结果,直接在本机上进行处理,对于特定的词语给予反馈,不受网络环节因素限制,随时随地,自由操控 拓灵SDK ...

    时代拓灵离线自定义语音唤醒词SDK集成调试过程

    离线自定义唤醒词顾名思义,省去上传语音到云端处理返回结果,直接在本机上进行处理,对于特定的词语给予反馈,不受网络环节因素限制。拓灵离线唤醒可以快速自定义唤醒词,性能优越。

    拓灵SDK demo运行效果图
    在这里插入图片描述

    集成步骤

    1. 前往时代拓灵官网下载离线唤醒词SDK demo

    2. http://yun.twirlingvr.com/index.php/home/sdkdownload/index.html

    3. 在这里插入图片描述

    4. 前往时代拓灵官网注册对应sdk试用项目,申请appid,设置app密码
      注意:时代拓灵提供的试用项目,只有14天的试用期,并且20个装机量项目
      http://yun.twirlingvr.com/index.php/home/sdkdownload/addTestPro.html

    在这里插入图片描述
    创建成功后页面右上角点击个人中兴->项目管理查看自己申请到的appid

    在这里插入图片描述
    在这里插入图片描述
    3. 生成唤醒词配置文件
    http://yun.twirlingvr.com/index.php/home/index/interaction.html

    在这里插入图片描述
    注册登录时代拓灵,页面向下翻,可以找到导出配置文件,根据要求选择唤醒语言,输入唤醒词每个唤醒词用#隔开,并且在下方输入每个唤醒词的对应阈值也同样使用#号隔开。点击导出配置文件,浏览器会自动下载一个xxxxx.dat文件这就是你的配置文件了。
    4. 解压下载的SDK demo
    解压后的文件夹是一个安卓工程,大致目录用途如下
    Audio 存放一个测试音频,可以用于通过读取音频方式测试唤醒
    Res res下存放了两个文件分别为model.bin和xxxxx.dat,model.bin是模型文件,xxxxx.dat是配置文件,用于设置唤醒词以及阈值
    Libs 下是存放的唤醒时调用的动态库
    5. 集成调试Demo
    注意:Demo需要文件读写权限和网络权限;
    将之前生成的配置文件以及模型文件拷贝到手机存储中,并且记下路径。
    使用Android Studio打开解压后的SDK demo,打开android_sdk\app\src\main\java\com\twirling\sdk\sdk_test\MainActivity.java文件,首先在onRequestPermissionsResult()方法中的WakeupInit()方法中填入自己申请到的appid和设置的密码,以及上一步中记下的手机中模型文件路径和配置文件路径。当填写完这些信息后,SDK Demo就可以正式工作了,十分简单。

    测试SDK功能

    时代拓灵SDK编译完成后在手机上运行如下图

    在这里插入图片描述
    顶部两个按钮分别对应两个功能:通过手机mic测试唤醒和通过已存储的音频测试唤醒
    中间区域是信息展示,统计唤醒次数,以及本次唤醒的得分。
    底部是当前加载的配置文件信息,比如我测试的这个就是救命和来人两个词语,每个词语的阈值都设置的0.7;
    使用过程SDK正常运行后,点击mic按钮,对着手机说出之前设置好的唤醒词,就会看见唤醒次数在不断累加,表明正确唤醒了。
    如何集成进自己项目小经验

    1. 将Demo导入IDE,跑起来。
    2. 查看layout中的activity_main.xml布局找到功能控件。
    3. 根据控件ID,在代码找到对应功能的的代码。
    4. 找到功能的核心代码以后,看看当前的方法或者类在哪里有用到,怎么用的,是如何初始化的然后集成到自己的工程里,就OK了。

    Tips:

    1、离线命令词识别支持多少命令词?
    离线识别的命令词是开发者自己定义,命令词最大长度为8个汉字。需要先构建语法,然后指定使用的语法。
    2、装机量怎么定义的?
    装机量授权:离线命令词识别按照装机量收费,购买后即获得相应授权。装机量按照使用了开发者应用的终端设备信息进行统计,即在终端设备上安装了应用并启用了离线引擎,即记为一个装机量。同一个终端设备上卸载(重装)应用均记为一个装机量,不重复计数。

    展开全文
  • 语音唤醒

    2021-05-16 08:19:19
    语音唤醒前言一、语音唤醒相关环境搭建二、使用步骤1.使用流程2.示例代码总结 前言 针对语音交互过程,提供了一种语音唤醒的方法供大家参考,语音交互采用snowboy离线语音唤醒引擎,snowboy已经被kitt.AI团队下架,...
  • 讯飞语音开发之语音唤醒

    万次阅读 2016-07-05 00:59:51
    只有前面讲到的语音合成,语音理解,语义理解,语音识别确实可以实现人机交流。...使用语音唤醒,首先你要在你的应用中开通语音唤醒服务。 设置唤醒词,设置的过程中最好是
  • android应用百度语音识别、语音合成和语音唤醒 首先申请百度语音识别:http://yuyin.baidu.com/ 下载SDK 有两种方式实现语音识别:API和SDK集成 唤醒功能默认唤醒词是百度一下或者小度你好,可以到官网去自定义唤醒...
  • Android——百度语音唤醒

    万次阅读 多人点赞 2016-10-10 22:53:16
    这篇文章我们主要介绍一下,百度语音唤醒。所谓语音唤醒是指说出指定的语音指令(自定义的唤醒词),使程序激活某个功能的能力。百度语音唤醒支持自定义唤醒词。我做过讯飞的语音唤醒,这两个比较起来,讯飞的语音...
  • 树莓派离线语音唤醒snowboy

    千次阅读 2020-11-27 09:10:08
    重新进行SDK的申请,值得注意的是,语音唤醒词和SDK是捆绑的,要是想要更换语音唤醒词的话必须要重新下载SDK文件。 这次我下载的SDK文件和上次的有所不同,选择了离线命令词识别,离线语音合成以及语音唤醒服务,...
  • 离线语音唤醒 snowboy 1、snowboy介绍、安装与测试 Snowboy 是一款高度可定制的唤醒词检测引擎,可以用于实时嵌入式系统,并且始终监听(即使离线)。当前,它可以运行在 Raspberry Pi、(Ubuntu)Linux 和 Mac OS...
  • 最近项目上需要实现语音调度,一开始是想用苹果原生speech Framework框架的,但是网上找了很久都没有原生实现语音唤醒功能的栗子,到时有不少百度,讯飞的语音唤醒,语音识别的栗子,不过都是单独实现的代码,没有将...
  • 讯飞语音唤醒、识别、合成

    千次阅读 2019-07-17 17:23:34
    文章目录讯飞SDK的使用官网SDK所提供的的文件官网Demo的使用自己新建工程导包步骤语音唤醒语音识别在线语音合成 讯飞SDK的使用 Demo链接: 语音唤醒 [link] ...
  • 讯飞语音唤醒

    千次阅读 2016-09-21 11:42:47
    唤醒功能,顾名思义,通过语音唤醒服务,做我们想做的事情。 效果图(开启应用后说讯飞语音或者讯飞语点唤醒) 源码下载 地址:http://download.csdn.net/detail/q4878802/9023213 步骤 1. 创建应用...
  • Unity 科大讯飞语音唤醒

    千次阅读 2020-07-15 17:28:53
    今天更新unity讯飞的语音唤醒功能,由于之前使用的是语音识别,识别出唤醒词来做了一个假的语音唤醒。 缺点:语音识别一直处于识别中。结果可想而知,一天的识别量达到了1W次,这次多么恐怖的一件事啊。 要想知道...
  • 关于讯飞开发平台的注册以及SDK下载: 请参考: ... · 离线名命令词 ...· 离线语音合成 ...· 离线唤醒 · 语音在线听写 准备工作: 1、jar包 地址:https://pan.baidu.com/s/1hsanJBe 密码:523
  • 树莓派3B+ 语音唤醒snowboy库的使用

    万次阅读 多人点赞 2018-12-16 23:18:23
    由于百度语音识别 linux版本的sdk默认不支持语音唤醒功能,想要在树莓派3b+上做一个语音唤醒+识别的小玩意儿,要想实现唤醒的功能,只能另寻他法,然后我在网络上搜索到了这个snowboy,它是一个语音唤醒引擎。...
  • 在百度语音SDKDemo的基础上保存语音并进行识别 项目参考 ... 最近在做公司的一个项目,基于百度的...语音唤醒 录音 语音交互结束后自动退出 返回识别结果 SDK中封装了唤醒的方法和识别的方法,现在需要做的就是把步骤2-
  • 科大讯飞语音唤醒sdk下载 到科大讯飞开放平台注册后,选择相应的开发环境,设定好语音唤醒的关键字(这里我设置的是Friday),下载sdk,得到这么些东西: API调用流程 参考文档中心的调用流程: 可以看到...
  • 目录安卓(Android)开发百度语音唤醒(识别)一:准备1:获取自定义唤醒词2:SDK下载3:将bdasr_V3_xxx_xxx.jar引入到项目libs文件中4:将armeabi,armeabi-v7a,arm64-v8a,x86,x86_64引入到项目jniLibs目录下。...
  • Android——讯飞语音唤醒简介及实现

    万次阅读 多人点赞 2017-04-29 11:07:20
    前段时间写了一个关于百度语音唤醒文章,最近有做了一个讯飞语音的应用,在这里把学习的资料整理一下。 唤醒的整个过程如下: (图源自讯飞官网) 讯飞的语音唤醒功能实现起来挺方便的(相比百度,百度语音...
  • 讯飞语音——唤醒

    万次阅读 2015-08-19 12:05:54
    讯飞语音唤醒 唤醒功能,顾名思义,通过语音,唤醒服务,做我们想做的事情。效果图(开启应用后说讯飞语音或者讯飞语点唤醒)源码下载 地址:http://download.csdn.net/detail/q4878802/9023213步骤1. 创建应用,...
  • 语音识别技术概述与调研 语音识别已经成为人工智能应用的一个重点,通过语音控制设备简单方便,在各个领域兴起了研究应用的热潮。数据、算法及芯片是语音识别技术的3个关键,大量优质的数据、精准快速的算法和高性能...
  • 百度语音SDK使用

    万次阅读 2017-03-09 18:09:03
    百度语音SDK提供: 语音识别:将声音转成文字 语音合成:将文字转成语音文件,然后播放语音文件,即文字变声音。 语音唤醒语音唤醒,激活运用程序
  • 下载语音唤醒SDK后,使用androidStudio测试官网demo的时候,点击唤醒出现参数无效(错误码:10106) 原因: 相关资源没有放好 解决: 查看官方开发文档发现,下载sdk后ivw是有变化的,需要使用res下的ivw文件...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,614
精华内容 645
关键字:

sdk语音唤醒