TTS(文本到语音)初学者知识和服务器端应用程序(MaryTTS)
背景
最近项目中有个用户输入英语输出音频的场景,因此开始学习了文本转语音的一些知识,并找到一些实现方案实现了需求。
TTS介绍
TTS(Text to Speech, 文本转语音)是指将一般语言文本转换为音频的技术。一般应用于智能助手、盲人助手等应用的语言交互模块中。
实现原理
输入文本(text),输出音频波形(waveform),一般流程分为两步:文本分析、声波生成。
1. 文本分析
提取文本中关于语音生成的信息。一般有3个流程:文字规范化、语音分析、还有韵律分析。
a. 文字规范化
这一步主要是确定语言文字组成,确定词句的开始结束,将非语言文字转为对应文字或者过滤去除。
b. 语音分析
这一步主要是把词句中的发音音标标记出来,以便后续根据音标组成生成词句音频。
c. 韵律分析
这一步主要是分析出词句的语音语调(重音、边界、音长、主频率),以生成更真实音频。
2. 声波生成
根据提取的信息生成声波波形。一般有两种方法:拼接法、参数法。
* 拼接法
需要准备大量音素或音节的音频库,根据文本分析出的信息,将词句对应的音素音节以适当的方式调节对齐拼接。
优点是音质比较高比较自然。
缺点是需要足够齐全的音频库和适合的拼接方式,不然输出的音频就会失真甚至错误。
* 参数法
使用经过学习的统计模型,输入文本分析结果,预测得到音频的波形参数,再合成生成结果音频。
优点是对音频库要求不高。
缺点是输出音质比较不自然。
服务端应用方案
参考了7 个开源的TTS(文本转语音)系统推荐一文,根据服务端需求选择使用了MaryTTS。
MaryTTS介绍
MaryTTS是一款基于Java语言的开源TTS系统。由德国人工智能研究中心DFKI的语言技术实验室和萨尔大学Saarland University的语音学机构合作创立,现由MMCI的多层次模型语音处理小组和DFKI维护。
当前5.2版本支持德语、英式美式英语、法语、意大利语、卢森堡语、俄语、瑞典语、泰卢固语和土耳其语,以及更多其他语言准备接入。同时,MaryTTS也带有便于快速添加新语言支持和生成语音的工具。
应用
MaryTTS在github(marytts)上提供开源的核心代码和服务端实现代码,也在bintray上提供了封装服务(附带一个美式女性英语音源)的依赖。同时,也有在线网站进行效果试用和可直接安装的应用(包含小工具)提供下载。
<repositories>
<repository>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>de.dfki.mary</groupId>
<artifactId>voice-cmu-slt-hsmm</artifactId>
<version>5.2</version>
</dependency>
</dependencies>
代码实现
分析源码,发现其中的主要类如下:
-
MaryConfig
音源、语言、合成参数等配置信息。 -
Mary
TTS系统的核心类,处理音源、配置等资源的加载,加载相关模块。 -
MaryRuntimeUtils
Mary的运行工具,提供给外部调用初始化、获取配置信息等方法。 -
LocalMaryInterface
默认实现的转码接口,可以选择配置一个环境中存在的音源,提供生成音频、生成声音信息文本等方法。
具体实现:
import marytts.LocalMaryInterface
import marytts.util.data.BufferedDoubleDataSource
import marytts.util.data.audio.DDSAudioInputStream
import marytts.util.data.audio.MaryAudioUtils
import java.io.File
import java.sql.Timestamp
import java.time.Instant
import javax.sound.sampled.AudioFileFormat
import javax.sound.sampled.AudioSystem
/**
* @author hac
* @description: 文本转Wav
*/
class TTWavUtil {
companion object {
private val ttsMap = MaryTTSVoiceType.values().associate {
val tts = LocalMaryInterface()
tts.voice = it.value // 设置音源
Pair(it, tts)
}
/**
* 文本转wav文件
* @param text 文本
* @param output 输出wav文件
* @param voiceType 声音类型
*/
fun ttWavFile(text: String, output: File, voiceType: MaryTTSVoiceType) {
val maryTTS = ttsMap[voiceType]!!
val audio = maryTTS.generateAudio(text)
val samples = MaryAudioUtils.getSamplesAsDoubleArray(audio)
val outputAudio = DDSAudioInputStream(BufferedDoubleDataSource(samples), audio.format)
AudioSystem.write(outputAudio, AudioFileFormat.Type.WAVE, output)
}
}
/**
* 声音类型
*/
enum class MaryTTSVoiceType(val code: Int, val value: String) {
CMU_SLT_HSMM(0, "cmu-slt-hsmm"),
DFKI_SPIKE_HSMM(1, "dfki-spike-hsmm"),
DFKI_POPPY_HSMM(2, "dfki-poppy-hsmm"),
;
}
}
添加音源
音源依赖会在MaryConfig
类加载的时候通过ServiceLoader
加载运行环境中存在的MaryConfig
子类。
private static final ServiceLoader<MaryConfig> configLoader = ServiceLoader.load(MaryConfig.class);
每个音源都可以以Jar包引入的方式添加到服务中。 而音源Jar包则可以通过MaryTTS提供的小工具生成的。将MaryTTS的应用软件包下载解压后,其bin目录下的marytts-component-installer就是生成音源Jar包的工具。 运行会出现GUI操作界面,选择需要的语言下需要的音源进行下载。 Jar包会被下载到解压目录下的lib目录下,将Jar包引入项目即可。
结语
初探了TTS知识并研究使用MaryTTS作为应用方案进行了开发,但是TTS背后还有更多值得深入学习的知识,如音频数字化技术、参数法中的HMM隐马尔可夫模型、新型声波生成方式中的神经网络算法Wavenet等,感兴趣也可再深入探索一番。
上一篇: 996 ICU