当前位置: 首页 > ops >正文

MeloTTS中文发音人训练

MeloTTS https://github.com/myshell-ai/MeloTTS

MeloTTS是一个可以把文字转换成声音的工具,它支持英语、西班牙语、法语、中文、日语和韩语等多种语言。

它可以让你听到不同的语言和口音,比如美式英语、英式英语、印度英语、澳大利亚英语等。

它还可以调节语速,让声音快速或慢速地说出来。它的声音非常自然和流畅,就像真人在说话一样。

接下来我们开始训练自己的音频。

1: 下载准备环境,要求有GPU环境。

git clone https://github.com/myshell-ai/MeloTTS.git
cd MeloTTS
pip install -e .
python -m unidic download

2: 原始发音人数据准备(我们用xmj2002/genshin_ch_10npc)

首先下载声音模型:
git clone https://hf-mirror.com/datasets/xmj2002/genshin_ch_10npc

将声音文件及中文文本提取出来

import numpy as np
from scipy.io import wavfile
from datasets import load_dataset
import os
#https://blog.lukeewin.top/archives/melotts-zh-model-train
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'# 指定目录路径
data_dir = "g:/xxxx/xunlian/genshin_ch_10npc/train"# 获取所有 .parquet 文件路径
parquet_files = [os.path.join(data_dir, f) for f in os.listdir(data_dir) if f.endswith(".parquet")]mls = load_dataset("parquet",split="train", data_files=parquet_files)ddir = "xunlian/spk_pai"
mpInpcName = {"派蒙": 0,
}
for sample in mls:npcName = sample["npcName"]  # 假设数据集中有 npcName 字段save_dir = os.path.join(ddir, npcName)os.makedirs(save_dir, exist_ok=True)print(f"文件夹已创建:{save_dir}")mpInpcName[npcName] = 0for sample in mls:npcName = sample["npcName"]  # 假设数据集中有 npcName 字段lg = sample['language']if len(sample['text']) > 0:#if sample['language'] == 'CHS' and len(sample['text']) > 0:print(sample)# 获取音频数据audio_array = sample["audio"]["array"]# 将音频数据缩放到 -32768 到 32767 之间audio_array = np.int16(audio_array / np.max(np.abs(audio_array)) * 32767)_dir = os.path.join(ddir, npcName)# 保存音频数据audio_path = os.path.join(_dir, f"{mpInpcName[npcName]}_{lg}.wav")wavfile.write(audio_path, sample["audio"]["sampling_rate"], audio_array)# 保存文本内容text_path = os.path.join(_dir, f"{mpInpcName[npcName]}_{lg}.txt")with open(text_path, "w", encoding="utf-8") as f:f.write(sample["text"])mpInpcName[npcName] += 1

3:原始音频转换成:音频转码 44.1k 1 pcm_s16le

我们使用,ffmpeg 命令行转换
ffmpeg 下载只需要到github下载最新版本就行 https://ffmpeg.org/download.html

ffmpeg -i "./zjdx/zjdx.wav" -ar 44100 -ac 1 -acodec pcm_s16le "./output/zjdx.wav"

import os
import subprocess
import shutil
import redef process_convert_audio(input_path: str, output_path: str):"""音频转码 44.1k 1 pcm_s16le@param input_path: 要转码的音频所在路径@param output_path: 转码后的音频保存路径@return:"""os.makedirs(output_path, exist_ok=True)if os.path.exists(input_path) and os.path.isdir(input_path):for root, dirs, files in os.walk(input_path):for audio in files:output_file_name = os.path.basename(audio)input_file = os.path.join(root, audio)output_file = os.path.join(output_path, output_file_name)#判断是否是文本文档,如果是文本文档直接处理特殊字符并且复制到输出目录,text = re.sub(r'<.*?>|「.*?」|\{.*?\}|#|\$UNRELEASED', '', txt)if audio.endswith(".txt"):try:# 读取文本内容with open(input_file, "r", encoding="utf-8") as f:txt = f.read()# 移除特殊字符processed_text = re.sub(r'<.*?>|「.*?」|\{.*?\}|#|\$UNRELEASED', '', txt)# 保存处理后的文本到输出目录with open(output_file, "w", encoding="utf-8") as f:f.write(processed_text)print(f"文本文件已处理: {output_file}")except Exception as e:print(f"处理文本文件失败: {input_file}, 错误: {e}")else:try:command = ["ffmpeg", "-y",  # 添加 -y 参数,强制覆盖输出文件"-i", input_file,"-ar", "44100",  # 设置采样率为 44.1kHz"-ac", "1",      # 设置单声道"-acodec", "pcm_s16le",  # 设置音频编码为 PCM 16-bit little-endianoutput_file]subprocess.run(command, check=True)print(f"转换成功: {output_file}")except subprocess.CalledProcessError as e:print(f"转换失败: {input_file}, 错误: {e}")if __name__ == "__main__":odir = "xunlian/spk_pai_44.1k"ddir = "xunlian/spk_pai"# 查找ddir里面所有的文件夹名字命名为npcNamenpcNames = [f.name for f in os.scandir(ddir) if f.is_dir()]# 循环调用process_convert_audiofor npcName in npcNames:process_convert_audio(os.path.join(ddir, npcName), os.path.join(odir, npcName))

4,音频降噪(此步可省略)

可用resemble-enhance降噪

pip install resemble-enhance --upgrade

5:生成metadata文件

from pathlib import Path
import redef gen_metadata(audio_path: str, label_path: str, metadata_file: str):"""生成 metadata.list 文件@param audio_path: 音频所在路径@param label_path: 标签所在的路径@param metadata_file: 保存生成后的 metadata.list 文件@return:"""label_dict = {}# 遍历标签文件if Path(label_path).exists() and Path(label_path).is_dir():for label_file in Path(label_path).glob("*.txt"):  # 遍历所有 .txt 文件label_name = label_file.stem  # 获取文件名(去掉扩展名)with label_file.open('r', encoding='utf-8') as f:txt = f.read()label_dict[label_name] = txt#删除metadata_fileif Path(metadata_file).exists():Path(metadata_file).unlink()# 遍历音频文件if Path(audio_path).exists() and Path(audio_path).is_dir():for audio_file in Path(audio_path).glob("*.wav"):  # 遍历所有 .wav 文件audio_name = audio_file.stem  # 获取文件名(去掉扩展名)if audio_name in label_dict:label_txt = label_dict[audio_name]if len(re.sub(r'[^\u4e00-\u9fff]', '', label_txt).strip()) != 0:with open(metadata_file, 'a', encoding='utf-8') as f:f.write(f'{audio_file}|ZH-zjdx|ZH|{label_txt}\n')f.flush()if __name__ == "__main__":odir = "xunlian/spk_pai_44.1k"npcNames = [f.name for f in Path(odir).iterdir() if f.is_dir()]for npcName in npcNames:audio_path = Path(odir) / npcNamegen_metadata(audio_path, audio_path, audio_path / "metadata.list")

这里面代码:|ZH-zjdx|ZH| 中ZH-zjdx代表你的发音人名字,可自定义。
ZH是原始音频文字,如果是中英文混合,可以改成ZH_MIX_EN

6: 修改中文底膜:

中文特化模型下载:
https://openi.pcl.ac.cn/Stardust_minus/Bert-VITS2/modelmanage/show_model

修改melo/download_utils.py对应的值

PRETRAINED_MODELS = {'G.pth': './model/basespeakers/pretrained/G.pth','D.pth': './model/basespeakers/pretrained/D.pth','DUR.pth': './model/basespeakers/pretrained/DUR.pth',
}

对应的你的下载G_0,D_0,DUR_0.可以用中英日底膜
https://openi.pcl.ac.cn/Stardust_minus/Bert-VITS2/modelmanage/model_readme_tmpl?name=Bert-VITS2%E4%B8%AD%E6%97%A5%E8%8B%B1%E5%BA%95%E6%A8%A1-fix

7:训练,生成config.json

使用如下命令:

PYTHONPATH=$PWD python /data-1T/apps/melotts/melo/preprocess_text.py --config_path /data-1T/apps/melotts/melo/configs/config.json --metadata /data-1T/apps/melotts/xunlian/output/metadata.list

把/data-1T/apps/melotts/xunlian/output/metadata.list改为自己的metadata.list文件路径。
运行上面的命令之后,会在metadata.list同级目录中生成几个文件,其中一个是config.json文件,我们需要打开这个文件,修改一些训练参数。

"train": {"log_interval": 200,"eval_interval": 1000,// 多少轮保存一个"seed": 52,"epochs": 10000, // 总共训练轮次"batch_size": 6,
......
}

根据自己的数据集大小和显卡情况修改。这里我训练的数据集为10066条数据,显卡为单张RTX4090D显卡,所以我这里设置epochs=500,batch_size=16。

8:创建目录 zh-zjdx 将 config.json 放入该目录下

这样做的目的是在训练启动的时候,会自动在源码中的melo/logs下面自动创建一个这样的目录,用于存放训练过程中的数据。

9:开始训练。

PYTHONPATH=$PWD bash ./melo/train.sh /data-1T/apps/melotts/zh-zjdx/config.json 1

上面这条命令中需要输入两个参数,一个是配置文件,一个是GPU数量,我这里只有一张显卡,所以最后一个参数是1。

10:推理

使用下面命令进行推理。

PYTHONPATH=$PWD python ./melo/infer.py --text "这个是如何改音标的?如果要训练方言的模型" -m ./logs/zh-zjdx/G_1000.pth -o ./out -l ZH

注意上面命令中并没有显示指定配置文件,其实代码内部会根据G_n.pth所在的目录中查找配置文件。

如果想要在网页端使用,那么需要修改app.py代码。

models = {'EN': TTS(language='EN', device=device),'ZH': TTS(language='ZH', device=device),'ZH-zjdx': TTS(language='ZH', device=device,config_path='./logs/zh-zjdx/config.json',ckpt_path='./logs/zh-zjdx/G_39000.pth'),
}
speaker_ids = models['EN'].hps.data.spk2iddefault_text_dict = {'ZH-zjdx': 'text-to-speech 领域近年来发展迅速','EN': 'The field of text-to-speech has seen rapid development recently.','ZH': 'text-to-speech 领域近年来发展迅速',
}.....language = gr.Radio(['EN','ZH','ZH-zjdx'], label='Language', value='EN')
......

然后启动这个app.py就可以在网页端进行语音合成了。
在这里插入图片描述

最后注意事项:如果你训练出来的音频是胡乱说话。根本听不出来说的什么,那么可能有两个问题导致的,

1:底膜没对,请参考6选项设置底膜
2:可能训练轮次不够或者原始音频量不够。

http://www.xdnf.cn/news/10831.html

相关文章:

  • CUDA与venv的配置
  • 【机器学习及深度学习】机器学习模型的误差:偏差、方差及噪声
  • vue2上传图片
  • matlab实现求解兰伯特问题
  • Filebeat技术之多行采集
  • java-spring
  • Blinko智能笔记系统实现跨平台同步与隐私保护的完整技术方案解析
  • 2025年MathorCup数学建模D题短途运输货量预测及车辆调度问题解题文档与程序
  • dataX(入门,mysql到doris)
  • 软件评测师 案例真题笔记
  • RDMA简介1之RDMA开发必要性
  • Java 中执行命令并使用指定配置文件的最佳实践
  • [蓝桥杯]生物芯片
  • 今日主题二分查找(寻找峰值 力扣162)
  • 初识小智AI项目
  • 酵母杂交那些事儿(一)
  • [Python] struct.unpack() 用法详解
  • 在 Linux 上安装 Nmap 工具
  • CSRF攻击与防御
  • 现代密码学介绍
  • 前端开发处理‘流式数据’与‘非流式数据’,在接收完整与非完整性数据时应该如何渲染和使用
  • 【产品研究】安克创新公司产品研究
  • 推荐算法八股
  • STM32外部中断(EXTI)以及旋转编码器的简介
  • 【深度学习-Day 22】框架入门:告别数据瓶颈 - 掌握PyTorch Dataset、DataLoader与TensorFlow tf.data实战
  • MongoTemplate常用api学习
  • [手写系列]从0到1开发并上线Edge浏览器插件
  • AJ-Report
  • 深拷贝与浅拷贝的区别?如何手写实现一个深拷贝?
  • 英语写作中“不少于(小于)”no less than替代no fewer than的用法