Android中提供的免费文字转语音功能TextToSpeech之快速入门用法(Android TTS 语音合成播报)

简要介绍

TextToSpeech简称 TTS,是Android 1.6版本中比较重要的新功能。将所指定的文本转成不同语言音频输出。它可以方便的嵌入到游戏或者应用程序中,增强用户体验。

在 Android 中,TTS全称叫做 Text to Speech,从字面就能理解它解决的问题是什么,把文本转为语音服务,意思就是你输入一段文本信息,然后Android 系统可以把这段文字播报出来。这种应用场景目前比较多是在各种语音助手APP上,很多手机系统集成商内部都有内置文本转语音服务,可以读当前页面上的文本信息。同样,在一些阅读类APP上我们也能看到相关服务,打开微信读书,里面就直接可以把当前页面直接用语音方式播放出来,特别适合哪种不方便拿着手机屏幕阅读的场景。

TTS engine依托于当前AndroidPlatform所支持的几种主要的语言:English、French、German、Italian和Spanish五大语言(暂时没有我们伟大的中文,至少Google的科学家们还没有把中文玩到炉火纯青的地步,先易后难也是理所当然。)TTS可以将文本随意的转换成以上任意五种语言的语音输出。与此同时,对于个别的语言版本将取决于不同的时区,例如:对于English,在TTS中可以分别输出美式和英式两种不同的版本(由此看出Google的做事风格真够细致,而正因为如此估计Google不加入中文的另外一种理由是中文的方言太多了)。

常见的有如下几种类型:

系统自带的 TTS 功能是不支持中文的,想要支持中文的话,需要借助第三方引擎,比如常见的科大讯飞、百度等。
如果换成支持中文引擎的话,一旦输入的文本中有夹杂着英文,那么有时候第三方TTS引擎有时候就很不友好,有时候会把英文单词每个字母读出来,英文甚至是发音不了,这里就需要注意下引擎的测试。
在设置 TTS 参数的时候,需要注意语速、音高、音调的上限值,有时候参数可能是0-100的范围,有时候有些参数是在0-10的范围,特别需要根据不同引擎参数的值类型去设定。

TTS 优劣势
从实现原理我们可以看到Android系统原生自带了一个TTS引擎。那么在此,我们就也可以去自定义TTS引擎,只有继承ITextToSpeechService接口即可,实现里面的方法。这就为后续自定义TTS引擎埋下伏笔了,因为系统默认的TTS引擎是不支持中文,那么市场上比较好的TTS相关产品,一般是集成讯飞或者Nuance等第三方供应商。

因此,我们也可以看到TTS优劣势:

优势:接口定义完善,有着完整的API接口方法,同时支持扩展,可根据自身开发业务需求重新打造TTS引擎,并且与原生接口做兼容,可适配。

劣势:原生系统TTS引擎支持的多国语言有限,目前不支持多实例和多通道。

完整代码


import android.content.Intent;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.Locale;

public class HomeActivity extends AppCompatActivity implements  TextToSpeech.OnInitListener  {

    private TextToSpeech tts;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);


        initTextToSpeech();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    speakText("语音设备检测结果正常。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    @Override
    public void onInit(int i) {
        if (i == TextToSpeech.SUCCESS) {

            // setLanguage设置语言
            int result = tts.setLanguage(Locale.CHINA);
            int result2 = tts.setLanguage(Locale.CHINESE);
            Log.e("tts:", "语言设置结果:"+result+":"+result2);
            // TextToSpeech.LANG_MISSING_DATA:表示语言的数据丢失
            // TextToSpeech.LANG_NOT_SUPPORTED:不支持
            if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                Toast.makeText(this, "数据丢失或不支持", Toast.LENGTH_SHORT).show();
            }else {
                //不支持中文就将语言设置为英文
                tts.setLanguage(Locale.US);
            }
        }
    }

    private void initTextToSpeech() {
        // 参数Context,TextToSpeech.OnInitListener
        tts = new TextToSpeech(this, this);
        // 设置音调,值越大声音越尖(女生),值越小则变成男声,1.0是常规
        tts.setPitch(1.0f);
        // 设置语速
//        tts.setSpeechRate(0.5f);

    }
    private void speakText(final String text) {

        Log.e("资源文件路径:", "准备朗读" );
        // validate
        if (TextUtils.isEmpty(text)) {
            Toast.makeText(HomeActivity.this, "请您输入要朗读的文字", Toast.LENGTH_SHORT).show();
            return;
        }

        // TODO validate success, do something
        if (tts != null && !tts.isSpeaking()) {
            /*
                TextToSpeech的speak方法有两个重载。
                // 执行朗读的方法
                speak(CharSequence text,int queueMode,Bundle params,String utteranceId);
                // 将朗读的的声音记录成音频文件
                synthesizeToFile(CharSequence text,Bundle params,File file,String utteranceId);
                第二个参数queueMode用于指定发音队列模式,两种模式选择
                (1)TextToSpeech.QUEUE_FLUSH:该模式下在有新任务时候会清除当前语音任务,执行新的语音任务
                (2)TextToSpeech.QUEUE_ADD:该模式下会把新的语音任务放到语音任务之后,
                等前面的语音任务执行完了才会执行新的语音任务
             */
            Log.e("资源文件路径:", "开始朗读");

            tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
        }


    }

    @Override
    protected void onStop() {
        super.onStop();
        // 不管是否正在朗读TTS都被打断
        tts.stop();
        // 关闭,释放资源
        tts.shutdown();
    }

    @Override
    protected void onDestroy() {
        if (tts != null) {
            tts.stop();
            tts.shutdown();
            tts = null;
        }
        super.onDestroy();
    }
}

要点免坑

在跳转到Activity后,直接调用 speak()方法,会发现没有声音,需要通过线程等待一点时间后,进行调用,tts需要完成初始化和相关配置。

		new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    speakText("现在开始识别,请做好准备,对准识别的文字。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

主要方法

		tts.setPitch();
		tts.setSpeechRate();
        tts.speak();
        tts.addSpeech();
        tts.setVoice();
        tts.setOnUtteranceProgressListener();
        tts.setEngineByPackageName();
        // 不管是否正在朗读TTS都被打断
        tts.stop();
        // 关闭,释放资源
        tts.shutdown();

自动加载缺失资源

/*
     Intent checkIntent = new Intent();
     checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
     startActivityForResult(checkIntent, ActivityResult_CODE);
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//        super.onActivityResult(requestCode, resultCode, data);

        if (ActivityResult_CODE == requestCode){
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS){
                Log.e(TAG, " android集成tts: "+resultCode );
                ttsRead();

            }else {
                //系统没有自带,网上下载
                Log.e(TAG, " android没有集成tts: "+resultCode );
                Intent installIntent = new Intent();
                installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installIntent);
            }
        }
    }*/
发布了52 篇原创文章 · 获赞 37 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u014374009/article/details/104225037