赞
踩
近几天有好多小伙伴咨询Sovits本地部署的问题,所以呢决定写个简易教程。
首先给出官方Github链接:GitHub - svc-develop-team/so-vits-svc: SoftVC VITS Singing Voice Conversion
本项目为开源、离线的项目,SvcDevelopTeam的所有成员与本项目的所有开发者以及维护者(以下简称贡献者)对本项目没有控制力。本项目的贡献者从未向任何组织或个人提供包括但不限于数据集提取、数据集加工、算力支持、训练支持、推理等一切形式的帮助;本项目的贡献者不知晓也无法知晓使用者使用该项目的用途。故一切基于本项目训练的AI模型和合成的音频都与本项目贡献者无关。一切由此造成的问题由使用者自行承担。
此项目完全离线运行,不能收集任何用户信息或获取用户输入数据。因此,这个项目的贡献者不知道所有的用户输入和模型,因此不负责任何用户输入。
本项目只是一个框架项目,本身并没有语音合成的功能,所有的功能都需要用户自己训练模型。同时,这个项目没有任何模型,任何二次分发的项目都与这个项目的贡献者无关。
两点强烈建议:
1、使用Linux系统(Windows也可以,但是略麻烦)
2、GPU的显存最好在12G以上(自己电脑显存不够的话可以使用云服务器,Colab或者Autodl等都可以)
训练Sovits的时候,需要一些原始音频数据,比如你想训练AI陈奕迅,那你就得获取陈奕迅的音频数据。B站有那种歌手歌曲合集的视频,可以一次性下载很多首歌,不用一首一首的下载,所以我的所有数据都是从B站获取的,当然别的渠道也可以,只要是WAV格式的都行。其他格式的音频数据也可以,但是需要借助代码或者工具来转换以下,略麻烦,不推荐。
首先打开B站,搜索XX歌手歌曲合集,点进去,选中红框内的链接复制下来。图片不让放。。这个很简单,有没有无所谓了~
- import os
- import subprocess
- import shutil
-
- # 视频链接列表
- video_urls = ["https://www.bilibili.com/video/BV1Gt411U73U"]
-
- # 视频保存的目录
- output_directory = "videos/eason"
-
-
- for url in video_urls:
- # 构建yt-dlp命令
- command = [
- "yt-dlp",
- "-o", os.path.join(output_directory, "%(title)s.%(ext)s"), # 输出路径
- url # 要下载的视频链接
- ]
-
- # 执行yt-dlp命令
- subprocess.run(command, check=True)
-
video_urls里面放入上面复制的链接就可以了,这里可以放多个链接,用逗号隔开就好。Video/eason是存放视频文件的地方,可以自定义。
需要训练的数据是音频数据,所以还要将上面的视频数据给分离一下,分成音频和视频。
- import os
- import moviepy.editor as mp
- from pydub import AudioSegment
- from multiprocessing import Pool
-
- def process_video(filename):
- if filename.endswith('.mp4'):
- # 读取视频文件
- video = mp.VideoFileClip(os.path.join(input_video_directory, filename))
-
- # 创建音频文件
- audio = video.audio
- audio_filename = os.path.splitext(filename)[0] + '.wav'
- audio.write_audiofile(os.path.join(output_audio_directory, audio_filename))
-
- # 创建无音频的视频文件
- video_without_audio = video.without_audio()
- video_filename = os.path.splitext(filename)[0] + '_no_audio.mp4'
- video_without_audio.write_videofile(os.path.join(output_video_directory, video_filename))
-
- # 视频输入和输出目录
- input_video_directory = 'video/eason'
- output_video_directory = 'audio_video/video'
-
- # 音频输出目录
- output_audio_directory = 'audio_video/audio'
- # 创建一个处理器池
- pool = Pool()
-
- # 使用多进程处理视频文件
- pool.map(process_video, os.listdir(input_video_directory))
-
- pool.close()
- pool.join()
这个input_video_directory就是第一步从B站下载到的视频的存放文件夹,output_video_directory是分离后的视频存放文件地址,output_audio_directory是音频存放地址,后续训练我们只用到output_audio_directory。
如果运行以后出现"no module named xx",那就是xx包没有安装,直接pip install xx -i 清华源就好。
第二步获取到的音频数据是人声和背景声,比如钢琴、小提琴和吉他声等。为了获得纯净的人声,需要利用算法将它们分开。
- import os
- os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
-
- from spleeter.separator import Separator
- import soundfile as sf
-
- def process_folder(input_folder_path, vocals_folder_path, accompaniment_folder_path):
- # 使用预训练模型 'spleeter:2stems' 进行声音分离
- separator = Separator('spleeter:2stems')
-
- # 获取文件夹中所有.wav文件的路径
- file_paths = [os.path.join(input_folder_path, f) for f in os.listdir(input_folder_path) if f.endswith('.wav')]
-
- # 逐个处理音频文件
- for file_path in file_paths:
- # 加载音频文件
- audio_data, sample_rate = sf.read(file_path)
-
- # 分离音频文件
- prediction = separator.separate(audio_data)
-
- # 获取音频文件名(不含后缀)
- file_name = os.path.splitext(os.path.basename(file_path))[0]
-
- # 保存人声到特定的文件夹
- sf.write(os.path.join(vocals_folder_path, file_name + '_vocals.wav'), prediction['vocals'], sample_rate)
-
- # 保存伴奏到特定的文件夹
- sf.write(os.path.join(accompaniment_folder_path, file_name + '_accompaniment.wav'), prediction['accompaniment'], sample_rate)
-
- # 使用你的音频文件夹路径替换下面的路径
- process_folder('audio_video/audio', 'vocals', 'accompaniment')
说明一下,process_folder函数里面第一个参数是第二步获取到的audio文件夹的地址,vocals是人声存放地址,这个就是我们的初始数据,accompaniment存放的是背景声,这个虽然训练用不到,但是后面会用到,不要删掉了。
一首歌通常4分钟左右,但是如果将整首歌直接送到模型,大概率会爆显存,所以现在把每一首歌切成很多个片段,每个片段长度在5-15秒左右,根据自己GPU显存来确定,我这里选择每段切成10s。
- import os
- import wave
- import audioop
-
- input_folder = "vocals"
- output_folder = "eason"
-
- if not os.path.exists(output_folder):
- os.makedirs(output_folder)
-
- for audio_file in os.listdir(input_folder):
- if audio_file.endswith('.wav'):
- audio_path = os.path.join(input_folder, audio_file)
-
- with wave.open(audio_path, 'rb') as audio:
- params = audio.getparams()
- frames_per_slice = params.framerate * 8 # 15 seconds of frames
-
- for i in range(0, params.nframes, frames_per_slice):
- audio.setpos(i)
- frames = audio.readframes(frames_per_slice)
-
- # If the audio is stereo, we need to half the slice size because it contains two channels
- if params.nchannels == 2:
- frames = audioop.tomono(frames, params.sampwidth, 0.5, 0.5)
-
- slice_file_name = f"{audio_file.split('.wav')[0]}_slice_{i//frames_per_slice}.wav"
- slice_path = os.path.join(output_folder, slice_file_name)
-
- with wave.open(slice_path, 'wb') as slice:
- slice.setnchannels(1 if params.nchannels == 2 else params.nchannels)
- slice.setsampwidth(params.sampwidth)
- slice.setframerate(params.framerate)
- slice.writeframes(frames)
这里面,input_folder是第三步人声的文件夹地址,output_folder是切片以后的声音片段文件夹的地址,建议将output_folder命名为歌手英文名。
上面的是我自己写的一些小工具,下面接着官方教程。
hubert_base.pt是声音编码器文件,把它下载下来将文件名改为checkpoint_best_legacy_500.pt
后,放在pretrain
目录下。
clean_G_320000.pth和clean_G_320000.pth是预训练底膜文件,分别改名成G_0.pth和D_0.pth文件放在logs/44k下面,PS这俩玩意找了半天才从huffingface找到,之前用的其他人的底膜,训练出来的电音小王子把我给整麻了。
model_0.pt是扩散模型预训练文件,放在logs/44k/diffusion下面,同样在huffingface找到了,huffingfaceNB!!!!!!!
链接:https://pan.baidu.com/s/1zhoqdZtY7ELmQLd0ZEzd0g?pwd=vda8
提取码:vda8
--来自百度网盘超级会员V4的分享
命令行切到so-vits-svc-4.1-Stable文件夹,然后运行resample.py
- cd so-vits-svc-4.1-Stable
-
- python resample.py
python preprocess_flist_config.py --speech_encoder vec768l12
运行完成后会生成config.json和diffusion.yaml文件夹,需要进行一些修改,搬运下官方解释:
cache_all_data
:加载所有数据集到内存中,某些平台的硬盘IO过于低下、同时内存容量 远大于 数据集体积时可以启用
duration
:训练时音频切片时长,可根据显存大小调整,注意,该值必须小于训练集内音频的最短时间!
batch_size
:单次训练加载到GPU的数据量,调整到低于显存容量的大小即可
timesteps
: 扩散模型总步数,默认为1000.
k_step_max
: 训练时可仅训练k_step_max
步扩散以节约训练时间,注意,该值必须小于timesteps
,0为训练整个扩散模型,注意,如果不训练整个扩散模型将无法使用仅扩散模型推理!
json文件夹可以用记事本打开
keep_ckpts
:训练时保留最后几个模型,0
为保留所有,默认只保留最后3
个
all_in_mem
:加载所有数据集到内存中,某些平台的硬盘IO过于低下、同时内存容量 远大于 数据集体积时可以启用
batch_size
:单次训练加载到GPU的数据量,调整到低于显存容量的大小即可
vocoder_name
: 选择一种声码器,默认为nsf-hifigan
.
python preprocess_hubert_f0.py --f0_predictor dio
这个过程比较缓慢,需要耐心等待。此外,最好保持硬盘内存剩余容量在10G以上。
python train.py -c configs/config.json -m 44k
这里其实还有个扩散模型训练,为了省事就只训练主模型。
模型训练结束后,模型文件保存在logs/44k
目录下,扩散模型在logs/44k/diffusion
下
python inference_main.py -m "logs/44k/G_30400.pth" -c "configs/config.json" -n "君の知らない物語-src.wav" -t 0 -s "nen"
logs/44k/G_30400.pth是训练出来的权重,根据自己训练结果调整
君の知らない物語-src.wav 是需要换声的音频
最后一个参数nen是你需要换声的对象的名字,与之前的纯净人声的文件夹名字一致,比如这里就是eason,需要注意的是我这里只同时训练了一个歌手,多个歌手需要将不同歌手切片后的声音片段放在不用文件夹里面,并且需要用不用的文件名区分,比如周杰伦可以用Jay来命名。
注意!!!!如果使用whisper-ppg
声音编码器进行推理,需要将--clip
设置为25,-lg
设置为1。否则将无法正常推理。
推理结果会放在results文件夹里面,一首歌的结果可能会分成两片或更多,自己合成一下,然后跟之前accompaniment文件夹里面对应的背景声合成一下就完事了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。