讯飞在线语音TTS队列策略

来源:互联网 发布:caffe linux cpu 安装 编辑:程序博客网 时间:2024/05/12 06:11

有一个需求,需要把收到的交易信息推送朗诵出来。由于android没有自带的中文tts,所以采用第三方sdk,有两种方式,一种是离线方式,这种方式还需要下载讯飞的另外一个app,麻烦且不合适。第二种为在线方式语音合成,这里采用第二种。你会发现,如果交易信息很频繁的话,一段话还没读完,另一端话就开始了,而且讯飞这块貌似没做好,需要我们上层封装。

import android.content.Context;import android.os.Bundle;import android.util.Log;import com.iflytek.cloud.ErrorCode;import com.iflytek.cloud.InitListener;import com.iflytek.cloud.SpeechConstant;import com.iflytek.cloud.SpeechError;import com.iflytek.cloud.SpeechSynthesizer;import com.iflytek.cloud.SpeechUtility;import com.iflytek.cloud.SynthesizerListener;import java.util.ArrayList;import java.util.List;/** * Created by Administrator on 2017/1/9. */public class TTSSpeech {    private static String TAG = TTSSpeech.class.getSimpleName();    private static class SingletonHolder {        private static final TTSSpeech INSTANCE = new TTSSpeech();    }    public static final TTSSpeech getInstance(Context context) {        if (!SingletonHolder.INSTANCE.isInit)            SingletonHolder.INSTANCE.init(context);        return SingletonHolder.INSTANCE;    }    // 语音合成对象    private SpeechSynthesizer mTts;    // 默认发音人    private String voicer = "xiaoyan";    private boolean isInit;    private List queue;    public TTSSpeech() {    }    public void init(Context context) {        // 注意: appid 必须和下载的SDK保持一致,否则会出现10407错误        SpeechUtility.createUtility(context, "appid=5872e9a8");        // 初始化合成对象        mTts = SpeechSynthesizer.createSynthesizer(context, mTtsInitListener);        queue = new ArrayList();        setParam();        isInit = true;    }    /**     * 初始化监听。     */    private InitListener mTtsInitListener = new InitListener() {        @Override        public void onInit(int code) {            Log.d(TAG, "InitListener init() code = " + code);            if (code != ErrorCode.SUCCESS) {            } else {                // 初始化成功,之后可以调用startSpeaking方法                // 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,                // 正确的做法是将onCreate中的startSpeaking调用移至这里            }        }    };    public void say(String content) {        queue.add(content);        if (!mTts.isSpeaking() && queue.size() == 1) {            Log.d(TAG, "-------------->say:" + content);            int code = mTts.startSpeaking(content, mTtsListener);            if (code != ErrorCode.SUCCESS) {                Log.e(TAG, "语音合成失败,错误码: " + code + " content:" + content);            }        }    }    /**     * 合成回调监听。     */    private SynthesizerListener mTtsListener = new SynthesizerListener() {        @Override        public void onSpeakBegin() {            Log.d(TAG, "-------------->onSpeakBegin");        }        @Override        public void onSpeakPaused() {            Log.d(TAG, "-------------->onSpeakPaused");        }        @Override        public void onSpeakResumed() {        }        @Override        public void onBufferProgress(int percent, int beginPos, int endPos,                                     String info) {            // 合成进度        }        @Override        public void onSpeakProgress(int percent, int beginPos, int endPos) {            // 播放进度        }        @Override        public void onCompleted(SpeechError speechError) {            Log.d(TAG, "-------------->onCompleted");            if (queue != null && queue.size() > 0) {                queue.remove(0);                if (queue.size() > 0) {                    int code = mTts.startSpeaking((String) queue.get(0), mTtsListener);                    if (code != ErrorCode.SUCCESS) {                        Log.e(TAG, "语音合成失败,错误码: " + code + " content:" + queue.get(0));                    }                }            }        }        @Override        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {            Log.d(TAG, "-------------->onEvent");            // 以下代码用于获取与云端的会话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);            //}        }    };    private void setParam() {        // 清空参数        mTts.setParameter(SpeechConstant.PARAMS, null);        // 根据合成引擎设置相应参数        mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);        // 设置在线合成发音人        mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);        //设置合成语速        mTts.setParameter(SpeechConstant.SPEED, "50");        //设置合成音调        mTts.setParameter(SpeechConstant.PITCH, "50");        //设置合成音量        mTts.setParameter(SpeechConstant.VOLUME, "50");        //设置播放器音频流类型        mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");        // 设置播放合成音频打断音乐播放,默认为true        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");    }    public void destory() {        queue.clear();        mTts.stopSpeaking();        // 退出时释放连接        mTts.destroy();    }}


public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TTSSpeech.getInstance(this).say("我是长江1号");        TTSSpeech.getInstance(this).say("我是长江2号");        TTSSpeech.getInstance(this).say("我是长江3号");        TTSSpeech.getInstance(this).say("我是长江4号");    }}

队列方式很简单,新建一个队列实例,先进先出,后进后出。。。

直接用List作为队列,读完就移除第一个,如果还有就继续读。。。

可能有个问题是,如果有其他因素(如突然来电)打断队列,队列就会中断。不知道会不会等因素完后继续播报。

0 0
原创粉丝点击