前言
当Stable Diffusion掀起AI绘画的热潮时,我就已深感人工智能的巨大潜力。后来在B站上,各种AI模型视频,尤其是AI翻唱歌曲的内容层出不穷,激起了我的好奇心。于是,我在Github上搜寻了一番,发现了许多开源的AI语音模型项目,发现其训练门槛并不高,便开始了我的探索之旅。起初只是出于好奇,但实际体验后,我被其逼真的效果深深震撼。因此,我整理了过去训练时的一些笔记,与大家分享我的心得体会,希望能帮助大家了解如何利用AI自动生成语音。
应用场景
个人应用
首先,我想简单分享一下我个人在AI语音模型训练方面的一些成果和实际应用。
我曾经训练过一个具有自己独特音色的唱歌模型。虽然高音部分仍然难以完美驾驭,但至少音调是准确的,也算是实现了我小小的唱歌梦想——不跑调就是最大的胜利。此外,我还训练了几个女声模型,最终挑选了两个并将它们融合,得到了一个略带烟嗓的女声模型,其效果令人满意。在使用这个模型处理一篇几千字的文章时,最多只会出现一两个地方有电音或变调的现象,这对于我个人而言是完全可以接受的。
目前,我特别喜欢使用这个混合模型来生成一些近现代文学作品的音频。有些文章,直接阅读可能难以沉浸其中,但通过聆听,却能让人更好地投入进去。记得以前读书时,我非常喜欢阅读纸质书籍,各种散文、名著都能静下心来细细品味。但现在,我变得有些浮躁,难以沉下心来。不过,内心深处仍然渴望接受文学的熏陶。我相信很多人可能理解我这种矛盾的心情。普通的TTS(文本转语音)转换效果对我来说难以接受,完全没有听下去的欲望。因此,我特地花了一个星期的时间来调整出目前所使用的音色。如果哪一天听腻了,我准备再花点时间换个口味,反正成本也不高,只需要几晚上的电费而已。
为了让使用过程更加便捷,我特意研究了音色推理部分的源代码,并临时编写了一个脚本,可以一键将指定文件夹中的txt文件转换成音频文件,同时还会生成vtt格式的字幕文件。我特意将微软TTS的语速调慢了20%,所以通常一篇3000字的文章转换成音频后时长约为15分钟,对我来说刚刚好。
在电脑上听音频时,我通常使用PotPlayer。这款播放器可以自动加载同一文件夹下的同名字幕文件,省去了不少麻烦,播放效果也相当不错。
除此之外,我还训练过几个用于实时转换音色的模型,简单来说就是AI版的变声器。以男声变女声为例,传统的变声器不仅需要打开变声功能,还需要使用者用尖细的音调说话才能达到逼真的效果。但AI变声器完全不需要,只需用正常的语气讲话即可。当然,目前的AI变声器还存在一些小缺陷,首先是如果显卡性能不够,延迟会比较高;其次是类似鼓掌、敲桌子等非人声也会被转换。在游戏中使用AI变声器进行语音交流,效果非常惊艳,偶尔玩玩还是挺有趣的。
更多应用
这些模型还可以接入智能家居系统HomeAssistant,但配置起来比较复杂,因为我不想在HomeAssistant的虚拟机中安装过多的依赖。如果想要接入,最好的方法是封装一个API接口的docker容器。不过,考虑到目前的需求,我还是暂时搁置了这个想法。或许等我训练出一个熟人的音色,想整蛊一下的时候,可以考虑开发一个玩玩。
如果将思路进一步发散,AI语音模型的应用场景其实非常广泛。如果稍微懂一些编程知识,就能玩出许多花样。例如,可以根据类似“甲:…… 乙:…… 旁白:……”格式的文本,编写一个脚本自动识别角色,并匹配不同的语音模型,从而批量制作广播剧。更复杂一些的应用,可以搭配Stable Diffusion等AI绘图软件,批量制作有声书短视频。如果难度再高一些,可以配合Ren’Py等简单的视觉小说引擎,自制文字游戏,或者将跑团群中的文字跑团游戏可视化为影音游戏,以此作为纪念。
当然,虽然我在此列举了许多应用方式,但并不建议大家轻易尝试,训练出来自己玩玩就好。如果真的想发布分享,建议在行动之前认真学习国家今年7月开始公布施行的《生成式人工智能服务管理暂行办法》以及其他相关法律,包括但不限于《中华人民共和国宪法》、《刑法》、《民法典》、《合同法》。
《民法典》
第一千零一十九条
任何组织或者个人不得以丑化、污损,或者利用信息技术手段伪造等方式侵害他人的肖像权。未经肖像权人同意,不得制作、使用、公开肖像权人的肖像,但是法律另有规定的除外。未经肖像权人同意,肖像作品权利人不得以发表、复制、发行、出租、展览等方式使用或者公开肖像权人的肖像。对自然人声音的保护,参照适用肖像权保护的有关规定。
第一千零二十四条
【名誉权】民事主体享有名誉权。任何组织或者个人不得以侮辱、诽谤等方式侵害他人的名誉权。
第一千零二十七条
【作品侵害名誉权】行为人发表的文学、艺术作品以真人真事或者特定人为描述对象,含有侮辱、诽谤内容,侵害他人名誉权的,受害人有权依法请求该行为人承担民事责任。行为人发表的文学、艺术作品不以特定人为描述对象,仅其中的情节与该特定人的情况相似的,不承担民事责任。
语音模型分类
这里我不会使用过于专业的术语,毕竟我也不是专门从事这个领域的,理解可能不够深入。就我目前了解到的开源项目而言,主要分为两类:一是文字转语音(TTS),类似于常见的语音合成功能;二是语音转语音,主要用于音色转换。许多此类开源项目的初衷是让用户能够使用自己喜爱的虚拟角色演唱自己喜欢的歌曲,因此通常主要功能是唱歌,同时也支持正常的说话。
文字转语音模型的训练通常比较困难,主要难点在于数据集的准备。为了实现文字与语音之间的一一对应,数据集的制作不仅需要大量的干声素材,还需要对每一条干声素材进行文本标注。虽然标注过程可以借助其他AI模型来简化,但人工校验AI标注的结果也是一项耗时费力的工作。当然,也可以选择不进行校验,但这样就无法保证最终训练出来的模型质量了。
语音转语音模型则相对容易上手。通常只需要保证有足够时长的高质量干声素材即可。我个人主要训练的就是这种模型。如果想使用这种模型实现TTS功能,可以先使用微软免费的在线TTS服务将文本转换为语音,然后再通过训练出来的音色模型将其转化为目标音色。听起来比较复杂,但实际上只需编写一个Python脚本调用edge-tts库即可轻松完成。
从TTS的效果来看,这种方法甚至比直接自己训练的文本转语音模型还要好。因为微软的TTS模型非常强大,相信大家都曾在电影解说视频中听到过“这个男人叫小帅”的开场白,这个配音使用的就是微软TTS服务中的“云希”。虽然现在“云希”的使用非常普遍,以至于大家听到后可能会觉得有些厌烦,但不可否认的是,其语音效果确实是最出色的之一。
开源项目推荐
AI语音类的开源项目非常多,这里我只推荐两个我自己用下来觉得训练方便、效果显著的项目。
so-vits-svc
SoftVC VITS Singing Voice Conversion是一个音色转换项目。之前网上流行的AI孙燕姿模型,很多都是用这个项目训练出来的。除了唱歌,它也可以用于正常说话的语音转换,音色还原度和咬字清晰度都是开源项目中的佼佼者。
不过,由于一些法律原因,这个项目之前删库重建过一次,之后项目组就不再发布官方训练底模了,所以想找到合适的底模比较麻烦。
Retrieval-based-Voice-Conversion-WebUI
RVC-Project项目可以用更少的素材和训练步数达到不错的音色还原度,而且实时转换的效率也比较高。如果想将其用作变声器,我更推荐使用这个项目。
开源模型社区
如果你没有条件自己训练模型,但又想体验AI语音合成的效果,最简单的方法就是部署好环境后,直接去开源模型社区下载现成的模型。我推荐使用Hugging Face,基本上所有开源项目都能在这里找到相关的模型,有些项目的底模找不到,也可以在这里碰碰运气。
本地训练门槛
这里我主要介绍本地训练的门槛,不讨论租借云端显卡进行训练的方案。
6 GB显存的英伟达显卡
训练大部分AI模型都需要用到高显存的N卡,语音模型算是其中要求比较低的,最低显存要求不算太高,一般的游戏显卡都能满足。
充足且清晰的单人音频素材
“充足”指的是符合目标项目提到的最低音频时长要求,不同的AI项目想要达到目标效果所需的素材时长是不同的。相较于音频时长,音频的质量更为关键,低质量的素材最终训练出来的模型必然不会完美。我这里没有强调必须是干声素材,因为背景音大部分情况下都可以通过人声分离软件进行剔除,后面会有更详细的讲解。
基础的Python编程知识
并不是说不会Python就无法自己训练AI模型,毕竟网上有很多所谓的整合包,下载解压后一键就可以开始训练。但是,如果没有这部分基础知识,在训练过程中遇到问题时会非常被动。更重要的是,即使训练出了模型,也无法将其自如地应用到更多的场景中。
举一个稍微复杂一点的例子:让服务器每天爬取当天的天气预报,如果出现下雨或极端天气,就自动生成一段提醒文本,然后自动调用语音模型将其转换为音频,最后通过DLNA传输的方式让房间中的音箱播报这段音频。这种场景非常美好,但需要一定的编程知识才能实现。
语音模型项目本地部署
我不想针对单一的AI语音项目来出一个具体的教程。如今AI发展迅猛,可能过一阵子就会因为一篇新算法的发表而出现更加优秀的训练项目。“授人以鱼不如授人以渔”,因此下面的内容更多的是分享一些解决问题的思路。
这里仅考虑使用Windows的情况。当然,如果实在不想折腾,也可以直接去B站上搜索对应项目的整合包,通常都能找到,开箱即用。
前期准备
相比直接安装Python,我个人更推荐使用集成工具Anaconda。它的优势是方便部署虚拟环境,可以很方便地为每个项目配置单独的运行环境。配置好环境后,只需要将整个项目文件打包,就可以放在任何其他电脑上运行,自己创建所谓的整合包。
Anaconda安装起来非常简单,去官网下载最新的安装包,然后按照指引完成安装即可。如果对安装过程存在疑问,可以在网上随便搜索一个教程,我就不赘述了。因为这些开源项目通常都是发布在Github上,下载速度可能较慢,可以使用Watt Toolkit或者Doget等工具对下载链接进行转换后再下载。也可以在Gitee上新建仓库,然后从Github上导入。
项目部署
查看文档
想要部署一个项目,首先要做的就是查看项目根目录下的readme.md文件。这个文件会默认显示在Github中该仓库的主页。
主要看哪些内容呢?
- 项目实现的功能。确定项目符合自己的需求。
- 训练模型需要的硬件配置。如果文档中没有特别强调,一般6 GB显存的N卡也就够用了;如果电脑配置不满足,但还是想尝试,可以使用类似谷歌Colab、百度飞桨等云计算平台。
- 支持的Python版本。目前开源的AI模型基本都是依托于PyTorch这一机器学习库编写的。如果文档中没有提及版本问题,可以使用较为稳妥的3.8版本。
- 训练用音频素材的要求。首先是音频格式及其采样率,大部分情况下是单声道44K采样率的WAV格式文件。虽然项目中可能有重采样的预处理程序,但最好初始输入的音频就符合项目要求。另一个是音频素材的单个时长及总时长,单个时长一般3~20秒都是可以的,最好控制在5~15秒,具体以项目文档为准;总时长个人经验并不是越长越好,正常两个小时左右就能达到不错的效果,部分特化的项目甚至只需要几分钟。不要太长的另一个原因主要是考虑到训练速度,如果素材总大小超过电脑内存上限的话,就无法一次将数据读取到内存中,训练速度会受到硬盘读取速度的限制,GPU占用率会因为读盘的操作而经常下降。
- 训练的命令。大型项目通常会有比较详细的训练步骤介绍。
拉取项目
接下来,自然是把项目文件拉取到本地。无论使用哪种方法,只要能下载到本地即可。
搭建环境
进入项目根目录,在此处打开CMD窗口,确保CMD窗口中显示的路径为当前项目根目录。如果不是,就用cd命令切换过来。注意,这里一定不要用PowerShell,否则会无法激活下面创建的虚拟环境。
然后,使用Anaconda在当前目录创建虚拟环境:
conda create -p .\env python=3.8
命令中Python的版本可以根据需要自行更改。我比较喜欢指定环境安装位置在项目根目录,方便后期打包备份。如果不准备在其他电脑上运行,也可以使用-n参数创建一个命名环境,这个环境通常会保存在当前电脑用户的文件夹下。
创建好Python虚拟环境后,需要在命令行中激活:
conda activate .\env
激活后,命令行前面会有一个小括号包裹的环境路径,一定要确保激活环境后再进行后面的操作。
接下来,输入下面的命令查看自己电脑的CUDA版本:
nvidia-smi
之后登录PyTorch的官网,官网上可以直接查看符合自己系统的安装命令。我一般直接选择Pip安装方式。在之前的命令窗中输入网页上的安装命令,等待下载安装完成。第一次安装可能会比较慢,后面如果创建别的虚拟环境,就可以直接使用系统内的缓存,安装速度会快很多。
这里可以看一下安装命令,不难发现安装了torch、torchvision、torchaudio这三个包,把它们的名字记一下,后面可能会用到。
除了安装PyTorch外,为了让项目正常运行,还需要安装requirements.txt文件中规定的所有库。正常支持Windows的项目会有一个额外的requirements_win.txt文件,如果有的话就使用这个文件,如果没有就使用requirements.txt。在安装之前,最好先打开这个文件,看看里面的库名是否包含之前安装过的那三个包,如果包含的话,就先手动删去,避免重新安装到错误的版本。准备工作完成后,运行如下命令:
pip install -r requirements_win.txt -i https://mirrors.aliyun.com/pypi/simple/
如果安装过程不报错,那就皆大欢喜。但如果报错了也不用慌,大部分都是包的版本问题,解决起来并不难。下面举几个例子作为参考。
常见错误1
这个错误是因为gradio没有符合要求的版本号。解决办法很简单,把txt文件中这个包的版本号删去,让包管理器自动寻找最新版本即可。
常见错误2
这个错误是因为多个不同的包对numpy版本的要求不同,包管理器无法找到符合所有包需求的numpy版本。解决方法其实在报错信息里已经写了,就是删去这些库的版本号。可以逐个删除尝试,尽可能少地修改txt文件。
常见错误3
这个错误发生的原因很多,解决办法也相应较多。可以按照错误提示中说的,试试看升级Pip,或者是安装Rust编译器。除此之外,还有一种解决办法就是限制一下对应包的版本号,比如我碰到的这个问题只需要将transformers的版本号限定在3.4即可。
下面放一张安装成功的截图,希望各位都能一次成功。
运行命令
之前项目部署那里提到过部分内容,比如激活虚拟环境的命令:
conda activate .\env
激活环境后,就可以按照项目文档中写的训练命令来依次执行了。不过,如果是简单的Python命令,也可以不激活环境,直接写出解释器的路径也可以调用,比如:
.\env\python webUI.py
效果等同于
conda activate .\env
python webUI.py
有时候部分命令需要频繁使用,每次都打开CMD窗口输入命令未免过于麻烦。这时候,我们可以编写一个bat后缀的文件来简化操作。
创建的方法也很简单,右击新建一个文本文档,也就是txt文件,然后将其重命名为bat拓展名的文件即可。双击这个文件就会自动在当前路径执行其中的命令。如果想要修改其中的命令,右击文件后点击编辑即可。下面给出一个通用的模板:
@echo off
call conda activate .\env
python webUI.pypy
pause
简单解释一下各个语句的意思:第一行表示关闭命令行输出,第二行表示激活当前环境,第三行写上任意想要运行的命令,第四行表示运行完成后等待用户确认再关闭命令行窗口。
数据集准备
学会上面这一套,基本所有的开源AI项目就都可以自行部署到本地了,可以说实现了整合包自由,看上哪个项目直接上手玩就是了。本节则分享一下我个人处理语音数据集的经验。
基础知识
整理数据集之前,请务必先搞清楚自己训练语音模型的用途,明确是唱歌用还是说话用,一个人唱歌和说话时的音色是有很大差别的。
唱歌用数据集的要求通常更高一些,除了时长的要求,音域也需要尽可能全覆盖,简单来说就是高音、低音最好都有,否则最终出来的模型就会在数据集缺失的音域产生哑音或音色失真之类的缺陷。
我本人五音不全,也曾经训练过自己音色的唱歌模型,结果只能说惨不忍睹,事实证明你本来唱不上去的调,换成AI还是唱不上去。唱歌数据集如果时长实在有限,可以适当添加一些音色相近的说话素材,但不能太多,质量大部分时候都比数量更重要。说话数据集就简单许多,尽量选用音色相近的正常语音素材即可。
获取音频素材
这里其实分几种情况,主要是根据训练模型的目的来划分。
第一种是只想要一个听着舒服的音色来进行TTS文本转语音,第二种是想先随便找点素材练练手看看效果。这两种需求最简单的素材获取方式就是去类似喜马拉雅、蜻蜓FM的音频网站上找一个主播,直接把他所有的音频下载下来,简单处理之后就可以开始训练。
第三种是想要训练自己或朋友的AI语音模型。这种情况下,有两种常见的处理手法:一种是用Au之类的录音软件专门录制干声;另一种是使用Voicemeeter之类的虚拟声卡软件将平常微信或QQ电话的音频录制下来。当然,如果是训练朋友的模型,请务必取得他的同意。如果是想要训练唱歌用的模型,可以安装一些K歌类的软件,大多都可以将音频保存下来。平常没事的时候唱几首,时长够了也就可以开始动手训练了。
第四种是想训练某个明星或主播的模型。歌星的话直接用他歌曲的人声部分即可;主播的话麻烦一点,得找直播切片提取出音轨;影视明星更加麻烦,得慢慢找视频素材单独切出角色语音,不是真爱或者闲得蛋疼不推荐尝试。
处理素材
这里讲一些常用的素材处理技巧,可以极大地提高处理效率。
人声分离
很多素材都会有背景音乐,人工去除难度太大,此时需要借助一些专用软件。我这里只推荐使用UVR5,目前市面上最强的免费声音分离软件。使用起来也非常简单,直接去官网下载安装好之后打开保持默认,勾选上Vocals Only选项,点击开始转换即可。
Vocals Only选项就是只输出人声音轨,不输出伴奏音轨。图中的这套配置可以轻松去除纯音乐的背景音,不过如果BGM是带有人声的歌曲就无能为力了,歌曲中的人声也会被保留。我本人对这个软件也没啥深入的研究,更多需求大家自行研究一下。
文件重命名
这个步骤非常关键,主要是很多项目都不支持中文文件名,所以素材在切片之前最好先重命名一下。文件数量少的话手工改一下问题不大,数量太多的话就比较头疼了。目前市面上批量重命名的工具不少,大家各显神通即可。我本人比较习惯用Python脚本,这里简单分享一个,大家会用就用。
import glob
import os
if __name__ == '__main__':
index = 1
for file in glob.glob("*.wav"):
os.rename(file, "{:04d}.wav".format(index))
index += 1
批量切除部分片段
有时候一些音频会有一个统一时长的开场白或结束语,手动切除就会很麻烦,这里同样给出一个Python脚本。
import glob
import os
from pydub import AudioSegment
def cut_one(input, output):
audio = AudioSegment.from_file(input, format="mp3")
# 切除开头 8 秒
audio = audio[8000:]
audio.export(output, format="mp3")
if __name__ == '__main__':
for file in glob.glob("*.mp3"):
out = os.path.join("cutted", os.path.split(file)[-1])
cut_one(file, out)
合并短音频
这个需求比较少见——比如有时候会用到一些游戏的角色语音来作为训练素材,但是这些素材可能单条都只有几秒钟时间,不太符合训练切片的时长要求。这时候可以使用Au这样的图形化软件手动拼接,也可以借用脚本,同样给出一个示例。
import glob
from pydub import AudioSegment
if __name__ == '__main__':
index = 1
for file in glob.glob("dirname/*.ogg"):
if index == 1:
audio = AudioSegment.from_ogg(file)
else:
audio += AudioSegment.from_ogg(file)
print(index)
index += 1
audio.export("merged.wav", format="wav")
音量统一
很多项目会有内置的脚本进行音量处理,如果没有就只能自己动手了,因为这个步骤是必不可少的,否则最终训练出来的模型也会出现类似的问题。想要达到最好的效果肯定是使用Au这样的专业软件进行调整,但是如果怕麻烦的话也可以使用脚本解决。
import glob
import os
from pydub import AudioSegment
if __name__ == '__main__':
# 统一化的音量大小,单位 dB
target_db = -10
os.makedirs("normalized", exist_ok=True)
for file in glob.glob("dirpath/*.wav"):
basename = os.path.basename(file)
audio = AudioSegment.from_file(file)
current_db = audio.dBFS
db_diff = target_db - current_db
normalized_audio = audio + db_diff
normalized_audio.export(
os.path.join("normalized", basename),
format="wav"
)
批量切片
切片是准备数据集必不可少的步骤,大部分项目对单条音频的时长都有限制,大多为5~15秒,手工切是肯定不可能的,毕竟几千条能把人累死。目前用的最多的是audio-slicer,有带图形化界面的版本,使用的时候保持默认设置即可。
删去过长过短音频
这个操作非常简单,为了处理过程的完整性简单提一下。将切片好的文件夹属性设置为常规文件,然后根据数据大小排序,依照顺序删去过长或过短的音频即可。
需要标注文本的音频
之前提过,训练文本转语音模型需要对音频进行文本标注。因为不同的项目对文本的标注格式会有些许差别,仔细看项目文档就是了,大部分项目会给出标注建议和相关工具,依照指示操作即可。
训练进度查看
对于很多新手朋友来说,训练模型时最大的疑惑可能就是怎么样算是训练完成了?如何判定训练进度是一件非常重要的事,否则闷头训练很容易浪费时间。要知道,模型并不是训练的时间越长效果越好。训练步数过多很有可能出现过拟合的情况,纸面参数好看结果却完全不如低步数时的效果。
目前大部分模型的训练代码中都会添加tensorboard的相关支持。借由tensorboard,我们就可以在训练的过程中实时跟踪关键训练参数。判断一个项目是否支持tensorboard很简单,直接看之前搭建环境时提到的requirements.txt文件即可,里面如果有这个包的名称就是支持的。
怎么打开参数面板也很简单,首先找到模型训练时保存checkpoints和日志的文件夹,一般就叫logs,在里面找到带有events打头文件的文件夹。这里要注意,这种文件只有在开始训练模型并在命令行产生输出后才会生成。
找到后记下其所在文件夹的路径,无论是绝对路径还是相对路径皆可。然后再开一个命令行窗口激活虚拟环境后输入下面的命令:
tensorboard --logdir dirname
命令中的dirname自行替换,如果出现如下输出则代表运行成功:
打开命令行中的本地链接后就可以看到监测面板:
里面的数据根据不同的项目会有差别,有的详细,有的可能只有loss这一部分。看不懂没有关系,会看曲线就行。其实大部分情况只看一张loss的图就够用了,有些叫total,有些叫reference loss,简单理解就是总偏差。通常这张图的曲线趋于平稳之后就可以结束训练了。
训练结束后就是纯主观的听音环节了。如果面板上有AUDIO选项卡的话,可以进入其中试听不同步数下的转换效果,框定一个大致的步数范围,然后可以挑选几个听下来不错的模型,找一些音频素材让其实际转换一下,再细品一下到底把哪个模型文件作为最终成品。很多时候并不是步数最高的模型效果最好,我就碰到过一个好玩的例子,特地训练了一个烟嗓的女声模型,结果训练到后面把烟嗓给训练没了,反倒是步数少的模型更加原汁原味。
训练参数设置
最后再提两个训练的小技巧:如果你的硬盘空间足够大的话,建议把训练参数中保留的checkpoints数量调大一点,像我一般直接调成100,这样挂一晚上之后所有的记录点模型都在,不会出现训练过头导致真正效果好的模型被删除而只能从头再来的折磨。另一个技巧就是如果参数中支持将训练数据一次性全部加载到内存中的话,在内存容量足够的情况下请务必开启这一功能,可以大大提高训练速度。
还有一个注意点,如果不是特殊需求的话,最好训练单人模型,因为单人模型后期进行音色融合的话更加简单灵活。我自己现在常用的就是两个音色融合之后的模型。
批量转换脚本
我本人现在用的是so-vits-svc-4.1-Stable,最开始的个人应用中提到的批量转换脚本如下,放在项目根目录就可以运行。因为是临时写的,也没有仔细优化过,代码写的比较乱,看不懂就只改最前面几个大写的参数。实在不会用就算了,用项目自带的网页工具手动转换也一样。
import asyncio
import edge_tts
import glob
import librosa
import numpy as np
import os
import re
import soundfile
from inference import infer_tool
from inference.infer_tool import Svc
# 微软 TTS 参数
# 音色,云希虽然是男声,但是说话节奏是最好的,不建议修改
VOICE = "zh-CN-YunxiNeural"
# 说话速率,根据喜好来
RATE = "-20%"
# 音量增强,根据喜好来
VOLUME = "+50%"
# 模型参数
# 模型文件路径
MODEL = "trained/female_RuiQian/female_RuiQian.pth"
# 模型对应配置文件路径
CONFIG = "trained/female_RuiQian/config.json"
# 说话人名称
SPEAKER = "female_RuiQian"
async def generate_one(filepath) -> None:
# 读取 txt 文件内容
with open(filepath, "r", encoding="utf-8") as f:
text = f.read().replace(" ", "").replace(" ", "").replace("\n", "").replace("\t", "").replace("\a", "")
# 微软 TTS 生成语音和字幕的保存路径
base_name = os.path.basename(filepath)
name = os.path.splitext(base_name)[0]
media = os.path.join("results", "raw_{}.mp3".format(name))
subtitle = os.path.join("results", "{}.vtt".format(name))
# 创建并保存微软 TTS 语音和字幕文件,需要联网,速度较慢
communicate = edge_tts.Communicate(text=text, voice=VOICE, rate=RATE, volume=VOLUME)
submaker = edge_tts.SubMaker()
with open(media, "wb") as file:
async for chunk in communicate.stream():
if chunk["type"] == "audio":
file.write(chunk["data"])
elif chunk["type"] == "WordBoundary":
# 向字幕文件中加入标点符号
chunk_text = chunk["text"].replace(" ", "")
pattern = "^" + chunk_text.replace("", ".*?").rstrip(".*?") + r"""[,。”:;、?)》}】!,.'";:?)>}\]]*"""
chunk_text = re.match(pattern, text).group()
print(chunk_text)
text = text[len(chunk_text):]
submaker.create_sub((chunk["offset"], chunk["duration"]), chunk_text)
with open(subtitle, "w", encoding="utf-8") as file:
file.write(submaker.generate_subs())
# 音频数据预处理,将 TTS 生成的 mp3 文件转为 wav
target_sr = 44100
y, sr = librosa.load(media)
resampled_y = librosa.resample(y, orig_sr=sr, target_sr=target_sr)
processed_audio = os.path.join("results", f"processed_{name}.wav")
soundfile.write(processed_audio, resampled_y, target_sr, subtype="PCM_16")
# 加载语音模型
model = Svc(MODEL,
CONFIG,
device=None,
cluster_model_path="",
nsf_hifigan_enhance=False,
diffusion_model_path="",
diffusion_config_path="",
shallow_diffusion=False,
only_diffusion=False,
spk_mix_enable=False,
feature_retrieval=""
)
# 模型推理参数
kwarg = {
"raw_audio_path": processed_audio,
"spk": SPEAKER,
"tran": 0,
"slice_db": -40,
"cluster_infer_ratio": 0,
"auto_predict_f0": True,
"noice_scale": 0.4,
"pad_seconds": 0.5,
"clip_seconds": 0,
"lg_num": 0,
"lgr_num": 0.75,
"f0_predictor": "rmvpe",
"enhancer_adaptive_key": 0,
"cr_threshold": 0.05,
"k_step": 100,
"use_spk_mix": False,
"second_encoding": False,
"loudness_envelope_adjustment": 1
}
# 音色转换推理
audio = model.slice_inference(**kwarg)
model.clear_empty()
res_path = os.path.join("results", "{}.wav".format(name))
# 保存最终音频
soundfile.write(res_path, audio, model.target_sample)
async def generate():
# 提前在根目录创建一个 text 文件夹,把要转换的 txt 文件放在里面
for file in glob.glob("text/*.txt"):
await generate_one(file)
if __name__ == "__main__":
loop = asyncio.get_event_loop_policy().get_event_loop()
try:
loop.run_until_complete(generate())
finally:
loop.close()
总结
本文深入探讨了如何使用开源项目训练自己的AI语音模型,涵盖了从环境搭建、数据集准备、模型训练到批量转换的各个环节,并分享了一些实用的技巧和经验。希望通过本文,能帮助大家掌握AI语音自动生成的基本原理和方法,为未来的学习和应用打下坚实的基础。随着AI技术的不断发展,语音合成技术也将迎来更加广阔的应用前景,例如个性化语音助手、智能客服、有声内容创作等。掌握这项技术,无疑将为我们在未来的竞争中赢得更多优势。