Android TTS(TextToSpeech)实践
一、介绍
TextToSpeech:将文本合成语音,立即播放或创建声音文件。
最简单的流程如下:
1.创建TextToSpeech后,它会找到一个适合的Engine进行连接,然后回调onInit,如果status不为0,则没有找到引擎。
2.在初始化成功后,调用speak就可以进行语音播报了。播报过程中,引擎会调用UtteranceProgressListener的回调函数,它是个抽象类,可以覆盖其他函数,如onRangeStart(String utteranceId, int start, int end, int frame) 可以在播报过程中可以拿到实时返回的读取字符位置,但它是在api 26以后才开始支持。
简单的TTS语音播报代码如下:
if (textToSpeech == null) {textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {@Overridepublic void onInit(int status) {textToSpeech.speak("你好,测试语音播报功能", TextToSpeech.QUEUE_ADD, null);textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {@Overridepublic void onStart(String utteranceId) {}@Overridepublic void onDone(String utteranceId) {}@Overridepublic void onError(String utteranceId) {}});}});
}
在实际场景中,可能会遇到以下问题需要抉择(尤其是在做海外市场)
1.支持引擎(引擎查询和设置)
2.支持语言(语言支持和下载)
3.版本兼容问题(回调版本支持)
接下来分别进行介绍。
二、实践-引擎
1.引擎是TTS核心部分,主要用于加载语言语音包,将文本转换为音频,及执行回调的部分。引擎的实现,需要继承TextToSpeechService,并且需要对以下方法进行实现:
protected abstract int onIsLanguageAvailable(String lang, String country, String variant)protected abstract String[] onGetLanguage()protected abstract int onLoadLanguage(String lang, String country, String variant)protected abstract void onStop()protected abstract void onSynthesizeText(SynthesisRequest request, SynthesisCallback callback)
详细的原理这里不进行讲解,可以参考下面两篇文章,讲的很详细:
https://blog.csdn.net/qq_30359699/article/details/105388575
https://blog.csdn.net/zhupumao/article/details/78960456
首先,虽然列出了要实现TextToSpeechService的方法,但我们如果只使用系统提供的引擎,则不需要自己继承TextToSpeechService并实现以上方法,但需要知道的是:
1.是否支持语言,支持语言列表及加载语言包:分别是onIsLanguageAvailable,onGetLanguage和onLoadLanguage
2.进行文本合成语音,需要在onSynthesizeText中实现,对应的回调也需要在方法中调用SynthesisCallback的方法
3.onStop停止语音合成
4.因为引擎是自定义实现的,所以会有自己的语言语音包来支持不同的国家语言(如果做海外市场要注意,引擎是否支持对应国家的语言),这些语言语音包依赖于引擎提供方是否提供
5.需要在AndroidManifest中,在自己的Service中,加入如下配置:
<intent-filter><action android:name="android.intent.action.TTS_SERVICE" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
说了这么多,如果使用系统的引擎,则可以忽略这部分内容,但对理解有帮助。
2.引擎支持,通常在不同品牌设备上,语音引擎可能有多个,并且都是系统级别的,如三星有GoogleTTSService和SamsungTTSService等,这个时候不选择引擎时,很有可能使用的是SamsungTTSService。这里我写了个获取引擎列表的方法如下:
public List<String> getEngines() {if (mContext == null) {throw new IllegalArgumentException("Please set mContext first!!");}ArrayList<String> engines = new ArrayList<>();PackageManager pm = mContext.getPackageManager();Intent intent = new Intent(TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE);List<ResolveInfo> resolveInfo = pm.queryIntentServices(intent,PackageManager.MATCH_DEFAULT_ONLY);for (ResolveInfo info: resolveInfo) {engines.add(info.serviceInfo.packageName);}return engines;
}
可以看到,主要是通过action:TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE来进行查询(自定义引擎的Service也必须设置action为TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE)。
而最终得到的,是所有继承TextToSpeechService实现引擎的包名列表,当使用指定引擎时,TextToSpeech会通过包名和action绑定到Service上。
好,不出意外的话,会包含google系统引擎的包名,“com.google.android.tts”,后面说到引擎时,都是继承了TextToSpeechService并实现了语音合成的包名。
3.有了引擎,我们在使用TextToSpeech的时候,就可以使用TextToSpeech(Context context, OnInitListener listener, String engine) 来连接到指定引擎了。
三、实践-Locale
Locale包含了语言,国家和多样性等信息,但并不全包含这些信息,如果使TextToSpeech播放不同国家的语言时,这时需要设置Locale给它。但TextToSpeech一定会播放吗,不一定,需要看引擎是否支持,必定真正工作的是引擎对应的Service。那么看下图:
文本输入给引擎之前,引擎需要加载语言语音包,如果支持指定的语言,则可以输出音频数据进行播放或写入文件,同时会执行回调。那么问题来了,如何知道引擎是否支持语言音乐包,如果不支持,如何下载?
那么问题可以总结如下:
1.查询引擎目前支持的语言语音包(引擎和语言音乐包是绑定的)
2.判断指定Locale是否支持
3.下载语言语音包
接下来分别介绍。
3.1查询引擎目前支持的语言语音包:
1).系统方式
2).使用TextToSpeech方式(指定引擎)
3.1.1系统方式:
分为两部,1.发送Intent给系统 2.在当前activity中接收和解析结果
发送Intent给系统
Intent checkIntent = new Intent();checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);checkIntent.setPackage(engine);activity.startActivityForResult(checkIntent, CHECK_REQUEST_CODE);
在当前activity中接收和解析结果(在onActivityResult中调用下面的方法获取Locale列表)
public List<Locale> checkSupportTTSLocale(int requestCode, int resultCode, Intent data) {ArrayList<Locale> locales = new ArrayList<>();if (requestCode == CHECK_REQUEST_CODE && resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS && data != null) {ArrayList<String> availableVoices = data.getStringArrayListExtra(TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);if (availableVoices != null && availableVoices.size() > 0) {for (String voice: availableVoices) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {String[] split = voice.split("-");if (split.length > 0) {Locale locale = split.length == 1 ? new Locale(split[0]) : (split.length == 2 ? new Locale(split[0], split[1]): new Locale(split[0], split[1], split[2]));locales.add(locale);}}}}}return locales;}
3.1.2使用TextToSpeech方式
public List<Locale> getSupportLocales() {ArrayList<Locale> locales = new ArrayList<>();if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {Set<Voice> voiceSet = textToSpeech.getVoices();for (Voice voice: voiceSet) {locales.add(voice.getLocale());}}return locales;}
重要:前提是textToSpeech指定了引擎,如textToSpeech = new TextToSpeech(context, listener, “com.google.android.tts”),查询到是“com.google.android.tts”支持的语音语音包对应的Locale列表。
3.2 判断指定Locale是否支持
通过之前的描述应该了解,Locale在不同引擎支持的情况不一样,且对应的语言语音包和引擎是绑定的,所以判断是否支持Locale可以通过TextToSpeech进行判断,通过下面两个方法都可以判断:
TextToSpeech.setLanguage(Locale)TextToSpeech.isLanguageAvailable(Locale)
3.3 下载语言语音包
当引擎暂不支持指定语言音乐包时,可以通过下载语言音乐包进行支持(若没有语言语音包就没办法了,不过google支持还是挺全的,其它引擎就不一定了)。
使用google系统引擎下载语言音乐包实现如下:
Intent installIntent = new Intent();installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);installIntent.setPackage(engine);activity.startActivityForResult(installIntent, INSTALL_REQUEST_CODE);
在系统页面下载完成之后,返回当前activity后,在onActivityResult中并不能查询到安装结果,还是需要3.1方式进行查询。
四、回调和部分方法
1.TextToSpeech.setOnUtteranceProgressListener(UtteranceProgressListener listener)
UtteranceProgressListener//API 15-public abstract void onStart(String utteranceId)//API 15 -public abstract void onDone(String utteranceId)//API 15 -public abstract void onError(String utteranceId) //API 23 -public void onStop(String utteranceId, boolean interrupted) //API 24 -public void onBeginSynthesis(String utteranceId, int sampleRateInHz, int audioFormat, int channelCount)//API 24 -public void onAudioAvailable(String utteranceId, byte[] audio) //API 26-public void onRangeStart(String utteranceId, int start, int end, int frame)
虽然回调方法不少,但如果是使用google引擎则注意兼容版本(国内实现的引擎应该比较完善,目前看到华为是支持类似onRangeStart的方法,这个方法能够实现实时单词高亮效果等)
2.设置语音属性
//设置音调高低,函数没有明确说明范围,我测试的范围0.5-3.0setPitch(float pitch) //设置语速,函数没有明确说明范围,我测试的范围0.5-3.0setSpeechRate(float speechRate)
这两个方法调用并不是实时生效,下次调用speak时才会生效
3.周期方法
//设置文本给引擎进行播报 speek //停止语音播报stop//关闭引擎shutdown
没有pause和resume,如果自己实现,建议在speek时进行分句操作。
五、总结
下面对调用进行总结:
1.查询引擎列表,使用需要的引擎实例化TextToSpeech
2.查询语言语音列表,如果不支持,可以通过系统方法(三方实现的调用三方下载语言语音包方法)进行安装
3.设置语言语音包给引擎
4.使用speak进行语音播报,可以在对应的回调中处理逻辑,但要注意支持API版本
5.使用完成时候记得shutdown释放资源
赋大概的时序图如下:
下面是参考的文档和可以参考的资源:
参考:
Android Speech之TTS(文本到语音)源码及流程分析_奔腾的小马-CSDN博客
TTS源码解析_zhupumao的博客-CSDN博客_tts文件解析错误
google例子:
https://android.googlesource.com/platform/development/+/master/samples/TtsEngine?autodive=0
github上高星地址:
https://github.com/ak1394/react-native-tts
https://github.com/gotev/android-speech
https://github.com/HMS-Core/hms-ml-demo
https://github.com/happyalu/Flite-TTS-Engine-for-Android
注:如有错误或探讨的地方,欢迎大家留言哈。
Android TTS(TextToSpeech)实践相关推荐
- Android TTS 中文 文字转语音 使用TextToSpeech Svox .
Android默认没有安装TTS数据包,无法文字转语音,而在设置里推荐的语音包是Pico TTS,并不支持中文,如果需要读中文,需要下载另外的第三方语音包,如:eSpeak,Svox,个人建议Svox ...
- Android TTS语音播报实践
在工作中遇到了语音播报的需求,在收到push后,用语音播报push携带的播报内容.类似于微信支付宝的收款信息一样.调研后主要的语音播报方案有一下几种: 基于第三方的TTS SDK,如百度.思必驰.讯飞 ...
- android系统tts TextToSpeech源码原理解析及定制tts引擎
TextToSpeech 即文字转语音服务,是Android系统提供的原生接口服务,原生的tts引擎应用通过检测系统语言,用户可以下载对应语言的资源文件,达到播报指定语音的文字的能力.但是一切都是在g ...
- Android TTS 中文 文字转语音 使用TextToSpeech Svox
Android默认没有安装TTS数据包,无法文字转语音,而在设置里推荐的语音包是Pico TTS,并不支持中文,如果需要读中文,需要下载另外的第三方语音包,如:eSpeak,Svox,个人建议Svox ...
- Android原生TTS(TextToSpeech)无效问题
Android原生TTS(TextToSpeech)无效问题 在使用安卓原生语音文字转语音时发现系统自带的语音合成引擎不支持中文语音,查找资料有一下几款语音引擎 com.svox.pico 系统自带不 ...
- 口播神器,基于Edge,微软TTS(text-to-speech)文字转语音免费开源库edge-tts实践(Python3.10)
不能否认,微软Azure在TTS(text-to-speech文字转语音)这个人工智能细分领域的影响力是统治级的,一如ChatGPT在NLP领域的随心所欲,予取予求.君不见几乎所有的抖音营销号口播均采 ...
- Android TTS 初体验
http://bbs.apkok.com/thread-1893-1-1.html 一.基础知识 TextToSpeech 简称TTS,称为语音合成,是Android 从1.6版本开始支持的新功能,能 ...
- Android TTS实现简单阅读器
本文原创版权归 51CTO winorlose2000 所有,转载请按如下方式于文章显示位置详细标明原创作者及出处,以示尊重!! 作者:winorlose2000 原文:http://vaero.bl ...
- 谷歌tts android手机自带引擎,自动下载android TTS引擎
Is there a way to install a language automatically? 是的,但这不会自动发生(未经用户同意),如docs所述: Since the installat ...
- Android TTS 支持中文
最近项目需求,要在android里面实现语音转文字朗读,TTS,于是上网各种搜索,比较好的是android有自带原生的api可以直接使用,android.speech.tts.TextToSpeech ...
最新文章
- 牛逼,国产开源的远程桌面火了,只有9MB,支持自建中继器!
- php正则过滤html标签_空格_换行符的代码,php正则过滤html标签、空格、换行符的代码(附说明)_php技巧...
- CentOS 6.4 i386 版本安装 FastDFS、使用Nginx作为文件访问WEB服务器
- (原创)无废话C#设计模式之二十二:总结(针对GOF23)
- 迁移学习 简而言之_简而言之SPIFFE
- leetcode870. 优势洗牌(贪心算法)
- C/C++使用Select检索MySQL中的数据
- glm编译错误问题解决 formal parameter with __declspec(align(#39;16#39;)) won#39;t be aligned...
- SAP License:SAP中现金管理实现
- 数据交换-电路/报文/分组交换
- 做港台项目开发遇到的一些非技术问题总汇。。。
- bada打地鼠应用程序简介
- math.abs() java_Java中使用Math.abs你入坑了?
- Room 使用解析(2.4.2 版本)
- python自然语言处理学习笔记一
- 硬件测试工程师的待遇和前景
- 安卓案例:读取与解析JSON
- 商业智能助力 银行业数据“挖金”
- 【20220207】【信号处理】三次样条插值原理详解
- 2017级算法模拟上机准备篇(一)