Android 离线文字转语音功能-TTS(Text To Speech)

简介: Android 离线文字转语音功能-TTS(Text To Speech)

前言


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


    Android系统从1.6版本开始就支持TTS, 不过遗憾的是系统默认的TTS引擎:Pico TTS,并不支持中文。


    在查找了许相关资料后, 发现很多的资源都已经失效, APK找不到, 对应的页面404. 更多的厂商则转成了开放平台甚至不再提供离线/免费服务.


目前找到的离线TTS


注:下面的链接可能需要科学上网才可以访问

image.png


使用


首先, 安装对应的TTS应用, 再在设置中设置对应的语音输出服务

一般设置的步骤为: 设置>无障碍>文字转语音(TTS)输出

image.png

程序调用只需使用SDK标准的TTS接口即可.

在介绍TTS使用的文章中, 下面这一段的代码, 对于前面的科大讯飞或ITRI TTS并没什么效果, 只是多了一个弹窗, 当然, 也可以理解为, 这两个APP并没有按标准接口开发.


//显示应用选择窗.
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
private TextToSpeech mTts;
protected void onActivityResult(
        int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_DATA_CHECK_CODE) {
        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
            // success, create the TTS instance
            mTts = new TextToSpeech(this, this);
        } else {
            // missing data, install it
            Intent installIntent = new Intent();
            installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
            startActivity(installIntent);
        }
    }
}

image.png


在程序中打印TTS所支持的语言及声音getAvailableLanguages和getVoices:


if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Set<Locale> ava = mTts.getAvailableLanguages();
            if (ava != null) {
                for (Locale l : ava) {
                    Logger.v(TAG, "supported " + l.toString());
                }
            } else {
                Logger.d(TAG, "no supported language");
            }
            Set<Voice> voices = mTts.getVoices();
            if(voices != null){
                for(Voice v : voices){
                    Logger.d(TAG, "TTS Voice: " + v.toString());
                }
            }
        }
        String engine = mTts.getDefaultEngine();
        Logger.d(TAG, "TTS Engine = " + engine);


2022-10-18 15:21:22.577 25266-25266 TextToSpeech       com.tts.test         I  Connected to ComponentInfo{tw.pu.tts/tw.pu.tts.UttsService}
2022-10-18 15:21:22.582 25266-26006 TextToSpeech       com.tts.test         I  Set up connection to ComponentInfo{tw.pu.tts/tw.pu.tts.UttsService}
2022-10-18 15:21:22.594 25266-25266 TTS                com.tts.test         D   onInit 0
2022-10-18 15:21:22.650 25266-25266 TTS                com.tts.test         V   supported zh
2022-10-18 15:21:22.650 25266-25266 TTS                com.tts.test         V   supported en
2022-10-18 15:21:22.650 25266-25266 TTS                com.tts.test         V   supported zh__#Hans
2022-10-18 15:21:22.650 25266-25266 TTS                com.tts.test         V   supported zh__#Hant
2022-10-18 15:21:22.690 25266-25266 TTS                com.tts.test         D   TTS Voice: Voice[Name: zh, locale: zh__#Hans, quality: 300, latency: 300, requiresNetwork: false, features: []]
2022-10-18 15:21:22.691 25266-25266 TTS                com.tts.test         D   TTS Voice: Voice[Name: en, locale: en, quality: 300, latency: 300, requiresNetwork: false, features: []]
2022-10-18 15:21:22.691 25266-25266 TTS                com.tts.test         D   TTS Voice: Voice[Name: zh, locale: zh, quality: 300, latency: 300, requiresNetwork: false, features: []]
2022-10-18 15:21:22.691 25266-25266 TTS                com.tts.test         D   TTS Voice: Voice[Name: zh, locale: zh__#Hant, quality: 300, latency: 300, requiresNetwork: false, features: []]
2022-10-18 15:21:22.698 25266-25266 TTS                com.tts.test         D   TTS Engine = tw.pu.tts


注: TTS的功能需要在TextToSpeech.OnInitListener回调, 并确认状态正常后才可以开始正常工作


完整代码TTS.java


import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech;
import android.speech.tts.Voice;
import java.util.Locale;
import java.util.Set;
public class TTS implements TextToSpeech.OnInitListener {
    final String TAG = "TTS";
    TextToSpeech mTts;
    public TTS(Context context){
        mTts = new TextToSpeech(context, this);
    }
    public TTS(Context context, TextToSpeech.OnInitListener lis){
        mTts = new TextToSpeech(context, this);
        setOnInitListener(lis);
    }
    final int DATA_CHECK_CODE = 0x774;
    @Deprecated
    public TTS(Activity activity){
        Intent checkIntent = new Intent(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        activity.startActivityForResult(checkIntent, 0x774);
    }
    @Deprecated
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        if (requestCode == DATA_CHECK_CODE) {
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                // success, create the TTS instance
                mTts = new TextToSpeech(activity, this);
            } else {
                // missing data, install it
                Intent installIntent = new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                activity.startActivity(installIntent);
            }
        }
    }
    public TextToSpeech getTts(){return mTts;}
    private void dump(){
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Set<Locale> ava = mTts.getAvailableLanguages();
            if (ava != null) {
                for (Locale l : ava) {
                    Logger.v(TAG, "supported " + l.toString());
                }
                //mTts.setLanguage(Locale.US);
            } else {
                Logger.d(TAG, "no supported language");
            }
            Set<Voice> voices = mTts.getVoices();
            if(voices != null){
                for(Voice v : voices){
                    Logger.d(TAG, "TTS Voice: " + v.toString());
                }
            }
        }
        String engine = mTts.getDefaultEngine();
        Logger.d(TAG, "TTS Engine = " + engine);
    }
    public void setSpeechSpeed(float speed){
        mTts.setSpeechRate(speed);
    }
    public void setVoiceFreq(float freq){
        mTts.setPitch(freq);
    }
    public void speak(String s){
        if(mTts == null){
            Logger.e(TAG, "speak failed: TTS not ready");
            return;
        }
        int res = mTts.speak(s, TextToSpeech.QUEUE_ADD, null);
        if(res != 0){
            Logger.w(TAG, "speak failed: " + res);
        }else{
            Logger.d(TAG, "speak " + s + " done");
        }
    }
    public void stop(){
        mTts.stop();
    }
    @Override
    public void onInit(int status) {
        Logger.d(TAG, "onInit " + status);
        if(status == 0) {
            dump();
            mTts.setPitch(1f);
            mTts.setSpeechRate(1f);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                AudioAttributes attr = new AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC).build();
                mTts.setAudioAttributes(attr);
            }
        }
        if(initLis != null)initLis.onInit(status);
    }
    TextToSpeech.OnInitListener initLis;
    public void setOnInitListener(TextToSpeech.OnInitListener initLis){
        this.initLis = initLis;
    }
}


参考


Android 中文語音引擎資源

Android中使用自带TextToSpeech实现离线语音合成功能

The 7 Best Text-to-Speech Apps for Android

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

An introduction to Text-To-Speech in Android


附:

文字转语音(TTS) 应用 (APK)


相关文章
|
1月前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!
|
2月前
|
Android开发
Android开发表情emoji功能开发
本文介绍了一种在Android应用中实现emoji表情功能的方法,通过将图片与表情字符对应,实现在`TextView`中的正常显示。示例代码展示了如何使用自定义适配器加载emoji表情,并在编辑框中输入或删除表情。项目包含完整的源码结构,可作为开发参考。视频演示和源码详情见文章内链接。
72 4
Android开发表情emoji功能开发
|
2月前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
54 3
|
3月前
|
JavaScript 前端开发 Android开发
让Vite+Vue3项目在Android端离线打开(不需要起服务)
让Vite+Vue3项目在Android端离线打开(不需要起服务)
118 10
|
4月前
|
编解码 测试技术 Android开发
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
本文详细介绍了如何利用CameraX库实现高质量的照片及视频拍摄功能,包括添加依赖、初始化、权限请求、配置预览与捕获等关键步骤。此外,还特别针对不同分辨率和帧率的视频拍摄提供了性能优化策略,确保应用既高效又稳定。
403 1
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
|
3月前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
293 3
|
3月前
|
Android开发 开发者
Android平台无纸化同屏如何实现实时录像功能
Android平台无纸化同屏,如果需要本地录像的话,实现难度不大,只要复用之前开发的录像模块的就可以,对我们来说,同屏采集这块,只是数据源不同而已,如果是自采集的其他数据,我们一样可以编码录像。
|
4月前
|
数据处理 开发工具 数据安全/隐私保护
Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路
本文探讨了Android平台上推流模块中添加文字与PNG水印的技术演进。自2015年起,为了满足应急指挥及安防领域的需求,逐步发展出三代水印技术:第一代为静态文字与图像水印;第二代实现了动态更新水印内容的能力,例如实时位置与时间信息;至第三代,则优化了数据传输效率,直接使用Bitmap对象传递水印数据至JNI层,减少了内存拷贝次数。这些迭代不仅提升了用户体验和技术效率,也体现了开发者追求极致与不断创新的精神。
|
4月前
|
图形学 Android开发
小功能⭐️Unity调用Android常用事件
小功能⭐️Unity调用Android常用事件
|
6月前
|
Android开发 Windows
如何离线下载 Microsoft Corporation II Windows Subsystem for Android
如何离线下载 Microsoft Corporation II Windows Subsystem for Android
141 1