使用国际音标进行神经文本语音转换的系统
项目描述
Larynx
🎥 演示视频
使用gruut和onnx(架构)的离线端到端文本语音转换系统。有9种语言的50种声音可用。
curl https://raw.githubusercontent.com/rhasspy/larynx/master/docker/larynx-server \
> ~/bin/larynx-server && chmod +755 ~/bin/larynx-server
larynx-server
访问http://localhost:5002进行测试页面。查看http://localhost:5002/openapi/以获取HTTP端点文档。
支持SSML的子集,可以使用多种声音和语言!
<speak>
The 1st thing to remember is that 9 languages are supported in Larynx TTS as of 10/19/2021 at 10:39am.
<voice name="harvard">
<s>
The current voice can be changed!
</s>
</voice>
<voice name="northern_english_male">
<s>Breaks are possible</s>
<break time="0.5s" />
<s>between sentences.</s>
</voice>
<s lang="en">
One language is never enough
</s>
<s lang="de">
Eine Sprache ist niemals genug
</s>
<s lang="sw">
Lugha moja haitoshi
</s>
</speak>
Larynx的目标是
- "足够好"的合成,以避免使用云服务
- 在Raspberry Pi 4(使用低质量声码器)上实时性能更快
- 广泛的语言支持(9种语言)
- 声音仅从公共数据集训练
您可以使用Larynx
- 托管文本语音HTTP端点
- 在命令行合成文本
- 读书给您听
样本
Docker安装
以下平台提供了预构建的Docker镜像
linux/amd64
- 桌面/笔记本电脑/服务器linux/arm64
- Raspberry Pi 64位linux/arm/v7
- Raspberry Pi 32位
这些镜像包括一个英语声音,但更多可以从Web界面下载。
《larynx》和《larynx-server》shell脚本封装了Docker镜像,允许您将Larynx用作命令行工具。
在Docker中手动运行Larynx网络服务器
docker run \
-it \
-p 5002:5002 \
-e "HOME=${HOME}" \
-v "$HOME:${HOME}" \
-v /usr/share/ca-certificates:/usr/share/ca-certificates \
-v /etc/ssl/certs:/etc/ssl/certs \
-w "${PWD}" \
--user "$(id -u):$(id -g)" \
rhasspy/larynx
下载的声音将存储在${HOME}/.local/share/larynx
。
访问http://localhost:5002进行测试页面。查看http://localhost:5002/openapi/以获取HTTP端点文档。
Debian安装
为bullseye预构建的Debian软件包可以下载,名称为larynx-tts_<VERSION>_<ARCH>.deb
,其中ARCH
可以是amd64
(大多数桌面和笔记本电脑)、armhf
(32位树莓派)或arm64
(64位树莓派)
典型桌面上的示例安装
sudo apt install ./larynx-tts_<VERSION>_amd64.deb
从那里,您可以运行larynx
命令或larynx-server
来启动网络服务器(http://localhost:5002)。
Python安装
您可能需要安装以下依赖项(除了Python 3.7+)
sudo apt-get install libopenblas-base libgomp1 libatomic1
在32位ARM系统(树莓派)上,您还需要
sudo apt-get install libatlas3-base libgfortran5
接下来,创建一个Python虚拟环境
python3 -m venv larynx_venv
source larynx_venv/bin/activate
pip3 install --upgrade pip
pip3 install --upgrade wheel setuptools
接下来,安装larynx
pip3 install -f 'https://synesthesiam.github.io/prebuilt-apps/' -f 'https://download.pytorch.org/whl/cpu/torch_stable.html' larynx
然后运行larynx
或larynx.server
以启动网络服务器。您也可以直接使用python3 -m larynx
和python3 -m larynx.server
执行Python模块。
声音/声码器下载
在命令行或网络服务器中使用时,会自动下载声音和声码器。您也可以手动下载每个声音。将它们解压缩到${HOME}/.local/share/larynx/voices
,以便目录结构遵循模式${HOME}/.local/share/larynx/voices/<language>,<voice>
。
命令行界面
Larynx具有灵活的命令行界面,可通过以下方式使用
- 为Docker的larynx脚本
- Debian软件包中的
larynx
命令 - Python安装的
larynx
或python3 -m larynx
基本合成
larynx -v <VOICE> "<TEXT>" > output.wav
其中<VOICE>
是一个语言名称(如en
、de
等)或声音名称(如ljspeech
、thorsten
等)。<TEXT>
可以包含多个句子,这些句子将组合成最终的输出WAV文件。这些句子也可以拆分为单独的WAV文件。
要调整输出质量,请使用-q <QUALITY>
,其中<QUALITY>
是“high”(最慢)、“medium”或“low”(最快)。
SSML合成
larynx --ssml -v <VOICE> "<SSML>" > output.wav
其中<SSML>
是有效的SSML。并非所有功能都受支持;例如
- 暂停(停顿)只能在句子之间发生,并且只能以秒或毫秒指定
- 只能通过名称引用声音
- 自定义词典尚不支持(但是可以使用
<phoneme ph="...">
)
如果您的SSML包含<mark>
标签,请将--mark-file <FILE>
添加到命令行。当遇到标记(句子之间)时,其名称将写入单独的行到文件中。
CUDA加速合成
使用--cuda
标志将利用可用的GPU
larynx --cuda 'This is spoken on the GPU.' > output.wav
添加--half
标志将启用半精度推理,这通常更快
larynx --cuda --half 'This is spoken on the GPU even faster.' > output.wav
为了使CUDA加速工作,您的声音必须包含PyTorch检查点文件(generator.pth
)。较旧的Larynx声音没有这些,因此您可能需要重新下载您的声音。
长文本
如果您的文本非常长,并且您想在其合成时听它,请使用--raw-stream
选项
larynx -v en --raw-stream < long.txt | aplay -r 22050 -c 1 -f S16_LE
每行输入都会被合成并以16位22050Hz单声道PCM格式写入标准输出。默认情况下,输出队列中会保留5句,只有当队列满时才会阻塞合成。您可以使用--raw-stream-queue-size
调整此值。此外,您还可以调整--max-thread-workers
来改变可用于合成的线程数量。
如果您的长文本是固定宽度的,段落之间用空行分隔,例如来自古腾堡计划的文本,请使用--process-on-blank-line
选项,这样句子就不会在行边界处被分割。例如,您可以这样听“爱丽丝梦游仙境”
curl --output - 'https://www.gutenberg.org/files/11/11-0.txt' | \
larynx -v ek --raw-stream --process-on-blank-line | aplay -r 22050 -c 1 -f S16_LE
多个WAV输出
将--output-dir
设置为一个目录,Larynx将为每个句子输出一个单独的WAV文件。
larynx -v en 'Test 1. Test 2.' --output-dir /path/to/wavs
默认情况下,每个WAV文件将使用(略微修改后的)句子文本命名。您可以使用--output-naming time
使用时间戳来命名WAV文件。要完全控制输出命名,--csv
命令行标志表示每个句子具有id|text
的形式,其中id
将是WAV文件的名字。
cat << EOF |
s01|The birch canoe slid on the smooth planks.
s02|Glue the sheet to the dark blue background.
s03|It's easy to tell the depth of a well.
s04|These days a chicken leg is a rare dish.
s05|Rice is often served in round bowls.
s06|The juice of lemons makes fine punch.
s07|The box was thrown beside the parked truck.
s08|The hogs were fed chopped corn and garbage.
s09|Four hours of steady work faced us.
s10|Large size in stockings is hard to sell.
EOF
larynx --csv --voice en --output-dir /path/to/wavs
交互模式
在没有文本输入和输出目录的情况下,Larynx将切换到交互模式。输入一个句子后,它将使用--play-command
(默认为SoX中的play
)播放。
larynx -v en
Reading text from stdin...
Hello world!<ENTER>
使用CTRL+D
或CTRL+C
退出。
GlowTTS设置
GlowTTS语音支持两个附加参数
--noise-scale
- 决定合成过程中说话者的波动性(0-1,默认为0.667)--length-scale
- 使声音说话者变慢(> 1)或变快(< 1)
声码器设置
--denoiser-strength
- 如果> 0则运行降噪器;一个小值如0.005是一个好的起点。
列出语音和声码器
larynx --list
MaryTTS兼容API
要使用Larynx作为MaryTTS服务器(例如,与Home Assistant一起使用)的替代品,请运行
docker run \
-it \
-p 59125:5002 \
-e "HOME=${HOME}" \
-v "$HOME:${HOME}" \
-v /usr/share/ca-certificates:/usr/share/ca-certificates \
-v /etc/ssl/certs:/etc/ssl/certs \
-w "${PWD}" \
--user "$(id -u):$(id -g)" \
rhasspy/larynx
现在应该可以通过HTTP端点/process
使用格式为<LANG>
或<VOICE>
的语音,例如en
或harvard
。
您可以通过在MaryTTS语音中添加;<QUALITY>
来指定声码器质量,其中QUALITY
是“高”、“中”或“低”。
例如:en;low
将使用最低质量(但速度最快)的声码器。这通常对于在树莓派上获得良好性能是必要的。
SSML
支持SSML的一个子集(使用--ssml
)
<speak>
- 将SSML文本包裹起来lang
- 设置文档的语言
<s>
- 句子(禁用自动句子分割)lang
- 设置句子的语言
<w>
/<token>
- 词(禁用自动标记化)<voice name="...">
- 设置内文本的语音voice
- 语音的名称或语言
<say-as interpret-as="">
- 强制解释内文本interpret-as
之一 "spell-out"、"date"、"number"、"time" 或 "currency"format
- 根据interpret-as
格式化文本的方式- number - "cardinal"、"ordinal"、"digits" 或 "year" 之一
- date - 带有 "d"(基数日)、"o"(序数日)、"m"(月份)或 "y"(年份)的字符串
<break time="">
- 暂停指定的时间- time - 秒("123s")或毫秒("123ms")
<mark name="">
- 用户定义的标记(写入--mark-file
或作为TextToSpeechResult
的一部分)- name - 标记的名称
<sub alias="">
- 用alias
替换内文本<phoneme ph="...">
- 为内文本提供音素ph
- 内文本每个单词的音素,由空格分隔
<lexicon id="...">
- 内联发音词典id
- 词典的唯一ID(用于<lookup ref="...">
)- 一个或多个具有
<lexeme>
子元素的<lexicon>
元素<grapheme role="...">WORD</grapheme>
- 单词文本(可选 [角色][#单词角色])<phoneme>P H O N E M E S</phoneme>
- 单词发音(音素由空格分隔)
<lookup ref="...">
- 对子元素使用内联发音词汇表ref
- 来自<lexicon id="...">
的 id
单词角色
在音素化过程中,单词角色用于消除发音歧义。除非手动指定,否则单词的角色是从其词性标签派生出来的,形式为 gruut:<TAG>
。对于缩写和 spell-out
,使用角色 gruut:letter
来指示例如,“a”应发音为 /eɪ/
而不是 /ə/
。
对于 en-us
,以下附加角色来自词性标注器
gruut:CD
- 数字gruut:DT
- 限定词gruut:IN
- 介词或从属连词gruut:JJ
- 形容词gruut:NN
- 名词gruut:PRP
- 人称代词gruut:RB
- 副词gruut:VB
- 动词gruut:VB
- 动词(过去时)
内联词汇表
通过 <lexicon>
和 <lookup>
标签支持内联发音词汇表。gruut 在这里与 SSML 标准 有所不同,只允许在 SSML 文档本身内定义词汇表。此外,<lexicon>
元素的 id
属性可以省略,以指示一个“默认”内联词汇表,该词汇表不需要相应的 <lookup>
标签。
例如,以下文档将为单词“tomato”产生三种不同的发音
<?xml version="1.0"?>
<speak version="1.1"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/10/synthesis
http://www.w3.org/TR/speech-synthesis11/synthesis.xsd"
xml:lang="en-US">
<lexicon xml:id="test" alphabet="ipa">
<lexeme>
<grapheme>
tomato
</grapheme>
<phoneme>
<!-- Individual phonemes are separated by whitespace -->
t ə m ˈɑ t oʊ
</phoneme>
</lexeme>
<lexeme>
<grapheme role="fake-role">
tomato
</grapheme>
<phoneme>
<!-- Made up pronunciation for fake word role -->
t ə m ˈi t oʊ
</phoneme>
</lexeme>
</lexicon>
<w>tomato</w>
<lookup ref="test">
<w>tomato</w>
<w role="fake-role">tomato</w>
</lookup>
</speak>
第一个“tomato”将在美国英语词汇表中查找(/t ə m ˈeɪ t oʊ/
)。在 <lookup>
标签的作用域内,第二个和第三个“tomato”单词将在内联词汇表中查找。第三个“tomato”单词有一个 角色附加(在这种情况下选择一个虚构的发音)。
甚至比 SSML 标准更远,gruut 允许您完全省略 <lexicon>
id。没有 id
,则不再需要 <lookup>
标签,允许您覆盖文档中任何单词的发音
<?xml version="1.0"?>
<speak version="1.1"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/10/synthesis
http://www.w3.org/TR/speech-synthesis11/synthesis.xsd"
xml:lang="en-US">
<!-- No id means change all words without a lookup -->
<lexicon>
<lexeme>
<grapheme>
tomato
</grapheme>
<phoneme>
t ə m ˈɑ t oʊ
</phoneme>
</lexeme>
</lexicon>
<w>tomato</w>
</speak>
这将使文档中所有“tomato”实例的发音为 /t ə m ˈɑ t oʊ/
(除非它们有 <lookup>
)。
文本到语音模型
- GlowTTS(50 种声音)
- 英语(
en-us
,27 种声音)- blizzard_fls(女声,口音,Blizzard)
- blizzard_lessac(女声,Blizzard)
- cmu_aew(男声,Arctic)
- cmu_ahw(男声,Arctic)
- cmu_aup(男声,口音,Arctic)
- cmu_bdl(男声,Arctic)
- cmu_clb(女声,Arctic)
- cmu_eey(女声,Arctic)
- cmu_fem(男声,Arctic)
- cmu_jmk(男声,Arctic)
- cmu_ksp(男声,口音,Arctic)
- cmu_ljm(女声,Arctic)
- cmu_lnh(女声,Arctic)
- cmu_rms(男声,Arctic)
- cmu_rxr(男声,Arctic)
- cmu_slp(女声,口音,Arctic)
- cmu_slt(女声,Arctic)
- ek(女声,口音,M-AILabs)
- harvard(女声,口音,CC/Attr/NC)
- 凯瑟琳(女性,CC0)
- ljspeech(女性,公共领域)
- mary_ann(女性,M-AILabs)
- northern_english_male(男性,CC/Attr/SA)
- scottish_english_male(男性,CC/Attr/SA)
- southern_english_female(女性,CC/Attr/SA)
- southern_english_male(男性,CC/Attr/SA)
- judy_bieber(女性,M-AILabs)
- 德语(
de-de
,7个声音) - 法语(
fr-fr
,3个声音) - 西班牙语(
es-es
,2个声音)- carlfm(男性,公共领域)
- karen_savage(女性,M-AILabs)
- 荷兰语(
nl
,4个声音) - 意大利语(
it-it
,2个声音) - 瑞典语(
sv-se
,1个声音)- talesyntese(男性,CC0)
- 斯瓦希里语(
sw
,1个声音)- blblia_takatifu(男性,Sermon Online)
- 俄语(
ru-ru
,3个声音)
- 英语(
语音合成器
- Hi-Fi GAN
- 通用大型(最慢)
- VCTK "小型"
- VCTK "中型"(最快)
基准测试
以下基准测试是在以下平台上进行的
- Core i7-8750H(
amd64
) - Raspberry Pi 4(
aarch64
) - Raspberry Pi 3(
armv7l
)
在每个质量级别上进行了多次运行,第一次运行被丢弃,以便使模型文件的缓存处于热状态。
RTF(实时因子)是合成音频所需时间除以合成音频持续时间的结果。RTF小于1表示音频能够以比实时更快的速度合成。
平台 | 质量 | RTF |
---|---|---|
amd64 | 高 | 0.25 |
amd64 | 中 | 0.06 |
amd64 | 低 | 0.05 |
-------- | ------- | --- |
aarch64 | 高 | 4.28 |
aarch64 | 中 | 1.82 |
aarch64 | 低 | 0.56 |
-------- | ------- | --- |
armv7l | 高 | 16.83 |
armv7l | 中 | 7.16 |
armv7l | 低 | 2.22 |
有关更多详细信息,请参阅scripts/
中的基准测试脚本。
架构
Larynx将文本语音合成分为4个不同的步骤
声音是在音素ids和梅尔频谱图上训练的。对于每种语言,使用可用数据最多的声音作为基础模型进行微调。