写点什么

Android TTS 语音播报实践

用户头像
轻口味
关注
发布于: 刚刚
Android TTS语音播报实践

在工作中遇到了语音播报的需求,在收到 push 后,用语音播报 push 携带的播报内容。类似于微信支付宝的收款信息一样。调研后主要的语音播报方案有一下几种:


  1. 基于第三方的 TTS SDK,如百度、思必驰、讯飞等;

  2. 自研 Native 的 TTS 引擎+模型;

  3. 基于云端的 TTS 方案;

  4. 使用手机自带的 TTS 引擎。


无外乎就是自研或者采购,本地或者云端。


先来点废话,介绍下 TTS 的发展。

TTS 现状及发展

语音合成又称文语转换(Text to Speech,TTS)技术,是语音处理领域的一个重要的研究方向,旨在让机器生成自然动听的人类语音。


TTS 技术主要分为两种:


  • 通用 TTS:适用于导航、语音播报、智能客服和大多数语音交互场景;

  • 个性化 TTS:主要应用于对声音质量较高的教育、长音频、直播以及影视游戏配音等场景中。


语音合成模型经过长时间的发展,由最初的基于拼接合成,到参数合成,逐渐达到了现阶段感情充沛的基于端到端合成,最新一代端到端合成降低了对语言学知识的要求,可批量实现多语种的合成系统,语音自然程度高。


语音合成技术内部分为前端和后端。


  • 前端主要负责文本的语音解析和处理,其处理内容主要包括语种、分词、词性预测、多音字处理、韵律预测、情感等。把文本上的发音的这些信息都预测出来之后,将信息送给 TTS 后端系统,后台声学系统融合这些信息后,将内容转换为语音。

  • 后端声学系统从第一代的语音拼接合成,到第二代的语音参数合成,到第三代端到端合成,后端声学系统的智能化程度逐步增加,训练素材需要标记的详细程度和难度也在逐步减弱。


TTS 在语音交互场景里的应用:



基于拼接合成


为了更好的拟合人声,拼接合成技术需要一个大规模的真人音库,音库内容按照音素和不同特征进行标注,合成时根据语言学特征寻找符合的音素,拼接起来完成合成。


  • 优点:效果接近真人,运算量低

  • 缺点:拼接而成,语音不连贯,依赖音库,需要人工介入制定很多挑选规则和参数,制作成本高。

基于参数合成


通过深度学习构建文本特征和音库之间的映射关系,构建参数合成模型,当输入一个语言学特征时,基于神经网络给出音频特征,后通过声码器合成语音波形。


  • 优点:音库数量需求不多,合成语音连接平稳,质量高;

  • 缺点:对声码器依赖程度高,同时,由于传统参数系统建模时存在信息损失,限制了合成语音表现力的进一步提升。

基于端到端(Tactron 为例)



端到端语音合成一定程度上解决了拼接合成和参数合成存在的缺陷。端到端合成系统直接输入文本或者注音字符,通过文本或者文本特征和语音直接建模,跳过声码器阶段,减少对声码器的依赖,弱化前端概念。


  • 优点:降低对语音学知识的要求,可方便的在不同语种上复制,批量实现几十种甚至更多语种的合成系统,语音自然程度高;

  • 缺点:运算量大,无法人工调优,实时性低。

方案选择

做这个功能的时候公司已经有团队在自研 TTS 引擎了,而且云端 TTS 服务已经跑起来了,并且之前也在外部采购了些云端 TTS 服务。但是由于我们的 Push 推送量级很大,不管是外采还是自研云端引擎的成本都很高,出于成本考虑,我们选择只能考虑使用端上的方案。


客户端实现有三种方案:


  1. 外采:出于成本考虑,淘汰;

  2. 自研引擎:语音团队基于参数的合成引擎已完成开发,但是没有人力支撑后续的调试,而播报的话术比较固定,并且对合成声音的音质要求不是特别高,所以选择了一种基于拼接的合成方案作为备选,语句的前部分和后部分使用完整的语音,中间变换部分通过逐字方式合成;

  3. 手机自带 TTS 引擎:Android 系统已自带了 TTS 引擎,但是并不是所有的手机都带了中文引擎。

Android TTS 引擎使用

初始化 TTS 引擎

class TTSListener implements TextToSpeech.OnInitListener {    @Override    public void onInit(int status) {      if (mSpeech != null) {        int isSupportChinese = mSpeech.isLanguageAvailable(Locale.CHINESE);//是否支持中文        mSpeech.getMaxSpeechInputLength();//最大播报文本长度
if (isSupportChinese == TextToSpeech.LANG_AVAILABLE) { int setLanRet = mSpeech.setLanguage(Locale.CHINESE);//设置语言 int setSpeechRateRet = mSpeech.setSpeechRate(1.0f);//设置语 int setPitchRet = mSpeech.setPitch(1.0f);//设置音量 String defaultEngine = mSpeech.getDefaultEngine();//默认引擎 if (status == TextToSpeech.SUCCESS) { //初始化TextToSpeech引擎成功,初始化成功后才可以play等 } } } else { //初始化TextToSpeech引擎失败 } } }
TextToSpeech mSpeech = new TextToSpeech(ContextHolder.appContext(), new TTSListener());
复制代码

设置播报状态回调

mSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {        @Override        public void onStart(String utteranceId) {          //播报开始        }
@Override public void onDone(String utteranceId) { //播报结束 }
@Override public void onError(String utteranceId) { //播报出错 } });
复制代码

开始播报

long utteranceId = System.currentTimeMillis();    HashMap ttsOptions = new HashMap<String, String>();    ttsOptions.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,        String.valueOf(utteranceId));//utterance,这个参数随便写,用于监听播报完成的回调中    ttsOptions.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, String.valueOf(1));//音量    ttsOptions.put(TextToSpeech.Engine.KEY_PARAM_STREAM,        String.valueOf(AudioManager.STREAM_NOTIFICATION));//播放类型    int ret = mSpeech.speak(tts, TextToSpeech.QUEUE_FLUSH, ttsOptions);    if (ret == TextToSpeech.SUCCESS) {      //播报成功    }
复制代码

文本转换为语音文件

long utteranceId = System.currentTimeMillis();File file = new File("/sdcard/audio_" + utteranceId + ".wav");int ret = synthesizeToFile("xxxxx", null, file, String.valueOf(utteranceId));if (ret == TextToSpeech.SUCCESS) {      //合成文件成功    }
复制代码

停止播放

调用mSpeech.stop();此时会触发 UtteranceProgressListener 的 onDone 回调。

销毁引擎

mSpeech.shutdown();
复制代码

Android11 适配

为兼容 Android11 系统手机,我们需要在应用程序 AndroidManifest.xml 文件中增加如下声明:


  <queries>    <intent>      <action android:name="android.intent.action.TTS_SERVICE"/>    </intent>  </queries>
复制代码


3.5.x 版本 Gradle 需要使用 3.5.4 以上版本才能识别 queries 属性。

TextToSpeech 手机兼容性问题

系统自带 TextToSpeech API 使用很方便,但是有些不支持中文引擎的手机就很头疼,而且市面上哪些手机支持哪些手机不支持我们没有底,所以线上跑了一波以后拿到了目前市面手机 TextToSpeech 中文引擎的支持情况。有九十款不支持的手机如下:


+--------------------------------------+| Xiaomi MI+9+Transparent+Edition      || Xiaomi MI+8                          || OnePlus GM1900                       || OnePlus GM1910                       || Redmi M2006C3LC                      || OnePlus IN2020                       || meizu 16T                            || Xiaomi MI+MAX+3                      || OnePlus ONEPLUS+A6010                || OnePlus ONEPLUS+A5010                || meizu meizu+17                       || Redmi Redmi+K30                      || OnePlus KB2000                       || OnePlus HD1900                       || OnePlus ONEPLUS+A6000                || meizu 16s                            || Xiaomi M2102K1C                      || Xiaomi M2002J9E                      || Redmi M2007J17C                      || OnePlus IN2010                       || meizu meizu+17+Pro                   || nubia NX659J                         || meizu 16s+Pro                        || meizu meizu+16Xs                     || Xiaomi Mi+10                         || Lenovo Lenovo+L78051                 || meizu MEIZU+18                       || OnePlus HD1910                       || Hisense HLTE226T                     || xiaomi Redmi+Note+8                  || Redmi Redmi+K30i+5G                  || Redmi M2007J3SC                      || Redmi M2004J19C                      || Redmi Redmi+Note+8+Pro               || Redmi M2104K10AC                     || xiaomi Redmi+Note+7                  || Redmi M2003J15SC                     || Xiaomi MIX+2S                        || Redmi Redmi+K30+Pro                  || nubia NX627J                         || Xiaomi MI+CC9+Pro                    || Redmi Redmi+K30+5G                   || meizu MEIZU+18+Pro                   || Xiaomi MI+9                          || Xiaomi M2102K1AC                     || Xiaomi MI+8+UD                       || blackshark AWM-A0                    || Xiaomi M2011K2C                      || Xiaomi MI+8+Lite                     || Sony XQ-AT72                         || Xiaomi Mi+10+Pro                     || Xiaomi M2102J2SC                     || OnePlus ONEPLUS+A5000                || Xiaomi M2101K9C                      || Redmi M2103K19C                      || xiaomi Redmi+Note+7+Pro              || nubia NX616J                         || Redmi M2012K10C                      || Xiaomi MIX+3                         || Redmi M2004J7AC                      || Xiaomi MI+CC9+Pro+Premium+Edition    || nubia NX619J                         || Xiaomi M2007J1SC                     || koobee X60+Pro                       || Xiaomi Redmi+K20+Pro                 || SMARTISAN DT1901A                    || Redmi M2004J7BC                      || asus ASUS_I001DA                     || HONOR HLK-AL00a                      || Redmi M2006J10C                      || Redmi M2012K11AC                     || blackshark SHARK+PRS-A0              || HONOR BKL-AL20                       || SMARTISAN DT1902A                    || ZTE ZTE+A2322                        || Redmi M2007J22C                      || blackshark SKW-A0                    || Nokia Nokia+X7                       || Redmi M2012K11C                      || HUAWEI MAR-AL00                      || Redmi Redmi+K30+Pro+Zoom+Edition     || nubia NX669J                         || Meizu 16+X                           || Xiaomi Redmi+K20+Pro+Premium+Edition || asus ASUS_I005DA                     || blackshark SHARK+KLE-A0              || Xiaomi MI+6                          || motorola XT2125-4                    || GIONEE 20190619G                     || HUAWEI ART-AL00m                     |+--------------------------------------+
复制代码


有些支持比较好的,如华为,可以在设置中选择发音音色。在系统设置---辅助功能---无障碍---文本转语音路径下可以选择引擎,调节语速音调:



并且点击引擎选项可以安装引擎提供的发音人语音包,并选择发音人:


总结

本文总结了 TTS 的现状及发展,并介绍了移动端实现 TTS 的几种方式以及如何系统提供的 TextToSpeech API、系统 API 的局限、如何做兼容性等。

发布于: 刚刚阅读数: 2
用户头像

轻口味

关注

🏆2021年InfoQ写作平台-签约作者 🏆 2017.10.17 加入

Android音视频、AI相关领域从业者,开源RTMP播放器:https://github.com/qingkouwei/oarplayer

评论

发布
暂无评论
Android TTS语音播报实践