Android开发之科大讯飞语音合成与播报

  • 一、效果图
  • 二、打开[讯飞开放平台](https://www.xfyun.cn/),注册登录后,找到我的应用,点击创建新应用。
  • 三、填写相关信息,然后点击提交。
  • 四、点击创建好的应用。
  • 五、可以看到APPID信息。
  • 六、往下滑可以下载SDK。
  • 七、下载到本地后,解压。
  • 八、把刚才解压后的libs中的文件复制到项目中的libs下。
    • **1.此时这个Msc.jar还是不可用的,下面鼠标右键点击它。**
    • 2.点击Add As Library…
    • 3.点击OK,此时你可以看到它可以展开了,就说明你的app模块中已经添加了这个jar的依赖了。
  • 九、复制assets文件夹到项目中。
  • 十、粘贴到main下面,如下图所示。
  • 十一、配置项目,打开build.gradle。
  • 十二、AndroidManifest.xml中配置权限。
  • 十三、新建一个MyApplication类。
    • 1.然后在AndroidManifest.xml中配置
  • 十四、主布局文件(activity_yy)
  • 十五、主java文件(YybbActivity)

今天做一个稍微复杂点的,Android集成科大讯飞实现语音合成与播报功能。
老规矩,直接进入正题。

一、效果图

二、打开讯飞开放平台,注册登录后,找到我的应用,点击创建新应用。

三、填写相关信息,然后点击提交。

四、点击创建好的应用。

五、可以看到APPID信息。

六、往下滑可以下载SDK。

七、下载到本地后,解压。


这里重点就是这个libs文件夹中的内容了。

八、把刚才解压后的libs中的文件复制到项目中的libs下。

1.此时这个Msc.jar还是不可用的,下面鼠标右键点击它。

2.点击Add As Library…

3.点击OK,此时你可以看到它可以展开了,就说明你的app模块中已经添加了这个jar的依赖了。

九、复制assets文件夹到项目中。

十、粘贴到main下面,如下图所示。

十一、配置项目,打开build.gradle。

 //资源设置sourceSets {main {jniLibs.srcDirs = ['libs']}}

十二、AndroidManifest.xml中配置权限。

 <!--连接网络权限,用于执行云端语音能力 --><uses-permission android:name="android.permission.INTERNET"/><!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --><uses-permission android:name="android.permission.RECORD_AUDIO"/><!--读取网络信息状态 --><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><!--获取当前wifi状态 --><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.WRITE_EXTERNAL_STORAGE"/><!--外存储读权限,构建语法需要用到此权限 --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

十三、新建一个MyApplication类。

package com.example;import android.app.Application;import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechUtility;
import org.xutils.x;
public class MyApplication extends Application {@Overridepublic void onCreate() {SpeechUtility.createUtility(MyApplication.this, SpeechConstant.APPID +"=\n" +"7b6e5ba7");super.onCreate();x.Ext.init(this);x.Ext.setDebug(BuildConfig.DEBUG);  //这个会影响性能}
}

1.然后在AndroidManifest.xml中配置

十四、主布局文件(activity_yy)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="750dp"android:orientation="vertical"><include layout="@layout/main_title_bar"/><EditTextandroid:id="@+id/et_text"android:gravity="top|left"android:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/Theme.TYLDApp"/><Buttonandroid:id="@+id/btn_play"android:text="开始播放"android:layout_width="200dp"android:textSize="20dp"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:background="@drawable/register_selector"android:layout_marginLeft="100dp"android:textColor="@color/white"/><Buttonandroid:id="@+id/btn_cancel"android:text="取消"android:layout_width="200dp"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:textColor="@color/white"android:textSize="20dp"android:background="@drawable/register_selector"android:layout_marginLeft="100dp"/><Buttonandroid:id="@+id/btn_pause"android:layout_width="200dp"android:layout_height="wrap_content"android:textColor="@color/white"android:textSize="20dp"android:background="@drawable/register_selector"android:layout_marginLeft="100dp"android:layout_marginTop="10dp"android:text="暂停播放" /><Buttonandroid:id="@+id/btn_resume"android:layout_width="200dp"android:layout_height="wrap_content"android:textColor="@color/white"android:textSize="20dp"android:background="@drawable/register_selector"android:layout_marginLeft="100dp"android:layout_marginTop="10dp"android:text="继续播放" /><LinearLayoutandroid:gravity="center_vertical"android:layout_width="match_parent"android:layout_height="50dp"android:orientation="horizontal"android:paddingStart="6dp"android:paddingEnd="6dp"><Viewandroid:layout_width="0dp"android:layout_height="0.5dp"android:layout_weight="1"android:background="#000" /><TextViewandroid:layout_marginStart="6dp"android:layout_marginEnd="6dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置"android:textColor="#000"android:textSize="16sp" /><Viewandroid:layout_width="0dp"android:layout_height="0.5dp"android:layout_weight="1"android:background="#000" /></LinearLayout><!--设置发音人--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"android:paddingStart="6dp"android:paddingEnd="6dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置发音人:"android:textColor="#000"android:textSize="16sp" /><Spinnerandroid:id="@+id/spinner"android:layout_width="0dp"android:layout_height="50dp"android:layout_weight="1" /></LinearLayout><!--设置语速--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp"android:gravity="center_vertical"android:paddingStart="6dp"android:paddingEnd="6dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置语速:"android:textColor="#000"android:textSize="16sp" /><SeekBarandroid:id="@+id/sb_speed"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:progress="50" /></LinearLayout><!--设置音调--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp"android:gravity="center_vertical"android:paddingStart="6dp"android:paddingEnd="6dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置音调:"android:textColor="#000"android:textSize="16sp" /><SeekBarandroid:id="@+id/sb_pitch"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:progress="50" /></LinearLayout><!--设置音量--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp"android:gravity="center_vertical"android:paddingStart="6dp"android:paddingEnd="6dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置音量:"android:textColor="#000"android:textSize="16sp" /><SeekBarandroid:id="@+id/sb_volume"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:progress="50" /></LinearLayout></LinearLayout>

十五、主java文件(YybbActivity)

package com.example.activity;import static com.iflytek.cloud.VerifierResult.TAG;import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.MemoryFile;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;import com.example.R;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.msc.util.FileUtil;
import com.iflytek.cloud.msc.util.log.DebugLog;import java.util.Vector;public class YybbActivity extends AppCompatActivity implements View.OnClickListener,AdapterView.OnItemSelectedListener {//语速private String speedValue = "50";//音调private String pitchValue = "50";//音量private String volumeValue = "50";//输入框private EditText etText;// 语音合成对象private SpeechSynthesizer mTts;// 默认发音人private String voicer = "xiaoyan";//发音人名称private static final String[] arrayName = {"讯飞小燕", "讯飞许久", "讯飞小萍", "讯飞小婧", "讯飞许小宝"};//发音人值private static final String[] arrayValue = {"xiaoyan", "aisjiuxu", "aisxping", "aisjinger", "aisbabyxu"};//数组适配器private ArrayAdapter<String> arrayAdapter;// 引擎类型private String mEngineType = SpeechConstant.TYPE_CLOUD;//播放的文字String text = " 属性:昔刘涓子晋末于丹阳郊外照射,忽见一物,高二丈许,射而中之,如雷电声若风雨。其夜不敢前追,诘旦率门徒子弟数人,寻纵至山下,见一小儿提罐,问何往为。";private Vector<byte[]> container = new Vector<>();//内存文件MemoryFile memoryFile;//总大小public volatile long mTotalSize = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_yy);//请求权限requestPermissions();initView();// 初始化合成对象mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);}/*** 初始化页面*/private void initView() {etText = findViewById(R.id.et_text);findViewById(R.id.btn_play).setOnClickListener(this);findViewById(R.id.btn_cancel).setOnClickListener(this);findViewById(R.id.btn_pause).setOnClickListener(this);findViewById(R.id.btn_resume).setOnClickListener(this);SeekBar sbSpeed = findViewById(R.id.sb_speed);SeekBar sbPitch = findViewById(R.id.sb_pitch);SeekBar sbVolume = findViewById(R.id.sb_volume);Spinner spinner = findViewById(R.id.spinner);//将可选内容与ArrayAdapter连接起来arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, arrayName);//设置下拉列表的风格arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);//将adapter 添加到spinner中spinner.setAdapter(arrayAdapter);//添加事件Spinner事件监听spinner.setOnItemSelectedListener(this);setSeekBar(sbSpeed, 1);setSeekBar(sbPitch, 2);setSeekBar(sbVolume, 3);}/*** 请求权限*/private void requestPermissions() {try {//Android6.0及以上版本if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {int permission = ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE);if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.WRITE_SETTINGS,Manifest.permission.READ_EXTERNAL_STORAGE}, 0x0010);}}} catch (Exception e) {e.printStackTrace();}}/*** 权限请求返回结果*/@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);}/*** 页面点击事件* @param v 控件*/@Overridepublic void onClick(View v) {if (mTts == null) {this.showTip("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");return;}switch (v.getId()) {case R.id.btn_play://开始合成//输入文本String etStr = etText.getText().toString().trim();if (!etStr.isEmpty()) {text = etStr;}//设置参数setParam();//开始合成播放int code = mTts.startSpeaking(text, mTtsListener);if (code != ErrorCode.SUCCESS) {showTip("语音合成失败,错误码: " + code);}break;case R.id.btn_cancel://取消合成mTts.stopSpeaking();break;case R.id.btn_pause://暂停播放mTts.pauseSpeaking();break;case R.id.btn_resume://继续播放mTts.resumeSpeaking();break;default:break;}}/*** 初始化监听。*/private InitListener mTtsInitListener = new InitListener() {@Overridepublic void onInit(int code) {Log.i(TAG, "InitListener init() code = " + code);if (code != ErrorCode.SUCCESS) {showTip("初始化失败,错误码:" + code);} else {showTip("初始化成功");}}};/*** Toast提示* @param msg*/private void showTip(String msg) {Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();}/*** 参数设置** @return*/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.VOICE_NAME, voicer);//设置语速mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);//设置音调mTts.setParameter(SpeechConstant.PITCH, pitchValue);//设置音量mTts.setParameter(SpeechConstant.VOLUME, volumeValue);} else {mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);mTts.setParameter(SpeechConstant.VOICE_NAME, "");}// 设置播放合成音频打断音乐播放,默认为truemTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "false");// 设置音频保存路径,保存音频格式支持pcm、wavmTts.setParameter(SpeechConstant.AUDIO_FORMAT, "pcm");mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, getExternalFilesDir(null) + "/msc/tts.pcm");}/*** 合成回调监听。*/private SynthesizerListener mTtsListener = new SynthesizerListener() {//开始播放@Overridepublic void onSpeakBegin() {Log.i(TAG, "开始播放");}//暂停播放@Overridepublic void onSpeakPaused() {Log.i(TAG, "暂停播放");}//继续播放@Overridepublic void onSpeakResumed() {Log.i(TAG, "继续播放");}//合成进度@Overridepublic void onBufferProgress(int percent, int beginPos, int endPos, String info) {Log.i(TAG, "合成进度:" + percent + "%");}//播放进度@Overridepublic void onSpeakProgress(int percent, int beginPos, int endPos) {// 播放进度Log.i(TAG, "播放进度:" + percent + "%");SpannableStringBuilder style = new SpannableStringBuilder(text);style.setSpan(new BackgroundColorSpan(Color.RED), beginPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);etText.setText(style);}//播放完成@Overridepublic void onCompleted(SpeechError error) {if (error == null) {Log.i(TAG, "播放完成," + container.size());DebugLog.LogD("播放完成," + container.size());for (int i = 0; i < container.size(); i++) {//写入文件writeToFile(container.get(i));}//保存文件FileUtil.saveFile(memoryFile, mTotalSize, getExternalFilesDir(null) + "/1.pcm");} else {//异常信息showTip(error.getPlainDescription(true));}}/*** 写入文件*/private void writeToFile(byte[] data) {if (data == null || data.length == 0) {return;}try {if (memoryFile == null) {Log.i(TAG, "memoryFile is null");String mFilepath = getExternalFilesDir(null) + "/1.pcm";memoryFile = new MemoryFile(mFilepath, 1920000);memoryFile.allowPurging(false);}memoryFile.writeBytes(data, 0, (int) mTotalSize, data.length);mTotalSize += data.length;} catch (Exception e) {e.printStackTrace();}}//事件@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.i(TAG, "session id =" + sid);}//当设置SpeechConstant.TTS_DATA_NOTIFY为1时,抛出buf数据if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);Log.i(TAG, "bufis =" + buf.length);container.add(buf);}}};
/*** 选中*/@Overridepublic void onItemSelected(AdapterView<?> parent, View view, int position, long id) {voicer = arrayValue[position];}@Overridepublic void onNothingSelected(AdapterView<?> parent) {}//设置SeekBarprivate void setSeekBar(SeekBar seekBar, final int type) {seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {switch (type) {case 1://设置语速 范围 1~100speedValue = Integer.toString(progress);break;case 2://设置音调  范围 1~100pitchValue = Integer.toString(progress);break;case 3://设置音量  范围 1~100volumeValue = Integer.toString(progress);break;default:break;}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) { }@Overridepublic void onStopTrackingTouch(SeekBar seekBar) { }});}}

到这里就结束了,你可以试试哦

Android开发之科大讯飞语音合成与播报相关推荐

  1. 关于科大讯飞语音合成的开发(先写个本地的,简单)

    1.首先在科大讯飞官网申请应用下载语音合成SDK,在项目中导入Msc.jar包,别忘了还有armeabi目录下的文件.然后建一个语音合成的工具类SpeechUtil_xf,具体代码下面贴出来,相信大家 ...

  2. Android 开发 框架系列 百度语音合成

    Android 开发 框架系列 百度语音合成 官方文档:http://ai.baidu.com/docs#/TTS-Android-SDK/6d5d6899 官方百度语音合成控制台:https://c ...

  3. Android开发笔记(一百零八)智能语音

    智能语音技术 如今越来越多的app用到了语音播报功能,例如地图导航.天气预报.文字阅读.口语训练等等.语音技术主要分两块,一块是语音转文字,即语音识别:另一块是文字转语音,即语音合成. 对中文来说,和 ...

  4. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  5. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  6. Android开发必备(干货源码放送大)

    Android源码大放送(实战开发必备) 文件夹 PATH 列表 │  javaapk.com文件列表生成工具.bat │  使用说明.txt │  免费下载更多源码.url │  目录列表.txt ...

  7. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  8. Android开发学习之使用百度语音识别SDK实现语音识别(上)

    作为移动互联网杀手级的交互方式,语音识别从问世以来就一直备受人们的关注,从IOS的Siri到国内的讯飞语音,语音识别技术在移动开发领域是最为充满前景和希望的技术.Android作为一个移动操作系统,其 ...

  9. 基于Google的嵌入式系统android开发语音技术(语音搜索,语音朗读文章,语音控制)

    android是Google推出的嵌入式操作系统,有着广泛的根基与基础.最近一个中关村的一个CEO朋友送了一个摩托罗拉android手机,想玩玩语音技术过把瘾.如何用android开发语音技术应用呢, ...

  10. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

最新文章

  1. FCN全连接卷积网络(5)--Fully Convolutional Networks for Semantic Segmentation阅读(相关工作部分)
  2. 缺失的第一个正数—leetcode41
  3. thinkphp gd 添加文字
  4. 定义空列表元素类型_【Python+Excel】做数据分析5--列表和元组读取和常用查询
  5. 考研数据结构--严版图相关代码 自用
  6. Sublime Text 插件-全栈开发收集
  7. 用python写一个脚本,自动连wifi,自动登录校园网
  8. SIT测试和UAT测试区别
  9. 移动政企Java线上测评_(重要)如何锻炼训练,确保通过企业线上测评 在线测评和职业性格测评...
  10. h5页面 请在微信客户端打开链接_如何看到“请在微信客户端打开链接”页面的源码?...
  11. 千锋培训的python
  12. Altium designer (AD)中如何设置区域规则和器件规则
  13. typec扩展坞hdmi没反应_全功能扩展坞Type-C Docking (扩展坞) 方案讲解-可实现拔插不掉屏...
  14. numpy数组的拼接(扩维拼接和非扩维拼接)
  15. 怎么把文件发给商家打印?如何给商家发送需打印的文件
  16. WDM在不同Windows版本上的音频支持
  17. hapi入门简介(入门实践)----净土小沙弥学hapi.js_第二篇
  18. jmp指令和call指令
  19. 解决 redis 存入中文,取出来是乱码wenti
  20. 模拟电路笔记(照片)

热门文章

  1. C语言中关于中文字符的存储及相关探索
  2. XWPFTemplate生成根据模板文件填充内容生成word文件
  3. 验证二叉树的前序序列化[抽象前序遍历]
  4. 鸡兔同笼html语言,鸡兔同笼有哪五种方法
  5. 任志强:房价至少还要涨十多年 北京房价不会跌
  6. 如何查找计算机主机地址,ip地址查询 怎么查询电脑IP地址?
  7. python标准库不需要导入即可使用其中的所有对象和方法_Python扩展库需导入以后才能使用其中的对象,Python标准库不需要导入即可使用其中的所有对象和方法...
  8. linux fifo文件,linux中的命名管道(FIFO)
  9. vue3+el-table表格表头增加斜线
  10. 多种方法对网页文字进行快速复制(仅供学习使用,勿践踏他人成果)