Android 开发 框架系列 百度语音合成
官方文档:http://ai.baidu.com/docs#/TTS-Android-SDK/6d5d6899
官方百度语音合成控制台:https://cloud.baidu.com/product/speech/tts
步骤一 申请授权
在百度语音控制台中申请使用语音合成的授权,填入相关数据后(注意:一定要选择Android填入正确的包名,不然可能会影响使用离线语音合成)。得到相应的APP_ID,APP_KEY,SECRET_KEY;然后在下载语音包SDK。
步骤二 导入依赖
这里有三组文件需要分别存放到指定目录(这些文件在语音包的sdk里都有):
第一 libs里的jar
请将这个jar导入libs文件夹里
第二 assets里的离线语音包dat与离线文字识别dat文件
注意这5个文件在代码里还要进行复制操作,将这些文件复制到外部存储的指定目录才能正常使用。
第三 jniLibs里的语音合成os文件
步骤三 个人的封装
使用方法可以参考百度,也可以参考我这个封装,但是请要多调试。因为百度的sdk经常变动,有时效性的。
接口class
/**
*@content:百度语音合成的接口class
*@time:2018-9-10
*@build:
*/ public interface SpeechListener {
void onInitFinish();
void onStart(Context context,String resultValue);
void onProgress(Context context,String resultValue,int current);
void onFinish(Context context,String resultValue);
void onError(Context context,String resultValue, SpeechError speechError);
}
配置信息class
/**
*@content:百度语音合成的数据管理class
*@time:2018-9-8
*@build:
*/ public class VoiceConfigData {
/**
* 账号组
*/
public static final String APP_ID = "请输入你的app id";
public static final String APP_KEY = "请输入你的app key";
public static final String SECRET_KEY = "请输入你的 secret key";
/**
* 模式 TtsMode.MIX; 离在线融合,在线优先; TtsMode.ONLINE 纯在线; 没有纯离线
*/
public static final TtsMode TTS_MODE = TtsMode.MIX; /**
*离线资源文件名称与离线资源转存路径
*/
public static final String TEMP_DIR = Environment.getExternalStorageDirectory() +"/"+"baiduTTS";//转存路径
//离线度丫丫
public static final String OFFLINE_FILE_ONE = "bd_etts_common_speech_as_mand_eng_high_am_v3.0.0_20170516.dat";
//离线女声
public static final String OFFLINE_FILE_TWO = "bd_etts_common_speech_f7_mand_eng_high_am-mix_v3.0.0_20170512.dat";
//离线男声
public static final String OFFLINE_FILE_THREE = "bd_etts_common_speech_m15_mand_eng_high_am-mix_v3.0.0_20170505.dat";
//yyjw 度逍遥
public static final String OFFLINE_FILE_FOUR = "bd_etts_common_speech_yyjw_mand_eng_high_am-mix_v3.0.0_20170512.dat";
//离线文字识别文件
public static final String TEXT_FILENAME = "bd_etts_text.dat";
}
百度语音合成工具class
package com.yt.owl.utils.BaiduVoiceUtil; import android.content.Context;
import android.media.AudioManager;
import android.util.Log;
import android.util.Pair; import com.baidu.tts.auth.AuthInfo;
import com.baidu.tts.chainofresponsibility.logger.LoggerProxy;
import com.baidu.tts.client.SpeechError;
import com.baidu.tts.client.SpeechSynthesizeBag;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.SpeechSynthesizerListener; import com.yt.owl.utils.FileHandleUtil; import java.util.ArrayList;
import java.util.List; /**
*@content:百度语音合成工具class
*@time:2018-9-10
*@build:
* 使用说明:先使用getI方法得到单例,在使用init方法初始化,初始化完成后在调用语音合成等等方法。
* 最后注意!请不要忘记了使用Destroy方法释放资源
*/
public class SpeakVoiceUtil {
private static final String TAG = "SpeakVoiceUtil";
private SpeechSynthesizer mSpeechSynthesizer;
private Context mContext;
private static SpeakVoiceUtil mSpeakVoiceUtil;
private SpeechListener mSpeechListener;
private SpeechSynthesizerListener mSpeechSynthesizerListener;
private SpeakVoiceUtil(){} public static SpeakVoiceUtil getI(){
if (mSpeakVoiceUtil == null){
mSpeakVoiceUtil = new SpeakVoiceUtil();
}
return mSpeakVoiceUtil;
} /**
* 初始化
* @param context 外部上下文
*/
public void init(Context context){
this.mContext = context;
if (mSpeakVoiceUtil == null){
Log.e(TAG, "Error SpeakVoiceUtil is null");
return;
}
initFile();
initTTs();
checkAuth();
if (mSpeechListener !=null) {
mSpeechListener.onInitFinish();
}
} /**
* 合成语音并且播放
* @param text 要合成的text文本
*/
public void speak(String text){
if (mSpeechSynthesizer == null) {
Log.e(TAG, "Error speak:mSpeechSynthesizer is null.");
return;
}
int result = mSpeechSynthesizer.speak(text);
checkResult(result, "speak");
Log.i(TAG, "播放语音:"+text);
} /**
* 停止语音合成和播放,清空列队
*/
public void stop() {
if(mSpeechSynthesizer == null){
Log.e(TAG, "Error stop:mSpeechSynthesizer is null.");
return;
}
int result = mSpeechSynthesizer.stop();
checkResult(result, "stop");
Log.i(TAG, "停止语音");
} /**
* 暂停播放。仅调用speak后生效
*/
public void pause() {
if(mSpeechSynthesizer == null){
Log.e(TAG, "Error pause:mSpeechSynthesizer is null.");
return;
}
int result = mSpeechSynthesizer.pause();
checkResult(result, "pause");
Log.i(TAG, "暂停语音");
} /**
* 继续播放。仅调用speak后生效,调用pause生效
*/
public void resume() {
if(mSpeechSynthesizer == null){
Log.e(TAG, "Error resume:mSpeechSynthesizer is null.");
return;
}
int result = mSpeechSynthesizer.resume();
checkResult(result, "resume");
Log.i(TAG, "恢复语音");
} /**
* 批量播放
*
* 使用demo
* List<SpeechSynthesizeBag> list = new ArrayList<>();
* SpeechSynthesizeBag s1 = new SpeechSynthesizeBag();
* s1.setText("开始批量播放");
* s1.setUtteranceId("1");
* list.add(s1);
* SpeechSynthesizeBag s2 = new SpeechSynthesizeBag();
* s2.setText("批量播放成功");
* s2.setUtteranceId("2");
* list.add(s2);
* SpeakVoiceUtil.getI().batchSpeak(list);
*/
public void batchSpeak(List<SpeechSynthesizeBag> list) {
if(mSpeechSynthesizer == null){
Log.e(TAG, "Error batchSpeak:mSpeechSynthesizer is null.");
return;
}
int result = mSpeechSynthesizer.batchSpeak(list);
checkResult(result, "batchSpeak");
} /**
* 释放资源
*/
public void Destroy() {
if (mSpeechSynthesizer != null) {
mSpeechSynthesizer.stop();
mSpeechSynthesizer.release();
mSpeechSynthesizer = null;
}
} public int setVoice(float leftVoice,float rightVoice){
if (mSpeechSynthesizer == null){
Log.e(TAG, "Error setVoice: mSpeechSynthesizer is null");
return -;
}
int result = mSpeechSynthesizer.setStereoVolume(leftVoice,rightVoice);
return result; } /**
* 语音播放监听接口回调
* @param SpeechListener 接口类
*/
public void onSpeechListener(SpeechListener SpeechListener){
this.mSpeechListener = SpeechListener; } /**
* 初始化语音参数
*/
private void initTTs(){
LoggerProxy.printable(true); // 日志打印在logcat中
mSpeechSynthesizer = SpeechSynthesizer.getInstance();
mSpeechSynthesizer.setContext(mContext);
getSpeechSynthesizerListener();
mSpeechSynthesizer.setSpeechSynthesizerListener(mSpeechSynthesizerListener);
int result = mSpeechSynthesizer.setAppId(VoiceConfigData.APP_ID);
checkResult(result,"setAppId");//检查结果
result = mSpeechSynthesizer.setApiKey(VoiceConfigData.APP_KEY,VoiceConfigData.SECRET_KEY);
checkResult(result,"setApiKey"); mSpeechSynthesizer.auth(VoiceConfigData.TTS_MODE);
// 文本模型文件路径 (离线引擎使用), 注意TEXT_FILENAME必须存在并且可读
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE,
VoiceConfigData.TEMP_DIR+"/"+VoiceConfigData.TEXT_FILENAME);
// 声学模型文件路径 (离线引擎使用), 注意TEXT_FILENAME必须存在并且可读
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE,
VoiceConfigData.TEMP_DIR+"/"+VoiceConfigData.OFFLINE_FILE_TWO);
// 以下setParam 参数选填。不填写则默认值生效
// 设置在线发声音人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "");
// 设置合成的音量,0-9 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "");
// 设置合成的语速,0-9 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "");
// 设置合成的语调,0-9 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, ""); // 设置参数的组合模式
// 该参数设置为TtsMode.MIX生效。即纯在线模式不生效。
// MIX_MODE_DEFAULT 默认 ,wifi状态下使用在线,非wifi离线。在线状态下,请求超时6s自动转离线
// MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI wifi状态下使用在线,非wifi离线。在线状态下, 请求超时1.2s自动转离线
// MIX_MODE_HIGH_SPEED_NETWORK , 3G 4G wifi状态下使用在线,其它状态离线。在线状态下,请求超时1.2s自动转离线
// MIX_MODE_HIGH_SPEED_SYNTHESIZE, 2G 3G 4G wifi状态下使用在线,其它状态离线。在线状态下,请求超时1.2s自动转离线
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT); mSpeechSynthesizer.setAudioStreamType(AudioManager.MODE_IN_CALL);//设置音频流出口
mSpeechSynthesizer.setStereoVolume(1f,1f);//设置音量 result = mSpeechSynthesizer.initTts(VoiceConfigData.TTS_MODE);//初始化在线模式:TtsMode.MIX; 离在线融合,在线优先; TtsMode.ONLINE 纯在线; 没有纯离线
checkResult(result, "initTts"); } /**
* 初始化文件,将assets目录的离线语音包复制到sd卡中
*/
private void initFile(){
Log.i(TAG, "开始初始化离线文件");
String [] files = {VoiceConfigData.OFFLINE_FILE_ONE,
VoiceConfigData.OFFLINE_FILE_TWO,
VoiceConfigData.OFFLINE_FILE_THREE,
VoiceConfigData.OFFLINE_FILE_FOUR,
VoiceConfigData.TEXT_FILENAME};
if (FileHandleUtil.isCanUseSD()){//判断sd卡是否可用
for (String file : files){
String filePath = VoiceConfigData.TEMP_DIR+"/"+file;
if (!FileHandleUtil.isFileExist(filePath)){
Log.i(TAG, "initFile 准备复制文件file:"+file+" 到指定目录:"+filePath);
FileHandleUtil.copyFromAssetsToSdcard(mContext,file,VoiceConfigData.TEMP_DIR);
}else {
Log.i(TAG, "initFile "+file+"文件存在不需要复制");
}
}
}else {
Log.e(TAG, "sdcard is null ...");
return;
}
} private void checkResult(int result, String method) {
if (result != ) {
Log.e(TAG, "error code :" + result + " method:" + method + ", 错误码文档:http://yuyin.baidu.com/docs/tts/122");
}
} /**
* 检查appId ak sk 是否填写正确,另外检查官网应用内设置的包名是否与运行时的包名一致。本demo的包名定义在build.gradle文件中
*
* @return
*/
private boolean checkAuth() {
AuthInfo authInfo = mSpeechSynthesizer.auth(VoiceConfigData.TTS_MODE);
if (!authInfo.isSuccess()) {
// 离线授权需要网站上的应用填写包名。本demo的包名是com.baidu.tts.sample,定义在build.gradle中
String errorMsg = authInfo.getTtsError().getDetailMessage();
Log.e(TAG, "error 鉴权失败 errorMsg=" + errorMsg);
return false;
} else {
Log.e(TAG, "验证通过,离线正式授权文件存在" );
return true;
}
} /**
* 语音合成监听接口回调方法
*/
private void getSpeechSynthesizerListener(){
if (mSpeechSynthesizerListener == null) {
Log.e(TAG, "初始化SpeechSynthesizerListener");
mSpeechSynthesizerListener = new SpeechSynthesizerListener() {
@Override
public void onSynthesizeStart(String s) {
Log.i(TAG, "onSynthesizeStart合成启动:返回码=" + s); } @Override
public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {
Log.i(TAG, "onSynthesizeDataArrived合成数据到达:" + "返回码=" + s + "; 字节=" + bytes + "; current=" + i); } @Override
public void onSynthesizeFinish(String s) {
Log.i(TAG, "onSynthesizeFinish合成完成:返回码=" + s); } @Override
public void onSpeechStart(String s) {
Log.i(TAG, "onSpeechStart语音开始:返回码=" + s);
if (mSpeechListener != null) {
mSpeechListener.onStart(mContext, s);
} } @Override
public void onSpeechProgressChanged(String s, int i) {
Log.i(TAG, "onSpeechProgressChanged语音播放中:返回码=" + s + "; current=" + i);
if (mSpeechListener != null) {
mSpeechListener.onProgress(mContext, s, i);
} } @Override
public void onSpeechFinish(String s) {
Log.i(TAG, "onSpeechFinish语音播放结束:返回码=" + s);
if (mSpeechListener != null) {
mSpeechListener.onFinish(mContext, s);
} } @Override
public void onError(String s, SpeechError speechError) {
Log.e(TAG, "onError异常:返回码=" + s + "; SpeechError=" + speechError);
if (mSpeechListener != null) {
mSpeechListener.onError(mContext, s, speechError);
} }
};
}
}
}
另外还有一些复制文件的的简单方法,我就不贴出来了。可以自行编写方法用于复制文件
Android 开发 框架系列 百度语音合成的更多相关文章
- Android 开发 框架系列 OkHttp拦截器
前言 此篇博客只讲解okhttp的拦截器功能的详细使用,如果你还不太了解okhttp可以参考我另外一篇博客 Android 开发 框架系列 OkHttp使用详解 添加Interceptor的简单例子 ...
- Android 开发 框架系列 Google的ORM框架 Room
目录 简介 导入工程 使用流程概况 一个简单的小Demo 深入学习 @Entity使用 自定义表名 tableName 自定义字段名@ColumnInfo 主键 @PrimaryKey 索引 @In ...
- Android 开发 框架系列 OkHttp使用详解
简介 okhttp是一个第三方类库,用于android中请求网络.这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) . ...
- Android 开发 框架系列 EventBus 事件总线
介绍 GitHub:https://github.com/greenrobot/EventBus 先聊聊EventBus 线程总线是干什么的,使用环境,优点.缺点. 干什么的? 一句话,简单统一数据传 ...
- android 开发 框架系列 使用 FileDownloader 实现检查更新的功能class
首先介绍一下FileDownloader GH :https://github.com/lingochamp/FileDownloader/blob/master/README-zh.md FileD ...
- Android 开发 框架系列 OkHttp文件上传功能实现(含断点续传)
前言 此篇博客只是上传功能的记录demo,如果你还不太了解okhttp可以参考我的另一篇博客https://www.cnblogs.com/guanxinjing/p/9708575.html 代码部 ...
- Android 开发 框架系列 OkHttp文件下载功能实现(含断点续传)
前言 此篇博客只是下载功能的记录demo,如果你还不太了解okhttp可以参考我的另一篇博客https://www.cnblogs.com/guanxinjing/p/9708575.html 代码部 ...
- Android 开发 框架系列 glide-transformations 图片处理基本使用
首先简单的介绍一下Gilde作用范围.Gilde功能十分强大,它可以实现图片处理.图片本地加载.图片网络加载.位图加载.图片内存缓存.图片磁盘缓存.Gif图片加载.使用简单轻松,轻松的后是它强大的心, ...
- Android 开发 框架系列 Android-Universal-Image-Loader 图片加载使用demo
Android-Universal-Image-Loader github地址:https://github.com/nostra13/Android-Universal-Image-Loader 加 ...
随机推荐
- linux c++ curl 根据IP地址获得当前网络的所在的地理位置
注意: 可能每个电脑的默认中文编码格式不同,有时会出现乱码,需要对返回内容进行编码转换,或者换成可指定编码格式的接口.如 搜狐IP地址查询接口(可设置编码):http://pv.sohu.com/c ...
- python基础提高演练(名片管理系统的开发)
综合应用 —— 名片管理系统 目标 综合应用已经学习过的知识点: 变量 流程控制 函数 模块 开发 名片管理系统 系统需求 1. 程序启动,显示名片管理系统欢迎界面,并显示功能菜单 ********* ...
- scott用户不存在
用的Oracle版本是12c,在解锁scott时提示用户不存在,于是搜解决方法,给出了两种方法: 一种是加载scott.sql文件(我的scott.sql文件是存在的,在Oracle安装目录下搜索一下 ...
- linux中运行.sql文件
1.linux目录结构 2.假设home下面有a.sql文件 先得use databasename,要不会报错 “No Database Selected” 然后source /home/a.sql ...
- mybatis(一、原理,一对多,多对一查询)
MyBatis框架及原理分析 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 ...
- AutoHotKey (AHK) 按键表+自定义快捷键简化操作的教程
自定义快捷键简化操作的教程 ① 下载安装AutoHotKey,并用记事本新建一个MyHotKey.ahk文件,录入如②中信息 ② 下图可以实现,按F6即可触发“Ctrl+C”的复制快捷键,同理F7可实 ...
- linux基础之LSB定义的常用目录详解
Linux基础之LSB定义的基本目录详解 1.LSB中FHS(Filesystem Hierarchy Standard)定义的一些文件 /boot:主要是存放引导文件的目录,比如内核文件(vmlin ...
- 软件测试_Linux
# Linux## 基础知识### 操作系统* 作为中间人,连接软件和硬件### Linux * 特点 * 免费+安全### 查看日志,定位bug,修改文件,搭建环境## 安装### 装虚拟机 vmw ...
- 《Linux内核原理与分析》第九周作业
课本:第八章 进程的切换和系统的一般执行过程 进行进程调度的时机 Linux内核通过schedule函数实现进程调度,schedule函数在运行队列中找到一个进程,把CPU分配给它 调用schedul ...
- 学习笔记TF050:TensorFlow源代码解析
TensorFlow目录结构. ACKNOWLEDGMENTS #TensorFlow版本声明 ADOPTERS.md #使用TensorFlow的人员或组织列表 AUTHORS #TensorFlo ...