先说一下这篇文章想要实现的功能:
我的初衷是想实现一个基于科大讯飞语音识别的类似于问答闯关的小Demo,即它来问我们来答他判断我们是否正确错误,然后给出回应。emmm,当然我这个也很low,也只是单纯的ABCD判断答案正确错误,如果你觉得不是你想要的可以自行绕路了。
把语音识别和语音合成限制在一个线程运行
我的初衷是想实现一个基于科大讯飞语音识别的类似于问答闯关的小Demo,即它来问我们来答他判断我们是否正确错误,然后给出回应。emmm,当然我这个也很low,也只是单纯的ABCD判断答案正确错误,如果你觉得不是你想要的可以自行绕路了。
这里主要的问题就是科大讯飞的语音识别和语音合成不能够很好的分离的原因,也就是如果把识别的开始放在合成的前面,我们想的是可以让他把题目读完,然后再开始识别,想法逻辑没什么问题,但科大讯飞却不能直接这样完成,如果直接这样调用,识别并不会等待合成结束再开始,而是相当于开启了新的线程,他的识别会自动录入自己合成的内容,他们之间并不会相互阻塞。
这是自己尝试的方法:
1.使用主线程休眠来卡住后一个动作的开始。
这个方法确实可行,但遇到了无法判断合成或者识别的时间,识别还好点,可以设置参数控制录音的总时长和休眠配合,倒是合成的时间无法判断而且合成对象的给出的isSpeaking()方法加while(){}不能卡住程序的执行,而且主活动休眠会让程序卡掉,过一会还会提示程序响应,很low,被迫放弃
失败2.使用线程来分离。
尝试从线程中用isSpeacking()来卡住线程,的确实现了想要的效果而且主活动不会停止,也就是界面不会卡掉,逼格就有了,可是一旦在线程里调用监听,APP就会挂掉
失败
3.使用Handler,在线程内部使用Handler.send(Message)来开启监听。
这次APP的确是不挂了,但是特码的又开始说给自己听了,听说同启,while(){}卡不住合成了也
失败解决方法:
使用合成监听和识别监听的回调方法,在其中结束识别和合成的方法中,调用还类中持有的自定义接口中的方法,在调用开始合成和开始识别的前把里面的自定义接口的引用设置成我们想要用的动作的接口对象,用这种设定完成动作指向。
贴一下部分代码,希望可以给你以启发:
//默认的合成回调对象 Speaker.SpeakCall speakCall = new Speaker.SpeakCall(){ @Override public void speckfinish() { //需要执行的动作 } };
具体的自定义接口和合成监听器的关系:
//自定义的接口对象 private SpeakCall mspeakcall; /** * 语音合成监听的回调接口 */ public interface SpeakCall{ void speckfinish(); } /** * 语音合成监听对象 */ private SynthesizerListener mTtsListener = new SynthesizerListener() { @Override public void onSpeakBegin() {} @Override public void onSpeakPaused() {} @Override public void onSpeakResumed() {} @Override public void onBufferProgress(int percent, int beginPos, int endPos, String info) { // TODO 缓冲的进度 Log.i(TAG, "缓冲 : " + percent); } @Override public void onSpeakProgress(int percent, int beginPos, int endPos) { // TODO 说话的进度 Log.i(TAG, "合成 : " + percent); } @Override public void onCompleted(SpeechError error) { if (error == null) { Log.i(TAG, "播放完成"); if(null!=mspeakcall){ mspeakcall.speckfinish(); } } else if (error != null) { showTip(error.getPlainDescription(true)); Log.i(TAG, error.getPlainDescription(true)); } } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { } };
查看评论