Android科大讯飞语音按队列播报
在Android开发中,语音播报经常使用,但是,在使用过程中会发现,如果语音来源过于块,频率过高,在前一条没有播放完的情况下会执行第二条播放,本篇文章用来解决这个问题。
一、科大讯飞语音集成:
1、在科大讯飞的开发者平台(科大讯飞开放平台)注册。我这里使用的是在线语音合成,下载SDK包。
2、将SDK包里面的libs里面的.so文件和jar包复制到你的项目中,并且引用.so文件和jar包,这里要注意的是,个人建议将所有CPU类型的.so文件都放到你的项目中,这样保证在所有设备中都能播放,虽然这样会导致项目变大。
3、在MyApplication中初始化:
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=******");
注意这里的APPID,不要丢了这个“=”号。
4、在使用到语音播放的地方,初始化语音引擎:
private SpeechSynthesizer mTts = SpeechSynthesizer.createSynthesizer(context, mTtsInitListener);
5、初始化中有两个参数,第一个是上下文,第二个是初始化回调:
private InitListener mTtsInitListener = new InitListener() {@Overridepublic void onInit(int code) {if (code != ErrorCode.SUCCESS) {Toast.showToast(context, "语音初始化失败,错误码:" + code);} else {AppLog.i("语音初始化成功");// 初始化成功,之后可以调用startSpeaking方法// 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,// 正确的做法是将onCreate中的startSpeaking调用移至这里}}};
6、播放:
public void playVoice(String msg) {mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");mTts.setParameter(SpeechConstant.SPEED, "60"); //播放速度mTts.setParameter(SpeechConstant.VOLUME, "80"); //播放音量mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); //引擎类型mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, "./sdcard/iflyket.pcm"); //声音文件地址mTts.startSpeaking(msg, mTtsListener);}
这里面可以配置播放人声(SpeechConstant.VOICE_NAME)、声音大小(peechConstant.VOLUME)、语速(SpeechConstant.SPEED),如果你发现你选择的人声无法通过手机系统声音控制声音大小时,将人声换成系统默认的“xiaoyan”,在mTts.startSpeaking(msg, mTtsListener);
配置中,第一个参数就是要播放的内容,第二个是播放回调:
private SynthesizerListener mTtsListener = new SynthesizerListener() {@Overridepublic void onSpeakBegin() {// AppLog.i("onSpeakBegin");}@Overridepublic void onSpeakPaused() {// AppLog.i("onSpeakPaused");}@Overridepublic void onSpeakResumed() {// AppLog.i("onSpeakResumed");}@Overridepublic void onBufferProgress(int percent, int beginPos, int endPos, String info) {}@Overridepublic void onSpeakProgress(int percent, int beginPos, int endPos) {}@Overridepublic void onCompleted(SpeechError error) {if (error == null) {if (!queue.isEmpty()) {presenter.playVoice(queue.poll());} else {isFirst = true;}} else if (error != null) {AppLog.i(error.getPlainDescription(true));}}@Overridepublic void onEvent(int eventType, int arg1, int arg2, Bundle obj) {// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因// 若使用本地能力,会话id为null// if (SpeechEvent.EVENT_SESSION_ID == eventType) {// String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);// Log.d(TAG, "session id =" + sid);// }}};
播放回调看法不言而喻了。
二、重点来了 解决播放跳跃问题:
1、首先来看下这个场景:比如有一个收银系统消息接受终端,每收一笔钱都播放一条“收款成功xxx元”,如果收银速度过款人客流大,当还没播放完第一条语音的时候,第二次收银已经结束了,此时一般情况就会每次播放都直接调用playVioce(String msg)这个这个方法,此时第一条没完,知己播放第二条了。还有一个情景就是,集成高德地图,语音是要自己合成的,同样用科大讯飞来播放路况,当路况复杂的情况下会出现一样的问题。
2、解决问题:解决这个问题的方法就是使用队列:
Queue<String> queue = new LinkedList<String>();
在我的项目的场景就是,每次收款一次,都会受到一次推送一串String,我要播放的就是这条String
//EvenBus接受推送过来的消息广播@Subscribe(threadMode = ThreadMode.MAIN)public void getMessage(PushEvent pushEvent) {Log.i("tag","收款:" + pushEvent.getMessage());String msg = pushEvent.getMessage();queue.offer(msg);//此处需要将语音添加到队列,保证一条播放完再播放下一条//必须第一次收到消息才能在这播放,以后每次收到消息将消息添加到队列,每次播放完后去队列里面取;if (isFirst) {playVoice(queue.poll());//保证播放方法这里只执行第一次isFirst = !isFirst;}}
明白的童鞋知道我这里使用的EvenBus来接受推送的消息,可以忽略。将推送过来的消息,放到队列queue中,注意,这里使用的是queue.offer(msg);
offer()这个方法,队列添加还有add()这个方法,这两个方法的不同之处就是offer在添加失败的时候不抛异常,所以不建议使用add()方法。使用
queue.poll()来出去队列中的数据,队列是先进先出的,每次poll都会将该条消息从队列中清除。
这里使用的一个变量isFirst来控制播放,只有初次播放的时候才在getMessage()中使用playVoice()方法,这里解决了每次收到消息后都会触发getMessage()这个方法里面的playVoice()。如果每次收到推送消息都调用playVoice(queue.poll());方法会导致少播放一条消息。
在播放回调的onCompleted()方法中继续取出队列里的消息播放,
@Overridepublic void onCompleted(SpeechError error) {if (error == null) {if (!queue.isEmpty()) {presenter.playVoice(queue.poll());} else {isFirst = true;}} else if (error != null) {AppLog.i(error.getPlainDescription(true));}}
看代码,当队列不为空的时候就继续取出队列里的消息播放,知道为空的时候将isFirst 置为true,否则在全部播放完后不能再次播放了。
三、这样就很完美的解决了播放跳跃问题,这样,无论有多少条消息,多频繁,每次播放都从队列里面取出,这样就达到了播放完一条再播放下一条的问题了。
四、由于这个例子是从自己项目中抽取出来的,没办法上源码,抱歉,写的不好的话请多指正!
Android科大讯飞语音按队列播报相关推荐
- Android 科大讯飞 语音转文字
Android 科大讯飞 语音转文字 语音听写SDK适配安卓6.0需要手动申请权限,各位可以自信查询资料实现,关于语音听写SDK的开发,参考科大讯飞开放平台官网为准 第一,首先去科大讯飞官网注册一个账 ...
- Android 科大讯飞语音SDK集成步骤
前言 科大讯飞语音虽好,其严格的认证与校验确实精密,不过也大大提高了开发者的集成难度,并非危言耸听,我想大多数人都有经历过 11210(用户ID与离线资源不匹配) 21480( 离线引擎GUID不一致 ...
- Android 科大讯飞 语音听写
这几天在搞一个语音识别的项目 用到i的是科大讯飞的语音服务,第一次搞语音识别,在这里记录一下,也希望对大家有用.废话不多说进入正题 一.要用到科大讯飞的语音识别功能,肯定是要他的开发者平台申请账号,创 ...
- 集成Android 科大讯飞免费在线语音合成播报功能(附源码)
概述 开篇先介绍一下'科大讯飞',毕竟是我家乡合肥的科技公司,我感到骄傲,更重要的是它在语音识别行业也是佼佼者,在如今人工智能横飞的时代,依然能够保持着较高水准的技术优势.在此,希望科大在AI之战中能 ...
- android 科大讯飞语音唤醒demo
demo地址:https://gitee.com/longlyblack_admin/VoiceCallSecondDemo API文档地址:http://mscdoc.xfyun.cn/androi ...
- Android科大讯飞语音集成,非常详细的使用讲解
讯飞语音开发集成地址http://www.xfyun.cn/ 解压后的doc文件夹下的msc develop 文件中有详细集成步骤 AppId: 1.先要注册开发者账户, 添加我的应用 , ...
- 教你用Android做二次开发,识别率达到科大讯飞语音输入水平 | 原力计划
作者 | Pek_KuaiJia 责编 | 夕颜 头图 | CSDN 下载自视觉中国 出品 | CSDN(ID:CSDNnews) 随着目前用户需求的精细化和智能化,很多时候我们需要在App内集成语音 ...
- 教你用 Android 做二次开发,识别率达到科大讯飞语音输入水平 | 原力计划
作者 | Pek_KuaiJia 责编 | 夕颜 头图 | CSDN 下载自视觉中国 出品 | CSDN(ID:CSDNnews) 随着目前用户需求的精细化和智能化,很多时候我们需要在App内集成语音 ...
- 科大讯飞语音无限制录音、识别功能的实现:Android studio(一)
最近想要做一款语音听写APP,在网上搜索关于如何使用科大讯飞语音的Demo少之又少,又或者是只是单纯的按照文档来实现简单的语音听写,远远不能满足需求,看了几天的文档和自己搜索的一些资料,还有这几天中遇 ...
最新文章
- 【好文】带你用Python开发个机器学习软件!
- matlab GM(2,1)模型
- python代码基础题-python3的基础练习题
- [你必须知道的.NET]第二十七回:interface到底继承于object吗?
- 尝鲜Ubuntu Server 12.04 LTS
- Boost:bimap双图的突变的测试程序
- jQuery 入门教程(5): 显示/隐藏内容
- python面试总结(五)内存管理与MYSQL引擎选择
- 最大数max(x,y,z)(信息学奥赛一本通-T1152)
- shell脚本和linux命令,Linux shell脚本全面学习(一)
- 雷军回应小米新 Logo 争议;马化腾排名第 15 位,2021 全球亿万富豪榜出炉!谷歌将停止使用甲骨文的财务软件|极客头条...
- 给Android SDK设置环境变量
- 多元统计分析朱建平pdf_应用多元统计分析课后答案朱建平版[精心整理].doc
- CentOS7镜像下载地址
- ubuntu16.04修改鼠标按键功能
- 如何转换视频格式?推荐这3款视频格式转换工具
- html代码 通用代码,html5可以通用的几段代码 | 睿客网
- linux中etc下的hosts(本地IP解析)文件详解
- 这是用原声js编写的地址选择器,使用select编写的三联选择器
- 关于心跳ajax请求pending状态(被挂起),stalled时间过长的问题。涉及tcp连接异常。