今天,我们来学习一下怎么在Android Studio快速集成讯飞SDK实现文字朗读功能,先看一下效果图:

第一步 :了解TTS语音服务

  TTS的全称为Text To Speech,即“从文本到语音”。它是同时运用语言学和心理学的杰出之作,在内置芯片的支持之下,通过神经网络的设计,把文字智能地转化为自然语音流。

  TTS技术对文本文件进行实时转换,转换时间之短可以秒计算。在其特有智能语音控制器作用下,文本输出的语音音律流畅,使得听者在听取信息时感觉自然,毫无机器语音输出的冷漠与生涩感。使用户可以听到清晰悦耳的音质和连贯流畅的语调

  讯飞语言服务分为在线合成和本地合成,其中本地合成需要下载语言包,这和google的TTS一样,但是google的TTS在有的手机中不被支持或者是不支持中文。在这里我们使用的是在线合成的方法,需要有一点点的网速,否则会出现网络缓慢,暂停播放的提示。

第二步:了解主要对象和方法

// 语音合成对象
private SpeechSynthesizer mTts;
// 语音听写对象
private SpeechRecognizer mIat;
//初始化TTS
mTts = SpeechSynthesizer.createSynthesizer(IatDemo.this, mTtsInitListener);
//主要方法 text为要读的文本
mTts.startSpeaking(text, mTtsListener);
//语音对象参数设置
// 设置听写引擎
mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
// 设置返回结果格式
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json"); String lag = mSharedPreferences.getString("iat_language_preference",
"mandarin");
if (lag.equals("en_us")) {
// 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
} else {
// 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
// 设置语言区域
mIat.setParameter(SpeechConstant.ACCENT, lag);
} // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000")); // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000")); // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1")); // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
// 注:AUDIO_FORMAT参数语记需要更新版本才能生效
mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav"); // 设置听写结果是否结果动态修正,为“1”则在听写过程中动态递增地返回结果,否则只在听写结束之后返回最终结果
// 注:该参数暂时只对在线听写有效
mIat.setParameter(SpeechConstant.ASR_DWA, mSharedPreferences.getString("iat_dwa_preference", "0"));

第三步:实现功能

package com.jerehedu.administrator.mysounddemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast; import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import com.iflytek.sunflower.FlowerCollector; import org.json.JSONException;
import org.json.JSONObject; import java.util.HashMap;
import java.util.LinkedHashMap; public class IatDemo extends Activity implements OnClickListener {
private static String TAG = IatDemo.class.getSimpleName();
// 语音合成对象
private SpeechSynthesizer mTts;
// 默认发音人
private String voicer = "xiaoyan";
// 缓冲进度
private int mPercentForBuffering = 0;
// 播放进度
private int mPercentForPlaying = 0;
// 云端/本地单选按钮
private RadioGroup mRadioGroup;
// 语音听写对象
private SpeechRecognizer mIat;
// 语音听写UI
private RecognizerDialog mIatDialog;
// 用HashMap存储听写结果
private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>(); private EditText mResultText;
private Toast mToast;
private SharedPreferences mSharedPreferences;
// 引擎类型
private String mEngineType = SpeechConstant.TYPE_CLOUD;
// 语记安装助手类
ApkInstaller mInstaller; @SuppressLint("ShowToast")
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.iatdemo); initLayout();
// 初始化识别无UI识别对象
// 使用SpeechRecognizer对象,可根据回调消息自定义界面;
mIat = SpeechRecognizer.createRecognizer(IatDemo.this, mInitListener); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
// 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源
mIatDialog = new RecognizerDialog(IatDemo.this, mInitListener); mSharedPreferences = getSharedPreferences("com.jredu.setting",
Activity.MODE_PRIVATE);
mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
mResultText = ((EditText) findViewById(R.id.iat_text));
mInstaller = new ApkInstaller(IatDemo.this); mTts = SpeechSynthesizer.createSynthesizer(IatDemo.this, mTtsInitListener);
mSharedPreferences = getSharedPreferences("com.jredu.setting", MODE_PRIVATE);
mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT); } /**
* 初始化Layout。
*/
private void initLayout() {
findViewById(R.id.iat_recognize).setOnClickListener(IatDemo.this);
findViewById(R.id.read).setOnClickListener(IatDemo.this); // 选择云端or本地
mEngineType = SpeechConstant.TYPE_CLOUD; } int ret = 0; // 函数调用返回值 @Override
public void onClick(View view) {
switch (view.getId()) { // 开始听写
// 如何判断一次听写结束:OnResult isLast=true 或者 onError
case R.id.iat_recognize:
mResultText.setText(null);// 清空显示内容
mIatResults.clear();
// 设置参数
setParam();
boolean isShowDialog = mSharedPreferences.getBoolean(
getString(R.string.pref_key_iat_show), true);
if (isShowDialog) {
// 显示听写对话框
mIatDialog.setListener(mRecognizerDialogListener);
mIatDialog.show();
showTip(getString(R.string.text_begin));
} else {
// 不显示听写对话框
ret = mIat.startListening(mRecognizerListener);
if (ret != ErrorCode.SUCCESS) {
showTip("听写失败,错误码:" + ret);
} else {
showTip(getString(R.string.text_begin));
}
}
break;
// 开始合成
// 收到onCompleted 回调时,合成结束、生成合成音频
// 合成的音频格式:只支持pcm格式
case R.id.read:
String text = ((EditText) findViewById(R.id.tts_text)).getText().toString();
Log.d("==",text);
// 设置参数
setParam(); int code = mTts.startSpeaking(text, mTtsListener);
// Log.d("======",""+code);
// /**
// * 只保存音频不进行播放接口,调用此接口请注释startSpeaking接口
// * text:要合成的文本,uri:需要保存的音频全路径,listener:回调接口
// */
// String path = Environment.getExternalStorageDirectory()+"/tts.pcm";
// int code = mTts.synthesizeToUri(text, path, mTtsListener); if (code != ErrorCode.SUCCESS) {
if(code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED){
//未安装则跳转到提示安装页面
mInstaller.install();
}else {
showTip("语音合成失败,错误码: " + code);
}
}
break;
// 音频流识别 default:
break;
}
}
/**
* 初始化监听。
*/
private InitListener mTtsInitListener = new InitListener() {
@Override
public void onInit(int code) {
Log.d(TAG, "InitListener init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:"+code);
} else {
// 初始化成功,之后可以调用startSpeaking方法
// 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,
// 正确的做法是将onCreate中的startSpeaking调用移至这里
}
}
}; /**
* 初始化监听器。
*/
private InitListener mInitListener = new InitListener() { @Override
public void onInit(int code) {
Log.d(TAG, "SpeechRecognizer init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:" + code);
}
}
};
/**
* 合成回调监听。
*/
private SynthesizerListener mTtsListener = new SynthesizerListener() { @Override
public void onSpeakBegin() {
showTip("开始播放");
} @Override
public void onSpeakPaused() {
showTip("暂停播放");
} @Override
public void onSpeakResumed() {
showTip("继续播放");
} @Override
public void onBufferProgress(int percent, int beginPos, int endPos,
String info) {
// 合成进度
mPercentForBuffering = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
} @Override
public void onSpeakProgress(int percent, int beginPos, int endPos) {
// 播放进度
mPercentForPlaying = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
} @Override
public void onCompleted(SpeechError error) {
if (error == null) {
showTip("播放完成");
} else if (error != null) {
showTip(error.getPlainDescription(true));
}
} @Override
public 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);
// }
}
}; /**
* 听写监听器。
*/
private RecognizerListener mRecognizerListener = new RecognizerListener() { @Override
public void onBeginOfSpeech() {
// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
showTip("开始说话");
} @Override
public void onError(SpeechError error) {
// Tips:
// 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
// 如果使用本地功能(语记)需要提示用户开启语记的录音权限。
showTip(error.getPlainDescription(true));
} @Override
public void onEndOfSpeech() {
// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
showTip("结束说话");
} @Override
public void onResult(RecognizerResult results, boolean isLast) {
Log.d(TAG, results.getResultString());
printResult(results); if (isLast) {
// TODO 最后的结果
}
} @Override
public void onVolumeChanged(int volume, byte[] data) {
showTip("当前正在说话,音量大小:" + volume);
Log.d(TAG, "返回音频数据:"+data.length);
} @Override
public 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);
// }
}
}; private void printResult(RecognizerResult results) {
String text = JsonParser.parseIatResult(results.getResultString()); String sn = null;
// 读取json结果中的sn字段
try {
JSONObject resultJson = new JSONObject(results.getResultString());
sn = resultJson.optString("sn");
} catch (JSONException e) {
e.printStackTrace();
} mIatResults.put(sn, text); StringBuffer resultBuffer = new StringBuffer();
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
} mResultText.setText(resultBuffer.toString());
mResultText.setSelection(mResultText.length());
} /**
* 听写UI监听器
*/
private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
public void onResult(RecognizerResult results, boolean isLast) {
printResult(results);
} /**
* 识别回调错误.
*/
public void onError(SpeechError error) {
showTip(error.getPlainDescription(true));
} }; private void showTip(final String str) {
mToast.setText(str);
mToast.show();
} /**
* 参数设置
*
* @param
* @return
*/
public void setParam() {
// 清空参数
mIat.setParameter(SpeechConstant.PARAMS, null); // 设置听写引擎
mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
// 设置返回结果格式
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json"); String lag = mSharedPreferences.getString("iat_language_preference",
"mandarin");
if (lag.equals("en_us")) {
// 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
} else {
// 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
// 设置语言区域
mIat.setParameter(SpeechConstant.ACCENT, lag);
} // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000")); // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000")); // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1")); // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
// 注:AUDIO_FORMAT参数语记需要更新版本才能生效
mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav"); // 设置听写结果是否结果动态修正,为“1”则在听写过程中动态递增地返回结果,否则只在听写结束之后返回最终结果
// 注:该参数暂时只对在线听写有效
mIat.setParameter(SpeechConstant.ASR_DWA, mSharedPreferences.getString("iat_dwa_preference", "0"));
} @Override
protected void onDestroy() {
super.onDestroy();
// 退出时释放连接
mIat.cancel();
mIat.destroy();
} @Override
protected void onResume() {
// 开放统计 移动数据统计分析
FlowerCollector.onResume(IatDemo.this);
FlowerCollector.onPageStart(TAG);
super.onResume();
} @Override
protected void onPause() {
// 开放统计 移动数据统计分析
FlowerCollector.onPageEnd(TAG);
FlowerCollector.onPause(IatDemo.this);
super.onPause();
} }
作者:杰瑞教育
出处:http://www.cnblogs.com/jerehedu/ 
版权声明:本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

技术咨询:
 

Android Studio快速集成讯飞SDK实现文字朗读功能的更多相关文章

  1. 集成讯飞听写iOS sdk到unity遇到的问题:weak成员和strong成员

    在unity里集成讯飞语音听写iOS sdk的过程中,遇到一个问题,官方的demo中可以将多次onResults回调返回的结果累积拼接起来组成一个完整的结果,而我集成过来以后就不能累积了,只拿到最后一 ...

  2. 讯飞SDK的使用

    在配置好Android Studio 2.3.3后,依照结合网上例子,动手创建讯飞语言听写app,最终手机上运行成功. 主要参考两篇博文(zqHero/XunFeiVoiceDEmo ,Android ...

  3. Android Studio快速开发之道

    概述 现如今开发越来越追求效率和节奏,节省出时间做更多的事情,除了开发技术上的封装等,开发工具的使用技巧也是很重要的,今天就根据自己的经验来给大家介绍一下Android Studio快速开发之道. P ...

  4. Android Studio中提示:Project SDK is not defined

    Android Studio中提示:Project SDK is not defined 2015 年 4 月 1 日 下午 9:04crifan已有2209人围观我来说几句 [背景] 之前用Andr ...

  5. Android Studio快速添加Gson以及GsonFormat的使用

    目录: 一.Android Studio快速添加Gson 二.Android Studio中GsonFormat的使用 三.在线JSON校验格式化工具 一.Android Studio快速添加Gson ...

  6. Android Studio快速开发之道(各种语法糖)

    现如今开发越来越追求效率和节奏,节省出时间做更多的事情,除了开发技术上的封装等,开发工具的使用技巧也是很重要的,今天就根据自己的经验来给大家介绍一下Android Studio快速开发之道. Post ...

  7. Android Studio 快速开发

    概述 现如今开发越来越追求效率和节奏,节省出时间做更多的事情,除了开发技术上的封装等,开发工具的使用技巧也是很重要的,今天就根据自己的经验来给大家介绍一下Android Studio快速开发之道. P ...

  8. Android Studio快速添加Gson Gsonformat

    一.Android Studio快速添加Gson 具体操作:       1.File->Project Structure: 2.app->Dependencies->" ...

  9. Android studio Unable to run mksdcard SDK tool

    /******************************************************************************************** * Andr ...

随机推荐

  1. BZOJ.4946.[NOI2017]蔬菜(贪心 离线)

    题目链接 因为有删除,考虑倒序处理某个p的询问. 那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜.那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间. 这样就只需考 ...

  2. ReentrantLock源码了解

    1).ReentrantLock.tryLock //获取没有被其他线程持有的锁 //1).当没有被任何线程持有时,首先将计数器设置为1,并设置当前持有锁的线程为当前线程,最后返回true //2). ...

  3. 喵哈哈村的魔法考试 Round #7 (Div.2) 题解

    喵哈哈村的魔法考试 Round #7 (Div.2) 注意!后四道题来自于周日的hihocoder offer收割赛第九场. 我建了个群:欢迎加入qscoj交流群,群号码:540667432 大概作为 ...

  4. Linux下Shell函数返回值实现种类

    shell在执行的时候是顺序执行的,也不存在什么多线程什么的. 一下是实现种类: 1.全局 g_result="" function testFunc() { g_result=' ...

  5. 让IIS支持10万并发

    适用的IIS版本:IIS 7.0, IIS 7.5, IIS 8.0 适用的Windows版本:Windows Server 2008, Windows Server 2008 R2, Windows ...

  6. Understanding the STM32F0's GPIO

    Understanding the STM32F0's GPIO This is the first part of the GPIO tutorial for the STM32F0Discover ...

  7. delphi 启动停止windows服务 转

    http://blog.csdn.net/haiou327/article/details/6106233 不用cmd用delphi如何实现启动停止windows服务建议参考一下Delphi的Sckt ...

  8. UIProgressView 详解

    自定义progressView   包括背景图片和进度条的图片以及进度条的高度. //进度条 UIProgressView *aProgressView = [[UIProgressView allo ...

  9. ios 判断app程序第一次启动方法

    if(![[NSUserDefaults standardUserDefaults] boolForKey:@"firstStart"]){ [[NSUserDefaults st ...

  10. Cannot convert type SomeClass to 'T'

    以下代码会出问题: public static T Protect<T>(Func<T> func, UserLevel pageRole) where T : ActionR ...