经过大量的研究和实验,我可以分享我的经验来回答我自己的问题。
Mozilla TTS Docker 映像能否用于训练(TL;DR:“否”)
Mozilla TTS docker 映像确实适合播放,似乎不适合用于训练。至少,即使在容器内运行 shell,我也无法接受培训。但是在找出导致 PIP 不满意的原因之后,在 Ubuntu 中启动和运行 Mozilla TTS 的过程变得非常简单。
使用 Python 3、PIP 和虚拟环境安装 Mozilla TTS
Mozilla TTS 的文档没有提到任何关于虚拟环境的内容,但恕我直言,它确实应该。虚拟环境确保您机器上不同的基于 Python 的应用程序的依赖关系不会发生冲突。
我在 WSL 上运行 Ubuntu 20.04,因此已经安装了 Python 3。鉴于此,在我的主文件夹中,以下是我用来获取 Mozilla TTS 工作副本的命令:
sudo apt-get install espeak
git clone https://github.com/mozilla/TTS mozilla-tts
python3 -m venv mozilla-tts
cd mozilla-tts
./bin/pip install -e .
这~/mozilla-tts
在我的主文件夹中创建了一个文件夹,其中包含 Mozilla TTS 代码。该文件夹被设置为虚拟环境,这意味着只要我执行 python 命令 via~/mozilla-tts/bin/python
和 PIP via ~/mozilla-tts/bin/pip
,Python 将仅使用该虚拟环境中存在的包。这消除了在运行时需要 root 权限pip
(因为我们不影响系统范围的包),并确保没有包冲突。分数!
训练模型的先决条件
为了在训练模型时获得最佳结果,您需要:
- 简短的录音(至少 100 个):
- 16 位单声道 PCM WAV 格式。
- 每个时间在 1 到 10 秒之间。
- 采样率为 22050 Hz。
- 具有最小的背景噪音和失真。
- 在开头、中间和结尾都不要长时间的停顿。
- 引用每个
metadata.csv
WAV 文件并指示 WAV 文件中所说的文本的文件。
- 为您的数据集和所选声码器(例如 Tacotron、WavGrad 等)量身定制的配置文件。
- 具有快速 CPU 的机器(理想情况下是支持 CUDA 和至少 12 GB GPU RAM 的 nVidia GPU;如果 GPU RAM 少于 8 GB,则无法有效使用 CUDA)。
- 大量 RAM(至少 16 GB 的 RAM 更好)。
准备音频文件
如果您的音频源与 WAV 格式不同,则需要使用Audacity或SoX等程序将文件转换为 WAV 格式。你还应该剪掉那些只是噪音、嗯、啊和其他声音的音频部分,这些声音并不是你正在训练的单词。
如果您的音频源不完美(即有一些背景噪音)、格式不同,或者恰好是更高的采样率或不同的分辨率(例如 24 位、32 位等),您可以执行一些清理和转换。这是一个基于Mozilla TTS Discourse 论坛早期脚本的脚本:
from pathlib import Path
import os
import subprocess
import soundfile as sf
import pyloudnorm as pyln
import sys
src = sys.argv[1]
rnn = "/PATH/TO/rnnoise_demo"
paths = Path(src).glob("**/*.wav")
for filepath in paths:
target_filepath=Path(str(filepath).replace("original", "converted"))
target_dir=os.path.dirname(target_filepath)
if (str(filepath) == str(target_filepath)):
raise ValueError("Source and target path are identical: " + str(target_filepath))
print("From: " + str(filepath))
print("To: " + str(target_filepath))
# Stereo to Mono; upsample to 48000Hz
subprocess.run(["sox", filepath, "48k.wav", "remix", "-", "rate", "48000"])
subprocess.run(["sox", "48k.wav", "-c", "1", "-r", "48000", "-b", "16", "-e", "signed-integer", "-t", "raw", "temp.raw"]) # convert wav to raw
subprocess.run([rnn, "temp.raw", "rnn.raw"]) # apply rnnoise
subprocess.run(["sox", "-r", "48k", "-b", "16", "-e", "signed-integer", "rnn.raw", "-t", "wav", "rnn.wav"]) # convert raw back to wav
subprocess.run(["mkdir", "-p", str(target_dir)])
subprocess.run(["sox", "rnn.wav", str(target_filepath), "remix", "-", "highpass", "100", "lowpass", "7000", "rate", "22050"]) # apply high/low pass filter and change sr to 22050Hz
data, rate = sf.read(target_filepath)
# peak normalize audio to -1 dB
peak_normalized_audio = pyln.normalize.peak(data, -1.0)
# measure the loudness first
meter = pyln.Meter(rate) # create BS.1770 meter
loudness = meter.integrated_loudness(data)
# loudness normalize audio to -25 dB LUFS
loudness_normalized_audio = pyln.normalize.loudness(data, loudness, -25.0)
sf.write(target_filepath, data=loudness_normalized_audio, samplerate=22050)
print("")
要使用上面的脚本,您需要检查并构建RNNoise 项目:
sudo apt update
sudo apt-get install build-essential autoconf automake gdb git libffi-dev zlib1g-dev libssl-dev
git clone https://github.com/xiph/rnnoise.git
cd rnnoise
./autogen.sh
./configure
make
您还需要安装 SoX:
sudo apt install sox
而且,您将需要pyloudnorm
通过./bin/pip
.
然后,只需自定义脚本,使其rnn
指向rnnoise_demo
命令的路径(构建 RNNoise 后,您可以在examples
文件夹中找到它)。然后,运行脚本,将源路径(您拥有 WAV 文件的文件夹)作为第一个命令行参数传递。确保“原始”一词出现在路径中的某处。脚本会自动将转换后的文件放到对应的路径下,original
修改为converted
; 例如,如果您的源路径是/path/to/files/original
,则脚本会自动将转换后的结果放在/path/to/files/converted
.
准备元数据
Mozilla TTS 支持几种不同的数据加载器,但最常见的一种是 LJSpeech。要使用它,我们可以组织我们的数据集以遵循 LJSpeech 约定。
首先,组织你的文件,使你有这样的结构:
- metadata.csv
- wavs/
- audio1.wav
- audio2.wav
...
- last_audio.wav
音频文件的命名似乎并不重要。但是,这些文件必须位于名为wavs
. 如果需要,您可以在里面使用子文件夹wavs
。
该metadata.csv
文件应采用以下格式:
audio1|line that's spoken in the first file
audio2|line that's spoken in the second file
last_audio|line that's spoken in the last file
注意:
- 没有标题行。
- 这些列通过管道符号 (|) 连接在一起。
- 每个 WAV 文件应该有一行。
- WAV 文件名在第一列,没有
wavs/
文件夹前缀,也没有.wav
后缀。
- WAV 中所说内容的文字描述写在第二列中,所有数字和缩写都拼写出来。
(我确实观察到 Mozilla TTS 文档中的步骤让您对元数据文件进行洗牌,然后将其拆分为“训练”集(metadata_train.csv
)和“验证”集(metadata_val.csv
),但 repo 中提供的示例配置都不是实际上配置为使用这些文件。我已经提出了一个问题,因为它对初学者来说是令人困惑/违反直觉的。)
准备config.json
文件
您需要准备一个描述如何配置自定义 TTS 的配置文件。在准备训练、执行训练和从自定义 TTS 生成音频时,Mozilla TTS 的多个部分都使用此文件。不幸的是,虽然这个文件非常重要,但 Mozilla TTS 的文档在很大程度上掩盖了如何自定义这个文件。
首先,从 Mozilla存储库创建默认 Tacotronconfig.json
文件的副本。然后,确保至少自定义audio.stats_path
、output_path
、phoneme_cache_path
和datasets.path
文件。
如果您愿意,您可以自定义其他参数,但默认值是一个不错的起点。例如,您可以更改run_name
以控制包含数据集的文件夹的命名。
不要更改datasets.name
参数(将其设置为“ljspeech”);否则你会得到与未定义的数据集类型相关的奇怪错误。数据集似乎是name
指使用的数据加载器的类型,而不是您所说的数据集。同样,我没有冒险更改model
设置,因为我还不知道系统如何使用该值。
准备中scale_stats.npy
大多数训练配置依赖于scale_stats.npy
基于训练集生成的统计文件。您可以使用./TTS/bin/compute_statistics.py
Mozilla TTS 存储库中的脚本来生成此文件。该脚本需要您的config.json
文件作为输入,并且是进行健全性检查以确保到目前为止一切正常的好步骤。
如果您位于本教程开始时创建的 Mozilla TTS 文件夹中,则可以运行以下命令示例(调整路径以适合您的项目):
./bin/python ./TTS/bin/compute_statistics.py --config_path /path/to/your/project/config.json --out_path /path/to/your/project/scale_stats.npy
如果成功,这将scale_stats.npy
在/path/to/your/project/scale_stats.npy
. 确保文件audio.stats_path
设置中的config.json
路径与此路径匹配。
训练模型
现在是关键时刻了——是时候开始训练你的模型了!
如果您位于本教程开始时创建的 Mozilla TTS 文件夹中,则可以运行以下命令示例来训练 Tacotron 模型(调整路径以适合您的项目):
./bin/python ./TTS/bin/train_tacotron.py --config_path /path/to/your/project/config.json
这个过程需要几个小时,甚至几天。如果您的机器支持 CUDA 并对其进行了正确配置,则该过程将比仅依靠 CPU 运行得更快。
如果您收到与“信号错误”或“收到信号”相关的任何错误,这通常表明您的机器没有足够的内存来进行操作。您可以以较少的并行度运行训练,但运行速度会慢得多。