5

我想使用我录制的音频样本在 Mozilla TTS 中创建自定义语音,但不知道如何开始。Mozilla TTS 项目有文档和教程,但我无法将这些部分组合在一起——似乎缺少一些基本信息,刚开始的人需要知道才能开始。

我有一些问题:

  1. 我看到 Mozilla TTS 有一个 Docker 映像,但它的文档涵盖了创建语音并且没有提及培训。我可以使用 Docker 映像进行培训吗?
  2. 如果我不能使用 Docker 映像进行训练,我如何获得在我的 Python 3 系统上运行的 Mozilla TTS 的功能副本?我尝试按照项目提供的命令进行操作,但出现依赖错误、版本冲突或关于没有足够权限安装软件包的错误。
  3. 为了训练模型,我需要什么信息?我需要什么音频格式?我看到我需要一个metadata.csv文件——我需要在该文件中放入什么?我在配置文件中自定义了什么?
  4. 大多数配置都引用了一个scale_stats.npy文件——我如何生成这个文件?
  5. 我如何进行培训?
4

1 回答 1

14

经过大量的研究和实验,我可以分享我的经验来回答我自己的问题。

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(因为我们不影响系统范围的包),并确保没有包冲突。分数!

训练模型的先决条件

为了在训练模型时获得最佳结果,您需要:

  1. 简短的录音(至少 100 个):
    • 16 位单声道 PCM WAV 格式。
    • 每个时间在 1 到 10 秒之间。
    • 采样率为 22050 Hz。
    • 具有最小的背景噪音和失真。
    • 在开头、中间和结尾都不要长时间的停顿。
  2. 引用每个metadata.csvWAV 文件并指示 WAV 文件中所说的文本的文件。
  3. 为您的数据集和所选声码器(例如 Tacotron、WavGrad 等)量身定制的配置文件。
  4. 具有快速 CPU 的机器(理想情况下是支持 CUDA 和至少 12 GB GPU RAM 的 nVidia GPU;如果 GPU RAM 少于 8 GB,则无法有效使用 CUDA)。
  5. 大量 RAM(至少 16 GB 的 RAM 更好)。

准备音频文件

如果您的音频源与 WAV 格式不同,则需要使用AudacitySoX等程序将文件转换为 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_pathoutput_pathphoneme_cache_pathdatasets.path文件。

如果您愿意,您可以自定义其他参数,但默认值是一个不错的起点。例如,您可以更改run_name以控制包含数据集的文件夹的命名。

不要更改datasets.name参数(将其设置为“ljspeech”);否则你会得到与未定义的数据集类型相关的奇怪错误。数据集似乎是name指使用的数据加载器的类型,而不是您所说的数据集。同样,我没有冒险更改model设置,因为我还不知道系统如何使用该值。

准备中scale_stats.npy

大多数训练配置依赖于scale_stats.npy基于训练集生成的统计文件。您可以使用./TTS/bin/compute_statistics.pyMozilla 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 运行得更快。

如果您收到与“信号错误”或“收到信号”相关的任何错误,这通常表明您的机器没有足够的内存来进行操作。您可以以较少的并行度运行训练,但运行速度会慢得多。

于 2021-02-21T22:00:08.890 回答