前言:

语音合成:
与语音听写相反,语音合成是将一段文字转换为语音,可根据需要合成出不同音色、语速和语调的声音,让机器像人一样开口说话

效果图:

2、直接上代码,配置不再重复说明了:

、TTSActivity.java

public class TTSActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "TTSActivity";// 语音合成对象private SpeechSynthesizer mTts;// 默认发音人private String voicer = "xiaoyan";//云端发音人名称列表(中文)private String[] mCloudVoicersEntries;//云端发音人名称列表(英文简称)private String[] mCloudVoicersValue;//音频流名称列表private String[] mCloudVoicersName;// 缓冲进度private int mPercentForBuffering = 0;// 播放进度private int mPercentForPlaying = 0;// 引擎类型private String mEngineType = SpeechConstant.TYPE_CLOUD;private MemoryFile memFile;public volatile long mTotalSize = 0;private Vector<byte[]> container = new Vector<>();private TextView voice_value1, voice_value2, voice_value3, progress;private SeekBar seekBar1, seekBar2, seekBar3;private Button ttsBtnPersonType,ttsBtnPersonSelect;//起始值50private int voiceNumber1 = 50, voiceNumber2 = 50, voiceNumber3 = 50;//播报的文字private EditText ttsText;//音频流类型private String voiceName;private SpannableStringBuilder builder;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_tts);//初始化控件findViewById(R.id.tts_play).setOnClickListener(this);findViewById(R.id.tts_cancel).setOnClickListener(this);findViewById(R.id.tts_pause).setOnClickListener(this);findViewById(R.id.tts_resume).setOnClickListener(this);voice_value1 = this.findViewById(R.id.voice_value1);voice_value2 = this.findViewById(R.id.voice_value2);voice_value3 = this.findViewById(R.id.voice_value3);seekBar1 = this.findViewById(R.id.seek_bar1);seekBar2 = this.findViewById(R.id.seek_bar2);seekBar3 = this.findViewById(R.id.seek_bar3);ttsText = this.findViewById(R.id.tts_text);progress = this.findViewById(R.id.progress);ttsBtnPersonType = this.findViewById(R.id.tts_btn_person_type);ttsBtnPersonSelect = this.findViewById(R.id.tts_btn_person_select);ttsBtnPersonType.setOnClickListener(this);ttsBtnPersonSelect.setOnClickListener(this);//seekbar滑动事件initSeekBarListener();// 初始化合成对象mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);mCloudVoicersEntries = getResources().getStringArray(R.array.voicer_cloud_entries);mCloudVoicersValue = getResources().getStringArray(R.array.voicer_cloud_values);mCloudVoicersName = getResources().getStringArray(R.array.stream_entries);}private void initSeekBarListener() {//语速seekBar1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) {//进度发生改变时会触发voice_value1.setText("语速:" + i);voiceNumber1 = i;}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {//按住SeekBar时会触发}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {//放开SeekBar时触发}});//音调seekBar2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) {voice_value2.setText("音调:" + i);voiceNumber2 = i;}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});//音量seekBar3.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) {voice_value3.setText("音量:" + i);voiceNumber3 = i;}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});}@Overridepublic void onClick(View view) {if (null == mTts) {// 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688showToast("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");return;}switch (view.getId()) {// 开始合成// 收到onCompleted 回调时,合成结束、生成合成音频// 合成的音频格式:只支持pcm格式case R.id.tts_play://恢复背景色为白色setTextStyle(0, ttsText.getText().toString().length(), Color.WHITE);// 设置参数setParam();/*** 只保存音频不进行播放接口,调用此接口请注释startSpeaking接口* text:要合成的文本,uri:需要保存的音频全路径,listener:回调接口*/int code = mTts.startSpeaking(ttsText.getText().toString(), mTtsListener);//String path = Environment.getExternalStorageDirectory() + "/tts.pcm";//int code = mTts.synthesizeToUri(texts, path, mTtsListener);if (code != ErrorCode.SUCCESS) {showToast("语音合成失败,错误码: " + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");}break;// 取消合成case R.id.tts_cancel://恢复背景色为白色setTextStyle(0, ttsText.getText().toString().length(), Color.WHITE);mTts.stopSpeaking();break;// 暂停播放case R.id.tts_pause:mTts.pauseSpeaking();break;// 继续播放case R.id.tts_resume:mTts.resumeSpeaking();break;// 选择发音人case R.id.tts_btn_person_select:showPresonSelectDialog();break;// 选择音频流类型case R.id.tts_btn_person_type:showVoiceSelectDialog();break;}}private int selectedNum = 0;private int selectedVoiceNum = 0;/*** 发音人选择。*/private void showPresonSelectDialog() {new AlertDialog.Builder(this).setTitle("在线合成发音人选项")// 单选框有几项,各是什么名字.setSingleChoiceItems(mCloudVoicersEntries, selectedNum,new DialogInterface.OnClickListener() { // 点击单选框后的处理public void onClick(DialogInterface dialog, int which) { // 点击了哪一项voicer = mCloudVoicersValue[which];//凯瑟琳、亨利(阿森纳)、玛丽切换文本至英文if ("catherine".equals(voicer) || "henry".equals(voicer) || "vimary".equals(voicer)) {ttsText.setText(R.string.text_tts_source_en);} else {//其他中文ttsText.setText(R.string.text_tts_source);}ttsBtnPersonSelect.setText("发音人:"+mCloudVoicersEntries[which]);selectedNum = which;dialog.dismiss();}}).show();}/*** 音频流类型选择*/private void showVoiceSelectDialog() {new AlertDialog.Builder(this).setTitle("在线合成发音人选项")// 单选框有几项,各是什么名字.setSingleChoiceItems(mCloudVoicersName, selectedVoiceNum,new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {voiceName = mCloudVoicersName[which];ttsBtnPersonType.setText("音频流类型:" + voiceName);dialog.dismiss();}}).show();}/*** 初始化监听。*/private InitListener mTtsInitListener = new InitListener() {@Overridepublic void onInit(int code) {Log.e(TAG, "InitListener init() code = " + code);if (code != ErrorCode.SUCCESS) {showToast("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");} else {// 初始化成功,之后可以调用startSpeaking方法// 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,// 正确的做法是将onCreate中的startSpeaking调用移至这里}}};/*** 合成回调监听。*/private SynthesizerListener mTtsListener = new SynthesizerListener() {@Overridepublic void onSpeakBegin() {showToast("开始播放");}@Overridepublic void onSpeakPaused() {showToast("暂停播放");}@Overridepublic void onSpeakResumed() {showToast("继续播放");}@Overridepublic void onBufferProgress(int percent, int beginPos, int endPos, String info) {// 合成进度Log.e(TAG, "onBufferProgress percent =" + percent);//记录暂停时的进度mPercentForBuffering = percent;//缓冲与播放进度showToast(String.format(getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying));}@Overridepublic void onSpeakProgress(int percent, int beginPos, int endPos) {// 播放进度Log.e(TAG, "onSpeakProgress percent =" + percent);mPercentForPlaying = percent;progress.setText("当前进度:" + percent + "%");setTextStyle(beginPos, endPos, Color.GREEN);}@Overridepublic void onCompleted(SpeechError error) {if (error == null) {//showToast("播放完成");Log.e(TAG, "onCompleted: 播放完成" + container.size());try {for (int i = 0; i < container.size(); i++) {writeToFile(container.get(i));}} catch (IOException e) {}//播放完成后保存至文件夹FileUtil.saveFile(memFile, mTotalSize, Environment.getExternalStorageDirectory() + "/helloword-Tts1.pcm");} else if (error != null) {showToast(error.getPlainDescription(true));}}@Overridepublic void onEvent(int eventType, int arg1, int arg2, Bundle obj) {//   以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因//   若使用本地能力,会话id为nullif (SpeechEvent.EVENT_SESSION_ID == eventType) {String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);Log.e(TAG, "onEventid =" + sid);}//当设置SpeechConstant.TTS_DATA_NOTIFY为1时,抛出buf数据if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);Log.e(TAG, "onEvent bufis =" + buf.length);container.add(buf);}}};/*** 设置文字背景色*/private void setTextStyle(int beginPos, int endPos, int color) {builder = new SpannableStringBuilder(ttsText.getText());///当前播放的文字背景设置为蓝色builder.setSpan(new BackgroundColorSpan(color), beginPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);ttsText.setText(builder);Log.e(TAG, "beginPos = " + beginPos + "  endPos = " + endPos);}/*** 参数设置*/private void setParam() {// 清空参数mTts.setParameter(SpeechConstant.PARAMS, null);// 根据合成引擎设置相应参数if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);//支持实时音频返回,仅在synthesizeToUri条件下支持mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY, "1");//    mTts.setParameter(SpeechConstant.TTS_BUFFER_TIME,"1");// 设置在线合成发音人mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);//设置合成语速(String 类型)mTts.setParameter(SpeechConstant.SPEED, voiceNumber1 + "");//设置合成音调mTts.setParameter(SpeechConstant.PITCH, voiceNumber2 + "");//设置合成音量mTts.setParameter(SpeechConstant.VOLUME, voiceNumber3 + "");} else {mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);mTts.setParameter(SpeechConstant.VOICE_NAME, "");}//设置播放器音频流类型mTts.setParameter(SpeechConstant.STREAM_TYPE, voiceName);// 设置播放合成音频打断音乐播放,默认为truemTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "false");// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/helloword-Tts2.wav");}@Overrideprotected void onDestroy() {super.onDestroy();if (null != mTts) {mTts.stopSpeaking();// 退出时释放连接mTts.destroy();}}@Overrideprotected void onResume() {//移动数据统计分析/*FlowerCollector.onResume(TtsDemo.this);FlowerCollector.onPageStart(TAG);*/super.onResume();}@Overrideprotected void onPause() {//移动数据统计分析/*FlowerCollector.onPageEnd(TAG);FlowerCollector.onPause(TtsDemo.this);*/super.onPause();}private void writeToFile(byte[] data) throws IOException {if (data == null || data.length == 0)return;try {if (memFile == null) {Log.e(TAG, "writeToFile: 写入文件夹");String mFilepath = Environment.getExternalStorageDirectory() + "/helloword-Tts1.pcm";memFile = new MemoryFile(mFilepath, 1920000);memFile.allowPurging(false);}memFile.writeBytes(data, 0, (int) mTotalSize, data.length);mTotalSize += data.length;} finally {}}/*** 展示吐司*/private void showToast(final String str) {Toast.makeText(this, str, Toast.LENGTH_SHORT).show();}}

、对应布局文件activity_tts.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"android:orientation="vertical"android:padding="10dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="讯飞合成示例"android:textSize="30sp" /><EditTextandroid:id="@+id/tts_text"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:text="@string/text_tts_source"android:textSize="20sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/voice_value1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="语速:50"android:textSize="18sp" /><SeekBarandroid:id="@+id/seek_bar1"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:maxHeight="2dp"android:padding="5dp"android:progress="50"android:thumb="@drawable/setting_p" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:layout_marginBottom="15dp"><TextViewandroid:id="@+id/voice_value2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="音调:50"android:textSize="18sp" /><SeekBarandroid:id="@+id/seek_bar2"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:maxHeight="2dp"android:padding="5dp"android:progress="50"android:thumb="@drawable/setting_p" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="15dp"><TextViewandroid:id="@+id/voice_value3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="音量:50"android:textSize="18sp" /><SeekBarandroid:id="@+id/seek_bar3"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:maxHeight="2dp"android:padding="5dp"android:progress="50"android:thumb="@drawable/setting_p" /></LinearLayout><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="注意:改变值后,需重新合成播放"android:textSize="18sp" /><TextViewandroid:id="@+id/progress"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:text="当前进度:0%"android:textSize="18sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/tts_btn_person_select"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="发音人:小燕"android:textSize="20sp" /><Buttonandroid:id="@+id/tts_btn_person_type"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="音频流类型:通话"android:textSize="18sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:gravity="center_horizontal"android:orientation="horizontal"><Buttonandroid:id="@+id/tts_play"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="开始合成"android:textSize="20sp" /><Buttonandroid:id="@+id/tts_cancel"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="取消"android:textSize="20sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:gravity="center_horizontal"android:orientation="horizontal"><Buttonandroid:id="@+id/tts_pause"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="暂停播放"android:textSize="20sp" /><Buttonandroid:id="@+id/tts_resume"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="继续播放"android:textSize="20sp" /></LinearLayout></LinearLayout>

、app\src\main\res\values\strings.xml添加:

 <string-array name="voicer_cloud_entries"><item>小燕—女青、中英、普通话</item><item>小宇—男青、中英、普通话</item><item>凯瑟琳—女青、英</item><item>亨利—男青、英</item><item>玛丽—女青、英</item><item>小研—女青、中英、普通话</item><item>小琪—女青、中英、普通话</item><item>小峰—男青、中英、普通话</item><item>小梅—女青、中英、粤语</item><item>小莉—女青、中英、台湾普通话</item><item>小蓉—女青、中、四川话</item><item>小芸—女青、中、东北话</item><item>小坤—男青、中、河南话</item><item>小强—男青、中、湖南话</item><item>小莹—女青、中、陕西话</item><item>小新—男童、中、普通话</item><item>楠楠—女童、中、普通话</item><item>老孙—男老、中、普通话</item></string-array><string-array name="voicer_cloud_values"><item>xiaoyan</item><item>xiaoyu</item><item>catherine</item><item>henry</item><item>vimary</item><item>vixy</item><item>xiaoqi</item><item>vixf</item><item>xiaomei</item><item>xiaolin</item><item>xiaorong</item><item>xiaoqian</item><item>xiaokun</item><item>xiaoqiang</item><item>vixying</item><item>xiaoxin</item><item>nannan</item><item>vils</item></string-array><string-array name="stream_entries"><item>通话</item><item>系统</item><item>铃声</item><item>音乐</item><item>闹铃</item><item>通知</item></string-array><string formatted="false" name="tts_toast_format">缓冲进度为%d%%,播放进度为%d%%</string><string name="text_tts_source_en">iFLYTEK is a national key software enterprise dedicated to the research of intelligent speech and language technologies, development of software and chip products, provision of speech information services, and integration of E-government systems. The intelligent speech technology of iFLYTEK, the core technology of the company, represents the top level in the world.</string><string name="text_tts_source">科大讯飞作为中国最大的智能语音技术提供商,在智能语音技术领域有着长期的研究积累,并在中文语音合成、语音识别、口语评测等多项技术上拥有国际领先的成果。科大讯飞是我国唯一以语音技术为产业化方向的“国家863计划成果产业化基地”…</string>

关于离线合成功能貌似要收费:

Android讯飞语音集成【在线语音合成2】相关推荐

  1. Android讯飞语音集成【语音评测3】

    前言: 语音评测(SpeechEvaluator): 通过智能语音技术自动对发音水平进行评价.发音错误.缺陷进行定位和问题分析.目前评音评测提供汉语.英语两种语言的评测,支持单字(汉语专有).词语 和 ...

  2. 讯飞社区android 源码,android 讯飞语音 demo

    [实例简介] android 讯飞语音 demo 博客地址:http://blog.csdn.net/chenshufei2/article/details/8496905 [实例截图] [核心代码] ...

  3. Android讯飞语音云语音听写学习

    讯飞语音云语音听写学习 这几天两个舍友都买了iPhone 6S,玩起了"Hey, Siri",我依旧对我的Nexus 5喊着"OK,Google".但种种原因, ...

  4. Android讯飞语音播报新闻

    1:讯飞开放平台注册登录:https://www.xfyun.cn/?ch=bdtg 2: 3:创建新应用获取APPID值 4:注册好就可以直接在项目中使用appid值 5:将下载的sdk中libs文 ...

  5. Android——讯飞语音唤醒简介及实现

    前段时间写了一个关于百度语音唤醒文章,最近有做了一个讯飞语音的应用,在这里把学习的资料整理一下. 唤醒的整个过程如下: (图源自讯飞官网) 讯飞的语音唤醒功能实现起来挺方便的(相比百度,百度语音And ...

  6. Android 讯飞语音开发

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 前段时间火了一个很牛的讯飞语音,去看官方文档,瞬间蒙逼,官方是用的eclipse,我用的Android Studio.好了,能上代 ...

  7. Android 讯飞语音开发(Android Studio)

    前段时间火了一个很牛的讯飞语音,去看官方文档,瞬间蒙逼,官方是用的eclipse,我用的Android Studio.好了,能上代码尽量不BB. 先来看看gradle里面要配置的东西. module里 ...

  8. android 讯飞语音 提示组件未安装,讯飞语音听写API 未安装组件 错误码21001

    在使用讯飞语音听写时,使用云端听写而不是使用本地出现这个未安装组件错误那可能就是so文件没有成功导入.文档中都是ADT环境的配置,在AndroidStudio中jar包等都和ADT差别不大,但是SO文 ...

  9. 讯飞语音集成(语音转文字,文字转语音)

    语音听写SDK适配安卓6.0需要手动申请权限 关于语音听写SDK的开发,参考科大讯飞开放平台官网为准 在百度搜索讯飞科技开放平台,自己注册账号 自己创建一个新应用 在控制台界面创建完应用,然后选择SD ...

最新文章

  1. Warning message:NAs introduced by coercion
  2. AI如何帮助我们理解意识——麻省理工最新大脑研究
  3. rsync服务器的配置
  4. 喜报!神策数据荣获“2019 银行业数字营销大赛”智能营销类金奖
  5. 爬虫开发10.scrapy框架之日志等级和请求传参
  6. android Arrays.fill()的使用
  7. 在一个类型的继承体系中,成员的构造顺序
  8. ML.NET 1.4 发布,跨平台机器学习框架
  9. 简述MapReduce执行过程?
  10. 循环神经网络LSTM RNN回归:sin曲线预测
  11. python给矩阵赋值_python 实现矩阵旋转
  12. MySQL 5.7--------多实例部署最佳实战
  13. no-repeat失效
  14. 瓦片地图面面观之投影
  15. 【Web前端HTML5CSS3】02-前端开发准备
  16. 分享一个电信永久0月租的手机卡
  17. 数学与神经网络关系大吗,神经网络与算法的关系
  18. BG-sentry的安装和配置
  19. 基于springboot二手交易平台
  20. ubantu 添加防火墙策略_linux - 如何在Ubuntu上设置简单的防火墙? - Ubuntu问答

热门文章

  1. android 音量键 长按,安卓手机强制恢复出厂设置 一般是关机状态下按住音量键下...
  2. Toad Keyword Uppercase
  3. scratch(图形化编程工具)做3.0版本的猫咪积木模拟器。
  4. java项目 异常如何解决方案,java 项目
  5. 微软产的避孕套最好?
  6. 开放平台下的商业模式浅析
  7. 小程序图片不显示的解决方法
  8. 国培 计算机远程培训心得,国培网络研修心得体会(通用4篇)
  9. 党建信息管理系统源码 完整程序包+搭建教程
  10. mysql truncate命令