Android TTS 初体验
http://bbs.apkok.com/thread-1893-1-1.html
一、基础知识
TextToSpeech 简称TTS,称为语音合成,是Android 从1.6版本开始支持的新功能,能将所指定的文本转成不同语言音频输出。
在具体介绍前我们先来看下Adnroid系统带的TTS设置界面,点击Settings->Speech synthesis,如下图所示:
图 1 Android TTS设置界面
当点击“Listen to an example”时,会发出“ This is an example of speech synthesis in English. ”,如果没有安装 TTS Data的话可以点击第二项安装,在 Default settings 可以设置 Speech rate 和 Language ,如下图 2 所示可以知道 TTS 支持的语言。
图2 TTS 语言选择
如果勾选“Always use my settings ”时要注意,设置了这个选项后那么我们就不能在程序中对 speech rate 和 Languages 进行设置了,这里的设置回覆盖我们程序中的设置。
TTS功能需要有TTS Engine的支持,下面我们就来了解下android提供的TTS Engine。
Android使用了叫Pico的支持多种语言的语音合成引擎,Pico在后台负责把分析输入的文本,把分本分成他能识别的各个片段,再把合成的各个语音片段以听起来比较自然的方式连接在一起,这个过程Android系统帮我们做,我们只把他当做一个神奇的过程就可以了。
TTS engine依托于当前 Android Platform 所支持的几种主要的语言: English 、 French 、 German 、 Italian 和 Spanish 五大语言 (暂时也是没有对中文提供支持)。 TTS可以将文本随意的转换成以上任意五种语言的语音输出。与此同时,对于个别的语言版本将取决于不同的时区,例如:对于 English ,在 TTS 中可以分别输出美式和英式两种不同的版本 。
二. 实例分析
下面我们先做一个具体的实例来亲自体会一下Android的TTS的效果。
我们做一个简单的输入英文句子然后朗读出来的例子,了解Android的TTS使用方法。
在具体做之前给个AndroidTTS的API的链接,
http://androidappdocs.appspot.com/reference/android/speech/tts/package-summary.html
可以先看下大概了解TTS提供的功能。
图3 Android TTS API
可以看到TTS提供了两个接口和两个类。
我们希望做的效果如下:
图4 实现效果图
上面一个输入框,点击Speak按钮则朗读上面的文字内容。
创建一个Android工程,工程名为AndroidTTSDemoFirst,其中SDK必须选择1.6版本及以上。
其中Main.xml文件很简单,如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <EditText android:id="@+id/inputText"
- android:hint="Input the text here!"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </EditText>
- <Button android:text="Speak"
- android:id="@+id/speakBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:enabled="false"
- ></Button>
- </LinearLayout>
Java文件的编写:
要使用TTS得实现OnInitListener接口
- public class AndroidTTSDemoFirst extends Activity implements OnInitListener {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- //实现TTS初始化接口
- @Override
- public void onInit(int status) {
- // TODO Auto-generated method stub
-
- }
- }
接着定义好下面要用到的几个变量:
- private EditText inputText = null;
- private Button speakBtn = null;
- private static final int REQ_TTS_STATUS_CHECK = 0;
- private static final String TAG = "TTS Demo";
- private TextToSpeech mTts;
虽然安装Android1.6版本及之后的Android机器都默认安装了TTS引擎,但某些设备可能会因为存储容量的限制而缺少安装和语言对应的资源文件,因此在使用TTS前,得先要检查是否安装了TTS语言数据,在onCreate函数中添加以下内容:
- //检查TTS数据是否已经安装并且可用
- Intent checkIntent = new Intent();
- checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
- startActivityForResult(checkIntent, REQ_TTS_STATUS_CHECK);
这里启动一个新的Intent去检查TTS数据是否已经安装,我们根据其返回的结果进行处理,如下所示:
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if(requestCode == REQ_TTS_STATUS_CHECK)
- {
- switch (resultCode) {
- case TextToSpeech.Engine.CHECK_VOICE_DATA_PASS:
- //这个返回结果表明TTS Engine可以用
- {
- mTts = new TextToSpeech(this, this);
- Log.v(TAG, "TTS Engine is installed!");
-
- }
-
- break;
- case TextToSpeech.Engine.CHECK_VOICE_DATA_BAD_DATA:
- //需要的语音数据已损坏
- case TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA:
- //缺少需要语言的语音数据
- case TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_VOLUME:
- //缺少需要语言的发音数据
- {
- //这三种情况都表明数据有错,重新下载安装需要的数据
- Log.v(TAG, "Need language stuff:"+resultCode);
- Intent dataIntent = new Intent();
- dataIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
- startActivity(dataIntent);
-
- }
- break;
- case TextToSpeech.Engine.CHECK_VOICE_DATA_FAIL:
- //检查失败
- default:
- Log.v(TAG, "Got a failure. TTS apparently not available");
- break;
- }
- }
- else
- {
- //其他Intent返回的结果
- }
- }
如果返回CHECK_VOICE_DATA_PASS表示检查成功,可以新建一个 TextToSpeech ,否则就去下载 TTS数据。
当TTS数据检测成功创建一个TextToSpeech后,就会调用接口OnInitListener中定义的回调函数
- //实现TTS初始化接口
- @Override
- public void onInit(int status) {
- // TODO Auto-generated method stub
- //TTS Engine初始化完成
- if(status == TextToSpeech.SUCCESS)
- {
- int result = mTts.setLanguage(Locale.US);
- //设置发音语言
- if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED)
- //判断语言是否可用
- {
- Log.v(TAG, "Language is not available");
- speakBtn.setEnabled(false);
- }
- else
- {
- mTts.speak("This is an example of speech synthesis.", TextToSpeech.QUEUE_ADD, null);
- speakBtn.setEnabled(true);
- }
- }
- }
在这个回调函数里,我们设置语言,然后就可以进行使用 TTS引擎进行操作了。
创建一个TextToSpeech是需要占用资源的,因此我们要适时的释放这个资源:
- @Override
- protected void onPause() {
- // TODO Auto-generated method stub
- super.onPause();
- if(mTts != null)
- //activity暂停时也停止TTS
- {
- mTts.stop();
- }
- }
-
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- super.onDestroy();
- //释放TTS的资源
- mTts.shutdown();
- }
最后,在onCreate函数中设置 EditText和Button的使用:
- inputText = (EditText)findViewById(R.id.inputText);
- speakBtn = (Button)findViewById(R.id.speakBtn);
- inputText.setText("This is an example of speech synthesis.");
- speakBtn.setOnClickListener(new OnClickListener() {
-
- public void onClick(View v) {
- // TODO Auto-generated method stub
- mTts.speak(inputText.getText().toString(), TextToSpeech.QUEUE_ADD, null);
- //朗读输入框里的内容
- }
- });
至此,我们的 Demo就完成了,当启动程序后,首先会朗读“ This is an example of speech synthesis in English. ”,然后你在EditText中输入内容,点击Speak按钮就能把内容给朗读出来。
文章对应的完整代码例子可以在这里下载:http://download.****.net/source/2610740
http://blog.****.net/ichliebephone/article/details/6373184
一. 基础知识
Android 从1.6 版本开始支持Text To Speech ,使用的是Pico 语音合成引擎,但是只支持 English 、 French 、 German 、 Italian 和 Spanish 五大语言,暂时没有对中文提供支持。因此使用 Android 默认的 TTS Engine 是没法朗读中文的。
不过有开源项目 eyes-free ( http://code.google.com/p/eyes-free/ , Android 上的 TTS 功能应该也是基于这个开源项目提供的)除了提供 Pico 外,还把支持其他更多语言语音合成的另一个 TTS 引擎 eSpeak 也移植到了 Android 平台,其中就支持中文的语音合成。
因此在安装了 eyes-free 提供的 TTS Service Extended 的 apk 后,就可以在程序中使用 eyes-free 提供的 TTS library ,并把 TTS Engine 设置为不是默认的 Pico ,而是 eSpeak ,就可以实现朗读中文了。不过经过测试,实际的效果还是很差的,只能说勉强可以朗读而已。
二. 实例分析
下面我们就通过一个具体的例子来说明朗读中文的实现过程。
希望实现的效果和之前的类似:
图 1 实现效果图
上面一个输入框,点击 “我说” 按钮则朗读上面的文字内容。
首先我们要到 eyes-free 那下载需要的 TTS library 的 jar 包 (http://code.google.com/p/eyes-free/downloads/detail?name=TTS_library_stub_3.0_market.jar&can=2&q=) 。
创建一个 Android 工程,工程名为 NiHaoTTS ,并且把下载的 jar 包放在 assets 文件夹下。右键点击工程,选择 properties , Java Build Path , Libraries , Add JARs, 往工程中添加进 assets 下的 jar 包 , 如下图所示:
图2 添加 TTS library jar 包
其中 main.xml 文件很简单,如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <EditText android:id="@+id/ttstext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="你好,我能说中文"> </EditText> <Button android:id="@+id/ttsbtn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="我说" android:enabled="false"> </Button> </LinearLayout>
Java 文件的编写:
Java 文件和之前的类似,只是因为使用了 eyes-free 的 TTS API ,而不是 Android 自带的 TTS API ,因此有些许改变。相关的 API 参考: http://eyes-free.googlecode.com/svn/trunk/documentation/tts/com/google/tts/package-summary.html ,其中我们可以看到基本和 Android 的 API ()类似,其中一个明显的区别是创建 TTS 对象这里使用的是 TextToSpeechBeta ,而之前我们使用的是 TextToSpeech 。
Java 完整的代码为:
- public class NiHaoTTS extends Activity implements OnInitListener{
- /** Called when the activity is first created. */
- private Button mBtn;
- private EditText mText;
- //使用com.google.tts包中的TextToSpeechBeta
- private TextToSpeechBeta mTTS;
public class NiHaoTTS extends Activity implements OnInitListener{ /** Called when the activity is first created. */ private Button mBtn; private EditText mText; //使用com.google.tts包中的TextToSpeechBeta private TextToSpeechBeta mTTS; private static final String TAG = "TTS Demo"; private static final int REQ_TTS_STATUS_CHECK = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //检查TTS数据是否已经安装并且可用 Intent checkIntent = new Intent(); checkIntent.setAction(TextToSpeechBeta.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(checkIntent, REQ_TTS_STATUS_CHECK); mText = (EditText)findViewById(R.id.ttstext); mBtn = (Button) findViewById(R.id.ttsbtn); mBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String ttsText = mText.getText().toString(); if(ttsText != "") { //读取文本框中的中文 mTTS.speak(ttsText, TextToSpeechBeta.QUEUE_ADD, null); } } }); } //实现TTS初始化接口 @Override public void onInit(int status, int version) { // TODO Auto-generated method stub Log.v(TAG, "version = " + String.valueOf(version)); //判断TTS初始化的返回版本号,如果为-1,表示没有安装对应的TTS数据 if(version == -1) { //提示安装所需的TTS数据 alertInstallEyesFreeTTSData(); } else { //TTS Engine初始化完成 if(status == TextToSpeechBeta.SUCCESS) { Log.v(TAG, "success to init tts"); //设置TTS引擎,com.google.tts即eSpeak支持的语言包含中文,使用Android系统默认的pico可以设置为com.svox.pico mTTS.setEngineByPackageNameExtended("com.google.tts"); int result = mTTS.setLanguage(Locale.CHINA); //设置发音语言 if(result == TextToSpeechBeta.LANG_MISSING_DATA || result == TextToSpeechBeta.LANG_NOT_SUPPORTED) //判断语言是否可用 { Log.v(TAG, "Language is not available"); mBtn.setEnabled(false); } else { mTTS.speak("你好,朋友!", TextToSpeechBeta.QUEUE_ADD, null); mBtn.setEnabled(true); } } else { Log.v(TAG, "failed to init tts"); } } } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == REQ_TTS_STATUS_CHECK) { switch (resultCode) { case TextToSpeechBeta.Engine.CHECK_VOICE_DATA_PASS: //这个返回结果表明TTS Engine可以用 { //使用的是TextToSpeechBeta mTTS = new TextToSpeechBeta(this, this); Log.v(TAG, "TTS Engine is installed!"); } break; case TextToSpeechBeta.Engine.CHECK_VOICE_DATA_BAD_DATA: //需要的语音数据已损坏 case TextToSpeechBeta.Engine.CHECK_VOICE_DATA_MISSING_DATA: //缺少需要语言的语音数据 case TextToSpeechBeta.Engine.CHECK_VOICE_DATA_MISSING_VOLUME: //缺少需要语言的发音数据 { //这三种情况都表明数据有错,重新下载安装需要的数据 Log.v(TAG, "Need language stuff:"+resultCode); Intent dataIntent = new Intent(); dataIntent.setAction(TextToSpeechBeta.Engine.ACTION_INSTALL_TTS_DATA); startActivity(dataIntent); } break; case TextToSpeechBeta.Engine.CHECK_VOICE_DATA_FAIL: //检查失败 default: Log.v(TAG, "Got a failure. TTS apparently not available"); break; } } else { //其他Intent返回的结果 } } //弹出对话框提示安装所需的TTS数据 private void alertInstallEyesFreeTTSData() { Builder alertInstall = new AlertDialog.Builder(this) .setTitle("缺少需要的语音包") .setMessage("下载安装缺少的语音包") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub //下载eyes-free的语音数据包 String ttsDataUrl = "http://eyes-free.googlecode.com/files/tts_3.1_market.apk"; Uri ttsDataUri = Uri.parse(ttsDataUrl); Intent ttsIntent = new Intent(Intent.ACTION_VIEW, ttsDataUri); startActivity(ttsIntent); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub finish(); } }); alertInstall.create().show(); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if(mTTS!=null){ mTTS.shutdown(); } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); if(mTTS != null) { mTTS.stop(); } } }
基本和我们之前学过的类似,其中不同的地方有:
( 1 ) TTS 的初始化回调函数多了一个版本号参数 version,
public void onInit( int status, int version) ,
如果返回的版本号 version 等于 -1 ,则表明还没有安装 eyes-free 提供的 TTS Service Extended ,提示进行下载和安装。
// 提示安装所需的 TTS 数据
alertInstallEyesFreeTTSData();
主要就是弹出对话框进行提示,然后链接到 eyes-free 的网站进行下载对应的 apk 。
// 弹出对话框提示安装所需的 TTS 数据
private void alertInstallEyesFreeTTSData()
{
Builder alertInstall = new AlertDialog.Builder( this )
.setTitle( " 缺少需要的语音包 " )
.setMessage( " 下载安装缺少的语音包 " )
.setPositiveButton( " 确定 " , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
// 下载 eyes-free 的语音数据包
String ttsDataUrl = "http://eyes-free.googlecode.com/files/tts_3.1_market.apk" ;
Uri ttsDataUri = Uri.parse (ttsDataUrl);
Intent ttsIntent = new Intent(Intent. ACTION_VIEW , ttsDataUri);
startActivity(ttsIntent);
}
})
.setNegativeButton( " 取消 " , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
finish();
}
});
alertInstall.create().show();
}
下载完进行安装,然后重新启动程序就可以运行。
( 2 )如果已经安装了,则可以进设置 TTS 引擎和需要合成的语言。
// 设置 TTS 引擎, com.google.tts 即 eSpeak 支持的语言包含中文,使用 Android 系统默认的 pico 可以设置为 com.svox.pico
mTTS .setEngineByPackageNameExtended( "com.google.tts" );
int result = mTTS .setLanguage(Locale. CHINA );
// 设置发音语言
其中如果设置为 com.google.tts 则表示使用 eSpeak 引擎,其包括对中文语音合成的支持。如果设置为 com.svox.pico 则表示使用 Pico 引擎,实际效果就是使用 Android 自带的 Pico 的效果,不过只支持 5 中语言,不支持中文。
除了这两块,其他和我们之前的程序基本一样。
然后就可以运行程序。因为模拟器开始时没有安装需要的 eyes-free 的 TTS Service Extended 的 apk ,因此会弹出提示对话框,点击确定开始下载,下载完进行安装,如下图所示。
图3 安装eyes-free的TTS
安装完会在应用程序中看到对应的图标,并且在 TTS 的设置中也会增加 eSpeak TTS 一项,如下图所示:
图4 安装了eyes-free的TTS
安装完后就可以再次打开 NiHaoTTS 程序,这时会有个选择询问使用哪个 TTS ,选择第二项,然后就可以在输入框中输入中文来朗读了。
图5 选择TTS
不过经过简单测试就知道了,中文朗读的效果基本没法实际使用的。
文章对应的完整代码例子可以在这里下载:
http://download.****.net/source/3237373
http://download.****.net/download/leiwuluan/3894785