Android TTS语音播报实践

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

image.png


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


  1. 基于第三方的TTS SDK,如百度、思必驰、讯飞等;
  2. 自研Native的TTS引擎+模型;
  3. 基于云端的TTS方案;
  4. 使用手机自带的TTS引擎。


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


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


TTS 现状及发展


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


TTS技术主要分为两种:


  • 通用TTS:适用于导航、语音播报、智能客服和大多数语音交互场景;
  • 个性化TTS:主要应用于对声音质量较高的教育、长音频、直播以及影视游戏配音等场景中。


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


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


  • 前端主要负责文本的语音解析和处理,其处理内容主要包括语种、分词、词性预测、多音字处理、韵律预测、情感等。把文本上的发音的这些信息都预测出来之后,将信息送给TTS后端系统,后台声学系统融合这些信息后,将内容转换为语音。
  • 后端声学系统从第一代的语音拼接合成,到第二代的语音参数合成,到第三代端到端合成,后端声学系统的智能化程度逐步增加,训练素材需要标记的详细程度和难度也在逐步减弱。


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


image.png


基于拼接合成


image.png


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


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


基于参数合成


image.png


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


  • 优点:音库数量需求不多,合成语音连接平稳,质量高;
  • 缺点:对声码器依赖程度高,同时,由于传统参数系统建模时存在信息损失,限制了合成语音表现力的进一步提升。


基于端到端(Tactron为例)


image.png


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


  • 优点:降低对语音学知识的要求,可方便的在不同语种上复制,批量实现几十种甚至更多语种的合成系统,语音自然程度高;
  • 缺点:运算量大,无法人工调优,实时性低。


方案选择


做这个功能的时候公司已经有团队在自研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中文引擎的支持情况。收集了694款手机,有90款不支持的手机。具体型号如下:


+--------------------------------------+
| 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合成,因为已经在我们的成本访问。也可以牺牲包体积和音质,通过拼接合成的方式在不支持的手机上提供TTS服务。


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


image.png

image.png


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


image.png


image.png


总结


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

目录
相关文章
|
8天前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的海洋中,自定义控件是那片璀璨的星辰。它不仅让应用界面设计变得丰富多彩,还提升了用户体验。本文将带你探索自定义控件的核心概念、实现过程以及优化技巧,让你的应用在众多竞争者中脱颖而出。
|
1月前
|
安全 Android开发 Kotlin
Android经典实战之SurfaceView原理和实践
本文介绍了 `SurfaceView` 这一强大的 UI 组件,尤其适合高性能绘制任务,如视频播放和游戏。文章详细讲解了 `SurfaceView` 的原理、与 `Surface` 类的关系及其实现示例,并强调了使用时需注意的线程安全、生命周期管理和性能优化等问题。
104 8
|
8天前
|
前端开发 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的世界里,自定义控件如同画家的画笔,能够绘制出独一无二的界面。通过掌握自定义控件的绘制技巧,开发者可以突破系统提供的界面元素限制,创造出既符合品牌形象又提供卓越用户体验的应用。本文将引导你了解自定义控件的核心概念,并通过一个简单的例子展示如何实现一个基本的自定义控件,让你的安卓应用在视觉和交互上与众不同。
|
16天前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
25 6
|
5月前
|
移动开发 安全 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第30天】 在移动开发领域,性能优化始终是关键议题之一。特别是对于Android开发者来说,如何在保证应用流畅性的同时,提升代码的执行效率,已成为不断探索的主题。近年来,Kotlin语言凭借其简洁、安全和实用的特性,在Android开发中得到了广泛的应用。其中,Kotlin协程作为一种新的并发处理机制,为编写异步、非阻塞性的代码提供了强大工具。本文将深入探讨Kotlin协程在Android开发中的应用实践,以及如何通过协程优化应用性能,帮助开发者构建更高效的Android应用。
|
25天前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
74 3
|
1月前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
2月前
|
XML 搜索推荐 Android开发
安卓开发中的自定义View组件实践
【8月更文挑战第30天】探索Android世界,自定义View是提升应用界面的关键。本文以简洁的语言带你了解如何创建自定义View,从基础到高级技巧,一步步打造个性化的UI组件。
|
2月前
|
缓存 Android开发 UED
安卓应用开发中的性能优化实践
【8月更文挑战第31天】在安卓的世界里,性能是王道。本文将带你深入理解如何通过代码优化和工具使用来提升你的安卓应用性能。我们将一起探索内存管理、布局优化、多线程处理等关键领域,并配以实用的代码示例,让你的应用飞一般地运行起来!
|
2月前
|
Java Android开发 开发者
探索安卓应用开发:从基础到实践
【8月更文挑战第31天】在这篇文章中,我们将一起踏上安卓应用开发的旅程。无论你是初学者还是有一定经验的开发者,这里都有适合你的内容。文章将引导你理解安卓开发的基础知识,然后通过实际的代码示例,带你一步步构建一个简单的应用程序。我们的目标是让读者能够不仅理解安卓开发的理论基础,还能通过动手实践来巩固这些知识。所以,拿起你的设备,让我们一起开始吧!