mirror of
https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git
synced 2026-01-21 03:20:23 +00:00
Compare commits
66 Commits
2.0.230528
...
2.0.230618
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1ace168fa | ||
|
|
41c345557f | ||
|
|
7fbfc60fcb | ||
|
|
e4417ce82f | ||
|
|
125a0a7b02 | ||
|
|
a42330f0ae | ||
|
|
bc5df2ff8e | ||
|
|
0812020c90 | ||
|
|
66667c8f50 | ||
|
|
a7647e4094 | ||
|
|
f92a923487 | ||
|
|
0db402c312 | ||
|
|
6ca9c853b0 | ||
|
|
44426b18b8 | ||
|
|
e7f204b32e | ||
|
|
75264d09b6 | ||
|
|
cbd29350fe | ||
|
|
a9a77f2556 | ||
|
|
ec0c39d9bc | ||
|
|
9253948f0d | ||
|
|
c5758a89db | ||
|
|
28383fbeee | ||
|
|
846be17351 | ||
|
|
4945fba0a3 | ||
|
|
602ee19cf9 | ||
|
|
0eb6bb67be | ||
|
|
a071f1e089 | ||
|
|
147d3c83b7 | ||
|
|
75d7c03d41 | ||
|
|
f349adc9df | ||
|
|
eb1a88cf7e | ||
|
|
4de5d0d551 | ||
|
|
c74727d487 | ||
|
|
78c88a4f75 | ||
|
|
d963c29fec | ||
|
|
986d92b261 | ||
|
|
e1f084177d | ||
|
|
fcce61b27f | ||
|
|
ff2793249d | ||
|
|
ec83e10b8f | ||
|
|
fada942ecd | ||
|
|
1b307a4222 | ||
|
|
b28f98fed3 | ||
|
|
297809bdfd | ||
|
|
692c245fad | ||
|
|
52c97ed464 | ||
|
|
6f1bc7d683 | ||
|
|
9ff976b155 | ||
|
|
f358fe7242 | ||
|
|
05b5af7c8c | ||
|
|
b7337d7bf1 | ||
|
|
99404baf94 | ||
|
|
a94c8e3a69 | ||
|
|
bf11700125 | ||
|
|
95cd1759c5 | ||
|
|
80929e472e | ||
|
|
a02019e428 | ||
|
|
4c28652ed9 | ||
|
|
c2f402d7d1 | ||
|
|
a68037be3c | ||
|
|
fa97c3f8bd | ||
|
|
89afd017ba | ||
|
|
5284e38c3d | ||
|
|
24f2ad44ea | ||
|
|
69071119a9 | ||
|
|
86b086e393 |
@@ -1,3 +1,24 @@
|
||||
### 20230618更新
|
||||
- v2增加32k和48k两个新预训练模型
|
||||
- 修复非f0模型推理报错
|
||||
- 对于超过一小时的训练集的索引建立环节,自动kmeans缩小特征处理以加速索引训练、加入和查询
|
||||
- 附送一个人声转吉他玩具仓库
|
||||
- 数据处理剔除异常值切片
|
||||
- onnx导出选项卡
|
||||
|
||||
失败的实验:
|
||||
- ~~特征检索增加时序维度:寄,没啥效果~~
|
||||
- ~~特征检索增加PCAR降维可选项:寄,数据大用kmeans缩小数据量,数据小降维操作耗时比省下的匹配耗时还多~~
|
||||
- ~~支持onnx推理(附带仅推理的小压缩包):寄,生成nsf还是需要pytorch~~
|
||||
- ~~训练时在音高、gender、eq、噪声等方面对输入进行随机增强:寄,没啥效果~~
|
||||
|
||||
todolist:
|
||||
- 接入小型声码器调研
|
||||
- 训练集音高识别支持crepe
|
||||
- crepe的精度支持和RVC-config同步
|
||||
- 对接F0编辑器
|
||||
|
||||
|
||||
### 20230528更新
|
||||
- 增加v2的jupyter notebook,韩文changelog,增加一些环境依赖
|
||||
- 增加呼吸、清辅音、齿音保护模式
|
||||
@@ -7,15 +28,6 @@
|
||||
- 人声伴奏分离、推理批量导出增加音频导出格式选项
|
||||
- 废弃32k模型的训练
|
||||
|
||||
todolist:
|
||||
- 特征检索增加时序维度
|
||||
- 特征检索增加pre-kmeans可选项
|
||||
- 特征检索增加PCAR降维可选项
|
||||
- 支持onnx推理(附带仅推理的小压缩包)
|
||||
- 训练时在音高、gender、eq、噪声等方面对输入进行随机增强
|
||||
- 补全v2版本的48k预训练模型
|
||||
|
||||
|
||||
### 20230513更新
|
||||
- 清除一键包内部老版本runtime内残留的infer_pack和uvr5_pack
|
||||
- 修复训练集预处理伪多进程的bug
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
### 2023-06-18
|
||||
- New pretrained v2 models: 32k and 48k
|
||||
- Fix non-f0 model inference errors
|
||||
- For training-set exceeding 1 hour, do automatic minibatch-kmeans to reduce feature shape, so that index training, adding, and searching will be much faster.
|
||||
- Provide a toy vocal2guitar huggingface space
|
||||
- Auto delete outlier short cut training-set audios
|
||||
- Onnx export tab
|
||||
|
||||
Failed experiments:
|
||||
- ~~Feature retrieval: add temporal feature retrieval: not effective~~
|
||||
- ~~Feature retrieval: add PCAR dimensionality reduction: searching is even slower~~
|
||||
- ~~Random data augmentation when training: not effective~~
|
||||
|
||||
todolist:
|
||||
- Vocos-RVC (tiny vocoder)
|
||||
- Crepe support for training
|
||||
- Half precision crepe inference
|
||||
- F0 editor support
|
||||
|
||||
### 2023-05-28
|
||||
- Add v2 jupyter notebook, korean changelog, fix some environment requirments
|
||||
- Add voiceless consonant and breath protection mode
|
||||
@@ -5,15 +24,7 @@
|
||||
- UVR5 vocal separation: support dereverb models and de-echo models
|
||||
- Add experiment name and version on the name of index
|
||||
- Support users to manually select export format of output audios when batch voice conversion processing and UVR5 vocal separation
|
||||
- 32k model training is no more supported
|
||||
|
||||
todolist:
|
||||
- Feature retrieval: add temporal feature retrieval
|
||||
- Feature retrieval: add pre-kmeans option
|
||||
- Feature retrieval: add PCAR dimensionality reduction
|
||||
- Add onnx inference support
|
||||
- Random data augmentation when training: pitch, gender, eq, noise
|
||||
- Add v2 version pretrained-models
|
||||
- v1 32k model training is no more supported
|
||||
|
||||
### 2023-05-13
|
||||
- Clear the redundant codes in the old version of runtime in the one-click-package: infer_pack and uvr5_pack
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
### 2023년 5월 28일 업데이트
|
||||
|
||||
- v2 jupyter notebook 추가, 한국어 업데이트 로그 추가, 의존성 모듈 일부 수정.
|
||||
- 무성음 및 숨소리 보호 모드 추가.
|
||||
- crepe-full pitch 감지 지원.
|
||||
- UVR5 보컬 분리: 디버브 및 디-에코 모델 지원.
|
||||
- index 이름에 experiment 이름과 버전 추가.
|
||||
- 배치 음성 변환 처리 및 UVR5 보컬 분리 시, 사용자가 수동으로 출력 오디오의 내보내기(export) 형식을 선택할 수 있도록 지원.
|
||||
- 32k 훈련 모델 지원 종료.
|
||||
|
||||
추후 업데이트 목록:
|
||||
|
||||
- 특징 검색: 시간적 특징 검색 추가.
|
||||
- 특징 검색: pre-kmeans 옵션 추가.
|
||||
- 특징 검색: PCAR 차원 축소 추가.
|
||||
- onnx 추론 지원 추가.
|
||||
- 학습 시 랜덤 데이터 증강: 음고, 성별, eq, 잡음.
|
||||
- v2 버전 사전 훈련된 모델 추가.
|
||||
|
||||
### 2023년 5월 13일 업데이트
|
||||
|
||||
- 원클릭 패키지의 이전 버전 런타임 내, 불필요한 코드(infer_pack 및 uvr5_pack) 제거.
|
||||
@@ -19,14 +38,7 @@
|
||||
- 추론 전, 1을 초과하는 과도한 볼륨 제한.
|
||||
- 데이터 전처리 매개변수 미세 조정.
|
||||
|
||||
추후 업데이트 목록:
|
||||
|
||||
- 일괄 음성 변환 처리 시, 사용자가 수동으로 출력 오디오의 내보내기 형식 선택기능 지원.
|
||||
- Crepe 피치 감지 지원.
|
||||
|
||||
이전 변경 로그:
|
||||
|
||||
### 2023년 4월 9일
|
||||
### 2023년 4월 9일 업데이트
|
||||
|
||||
- GPU 이용률 향상을 위해 훈련 파라미터 수정: A100은 25%에서 약 90%로 증가, V100: 50%에서 약 90%로 증가, 2060S: 60%에서 약 85%로 증가, P40: 25%에서 약 95%로 증가.
|
||||
훈련 속도가 크게 향상.
|
||||
@@ -53,17 +65,13 @@
|
||||
- 일부 오디오 형식에 대한 UVR5 보컬 동반 분리에서의 버그 수정.
|
||||
- 실시간 음성 변경 미니-GUI는 이제 non-40k 및 non-lazy 피치 모델을 지원합니다.
|
||||
|
||||
### 미래 계획
|
||||
### 추후 계획
|
||||
|
||||
Features:
|
||||
|
||||
- 각 에폭 저장에 대해 소형 모델 추출 옵션 추가.
|
||||
- 추론 중 지정된 경로로 추가 mp3 내보내기 옵션 추가.
|
||||
- 다중 사용자 훈련 탭 지원.(최대 4명)
|
||||
|
||||
Base model:
|
||||
|
||||
- 호흡 wav 파일을 수집하여 훈련 데이터셋에 추가, 이로써 왜곡된 호흡 소리 문제를 해결.
|
||||
- 현재 확장된 노래 데이터셋을 이용하여 기본 모델을 훈련 중이며, 이는 미래에 발표될 예정.
|
||||
- Discriminator 업그레이드.
|
||||
- self-supervised 특성 구조 업그레이드.
|
||||
- 훈련 데이터셋에 숨소리 wav 파일을 추가하여, 보컬의 호흡이 노이즈로 변환되는 문제 수정.
|
||||
- 보컬 훈련 세트의 기본 모델을 추가하기 위한 작업을 진행중이며, 이는 향후에 발표될 예정.
|
||||
|
||||
31
MDXNet.py
31
MDXNet.py
@@ -86,7 +86,12 @@ def get_models(device, dim_f, dim_t, n_fft):
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
cpu = torch.device("cpu")
|
||||
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
||||
if torch.cuda.is_available():
|
||||
device = torch.device("cuda:0")
|
||||
elif torch.backends.mps.is_available():
|
||||
device = torch.device("mps")
|
||||
else:
|
||||
device = torch.device("cpu")
|
||||
|
||||
|
||||
class Predictor:
|
||||
@@ -201,10 +206,26 @@ class Predictor:
|
||||
mix = mix.T
|
||||
sources = self.demix(mix.T)
|
||||
opt = sources[0].T
|
||||
sf.write(
|
||||
"%s/%s_main_vocal.%s" % (vocal_root, basename, format), mix - opt, rate
|
||||
)
|
||||
sf.write("%s/%s_others.%s" % (others_root, basename, format), opt, rate)
|
||||
if format in ["wav", "flac"]:
|
||||
sf.write(
|
||||
"%s/%s_main_vocal.%s" % (vocal_root, basename, format), mix - opt, rate
|
||||
)
|
||||
sf.write("%s/%s_others.%s" % (others_root, basename, format), opt, rate)
|
||||
else:
|
||||
path_vocal = "%s/%s_main_vocal.wav" % (vocal_root, basename)
|
||||
path_other = "%s/%s_others.wav" % (others_root, basename)
|
||||
sf.write(path_vocal, mix - opt, rate)
|
||||
sf.write(path_other, opt, rate)
|
||||
if os.path.exists(path_vocal):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path_vocal, path_vocal[:-4] + ".%s" % format)
|
||||
)
|
||||
if os.path.exists(path_other):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path_other, path_other[:-4] + ".%s" % format)
|
||||
)
|
||||
|
||||
|
||||
class MDXNetDereverb:
|
||||
|
||||
11
README.md
11
README.md
@@ -21,6 +21,9 @@
|
||||
|
||||
[**English**](./docs/README.en.md) | [**中文简体**](./README.md) | [**日本語**](./docs/README.ja.md) | [**한국어**](./docs/README.ko.md) ([**韓國語**](./docs/README.ko.han.md))
|
||||
|
||||
:fire: 使用了RVC变声器训练的人声转木吉他模型在线demo:fire: :https://huggingface.co/spaces/lj1995/vocal2guitar
|
||||
|
||||
:fire: RVC人声转吉他效果展示视频:fire: :https://www.bilibili.com/video/BV19W4y1D7tT/
|
||||
|
||||
> 点此查看我们的[演示视频](https://www.bilibili.com/video/BV1pm4y1z7Gm/) !
|
||||
|
||||
@@ -64,14 +67,6 @@ poetry install
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**注意**
|
||||
1. 英特尔`MacOS`下使用pip安装`faiss 1.7.0`以上版本会导致抛出段错误,在手动安装时,如需安装最新版,请使用`conda`;如只能使用`pip`,请指定使用`1.7.0`版本。
|
||||
2. `MacOS`下如`faiss`安装失败,可尝试通过`brew`安装`Swig`
|
||||
|
||||
```bash
|
||||
brew install swig
|
||||
```
|
||||
|
||||
## 其他预模型准备
|
||||
RVC需要其他一些预模型来推理和训练。
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"!apt-get -y install build-essential python3-dev ffmpeg\n",
|
||||
"!pip3 install --upgrade setuptools wheel\n",
|
||||
"!pip3 install --upgrade pip\n",
|
||||
"!pip3 install faiss-gpu fairseq gradio ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
|
||||
"!pip3 install faiss-cpu==1.7.2 fairseq gradio==3.14.0 ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "wjddIFr1oS3W"
|
||||
@@ -378,4 +378,4 @@
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"!apt-get -y install build-essential python3-dev ffmpeg\n",
|
||||
"!pip3 install --upgrade setuptools wheel\n",
|
||||
"!pip3 install --upgrade pip\n",
|
||||
"!pip3 install faiss-gpu fairseq gradio ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
|
||||
"!pip3 install faiss-cpu==1.7.2 fairseq gradio==3.14.0 ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -47,11 +47,12 @@
|
||||
"source": [
|
||||
"#@title 克隆仓库\n",
|
||||
"\n",
|
||||
"!mkdir Retrieval-based-Voice-Conversion-WebUI\n",
|
||||
"%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
|
||||
"!git init\n",
|
||||
"!git remote add origin https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git\n",
|
||||
"!git fetch origin cfd984812804ddc9247d65b14c82cd32e56c1133 --depth=1 \n",
|
||||
"!git reset --hard FETCH_HEAD\n",
|
||||
"%cd /content/Retrieval-based-Voice-Conversion-WebUI"
|
||||
"!git reset --hard FETCH_HEAD"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
322
app.py
Normal file
322
app.py
Normal file
@@ -0,0 +1,322 @@
|
||||
import io
|
||||
import os
|
||||
import torch
|
||||
|
||||
# os.system("wget -P cvec/ https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt")
|
||||
import gradio as gr
|
||||
import librosa
|
||||
import numpy as np
|
||||
import soundfile
|
||||
import logging
|
||||
from fairseq import checkpoint_utils
|
||||
from my_utils import load_audio
|
||||
from vc_infer_pipeline import VC
|
||||
import traceback
|
||||
from config import Config
|
||||
from infer_pack.models import (
|
||||
SynthesizerTrnMs256NSFsid,
|
||||
SynthesizerTrnMs256NSFsid_nono,
|
||||
SynthesizerTrnMs768NSFsid,
|
||||
SynthesizerTrnMs768NSFsid_nono,
|
||||
)
|
||||
from i18n import I18nAuto
|
||||
|
||||
logging.getLogger("numba").setLevel(logging.WARNING)
|
||||
logging.getLogger("markdown_it").setLevel(logging.WARNING)
|
||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||
logging.getLogger("matplotlib").setLevel(logging.WARNING)
|
||||
|
||||
i18n = I18nAuto()
|
||||
i18n.print()
|
||||
|
||||
config = Config()
|
||||
|
||||
weight_root = "weights"
|
||||
weight_uvr5_root = "uvr5_weights"
|
||||
index_root = "logs"
|
||||
names = []
|
||||
hubert_model = None
|
||||
for name in os.listdir(weight_root):
|
||||
if name.endswith(".pth"):
|
||||
names.append(name)
|
||||
index_paths = []
|
||||
for root, dirs, files in os.walk(index_root, topdown=False):
|
||||
for name in files:
|
||||
if name.endswith(".index") and "trained" not in name:
|
||||
index_paths.append("%s/%s" % (root, name))
|
||||
|
||||
|
||||
def get_vc(sid):
|
||||
global n_spk, tgt_sr, net_g, vc, cpt, version
|
||||
if sid == "" or sid == []:
|
||||
global hubert_model
|
||||
if hubert_model != None: # 考虑到轮询, 需要加个判断看是否 sid 是由有模型切换到无模型的
|
||||
print("clean_empty_cache")
|
||||
del net_g, n_spk, vc, hubert_model, tgt_sr # ,cpt
|
||||
hubert_model = net_g = n_spk = vc = hubert_model = tgt_sr = None
|
||||
if torch.cuda.is_available():
|
||||
torch.cuda.empty_cache()
|
||||
###楼下不这么折腾清理不干净
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
version = cpt.get("version", "v1")
|
||||
if version == "v1":
|
||||
if if_f0 == 1:
|
||||
net_g = SynthesizerTrnMs256NSFsid(
|
||||
*cpt["config"], is_half=config.is_half
|
||||
)
|
||||
else:
|
||||
net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
|
||||
elif version == "v2":
|
||||
if if_f0 == 1:
|
||||
net_g = SynthesizerTrnMs768NSFsid(
|
||||
*cpt["config"], is_half=config.is_half
|
||||
)
|
||||
else:
|
||||
net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
|
||||
del net_g, cpt
|
||||
if torch.cuda.is_available():
|
||||
torch.cuda.empty_cache()
|
||||
cpt = None
|
||||
return {"visible": False, "__type__": "update"}
|
||||
person = "%s/%s" % (weight_root, sid)
|
||||
print("loading %s" % person)
|
||||
cpt = torch.load(person, map_location="cpu")
|
||||
tgt_sr = cpt["config"][-1]
|
||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
version = cpt.get("version", "v1")
|
||||
if version == "v1":
|
||||
if if_f0 == 1:
|
||||
net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=config.is_half)
|
||||
else:
|
||||
net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
|
||||
elif version == "v2":
|
||||
if if_f0 == 1:
|
||||
net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=config.is_half)
|
||||
else:
|
||||
net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
|
||||
del net_g.enc_q
|
||||
print(net_g.load_state_dict(cpt["weight"], strict=False))
|
||||
net_g.eval().to(config.device)
|
||||
if config.is_half:
|
||||
net_g = net_g.half()
|
||||
else:
|
||||
net_g = net_g.float()
|
||||
vc = VC(tgt_sr, config)
|
||||
n_spk = cpt["config"][-3]
|
||||
return {"visible": True, "maximum": n_spk, "__type__": "update"}
|
||||
|
||||
|
||||
def load_hubert():
|
||||
global hubert_model
|
||||
models, _, _ = checkpoint_utils.load_model_ensemble_and_task(
|
||||
["hubert_base.pt"],
|
||||
suffix="",
|
||||
)
|
||||
hubert_model = models[0]
|
||||
hubert_model = hubert_model.to(config.device)
|
||||
if config.is_half:
|
||||
hubert_model = hubert_model.half()
|
||||
else:
|
||||
hubert_model = hubert_model.float()
|
||||
hubert_model.eval()
|
||||
|
||||
|
||||
def vc_single(
|
||||
sid,
|
||||
input_audio_path,
|
||||
f0_up_key,
|
||||
f0_file,
|
||||
f0_method,
|
||||
file_index,
|
||||
file_index2,
|
||||
# file_big_npy,
|
||||
index_rate,
|
||||
filter_radius,
|
||||
resample_sr,
|
||||
rms_mix_rate,
|
||||
protect,
|
||||
): # spk_item, input_audio0, vc_transform0,f0_file,f0method0
|
||||
global tgt_sr, net_g, vc, hubert_model, version
|
||||
if input_audio_path is None:
|
||||
return "You need to upload an audio", None
|
||||
f0_up_key = int(f0_up_key)
|
||||
try:
|
||||
audio = input_audio_path[1] / 32768.0
|
||||
if len(audio.shape) == 2:
|
||||
audio = np.mean(audio, -1)
|
||||
audio = librosa.resample(audio, orig_sr=input_audio_path[0], target_sr=16000)
|
||||
audio_max = np.abs(audio).max() / 0.95
|
||||
if audio_max > 1:
|
||||
audio /= audio_max
|
||||
times = [0, 0, 0]
|
||||
if hubert_model == None:
|
||||
load_hubert()
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
file_index = (
|
||||
(
|
||||
file_index.strip(" ")
|
||||
.strip('"')
|
||||
.strip("\n")
|
||||
.strip('"')
|
||||
.strip(" ")
|
||||
.replace("trained", "added")
|
||||
)
|
||||
if file_index != ""
|
||||
else file_index2
|
||||
) # 防止小白写错,自动帮他替换掉
|
||||
# file_big_npy = (
|
||||
# file_big_npy.strip(" ").strip('"').strip("\n").strip('"').strip(" ")
|
||||
# )
|
||||
audio_opt = vc.pipeline(
|
||||
hubert_model,
|
||||
net_g,
|
||||
sid,
|
||||
audio,
|
||||
input_audio_path,
|
||||
times,
|
||||
f0_up_key,
|
||||
f0_method,
|
||||
file_index,
|
||||
# file_big_npy,
|
||||
index_rate,
|
||||
if_f0,
|
||||
filter_radius,
|
||||
tgt_sr,
|
||||
resample_sr,
|
||||
rms_mix_rate,
|
||||
version,
|
||||
protect,
|
||||
f0_file=f0_file,
|
||||
)
|
||||
if resample_sr >= 16000 and tgt_sr != resample_sr:
|
||||
tgt_sr = resample_sr
|
||||
index_info = (
|
||||
"Using index:%s." % file_index
|
||||
if os.path.exists(file_index)
|
||||
else "Index not used."
|
||||
)
|
||||
return "Success.\n %s\nTime:\n npy:%ss, f0:%ss, infer:%ss" % (
|
||||
index_info,
|
||||
times[0],
|
||||
times[1],
|
||||
times[2],
|
||||
), (tgt_sr, audio_opt)
|
||||
except:
|
||||
info = traceback.format_exc()
|
||||
print(info)
|
||||
return info, (None, None)
|
||||
|
||||
|
||||
app = gr.Blocks()
|
||||
with app:
|
||||
with gr.Tabs():
|
||||
with gr.TabItem("在线demo"):
|
||||
gr.Markdown(
|
||||
value="""
|
||||
RVC 在线demo
|
||||
"""
|
||||
)
|
||||
sid = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names))
|
||||
with gr.Column():
|
||||
spk_item = gr.Slider(
|
||||
minimum=0,
|
||||
maximum=2333,
|
||||
step=1,
|
||||
label=i18n("请选择说话人id"),
|
||||
value=0,
|
||||
visible=False,
|
||||
interactive=True,
|
||||
)
|
||||
sid.change(
|
||||
fn=get_vc,
|
||||
inputs=[sid],
|
||||
outputs=[spk_item],
|
||||
)
|
||||
gr.Markdown(
|
||||
value=i18n("男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ")
|
||||
)
|
||||
vc_input3 = gr.Audio(label="上传音频(长度小于90秒)")
|
||||
vc_transform0 = gr.Number(label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0)
|
||||
f0method0 = gr.Radio(
|
||||
label=i18n("选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU"),
|
||||
choices=["pm", "harvest", "crepe"],
|
||||
value="pm",
|
||||
interactive=True,
|
||||
)
|
||||
filter_radius0 = gr.Slider(
|
||||
minimum=0,
|
||||
maximum=7,
|
||||
label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
|
||||
value=3,
|
||||
step=1,
|
||||
interactive=True,
|
||||
)
|
||||
with gr.Column():
|
||||
file_index1 = gr.Textbox(
|
||||
label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
|
||||
value="",
|
||||
interactive=False,
|
||||
visible=False,
|
||||
)
|
||||
file_index2 = gr.Dropdown(
|
||||
label=i18n("自动检测index路径,下拉式选择(dropdown)"),
|
||||
choices=sorted(index_paths),
|
||||
interactive=True,
|
||||
)
|
||||
index_rate1 = gr.Slider(
|
||||
minimum=0,
|
||||
maximum=1,
|
||||
label=i18n("检索特征占比"),
|
||||
value=0.88,
|
||||
interactive=True,
|
||||
)
|
||||
resample_sr0 = gr.Slider(
|
||||
minimum=0,
|
||||
maximum=48000,
|
||||
label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
|
||||
value=0,
|
||||
step=1,
|
||||
interactive=True,
|
||||
)
|
||||
rms_mix_rate0 = gr.Slider(
|
||||
minimum=0,
|
||||
maximum=1,
|
||||
label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
|
||||
value=1,
|
||||
interactive=True,
|
||||
)
|
||||
protect0 = gr.Slider(
|
||||
minimum=0,
|
||||
maximum=0.5,
|
||||
label=i18n("保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"),
|
||||
value=0.33,
|
||||
step=0.01,
|
||||
interactive=True,
|
||||
)
|
||||
f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"))
|
||||
but0 = gr.Button(i18n("转换"), variant="primary")
|
||||
vc_output1 = gr.Textbox(label=i18n("输出信息"))
|
||||
vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
|
||||
but0.click(
|
||||
vc_single,
|
||||
[
|
||||
spk_item,
|
||||
vc_input3,
|
||||
vc_transform0,
|
||||
f0_file,
|
||||
f0method0,
|
||||
file_index1,
|
||||
file_index2,
|
||||
# file_big_npy1,
|
||||
index_rate1,
|
||||
filter_radius0,
|
||||
resample_sr0,
|
||||
rms_mix_rate0,
|
||||
protect0,
|
||||
],
|
||||
[vc_output1, vc_output2],
|
||||
)
|
||||
|
||||
|
||||
app.launch()
|
||||
46
configs/32k_v2.json
Normal file
46
configs/32k_v2.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"train": {
|
||||
"log_interval": 200,
|
||||
"seed": 1234,
|
||||
"epochs": 20000,
|
||||
"learning_rate": 1e-4,
|
||||
"betas": [0.8, 0.99],
|
||||
"eps": 1e-9,
|
||||
"batch_size": 4,
|
||||
"fp16_run": true,
|
||||
"lr_decay": 0.999875,
|
||||
"segment_size": 12800,
|
||||
"init_lr_ratio": 1,
|
||||
"warmup_epochs": 0,
|
||||
"c_mel": 45,
|
||||
"c_kl": 1.0
|
||||
},
|
||||
"data": {
|
||||
"max_wav_value": 32768.0,
|
||||
"sampling_rate": 32000,
|
||||
"filter_length": 1024,
|
||||
"hop_length": 320,
|
||||
"win_length": 1024,
|
||||
"n_mel_channels": 80,
|
||||
"mel_fmin": 0.0,
|
||||
"mel_fmax": null
|
||||
},
|
||||
"model": {
|
||||
"inter_channels": 192,
|
||||
"hidden_channels": 192,
|
||||
"filter_channels": 768,
|
||||
"n_heads": 2,
|
||||
"n_layers": 6,
|
||||
"kernel_size": 3,
|
||||
"p_dropout": 0,
|
||||
"resblock": "1",
|
||||
"resblock_kernel_sizes": [3,7,11],
|
||||
"resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
|
||||
"upsample_rates": [10,8,2,2],
|
||||
"upsample_initial_channel": 512,
|
||||
"upsample_kernel_sizes": [20,16,4,4],
|
||||
"use_spectral_norm": false,
|
||||
"gin_channels": 256,
|
||||
"spk_embed_dim": 109
|
||||
}
|
||||
}
|
||||
46
configs/48k_v2.json
Normal file
46
configs/48k_v2.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"train": {
|
||||
"log_interval": 200,
|
||||
"seed": 1234,
|
||||
"epochs": 20000,
|
||||
"learning_rate": 1e-4,
|
||||
"betas": [0.8, 0.99],
|
||||
"eps": 1e-9,
|
||||
"batch_size": 4,
|
||||
"fp16_run": true,
|
||||
"lr_decay": 0.999875,
|
||||
"segment_size": 11520,
|
||||
"init_lr_ratio": 1,
|
||||
"warmup_epochs": 0,
|
||||
"c_mel": 45,
|
||||
"c_kl": 1.0
|
||||
},
|
||||
"data": {
|
||||
"max_wav_value": 32768.0,
|
||||
"sampling_rate": 48000,
|
||||
"filter_length": 2048,
|
||||
"hop_length": 480,
|
||||
"win_length": 2048,
|
||||
"n_mel_channels": 128,
|
||||
"mel_fmin": 0.0,
|
||||
"mel_fmax": null
|
||||
},
|
||||
"model": {
|
||||
"inter_channels": 192,
|
||||
"hidden_channels": 192,
|
||||
"filter_channels": 768,
|
||||
"n_heads": 2,
|
||||
"n_layers": 6,
|
||||
"kernel_size": 3,
|
||||
"p_dropout": 0,
|
||||
"resblock": "1",
|
||||
"resblock_kernel_sizes": [3,7,11],
|
||||
"resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
|
||||
"upsample_rates": [12,10,2,2],
|
||||
"upsample_initial_channel": 512,
|
||||
"upsample_kernel_sizes": [24,20,4,4],
|
||||
"use_spectral_norm": false,
|
||||
"gin_channels": 256,
|
||||
"spk_embed_dim": 109
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,10 @@ An easy-to-use Voice Conversion framework based on VITS.<br><br>
|
||||
|
||||
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
|
||||
|
||||
:fire: A online demo using RVC that convert Vocal to Acoustic Guitar audio:fire: :https://huggingface.co/spaces/lj1995/vocal2guitar
|
||||
|
||||
:fire: Vocal2Guitar demo video:fire: :https://www.bilibili.com/video/BV19W4y1D7tT/
|
||||
|
||||
> Check our [Demo Video](https://www.bilibili.com/video/BV1pm4y1z7Gm/) here!
|
||||
|
||||
> Realtime Voice Conversion Software using RVC : [w-okada/voice-changer](https://github.com/w-okada/voice-changer)
|
||||
@@ -56,8 +60,6 @@ poetry install
|
||||
```
|
||||
You can also use pip to install the dependencies
|
||||
|
||||
**Notice**: `faiss 1.7.2` will raise Segmentation Fault: 11 under `MacOS`, please use `pip install faiss-cpu==1.7.0` if you use pip to install it manually.
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
@@ -61,8 +61,6 @@ poetry install
|
||||
|
||||
pipでも依存関係のインストールが可能です:
|
||||
|
||||
**注意**:`faiss 1.7.2`は`macOS`で`Segmentation Fault: 11`を起こすので、マニュアルインストールする場合は、 `pip install faiss-cpu==1.7.0`を実行してください。
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
@@ -58,8 +58,6 @@ poetry install
|
||||
```
|
||||
pip를 活用하여依存를 設置하여도 無妨합니다.
|
||||
|
||||
**公知**: `MacOS`에서 `faiss 1.7.2`를 使用하면 Segmentation Fault: 11 誤謬가 發生할 수 있습니다. 手動으로 pip를 使用하여 設置하는境遇 `pip install faiss-cpu==1.7.0`을 使用해야 합니다.
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
@@ -64,8 +64,6 @@ poetry install
|
||||
|
||||
pip를 활용하여 dependencies를 설치하여도 무방합니다.
|
||||
|
||||
**공지**: `MacOS`에서 `faiss 1.7.2`를 사용하면 Segmentation Fault: 11 오류가 발생할 수 있습니다. 수동으로 pip를 사용하여 설치하는 경우 `pip install faiss-cpu==1.7.0`을 사용해야 합니다.
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
@@ -86,7 +86,7 @@ class FeatureInput(object):
|
||||
# use 0 or 1
|
||||
f0_mel[f0_mel <= 1] = 1
|
||||
f0_mel[f0_mel > self.f0_bin - 1] = self.f0_bin - 1
|
||||
f0_coarse = np.rint(f0_mel).astype(np.int)
|
||||
f0_coarse = np.rint(f0_mel).astype(int)
|
||||
assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, (
|
||||
f0_coarse.max(),
|
||||
f0_coarse.min(),
|
||||
|
||||
@@ -63,6 +63,13 @@ def readwave(wav_path, normalize=False):
|
||||
|
||||
# HuBERT model
|
||||
printt("load model(s) from {}".format(model_path))
|
||||
# if hubert model is exist
|
||||
if os.access(model_path, os.F_OK) == False:
|
||||
printt(
|
||||
"Error: Extracting is shut down because %s does not exist, you may download it from https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main"
|
||||
% model_path
|
||||
)
|
||||
exit(0)
|
||||
models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
|
||||
[model_path],
|
||||
suffix="",
|
||||
|
||||
141
gui.py
141
gui.py
@@ -10,7 +10,9 @@
|
||||
增加无索引支持
|
||||
f0算法改harvest(怎么看就只有这个会影响CPU占用),但是不这么改效果不好
|
||||
"""
|
||||
import os, sys, traceback
|
||||
import os, sys, traceback, re
|
||||
|
||||
import json
|
||||
|
||||
now_dir = os.getcwd()
|
||||
sys.path.append(now_dir)
|
||||
@@ -27,6 +29,7 @@ import torch.nn.functional as F
|
||||
import torchaudio.transforms as tat
|
||||
import scipy.signal as signal
|
||||
|
||||
|
||||
# import matplotlib.pyplot as plt
|
||||
from infer_pack.models import (
|
||||
SynthesizerTrnMs256NSFsid,
|
||||
@@ -38,6 +41,7 @@ from i18n import I18nAuto
|
||||
|
||||
i18n = I18nAuto()
|
||||
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
current_dir = os.getcwd()
|
||||
|
||||
|
||||
class RVC:
|
||||
@@ -150,8 +154,12 @@ class RVC:
|
||||
assert feats.dim() == 1, feats.dim()
|
||||
feats = feats.view(1, -1)
|
||||
padding_mask = torch.BoolTensor(feats.shape).fill_(False)
|
||||
if Config.is_half:
|
||||
feats = feats.half()
|
||||
else:
|
||||
feats = feats.float()
|
||||
inputs = {
|
||||
"source": feats.half().to(device),
|
||||
"source": feats.to(device),
|
||||
"padding_mask": padding_mask.to(device),
|
||||
"output_layer": 9 if self.version == "v1" else 12,
|
||||
}
|
||||
@@ -245,7 +253,29 @@ class GUI:
|
||||
|
||||
self.launcher()
|
||||
|
||||
def load(self):
|
||||
input_devices, output_devices, _, _ = self.get_devices()
|
||||
try:
|
||||
with open("values1.json", "r") as j:
|
||||
data = json.load(j)
|
||||
except:
|
||||
with open("values1.json", "w") as j:
|
||||
data = {
|
||||
"pth_path": " ",
|
||||
"index_path": " ",
|
||||
"sg_input_device": input_devices[sd.default.device[0]],
|
||||
"sg_output_device": output_devices[sd.default.device[1]],
|
||||
"threhold": "-45",
|
||||
"pitch": "0",
|
||||
"index_rate": "0",
|
||||
"block_time": "1",
|
||||
"crossfade_length": "0.04",
|
||||
"extra_time": "1",
|
||||
}
|
||||
return data
|
||||
|
||||
def launcher(self):
|
||||
data = self.load()
|
||||
sg.theme("LightBlue3")
|
||||
input_devices, output_devices, _, _ = self.get_devices()
|
||||
layout = [
|
||||
@@ -254,26 +284,50 @@ class GUI:
|
||||
title=i18n("加载模型"),
|
||||
layout=[
|
||||
[
|
||||
sg.Input(default_text="hubert_base.pt", key="hubert_path"),
|
||||
sg.FileBrowse(i18n("Hubert模型")),
|
||||
],
|
||||
[
|
||||
sg.Input(default_text="TEMP\\atri.pth", key="pth_path"),
|
||||
sg.FileBrowse(i18n("选择.pth文件")),
|
||||
sg.Input(
|
||||
default_text="hubert_base.pt",
|
||||
key="hubert_path",
|
||||
disabled=True,
|
||||
),
|
||||
sg.FileBrowse(
|
||||
i18n("Hubert模型"),
|
||||
initial_folder=os.path.join(os.getcwd()),
|
||||
file_types=((". pt"),),
|
||||
),
|
||||
],
|
||||
[
|
||||
sg.Input(
|
||||
default_text="TEMP\\added_IVF512_Flat_atri_baseline_src_feat.index",
|
||||
default_text=data.get("pth_path", ""),
|
||||
key="pth_path",
|
||||
),
|
||||
sg.FileBrowse(
|
||||
i18n("选择.pth文件"),
|
||||
initial_folder=os.path.join(os.getcwd(), "weights"),
|
||||
file_types=((". pth"),),
|
||||
),
|
||||
],
|
||||
[
|
||||
sg.Input(
|
||||
default_text=data.get("index_path", ""),
|
||||
key="index_path",
|
||||
),
|
||||
sg.FileBrowse(i18n("选择.index文件")),
|
||||
sg.FileBrowse(
|
||||
i18n("选择.index文件"),
|
||||
initial_folder=os.path.join(os.getcwd(), "logs"),
|
||||
file_types=((". index"),),
|
||||
),
|
||||
],
|
||||
[
|
||||
sg.Input(
|
||||
default_text="你不需要填写这个You don't need write this.",
|
||||
key="npy_path",
|
||||
disabled=True,
|
||||
),
|
||||
sg.FileBrowse(
|
||||
i18n("选择.npy文件"),
|
||||
initial_folder=os.path.join(os.getcwd(), "logs"),
|
||||
file_types=((". npy"),),
|
||||
),
|
||||
sg.FileBrowse(i18n("选择.npy文件")),
|
||||
],
|
||||
],
|
||||
)
|
||||
@@ -286,7 +340,7 @@ class GUI:
|
||||
sg.Combo(
|
||||
input_devices,
|
||||
key="sg_input_device",
|
||||
default_value=input_devices[sd.default.device[0]],
|
||||
default_value=data.get("sg_input_device", ""),
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -294,7 +348,7 @@ class GUI:
|
||||
sg.Combo(
|
||||
output_devices,
|
||||
key="sg_output_device",
|
||||
default_value=output_devices[sd.default.device[1]],
|
||||
default_value=data.get("sg_output_device", ""),
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -311,7 +365,7 @@ class GUI:
|
||||
key="threhold",
|
||||
resolution=1,
|
||||
orientation="h",
|
||||
default_value=-30,
|
||||
default_value=data.get("threhold", ""),
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -321,7 +375,7 @@ class GUI:
|
||||
key="pitch",
|
||||
resolution=1,
|
||||
orientation="h",
|
||||
default_value=12,
|
||||
default_value=data.get("pitch", ""),
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -331,7 +385,7 @@ class GUI:
|
||||
key="index_rate",
|
||||
resolution=0.01,
|
||||
orientation="h",
|
||||
default_value=0.5,
|
||||
default_value=data.get("index_rate", ""),
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -346,7 +400,7 @@ class GUI:
|
||||
key="block_time",
|
||||
resolution=0.1,
|
||||
orientation="h",
|
||||
default_value=1.0,
|
||||
default_value=data.get("block_time", ""),
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -356,7 +410,7 @@ class GUI:
|
||||
key="crossfade_length",
|
||||
resolution=0.01,
|
||||
orientation="h",
|
||||
default_value=0.08,
|
||||
default_value=data.get("crossfade_length", ""),
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -366,7 +420,7 @@ class GUI:
|
||||
key="extra_time",
|
||||
resolution=0.01,
|
||||
orientation="h",
|
||||
default_value=0.05,
|
||||
default_value=data.get("extra_time", ""),
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -384,7 +438,6 @@ class GUI:
|
||||
sg.Text("0", key="infer_time"),
|
||||
],
|
||||
]
|
||||
|
||||
self.window = sg.Window("RVC - GUI", layout=layout)
|
||||
self.event_handler()
|
||||
|
||||
@@ -395,16 +448,45 @@ class GUI:
|
||||
self.flag_vc = False
|
||||
exit()
|
||||
if event == "start_vc" and self.flag_vc == False:
|
||||
self.set_values(values)
|
||||
print(str(self.config.__dict__))
|
||||
print("using_cuda:" + str(torch.cuda.is_available()))
|
||||
self.start_vc()
|
||||
if self.set_values(values) == True:
|
||||
print("using_cuda:" + str(torch.cuda.is_available()))
|
||||
self.start_vc()
|
||||
settings = {
|
||||
"pth_path": values["pth_path"],
|
||||
"index_path": values["index_path"],
|
||||
"sg_input_device": values["sg_input_device"],
|
||||
"sg_output_device": values["sg_output_device"],
|
||||
"threhold": values["threhold"],
|
||||
"pitch": values["pitch"],
|
||||
"index_rate": values["index_rate"],
|
||||
"block_time": values["block_time"],
|
||||
"crossfade_length": values["crossfade_length"],
|
||||
"extra_time": values["extra_time"],
|
||||
}
|
||||
with open("values1.json", "w") as j:
|
||||
json.dump(settings, j)
|
||||
if event == "stop_vc" and self.flag_vc == True:
|
||||
self.flag_vc = False
|
||||
|
||||
def set_values(self, values):
|
||||
if len(values["pth_path"].strip()) == 0:
|
||||
sg.popup(i18n("请选择pth文件"))
|
||||
return False
|
||||
if len(values["index_path"].strip()) == 0:
|
||||
sg.popup(i18n("请选择index文件"))
|
||||
return False
|
||||
pattern = re.compile("[^\x00-\x7F]+")
|
||||
if pattern.findall(values["hubert_path"]):
|
||||
sg.popup(i18n("hubert模型路径不可包含中文"))
|
||||
return False
|
||||
if pattern.findall(values["pth_path"]):
|
||||
sg.popup(i18n("pth文件路径不可包含中文"))
|
||||
return False
|
||||
if pattern.findall(values["index_path"]):
|
||||
sg.popup(i18n("index文件路径不可包含中文"))
|
||||
return False
|
||||
self.set_devices(values["sg_input_device"], values["sg_output_device"])
|
||||
self.config.hubert_path = values["hubert_path"]
|
||||
self.config.hubert_path = os.path.join(current_dir, "hubert_base.pt")
|
||||
self.config.pth_path = values["pth_path"]
|
||||
self.config.index_path = values["index_path"]
|
||||
self.config.npy_path = values["npy_path"]
|
||||
@@ -416,6 +498,7 @@ class GUI:
|
||||
self.config.I_noise_reduce = values["I_noise_reduce"]
|
||||
self.config.O_noise_reduce = values["O_noise_reduce"]
|
||||
self.config.index_rate = values["index_rate"]
|
||||
return True
|
||||
|
||||
def start_vc(self):
|
||||
torch.cuda.empty_cache()
|
||||
@@ -580,10 +663,14 @@ class GUI:
|
||||
if d["max_output_channels"] > 0
|
||||
]
|
||||
input_devices_indices = [
|
||||
d["index"] for d in devices if d["max_input_channels"] > 0
|
||||
d["index"] if "index" in d else d["name"]
|
||||
for d in devices
|
||||
if d["max_input_channels"] > 0
|
||||
]
|
||||
output_devices_indices = [
|
||||
d["index"] for d in devices if d["max_output_channels"] > 0
|
||||
d["index"] if "index" in d else d["name"]
|
||||
for d in devices
|
||||
if d["max_output_channels"] > 0
|
||||
]
|
||||
return (
|
||||
input_devices,
|
||||
|
||||
177
i18n/en_US.json
177
i18n/en_US.json
@@ -1,92 +1,93 @@
|
||||
{
|
||||
"很遗憾您这没有能用的显卡来支持您训练": "No supported GPU is found. Training may be slow or unavailable.",
|
||||
"是": "yes",
|
||||
"step1:正在处理数据": "step 1: processing data",
|
||||
"step2a:无需提取音高": "step 2a: skipping pitch extraction",
|
||||
"step2b:正在提取特征": "step 2b: extracting features",
|
||||
"step3a:正在训练模型": "step 3a: model traning started",
|
||||
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "Training complete. Logs are available in the console, or the 'train.log' under experiment folder",
|
||||
"全流程结束!": "all processes have been completed!",
|
||||
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "This software is open source under the MIT license, the author does not have any control over the software, and those who use the software and spread the sounds exported by the software are solely responsible. <br>If you do not agree with this clause, you cannot use or quote any codes and files in the software package. See root directory <b>Agreement-LICENSE.txt</b> for details.",
|
||||
"很遗憾您这没有能用的显卡来支持您训练": "Unfortunately, there is no compatible GPU available to support your training.",
|
||||
"是": "Yes",
|
||||
"step1:正在处理数据": "Step 1: Processing data",
|
||||
"step2a:无需提取音高": "Step 2a: Skipping pitch extraction",
|
||||
"step2b:正在提取特征": "Step 2b: Extracting features",
|
||||
"step3a:正在训练模型": "Step 3a: Model training started",
|
||||
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "Training complete. You can check the training logs in the console or the 'train.log' file under the experiment folder.",
|
||||
"全流程结束!": "All processes have been completed!",
|
||||
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "This software is open source under the MIT license. The author does not have any control over the software. Users who use the software and distribute the sounds exported by the software are solely responsible. <br>If you do not agree with this clause, you cannot use or reference any codes and files within the software package. See the root directory <b>Agreement-LICENSE.txt</b> for details.",
|
||||
"模型推理": "Model Inference",
|
||||
"推理音色": "Inferencing voice:",
|
||||
"刷新音色列表和索引路径": "Refresh voice list and index path",
|
||||
"卸载音色省显存": "Unload voice to save GPU memory:",
|
||||
"请选择说话人id": "Select Singer/Speaker ID:",
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "It is recommended +12key for male to female conversion, and -12key for female to male conversion. If the sound range goes too far and the voice is distorted, you can also adjust it to the appropriate range by yourself. ",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "transpose(Input must be integer, represents number of semitones. Example: octave sharp: 12;octave flat: -12):",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "Enter the path of the audio file to be processed (the default is example of the correct format(Windows)):",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "Select the algorithm for pitch extraction.('pm': fast conversions; 'harvest': better pitch accuracy, but conversion might be extremely slow):",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": "If >=3: using median filter for f0. The number is median filter radius.",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "Path to Feature index file(If null, use dropdown result):",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "Path to the '.index' file in 'logs' directory is auto detected. Pick the matching file from the dropdown:",
|
||||
"特征文件路径": "Path to Feature file:",
|
||||
"请选择说话人id": "Select Speaker/Singer ID:",
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "Recommended +12 key for male to female conversion, and -12 key for female to male conversion. If the sound range goes too far and the voice is distorted, you can also adjust it to the appropriate range by yourself.",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "Transpose (integer, number of semitones, raise by an octave: 12, lower by an octave: -12):",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "Enter the path of the audio file to be processed (default is the correct format example):",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "Select the pitch extraction algorithm ('pm': faster extraction but lower-quality speech; 'harvest': better bass but extremely slow; 'crepe': better quality but GPU intensive):",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": "If >=3: apply median filtering to the harvested pitch results. The value represents the filter radius and can reduce breathiness.",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "Path to the feature index file. Leave blank to use the selected result from the dropdown:",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "Auto-detect index path and select from the dropdown:",
|
||||
"特征文件路径": "Path to feature file:",
|
||||
"检索特征占比": "Search feature ratio:",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "Resample the audio in post-processing to a different sample rate.(Default(0): No post-resampling):",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "Use volume envelope of input to mix or replace the volume envelope of output, the closer the rate is to 1, the more output envelope is used.(Default(1): don't mix input envelope):",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0 curve file(optional),one pitch per line. Overrides the default F0 and ups and downs :",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "Resample the output audio in post-processing to the final sample rate. Set to 0 for no resampling:",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "Use the volume envelope of the input to replace or mix with the volume envelope of the output. The closer the ratio is to 1, the more the output envelope is used:",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "Protect voiceless consonants and breath sounds to prevent artifacts such as tearing in electronic music. Set to 0.5 to disable. Decrease the value to increase protection, but it may reduce indexing accuracy:",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0 curve file (optional). One pitch per line. Replaces the default F0 and pitch modulation:",
|
||||
"转换": "Convert",
|
||||
"输出信息": "Output message",
|
||||
"输出音频(右下角三个点,点了可以下载)": "Export audio (Click on the three dots in the bottom right corner to download)",
|
||||
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "For batch conversion, input the audio folder to be converted, or upload multiple audio files, and output the converted audio in the specified folder ('opt' by default). ",
|
||||
"指定输出文件夹": "Path to output folder:",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Enter the path of the audio folder to be processed (just go to the address bar of the file manager and copy it)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "You can also input audio files in batches, choose one of the two, and read the folder first",
|
||||
"伴奏人声分离": "Seperation of Accompaniment and Vocal",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "Batch processing of vocal accompaniment separation using UVR5 Model. <br>If input is without harmony, use HP2; If with harmony and the extracted vocals do not need harmony, use HP5<br>Example of legal folder path format: E:\\ codes\\py39\\vits_vc_gpu\\Egret Shuanghua test sample (just go to the address bar of the file manager and copy it)",
|
||||
"输入待处理音频文件夹路径": "Path to Input audio folder:",
|
||||
"输出信息": "Output information",
|
||||
"输出音频(右下角三个点,点了可以下载)": "Export audio (click on the three dots in the lower right corner to download)",
|
||||
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "Batch conversion. Enter the folder containing the audio files to be converted or upload multiple audio files. The converted audio will be output in the specified folder (default: 'opt').",
|
||||
"指定输出文件夹": "Specify output folder:",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Enter the path of the audio folder to be processed (copy it from the address bar of the file manager):",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "You can also input audio files in batches. Choose one of the two options. Priority is given to reading from the folder.",
|
||||
"导出文件格式": "Export file format",
|
||||
"伴奏人声分离&去混响&去回声": "Vocals/Accompaniment Separation & Reverberation Removal",
|
||||
"输入待处理音频文件夹路径": "Enter the path of the audio folder to be processed:",
|
||||
"模型": "Model",
|
||||
"指定输出人声文件夹": "Path to vocals output folder:",
|
||||
"指定输出乐器文件夹": "Path to instrumentals output folder:",
|
||||
"指定输出主人声文件夹": "Specify the output folder for vocals:",
|
||||
"指定输出非主人声文件夹": "Specify the output folder for accompaniment:",
|
||||
"训练": "Train",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: Fill in the experimental configuration. The experimental data is placed under 'logs', and each experiment has a folder. You need to manually enter the experimental name path, which contains the experimental configuration, logs, and model files obtained from training. ",
|
||||
"输入实验名": "Experiment name:",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "Step 1: Fill in the experimental configuration. Experimental data is stored in the 'logs' folder, with each experiment having a separate folder. Manually enter the experiment name path, which contains the experimental configuration, logs, and trained model files.",
|
||||
"输入实验名": "Enter the experiment name:",
|
||||
"目标采样率": "Target sample rate:",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "If the model have pitch guidance (Required for singing as Input; Optional for speech as Input, but recommended):",
|
||||
"版本(目前仅40k支持了v2)": "Model architecture version (v2 version only supports 40k sample rate for testing purposes):",
|
||||
"提取音高和处理数据使用的CPU进程数": "Threads of CPU, for pitch extraction and dataset processing:",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: Automatically traverse all files that can be decoded into audio in the training folder and perform slice normalization. Generates 2 wav folders in the experiment directory; Only single-singer/speaker training is supported for the time being. ",
|
||||
"输入训练文件夹路径": "Path to training folder:",
|
||||
"请指定说话人id": "Specify Singer/Speaker ID:",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Whether the model has pitch guidance (required for singing, optional for speech):",
|
||||
"版本": "Version",
|
||||
"提取音高和处理数据使用的CPU进程数": "Number of CPU processes used for pitch extraction and data processing:",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "Step 2a: Automatically traverse all files in the training folder that can be decoded into audio and perform slice normalization. Generates 2 wav folders in the experiment directory. Currently, only single-singer/speaker training is supported.",
|
||||
"输入训练文件夹路径": "Enter the path of the training folder:",
|
||||
"请指定说话人id": "Please specify the speaker/singer ID:",
|
||||
"处理数据": "Process data",
|
||||
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "step2b: Use CPU to extract pitch (if the model has pitch), use GPU to extract features (must specify GPU)",
|
||||
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Enter GPU Index(es),separated by '-'.(Example: 0-1-2 to select card 1, 2 and 3):",
|
||||
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "Step 2b: Use CPU to extract pitch (if the model has pitch), use GPU to extract features (select GPU index):",
|
||||
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Enter the GPU index(es) separated by '-', e.g., 0-1-2 to use GPU 0, 1, and 2:",
|
||||
"显卡信息": "GPU Information",
|
||||
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Select pitch extraction algorithm.('pm': fastest extraction but lower-quality speech; 'dio': improved speech but slower extraction; 'harvest': best quality but slowest extraction):",
|
||||
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Select the pitch extraction algorithm ('pm': faster extraction but lower-quality speech; 'dio': improved speech but slower extraction; 'harvest': better quality but slower extraction):",
|
||||
"特征提取": "Feature extraction",
|
||||
"step3: 填写训练设置, 开始训练模型和索引": "step3: Fill in the training settings, start training the model and index",
|
||||
"保存频率save_every_epoch": "Saving frequency (save_every_epoch):",
|
||||
"step3: 填写训练设置, 开始训练模型和索引": "Step 3: Fill in the training settings and start training the model and index",
|
||||
"保存频率save_every_epoch": "Save frequency (save_every_epoch):",
|
||||
"总训练轮数total_epoch": "Total training epochs (total_epoch):",
|
||||
"每张显卡的batch_size": "batch_size for every GPU:",
|
||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "Save only the latest ckpt file to reduce disk usage:",
|
||||
"否": "no",
|
||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Cache all training sets to GPU Memory. Small data(~under 10 minutes) can be cached to speed up training, but large data caching will eats up the GPU Memory and may not increase the speed :",
|
||||
"是否在每次保存时间点将最终小模型保存至weights文件夹": "Save a small finished model to the 'weights' directory for every epoch matching the specified 'save frequency' :",
|
||||
"加载预训练底模G路径": "Load pre-trained base model G path.",
|
||||
"加载预训练底模D路径": "Load pre-trained base model D path.",
|
||||
"训练模型": "Train model.",
|
||||
"每张显卡的batch_size": "Batch size per GPU:",
|
||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "Save only the latest '.ckpt' file to save disk space:",
|
||||
"否": "No",
|
||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Cache all training sets to GPU memory. Caching small datasets (less than 10 minutes) can speed up training, but caching large datasets will consume a lot of GPU memory and may not provide much speed improvement:",
|
||||
"是否在每次保存时间点将最终小模型保存至weights文件夹": "Save a small final model to the 'weights' folder at each save point:",
|
||||
"加载预训练底模G路径": "Load pre-trained base model G path:",
|
||||
"加载预训练底模D路径": "Load pre-trained base model D path:",
|
||||
"训练模型": "Train model",
|
||||
"训练特征索引": "Train feature index",
|
||||
"一键训练": "One-click training",
|
||||
"ckpt处理": "ckpt Processing",
|
||||
"模型融合, 可用于测试音色融合": "Model Fusion, which can be used to test timbre fusion",
|
||||
"模型融合, 可用于测试音色融合": "Model fusion, can be used to test timbre fusion",
|
||||
"A模型路径": "Path to Model A:",
|
||||
"B模型路径": "Path to Model B:",
|
||||
"A模型权重": "Weight(w) for model A:",
|
||||
"A模型权重": "Weight (w) for Model A:",
|
||||
"模型是否带音高指导": "Whether the model has pitch guidance:",
|
||||
"要置入的模型信息": "Model information to be placed:",
|
||||
"保存的模型名不带后缀": "Saved modelname(without extension):",
|
||||
"保存的模型名不带后缀": "Saved model name (without extension):",
|
||||
"模型版本型号": "Model architecture version:",
|
||||
"融合": "Fusion",
|
||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modify model information (only small model files extracted from the 'weights' folder are supported)",
|
||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modify model information (only supported for small model files extracted from the 'weights' folder)",
|
||||
"模型路径": "Path to Model:",
|
||||
"要改的模型信息": "Model information to be modified:",
|
||||
"保存的文件名, 默认空为和源文件同名": "Savefile Name. Default(empty): Name is the same as the source file :",
|
||||
"保存的文件名, 默认空为和源文件同名": "Save file name (default: same as the source file):",
|
||||
"修改": "Modify",
|
||||
"查看模型信息(仅支持weights文件夹下提取的小模型文件)": "View model information (only small model files extracted from the 'weights' folder are supported)",
|
||||
"查看模型信息(仅支持weights文件夹下提取的小模型文件)": "View model information (only supported for small model files extracted from the 'weights' folder)",
|
||||
"查看": "View",
|
||||
"模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "Model extraction (enter the path of the large file model under the logs folder), which is suitable for half of the training and does not want to train the model without automatically extracting and saving the small file model, or if you want to test the intermediate model",
|
||||
"保存名": "Savefile Name:",
|
||||
"模型是否带音高指导,1是0否": "Whether the model has pitch guidance(1: yes, 0: no):",
|
||||
"模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "Model extraction (enter the path of the large file model under the 'logs' folder). This is useful if you want to stop training halfway and manually extract and save a small model file, or if you want to test an intermediate model:",
|
||||
"保存名": "Save name:",
|
||||
"模型是否带音高指导,1是0否": "Whether the model has pitch guidance (1: yes, 0: no):",
|
||||
"提取": "Extract",
|
||||
"Onnx导出": "Export Onnx",
|
||||
"RVC模型路径": "RVC Model Path:",
|
||||
@@ -94,32 +95,42 @@
|
||||
"MoeVS模型": "MoeVS Model",
|
||||
"导出Onnx模型": "Export Onnx Model",
|
||||
"常见问题解答": "FAQ (Frequently Asked Questions)",
|
||||
"招募音高曲线前端编辑器": "Recruit front-end editors for pitch curves",
|
||||
"加开发群联系我xxxxx": "Want to join the development chat group? contact me xxxxx",
|
||||
"招募音高曲线前端编辑器": "Recruiting front-end editors for pitch curves",
|
||||
"加开发群联系我xxxxx": "Join the development group and contact me at xxxxx",
|
||||
"点击查看交流、问题反馈群号": "Click to view the communication and problem feedback group number",
|
||||
"xxxxx": "xxxxx",
|
||||
"加载模型": "load model",
|
||||
"Hubert模型": "Hubert File",
|
||||
"加载模型": "Load model",
|
||||
"Hubert模型": "Hubert Model",
|
||||
"选择.pth文件": "Select the .pth file",
|
||||
"选择.index文件": "Select the .index file",
|
||||
"选择.npy文件": "Select the .npy file",
|
||||
"输入设备": "input device",
|
||||
"输出设备": "output device",
|
||||
"输入设备": "Input device",
|
||||
"输出设备": "Output device",
|
||||
"音频设备(请使用同种类驱动)": "Audio device (please use the same type of driver)",
|
||||
"响应阈值": "response threshold",
|
||||
"音调设置": "tone setting",
|
||||
"响应阈值": "Response threshold",
|
||||
"音调设置": "Pitch settings",
|
||||
"Index Rate": "Index Rate",
|
||||
"常规设置": "general settings",
|
||||
"常规设置": "General settings",
|
||||
"采样长度": "Sample length",
|
||||
"淡入淡出长度": "fade length",
|
||||
"额外推理时长": "extra inference time",
|
||||
"输入降噪": "Input Noise Reduction",
|
||||
"输出降噪": "Output Noise Reduction",
|
||||
"性能设置": "Compute Performance settings",
|
||||
"开始音频转换": "start audio conversion",
|
||||
"停止音频转换": "stop audio conversion",
|
||||
"导出文件格式": "output file format",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "Protect voiceless consonant and breath, less artifact. 0.5: don' use it. The number smaller, the stronger protection.",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "Select pitch extraction algorithm.('pm': fastest extraction but lower-quality speech; 'dio': improved speech but slower extraction; 'harvest': better quality but slowest extraction; 'crepe': best quality but GPU needed. )",
|
||||
"推理时间(ms):": "Inference Time(ms):"
|
||||
}
|
||||
"淡入淡出长度": "Fade length",
|
||||
"额外推理时长": "Extra inference time",
|
||||
"输入降噪": "Input noise reduction",
|
||||
"输出降噪": "Output noise reduction",
|
||||
"性能设置": "Performance settings",
|
||||
"开始音频转换": "Start audio conversion",
|
||||
"停止音频转换": "Stop audio conversion",
|
||||
"推理时间(ms):": "Inference time (ms):",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型。 <br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。 <br>模型分为三类: <br>1、保留人声:不带和声的音频选这个,对主人声保留比HP5更好。内置HP2和HP3两个模型,HP3可能轻微漏伴奏但对主人声保留比HP2稍微好一丁点; <br>2、仅保留主人声:带和声的音频选这个,对主人声可能有削弱。内置HP5一个模型; <br> 3、去混响、去延迟模型(by FoxJoy):<br> (1)MDX-Net(onnx_dereverb):对于双通道混响是最好的选择,不能去除单通道混响;<br> (234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底,DeReverb额外去除混响,可去除单声道混响,但是对高频重的板式混响去不干净。<br>去混响/去延迟,附:<br>1、DeEcho-DeReverb模型的耗时是另外2个DeEcho模型的接近2倍;<br>2、MDX-Net-Dereverb模型挺慢的;<br>3、个人推荐的最干净的配置是先MDX-Net再DeEcho-Aggressive。":"Batch processing for vocal accompaniment separation using the UVR5 model.<br>Example of a valid folder path format: D:\\path\\to\\input\\folder (copy it from the file manager address bar).<br>The model is divided into three categories:<br>1. Preserve vocals: Choose this option for audio without harmonies. It preserves vocals better than HP5. It includes two built-in models: HP2 and HP3. HP3 may slightly leak accompaniment but preserves vocals slightly better than HP2.<br>2. Preserve main vocals only: Choose this option for audio with harmonies. It may weaken the main vocals. It includes one built-in model: HP5.<br>3. De-reverb and de-delay models (by FoxJoy):<br> (1) MDX-Net: The best choice for stereo reverb removal but cannot remove mono reverb;<br> (234) DeEcho: Removes delay effects. Aggressive mode removes more thoroughly than Normal mode. DeReverb additionally removes reverb and can remove mono reverb, but not very effectively for heavily reverberated high-frequency content.<br>De-reverb/de-delay notes:<br>1. The processing time for the DeEcho-DeReverb model is approximately twice as long as the other two DeEcho models.<br>2. The MDX-Net-Dereverb model is quite slow.<br>3. The recommended cleanest configuration is to apply MDX-Net first and then DeEcho-Aggressive.",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型。": "Batch processing for vocal accompaniment separation using the UVR5 model.",
|
||||
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Example of a valid folder path format: D:\\path\\to\\input\\folder (copy it from the file manager address bar).",
|
||||
"模型分为三类:": "The model is divided into three categories:",
|
||||
"1、保留人声:不带和声的音频选这个,对主人声保留比HP5更好。内置HP2和HP3两个模型,HP3可能轻微漏伴奏但对主人声保留比HP2稍微好一丁点;": "1. Preserve vocals: Choose this option for audio without harmonies. It preserves vocals better than HP5. It includes two built-in models: HP2 and HP3. HP3 may slightly leak accompaniment but preserves vocals slightly better than HP2.",
|
||||
"2、仅保留主人声:带和声的音频选这个,对主人声可能有削弱。内置HP5一个模型;": "2. Preserve main vocals only: Choose this option for audio with harmonies. It may weaken the main vocals. It includes one built-in model: HP5.",
|
||||
"3、去混响、去延迟模型(by FoxJoy):": "3. De-reverb and de-delay models (by FoxJoy):",
|
||||
"(1)MDX-Net:对于双通道混响是最好的选择,不能去除单通道混响;": "(1) MDX-Net: The best choice for stereo reverb removal but cannot remove mono reverb;",
|
||||
"(234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底,DeReverb额外去除混响,可去除单声道混响,但是对高频重的板式混响去不干净。": "(234) DeEcho: Removes delay effects. Aggressive mode removes more thoroughly than Normal mode. DeReverb additionally removes reverb and can remove mono reverb, but not very effectively for heavily reverberated high-frequency content.",
|
||||
"去混响/去延迟,附:": "De-reverb/de-delay notes:",
|
||||
"1、DeEcho-DeReverb模型的耗时是另外2个DeEcho模型的接近2倍;": "1. The processing time for the DeEcho-DeReverb model is approximately twice as long as the other two DeEcho models.",
|
||||
"2、MDX-Net-Dereverb模型挺慢的;": "2. The MDX-Net-Dereverb model is quite slow.",
|
||||
"3、个人推荐的最干净的配置是先MDX-Net再DeEcho-Aggressive。": "3. The recommended cleanest configuration is to apply MDX-Net first and then DeEcho-Aggressive."
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "Tecla +12 recomendada para conversión de voz de hombre a mujer, tecla -12 para conversión de voz de mujer a hombre. Si el rango de tono es demasiado amplio y causa distorsión, ajústelo usted mismo a un rango adecuado.",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "Cambio de tono (entero, número de semitonos, subir una octava +12 o bajar una octava -12)",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "Ingrese la ruta del archivo del audio que se procesará (el formato predeterminado es el ejemplo correcto)",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "Seleccione el algoritmo para la extracción de tono. Use 'pm' para acelerar las voces cantadas, o use 'harvest' para mejorar las voces bajas, pero es extremadamente lento.",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特征检索库文件路径,为空则使用下拉的选择结果",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "自动检测index路径,下拉式选择(dropdown)",
|
||||
@@ -24,6 +24,7 @@
|
||||
"检索特征占比": "Proporción de función de búsqueda",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "Archivo de curva F0, opcional, un tono por línea, en lugar de F0 predeterminado y cambio de tono",
|
||||
"转换": "Conversión",
|
||||
"输出信息": "Información de salida",
|
||||
@@ -32,18 +33,18 @@
|
||||
"指定输出文件夹": "Especificar carpeta de salida",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Ingrese la ruta a la carpeta de audio que se procesará (simplemente cópiela desde la barra de direcciones del administrador de archivos)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "También se pueden ingresar múltiples archivos de audio, cualquiera de las dos opciones, con prioridad dada a la carpeta",
|
||||
"伴奏人声分离": "Instrumental and vocal separation",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "Procesamiento por lotes de separación instrumental y vocal utilizando el modelo UVR5. <br>Utilice HP2 para la separación vocal sin armónicos, y utilice HP5 para la separación vocal con armónicos y las voces extraídas no necesitan tener armónicos. <br>Ejemplo de una ruta de carpeta calificada: E:\\codes\\py39\\vits_vc_gpu\\test_sample (simplemente cópielo desde la barra de direcciones del administrador de archivos)",
|
||||
"导出文件格式": "导出文件格式",
|
||||
"伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
|
||||
"输入待处理音频文件夹路径": "Ingrese la ruta a la carpeta de audio que se procesará",
|
||||
"模型": "Modelo",
|
||||
"指定输出人声文件夹": "Especificar la carpeta de salida de voces",
|
||||
"指定输出乐器文件夹": "Especificar la carpeta de salida de instrumentales",
|
||||
"指定输出主人声文件夹": "指定输出主人声文件夹",
|
||||
"指定输出非主人声文件夹": "指定输出非主人声文件夹",
|
||||
"训练": "Entrenamiento",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "paso 1: Complete la configuración del experimento. Los datos del experimento se almacenan en el directorio 'logs', con cada experimento en una carpeta separada. La ruta del nombre del experimento debe ingresarse manualmente y debe contener la configuración del experimento, los registros y los archivos del modelo entrenado.",
|
||||
"输入实验名": "Ingrese el nombre del modelo",
|
||||
"目标采样率": "Tasa de muestreo objetivo",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Si el modelo tiene guía de tono (necesaria para cantar, pero no para hablar)",
|
||||
"版本(目前仅40k支持了v2)": "版本(目前仅40k支持了v2)",
|
||||
"版本": "版本",
|
||||
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "paso 2a: recorra automáticamente la carpeta de capacitación y corte y normalice todos los archivos de audio que se pueden decodificar en audio. Se generarán dos carpetas 'wav' en el directorio del experimento. Actualmente, solo se admite la capacitación de una sola persona.",
|
||||
"输入训练文件夹路径": "Introduzca la ruta de la carpeta de entrenamiento",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性から女性へは+12キーをお勧めします。女性から男性へは-12キーをお勧めします。音域が広すぎて音質が劣化した場合は、適切な音域に自分で調整することもできます。",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "ピッチ変更(整数、半音数、上下オクターブ12-12)",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "処理対象音声ファイルのパスを入力してください(デフォルトは正しいフォーマットの例です)",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "ピッチ抽出アルゴリズムを選択してください。歌声の場合は、pmを使用して速度を上げることができます。低音が重要な場合は、harvestを使用できますが、非常に遅くなります。",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3 次に、harvestピッチの認識結果に対してメディアンフィルタを使用します。値はフィルター半径で、ミュートを減衰させるために使用します。",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特徴検索ライブラリへのパス 空の場合はドロップダウンで選択",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "インデックスパスの自動検出 ドロップダウンで選択",
|
||||
@@ -24,6 +24,7 @@
|
||||
"检索特征占比": "検索特徴率",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "最終的なサンプリングレートへのポストプロセッシングのリサンプリング リサンプリングしない場合は0",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "入力ソースの音量エンベロープと出力音量エンベロープの融合率 1に近づくほど、出力音量エンベロープの割合が高くなる",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0(最低共振周波数)カーブファイル(オプション、1行に1ピッチ、デフォルトのF0(最低共振周波数)とエレベーションを置き換えます。)",
|
||||
"转换": "変換",
|
||||
"输出信息": "出力情報",
|
||||
@@ -32,18 +33,18 @@
|
||||
"指定输出文件夹": "出力フォルダを指定してください",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "処理対象音声フォルダーのパスを入力してください(ファイルマネージャのアドレスバーからコピーしてください)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "複数の音声ファイルを一括で入力することもできますが、フォルダーを優先して読み込みます",
|
||||
"伴奏人声分离": "伴奏とボーカルの分離",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "UVR5モデルを使用した、声帯分離バッチ処理です。<br>HP2はハーモニー、ハーモニーのあるボーカルとハーモニーのないボーカルを抽出したものはHP5を使ってください <br>フォルダーパスの形式例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(エクスプローラーのアドレスバーからコピーするだけです)",
|
||||
"导出文件格式": "导出文件格式",
|
||||
"伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
|
||||
"输入待处理音频文件夹路径": "処理するオーディオファイルのフォルダパスを入力してください",
|
||||
"模型": "モデル",
|
||||
"指定输出人声文件夹": "人の声を出力するフォルダを指定してください",
|
||||
"指定输出乐器文件夹": "楽器の出力フォルダを指定してください",
|
||||
"指定输出主人声文件夹": "指定输出主人声文件夹",
|
||||
"指定输出非主人声文件夹": "指定输出非主人声文件夹",
|
||||
"训练": "トレーニング",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "ステップ1:実験設定を入力します。実験データはlogsに保存され、各実験にはフォルダーがあります。実験名のパスを手動で入力する必要があり、実験設定、ログ、トレーニングされたモデルファイルが含まれます。",
|
||||
"输入实验名": "モデル名",
|
||||
"目标采样率": "目標サンプリングレート",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "モデルに音高ガイドがあるかどうか(歌唱には必要ですが、音声には必要ありません)",
|
||||
"版本(目前仅40k支持了v2)": "バージョン(現在v2をサポートしているのは40kのみ)",
|
||||
"版本": "バージョン",
|
||||
"提取音高和处理数据使用的CPU进程数": "ピッチの抽出やデータ処理に使用するCPUスレッド数",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "ステップ2a: 訓練フォルダー内のすべての音声ファイルを自動的に探索し、スライスと正規化を行い、2つのwavフォルダーを実験ディレクトリに生成します。現在は一人でのトレーニングのみをサポートしています。",
|
||||
"输入训练文件夹路径": "トレーニング用フォルダのパスを入力してください",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "变调(整数, 半音数量, 升八度12降八度-12)",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "输入待处理音频文件路径(默认是正确格式示例)",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特征检索库文件路径,为空则使用下拉的选择结果",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "自动检测index路径,下拉式选择(dropdown)",
|
||||
@@ -24,6 +24,7 @@
|
||||
"检索特征占比": "检索特征占比",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调",
|
||||
"转换": "转换",
|
||||
"输出信息": "输出信息",
|
||||
@@ -32,18 +33,18 @@
|
||||
"指定输出文件夹": "指定输出文件夹",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹",
|
||||
"伴奏人声分离": "伴奏人声分离",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)",
|
||||
"导出文件格式": "导出文件格式",
|
||||
"伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
|
||||
"输入待处理音频文件夹路径": "输入待处理音频文件夹路径",
|
||||
"模型": "模型",
|
||||
"指定输出人声文件夹": "指定输出人声文件夹",
|
||||
"指定输出乐器文件夹": "指定输出乐器文件夹",
|
||||
"指定输出主人声文件夹": "指定输出主人声文件夹",
|
||||
"指定输出非主人声文件夹": "指定输出非主人声文件夹",
|
||||
"训练": "训练",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ",
|
||||
"输入实验名": "输入实验名",
|
||||
"目标采样率": "目标采样率",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否带音高指导(唱歌一定要, 语音可以不要)",
|
||||
"版本(目前仅40k支持了v2)": "版本(目前仅40k支持了v2)",
|
||||
"版本": "版本",
|
||||
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ",
|
||||
"输入训练文件夹路径": "输入训练文件夹路径",
|
||||
@@ -118,8 +119,5 @@
|
||||
"性能设置": "性能设置",
|
||||
"开始音频转换": "开始音频转换",
|
||||
"停止音频转换": "停止音频转换",
|
||||
"导出文件格式": "导出文件格式",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
|
||||
"推理时间(ms):": "推理时间(ms):"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key,女性轉男性推薦-12key,如果音域爆炸導致音色失真也可以自己調整到合適音域。",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "選擇音高提取演算法,輸入歌聲可用 pm 提速,harvest 低音好但巨慢無比",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3則使用對harvest音高識別的結果使用中值濾波,數值為濾波半徑,使用可以削弱啞音",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特徵檢索庫檔路徑,為空則使用下拉的選擇結果",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "自動檢測index路徑,下拉式選擇(dropdown)",
|
||||
@@ -24,6 +24,7 @@
|
||||
"检索特征占比": "檢索特徵佔比",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例,越靠近1越使用輸出包絡",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
||||
"转换": "轉換",
|
||||
"输出信息": "輸出訊息",
|
||||
@@ -32,18 +33,18 @@
|
||||
"指定输出文件夹": "指定輸出資料夾",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾",
|
||||
"伴奏人声分离": "伴奏人聲分離",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人聲伴奏分離批量處理,使用UVR5模型。<br>不帶和聲用HP2,帶和聲且提取的人聲不需要和聲用HP5<br>合格的資料夾路徑格式舉例:E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去檔案管理員地址欄複製就行了)",
|
||||
"导出文件格式": "導出檔格式",
|
||||
"伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
|
||||
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
|
||||
"模型": "模型",
|
||||
"指定输出人声文件夹": "指定輸出人聲資料夾",
|
||||
"指定输出乐器文件夹": "指定輸出樂器資料夾",
|
||||
"指定输出主人声文件夹": "指定输出主人声文件夹",
|
||||
"指定输出非主人声文件夹": "指定输出非主人声文件夹",
|
||||
"训练": "訓練",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1:填寫實驗配置。實驗數據放在logs下,每個實驗一個資料夾,需手動輸入實驗名路徑,內含實驗配置、日誌、訓練得到的模型檔案。",
|
||||
"输入实验名": "輸入實驗名稱",
|
||||
"目标采样率": "目標取樣率",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
||||
"版本(目前仅40k支持了v2)": "版本(目前僅40k支持了v2)",
|
||||
"版本": "版本",
|
||||
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
||||
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
||||
@@ -118,8 +119,5 @@
|
||||
"性能设置": "效能設定",
|
||||
"开始音频转换": "開始音訊轉換",
|
||||
"停止音频转换": "停止音訊轉換",
|
||||
"导出文件格式": "導出檔格式",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||
"推理时间(ms):": "推理時間(ms):"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key,女性轉男性推薦-12key,如果音域爆炸導致音色失真也可以自己調整到合適音域。",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "選擇音高提取演算法,輸入歌聲可用 pm 提速,harvest 低音好但巨慢無比",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3則使用對harvest音高識別的結果使用中值濾波,數值為濾波半徑,使用可以削弱啞音",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特徵檢索庫檔路徑,為空則使用下拉的選擇結果",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "自動檢測index路徑,下拉式選擇(dropdown)",
|
||||
@@ -24,6 +24,7 @@
|
||||
"检索特征占比": "檢索特徵佔比",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例,越靠近1越使用輸出包絡",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
||||
"转换": "轉換",
|
||||
"输出信息": "輸出訊息",
|
||||
@@ -32,18 +33,18 @@
|
||||
"指定输出文件夹": "指定輸出資料夾",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾",
|
||||
"伴奏人声分离": "伴奏人聲分離",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人聲伴奏分離批量處理,使用UVR5模型。<br>不帶和聲用HP2,帶和聲且提取的人聲不需要和聲用HP5<br>合格的資料夾路徑格式舉例:E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去檔案管理員地址欄複製就行了)",
|
||||
"导出文件格式": "導出檔格式",
|
||||
"伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
|
||||
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
|
||||
"模型": "模型",
|
||||
"指定输出人声文件夹": "指定輸出人聲資料夾",
|
||||
"指定输出乐器文件夹": "指定輸出樂器資料夾",
|
||||
"指定输出主人声文件夹": "指定输出主人声文件夹",
|
||||
"指定输出非主人声文件夹": "指定输出非主人声文件夹",
|
||||
"训练": "訓練",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1:填寫實驗配置。實驗數據放在logs下,每個實驗一個資料夾,需手動輸入實驗名路徑,內含實驗配置、日誌、訓練得到的模型檔案。",
|
||||
"输入实验名": "輸入實驗名稱",
|
||||
"目标采样率": "目標取樣率",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
||||
"版本(目前仅40k支持了v2)": "版本(目前僅40k支持了v2)",
|
||||
"版本": "版本",
|
||||
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
||||
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
||||
@@ -118,8 +119,5 @@
|
||||
"性能设置": "效能設定",
|
||||
"开始音频转换": "開始音訊轉換",
|
||||
"停止音频转换": "停止音訊轉換",
|
||||
"导出文件格式": "導出檔格式",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||
"推理时间(ms):": "推理時間(ms):"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key,女性轉男性推薦-12key,如果音域爆炸導致音色失真也可以自己調整到合適音域。",
|
||||
"变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)",
|
||||
"输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "選擇音高提取演算法,輸入歌聲可用 pm 提速,harvest 低音好但巨慢無比",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3則使用對harvest音高識別的結果使用中值濾波,數值為濾波半徑,使用可以削弱啞音",
|
||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特徵檢索庫檔路徑,為空則使用下拉的選擇結果",
|
||||
"自动检测index路径,下拉式选择(dropdown)": "自動檢測index路徑,下拉式選擇(dropdown)",
|
||||
@@ -24,6 +24,7 @@
|
||||
"检索特征占比": "檢索特徵佔比",
|
||||
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
||||
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例,越靠近1越使用輸出包絡",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
||||
"转换": "轉換",
|
||||
"输出信息": "輸出訊息",
|
||||
@@ -32,18 +33,18 @@
|
||||
"指定输出文件夹": "指定輸出資料夾",
|
||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)",
|
||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾",
|
||||
"伴奏人声分离": "伴奏人聲分離",
|
||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人聲伴奏分離批量處理,使用UVR5模型。<br>不帶和聲用HP2,帶和聲且提取的人聲不需要和聲用HP5<br>合格的資料夾路徑格式舉例:E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去檔案管理員地址欄複製就行了)",
|
||||
"导出文件格式": "導出檔格式",
|
||||
"伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
|
||||
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
|
||||
"模型": "模型",
|
||||
"指定输出人声文件夹": "指定輸出人聲資料夾",
|
||||
"指定输出乐器文件夹": "指定輸出樂器資料夾",
|
||||
"指定输出主人声文件夹": "指定输出主人声文件夹",
|
||||
"指定输出非主人声文件夹": "指定输出非主人声文件夹",
|
||||
"训练": "訓練",
|
||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1:填寫實驗配置。實驗數據放在logs下,每個實驗一個資料夾,需手動輸入實驗名路徑,內含實驗配置、日誌、訓練得到的模型檔案。",
|
||||
"输入实验名": "輸入實驗名稱",
|
||||
"目标采样率": "目標取樣率",
|
||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
||||
"版本(目前仅40k支持了v2)": "版本(目前僅40k支持了v2)",
|
||||
"版本": "版本",
|
||||
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
||||
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
||||
@@ -118,8 +119,5 @@
|
||||
"性能设置": "效能設定",
|
||||
"开始音频转换": "開始音訊轉換",
|
||||
"停止音频转换": "停止音訊轉換",
|
||||
"导出文件格式": "導出檔格式",
|
||||
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||
"推理时间(ms):": "推理時間(ms):"
|
||||
}
|
||||
|
||||
421
infer-web.py
421
infer-web.py
@@ -1,14 +1,46 @@
|
||||
import torch, os, traceback, sys, warnings, shutil, numpy as np
|
||||
|
||||
os.environ["no_proxy"] = "localhost, 127.0.0.1, ::1"
|
||||
import threading
|
||||
from time import sleep
|
||||
from subprocess import Popen
|
||||
import faiss
|
||||
from random import shuffle
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
now_dir = os.getcwd()
|
||||
sys.path.append(now_dir)
|
||||
import traceback, pdb
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
os.environ["no_proxy"] = "localhost, 127.0.0.1, ::1"
|
||||
import logging
|
||||
import threading
|
||||
from random import shuffle
|
||||
from subprocess import Popen
|
||||
from time import sleep
|
||||
|
||||
import faiss
|
||||
import ffmpeg
|
||||
import gradio as gr
|
||||
import soundfile as sf
|
||||
from config import Config
|
||||
from fairseq import checkpoint_utils
|
||||
from i18n import I18nAuto
|
||||
from infer_pack.models import (
|
||||
SynthesizerTrnMs256NSFsid,
|
||||
SynthesizerTrnMs256NSFsid_nono,
|
||||
SynthesizerTrnMs768NSFsid,
|
||||
SynthesizerTrnMs768NSFsid_nono,
|
||||
)
|
||||
from infer_pack.models_onnx import SynthesizerTrnMsNSFsidM
|
||||
from infer_uvr5 import _audio_pre_, _audio_pre_new
|
||||
from MDXNet import MDXNetDereverb
|
||||
from my_utils import load_audio
|
||||
from train.process_ckpt import change_info, extract_small_model, merge, show_info
|
||||
from vc_infer_pipeline import VC
|
||||
from sklearn.cluster import MiniBatchKMeans
|
||||
|
||||
logging.getLogger("numba").setLevel(logging.WARNING)
|
||||
|
||||
|
||||
tmp = os.path.join(now_dir, "TEMP")
|
||||
shutil.rmtree(tmp, ignore_errors=True)
|
||||
shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)
|
||||
@@ -19,40 +51,44 @@ os.makedirs(os.path.join(now_dir, "weights"), exist_ok=True)
|
||||
os.environ["TEMP"] = tmp
|
||||
warnings.filterwarnings("ignore")
|
||||
torch.manual_seed(114514)
|
||||
from i18n import I18nAuto
|
||||
import ffmpeg
|
||||
from MDXNet import MDXNetDereverb
|
||||
|
||||
|
||||
config = Config()
|
||||
i18n = I18nAuto()
|
||||
i18n.print()
|
||||
# 判断是否有能用来训练和加速推理的N卡
|
||||
ngpu = torch.cuda.device_count()
|
||||
gpu_infos = []
|
||||
mem = []
|
||||
if (not torch.cuda.is_available()) or ngpu == 0:
|
||||
if_gpu_ok = False
|
||||
else:
|
||||
if_gpu_ok = False
|
||||
if_gpu_ok = False
|
||||
|
||||
if torch.cuda.is_available() or ngpu != 0:
|
||||
for i in range(ngpu):
|
||||
gpu_name = torch.cuda.get_device_name(i)
|
||||
if (
|
||||
"10" in gpu_name
|
||||
or "16" in gpu_name
|
||||
or "20" in gpu_name
|
||||
or "30" in gpu_name
|
||||
or "40" in gpu_name
|
||||
or "A2" in gpu_name.upper()
|
||||
or "A3" in gpu_name.upper()
|
||||
or "A4" in gpu_name.upper()
|
||||
or "P4" in gpu_name.upper()
|
||||
or "A50" in gpu_name.upper()
|
||||
or "70" in gpu_name
|
||||
or "80" in gpu_name
|
||||
or "90" in gpu_name
|
||||
or "M4" in gpu_name.upper()
|
||||
or "T4" in gpu_name.upper()
|
||||
or "TITAN" in gpu_name.upper()
|
||||
): # A10#A100#V100#A40#P40#M40#K80#A4500
|
||||
if any(
|
||||
value in gpu_name.upper()
|
||||
for value in [
|
||||
"10",
|
||||
"16",
|
||||
"20",
|
||||
"30",
|
||||
"40",
|
||||
"A2",
|
||||
"A3",
|
||||
"A4",
|
||||
"P4",
|
||||
"A50",
|
||||
"500",
|
||||
"A60",
|
||||
"70",
|
||||
"80",
|
||||
"90",
|
||||
"M4",
|
||||
"T4",
|
||||
"TITAN",
|
||||
]
|
||||
):
|
||||
# A10#A100#V100#A40#P40#M40#K80#A4500
|
||||
if_gpu_ok = True # 至少有一张能用的N卡
|
||||
gpu_infos.append("%s\t%s" % (i, gpu_name))
|
||||
mem.append(
|
||||
@@ -64,32 +100,13 @@ else:
|
||||
+ 0.4
|
||||
)
|
||||
)
|
||||
if if_gpu_ok == True and len(gpu_infos) > 0:
|
||||
if if_gpu_ok and len(gpu_infos) > 0:
|
||||
gpu_info = "\n".join(gpu_infos)
|
||||
default_batch_size = min(mem) // 2
|
||||
else:
|
||||
gpu_info = i18n("很遗憾您这没有能用的显卡来支持您训练")
|
||||
default_batch_size = 1
|
||||
gpus = "-".join([i[0] for i in gpu_infos])
|
||||
from infer_pack.models import (
|
||||
SynthesizerTrnMs256NSFsid,
|
||||
SynthesizerTrnMs256NSFsid_nono,
|
||||
SynthesizerTrnMs768NSFsid,
|
||||
SynthesizerTrnMs768NSFsid_nono,
|
||||
)
|
||||
import soundfile as sf
|
||||
from fairseq import checkpoint_utils
|
||||
import gradio as gr
|
||||
import logging
|
||||
from vc_infer_pipeline import VC
|
||||
from config import Config
|
||||
from infer_uvr5 import _audio_pre_, _audio_pre_new
|
||||
from my_utils import load_audio
|
||||
from train.process_ckpt import show_info, change_info, merge, extract_small_model
|
||||
|
||||
config = Config()
|
||||
# from trainset_preprocess_pipeline import PreProcess
|
||||
logging.getLogger("numba").setLevel(logging.WARNING)
|
||||
|
||||
|
||||
class ToolButton(gr.Button, gr.components.FormComponent):
|
||||
@@ -163,7 +180,7 @@ def vc_single(
|
||||
if audio_max > 1:
|
||||
audio /= audio_max
|
||||
times = [0, 0, 0]
|
||||
if hubert_model == None:
|
||||
if not hubert_model:
|
||||
load_hubert()
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
file_index = (
|
||||
@@ -202,7 +219,7 @@ def vc_single(
|
||||
protect,
|
||||
f0_file=f0_file,
|
||||
)
|
||||
if resample_sr >= 16000 and tgt_sr != resample_sr:
|
||||
if tgt_sr != resample_sr >= 16000:
|
||||
tgt_sr = resample_sr
|
||||
index_info = (
|
||||
"Using index:%s." % file_index
|
||||
@@ -272,11 +289,24 @@ def vc_multi(
|
||||
if "Success" in info:
|
||||
try:
|
||||
tgt_sr, audio_opt = opt
|
||||
sf.write(
|
||||
"%s/%s.%s" % (opt_root, os.path.basename(path), format1),
|
||||
audio_opt,
|
||||
tgt_sr,
|
||||
)
|
||||
if format1 in ["wav", "flac"]:
|
||||
sf.write(
|
||||
"%s/%s.%s" % (opt_root, os.path.basename(path), format1),
|
||||
audio_opt,
|
||||
tgt_sr,
|
||||
)
|
||||
else:
|
||||
path = "%s/%s.wav" % (opt_root, os.path.basename(path))
|
||||
sf.write(
|
||||
path,
|
||||
audio_opt,
|
||||
tgt_sr,
|
||||
)
|
||||
if os.path.exists(path):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path, path[:-4] + ".%s" % format1)
|
||||
)
|
||||
except:
|
||||
info += traceback.format_exc()
|
||||
infos.append("%s->%s" % (os.path.basename(path), info))
|
||||
@@ -367,11 +397,11 @@ def uvr(model_name, inp_root, save_root_vocal, paths, save_root_ins, agg, format
|
||||
|
||||
|
||||
# 一个选项卡全局只能有一个音色
|
||||
def get_vc(sid):
|
||||
def get_vc(sid, to_return_protect0, to_return_protect1):
|
||||
global n_spk, tgt_sr, net_g, vc, cpt, version
|
||||
if sid == "" or sid == []:
|
||||
global hubert_model
|
||||
if hubert_model != None: # 考虑到轮询, 需要加个判断看是否 sid 是由有模型切换到无模型的
|
||||
if hubert_model is not None: # 考虑到轮询, 需要加个判断看是否 sid 是由有模型切换到无模型的
|
||||
print("clean_empty_cache")
|
||||
del net_g, n_spk, vc, hubert_model, tgt_sr # ,cpt
|
||||
hubert_model = net_g = n_spk = vc = hubert_model = tgt_sr = None
|
||||
@@ -405,6 +435,23 @@ def get_vc(sid):
|
||||
tgt_sr = cpt["config"][-1]
|
||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
if if_f0 == 0:
|
||||
to_return_protect0 = to_return_protect1 = {
|
||||
"visible": False,
|
||||
"value": 0.5,
|
||||
"__type__": "update",
|
||||
}
|
||||
else:
|
||||
to_return_protect0 = {
|
||||
"visible": True,
|
||||
"value": to_return_protect0,
|
||||
"__type__": "update",
|
||||
}
|
||||
to_return_protect1 = {
|
||||
"visible": True,
|
||||
"value": to_return_protect1,
|
||||
"__type__": "update",
|
||||
}
|
||||
version = cpt.get("version", "v1")
|
||||
if version == "v1":
|
||||
if if_f0 == 1:
|
||||
@@ -425,7 +472,11 @@ def get_vc(sid):
|
||||
net_g = net_g.float()
|
||||
vc = VC(tgt_sr, config)
|
||||
n_spk = cpt["config"][-3]
|
||||
return {"visible": True, "maximum": n_spk, "__type__": "update"}
|
||||
return (
|
||||
{"visible": True, "maximum": n_spk, "__type__": "update"},
|
||||
to_return_protect0,
|
||||
to_return_protect1,
|
||||
)
|
||||
|
||||
|
||||
def change_choices():
|
||||
@@ -457,7 +508,7 @@ sr_dict = {
|
||||
|
||||
def if_done(done, p):
|
||||
while 1:
|
||||
if p.poll() == None:
|
||||
if p.poll() is None:
|
||||
sleep(0.5)
|
||||
else:
|
||||
break
|
||||
@@ -470,7 +521,7 @@ def if_done_multi(done, ps):
|
||||
# 只要有一个进程未结束都不停
|
||||
flag = 1
|
||||
for p in ps:
|
||||
if p.poll() == None:
|
||||
if p.poll() is None:
|
||||
flag = 0
|
||||
sleep(0.5)
|
||||
break
|
||||
@@ -505,7 +556,7 @@ def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):
|
||||
with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
|
||||
yield (f.read())
|
||||
sleep(1)
|
||||
if done[0] == True:
|
||||
if done[0]:
|
||||
break
|
||||
with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
|
||||
log = f.read()
|
||||
@@ -543,7 +594,7 @@ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19):
|
||||
) as f:
|
||||
yield (f.read())
|
||||
sleep(1)
|
||||
if done[0] == True:
|
||||
if done[0]:
|
||||
break
|
||||
with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
|
||||
log = f.read()
|
||||
@@ -591,7 +642,7 @@ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19):
|
||||
with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
|
||||
yield (f.read())
|
||||
sleep(1)
|
||||
if done[0] == True:
|
||||
if done[0]:
|
||||
break
|
||||
with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
|
||||
log = f.read()
|
||||
@@ -600,43 +651,107 @@ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19):
|
||||
|
||||
|
||||
def change_sr2(sr2, if_f0_3, version19):
|
||||
vis_v = True if sr2 == "40k" else False
|
||||
if sr2 != "40k":
|
||||
version19 = "v1"
|
||||
path_str = "" if version19 == "v1" else "_v2"
|
||||
version_state = {"visible": vis_v, "__type__": "update"}
|
||||
if vis_v == False:
|
||||
version_state["value"] = "v1"
|
||||
f0_str = "f0" if if_f0_3 else ""
|
||||
if_pretrained_generator_exist = os.access(
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
|
||||
)
|
||||
if_pretrained_discriminator_exist = os.access(
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
|
||||
)
|
||||
if not if_pretrained_generator_exist:
|
||||
print(
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2),
|
||||
"not exist, will not use pretrained model",
|
||||
)
|
||||
if not if_pretrained_discriminator_exist:
|
||||
print(
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2),
|
||||
"not exist, will not use pretrained model",
|
||||
)
|
||||
return (
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2),
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2),
|
||||
version_state,
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
|
||||
if if_pretrained_generator_exist
|
||||
else "",
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
|
||||
if if_pretrained_discriminator_exist
|
||||
else "",
|
||||
)
|
||||
|
||||
|
||||
def change_version19(sr2, if_f0_3, version19):
|
||||
path_str = "" if version19 == "v1" else "_v2"
|
||||
if sr2 == "32k" and version19 == "v1":
|
||||
sr2 = "40k"
|
||||
to_return_sr2 = (
|
||||
{"choices": ["40k", "48k"], "__type__": "update", "value": sr2}
|
||||
if version19 == "v1"
|
||||
else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}
|
||||
)
|
||||
f0_str = "f0" if if_f0_3 else ""
|
||||
return "pretrained%s/%sG%s.pth" % (
|
||||
path_str,
|
||||
f0_str,
|
||||
sr2,
|
||||
), "pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
|
||||
if_pretrained_generator_exist = os.access(
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
|
||||
)
|
||||
if_pretrained_discriminator_exist = os.access(
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
|
||||
)
|
||||
if not if_pretrained_generator_exist:
|
||||
print(
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2),
|
||||
"not exist, will not use pretrained model",
|
||||
)
|
||||
if not if_pretrained_discriminator_exist:
|
||||
print(
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2),
|
||||
"not exist, will not use pretrained model",
|
||||
)
|
||||
return (
|
||||
"pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
|
||||
if if_pretrained_generator_exist
|
||||
else "",
|
||||
"pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
|
||||
if if_pretrained_discriminator_exist
|
||||
else "",
|
||||
to_return_sr2,
|
||||
)
|
||||
|
||||
|
||||
def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15
|
||||
path_str = "" if version19 == "v1" else "_v2"
|
||||
if_pretrained_generator_exist = os.access(
|
||||
"pretrained%s/f0G%s.pth" % (path_str, sr2), os.F_OK
|
||||
)
|
||||
if_pretrained_discriminator_exist = os.access(
|
||||
"pretrained%s/f0D%s.pth" % (path_str, sr2), os.F_OK
|
||||
)
|
||||
if not if_pretrained_generator_exist:
|
||||
print(
|
||||
"pretrained%s/f0G%s.pth" % (path_str, sr2),
|
||||
"not exist, will not use pretrained model",
|
||||
)
|
||||
if not if_pretrained_discriminator_exist:
|
||||
print(
|
||||
"pretrained%s/f0D%s.pth" % (path_str, sr2),
|
||||
"not exist, will not use pretrained model",
|
||||
)
|
||||
if if_f0_3:
|
||||
return (
|
||||
{"visible": True, "__type__": "update"},
|
||||
"pretrained%s/f0G%s.pth" % (path_str, sr2),
|
||||
"pretrained%s/f0D%s.pth" % (path_str, sr2),
|
||||
"pretrained%s/f0G%s.pth" % (path_str, sr2)
|
||||
if if_pretrained_generator_exist
|
||||
else "",
|
||||
"pretrained%s/f0D%s.pth" % (path_str, sr2)
|
||||
if if_pretrained_discriminator_exist
|
||||
else "",
|
||||
)
|
||||
return (
|
||||
{"visible": False, "__type__": "update"},
|
||||
"pretrained%s/G%s.pth" % (path_str, sr2),
|
||||
"pretrained%s/D%s.pth" % (path_str, sr2),
|
||||
("pretrained%s/G%s.pth" % (path_str, sr2))
|
||||
if if_pretrained_generator_exist
|
||||
else "",
|
||||
("pretrained%s/D%s.pth" % (path_str, sr2))
|
||||
if if_pretrained_discriminator_exist
|
||||
else "",
|
||||
)
|
||||
|
||||
|
||||
@@ -727,10 +842,14 @@ def click_train(
|
||||
# 生成config#无需生成config
|
||||
# cmd = python_cmd + " train_nsf_sim_cache_sid_load_pretrain.py -e mi-test -sr 40k -f0 1 -bs 4 -g 0 -te 10 -se 5 -pg pretrained/f0G40k.pth -pd pretrained/f0D40k.pth -l 1 -c 0"
|
||||
print("use gpus:", gpus16)
|
||||
if pretrained_G14 == "":
|
||||
print("no pretrained Generator")
|
||||
if pretrained_D15 == "":
|
||||
print("no pretrained Discriminator")
|
||||
if gpus16:
|
||||
cmd = (
|
||||
config.python_cmd
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -g %s -te %s -se %s -pg %s -pd %s -l %s -c %s -sw %s -v %s"
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s"
|
||||
% (
|
||||
exp_dir1,
|
||||
sr2,
|
||||
@@ -739,8 +858,8 @@ def click_train(
|
||||
gpus16,
|
||||
total_epoch11,
|
||||
save_epoch10,
|
||||
pretrained_G14,
|
||||
pretrained_D15,
|
||||
"-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
|
||||
"-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
|
||||
1 if if_save_latest13 == i18n("是") else 0,
|
||||
1 if if_cache_gpu17 == i18n("是") else 0,
|
||||
1 if if_save_every_weights18 == i18n("是") else 0,
|
||||
@@ -750,7 +869,7 @@ def click_train(
|
||||
else:
|
||||
cmd = (
|
||||
config.python_cmd
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -te %s -se %s -pg %s -pd %s -l %s -c %s -sw %s -v %s"
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s"
|
||||
% (
|
||||
exp_dir1,
|
||||
sr2,
|
||||
@@ -758,8 +877,8 @@ def click_train(
|
||||
batch_size12,
|
||||
total_epoch11,
|
||||
save_epoch10,
|
||||
pretrained_G14,
|
||||
pretrained_D15,
|
||||
"-pg %s" % pretrained_G14 if pretrained_G14 != "" else "\b",
|
||||
"-pd %s" % pretrained_D15 if pretrained_D15 != "" else "\b",
|
||||
1 if if_save_latest13 == i18n("是") else 0,
|
||||
1 if if_cache_gpu17 == i18n("是") else 0,
|
||||
1 if if_save_every_weights18 == i18n("是") else 0,
|
||||
@@ -781,11 +900,12 @@ def train_index(exp_dir1, version19):
|
||||
if version19 == "v1"
|
||||
else "%s/3_feature768" % (exp_dir)
|
||||
)
|
||||
if os.path.exists(feature_dir) == False:
|
||||
if not os.path.exists(feature_dir):
|
||||
return "请先进行特征提取!"
|
||||
listdir_res = list(os.listdir(feature_dir))
|
||||
if len(listdir_res) == 0:
|
||||
return "请先进行特征提取!"
|
||||
infos = []
|
||||
npys = []
|
||||
for name in sorted(listdir_res):
|
||||
phone = np.load("%s/%s" % (feature_dir, name))
|
||||
@@ -794,10 +914,30 @@ def train_index(exp_dir1, version19):
|
||||
big_npy_idx = np.arange(big_npy.shape[0])
|
||||
np.random.shuffle(big_npy_idx)
|
||||
big_npy = big_npy[big_npy_idx]
|
||||
if big_npy.shape[0] > 2e5:
|
||||
# if(1):
|
||||
infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
|
||||
yield "\n".join(infos)
|
||||
try:
|
||||
big_npy = (
|
||||
MiniBatchKMeans(
|
||||
n_clusters=10000,
|
||||
verbose=True,
|
||||
batch_size=256 * config.n_cpu,
|
||||
compute_labels=False,
|
||||
init="random",
|
||||
)
|
||||
.fit(big_npy)
|
||||
.cluster_centers_
|
||||
)
|
||||
except:
|
||||
info = traceback.format_exc()
|
||||
print(info)
|
||||
infos.append(info)
|
||||
yield "\n".join(infos)
|
||||
|
||||
np.save("%s/total_fea.npy" % exp_dir, big_npy)
|
||||
# n_ivf = big_npy.shape[0] // 39
|
||||
n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
|
||||
infos = []
|
||||
infos.append("%s,%s" % (big_npy.shape, n_ivf))
|
||||
yield "\n".join(infos)
|
||||
index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
|
||||
@@ -986,7 +1126,7 @@ def train1key(
|
||||
if gpus16:
|
||||
cmd = (
|
||||
config.python_cmd
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -g %s -te %s -se %s -pg %s -pd %s -l %s -c %s -sw %s -v %s"
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s"
|
||||
% (
|
||||
exp_dir1,
|
||||
sr2,
|
||||
@@ -995,8 +1135,8 @@ def train1key(
|
||||
gpus16,
|
||||
total_epoch11,
|
||||
save_epoch10,
|
||||
pretrained_G14,
|
||||
pretrained_D15,
|
||||
"-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
|
||||
"-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
|
||||
1 if if_save_latest13 == i18n("是") else 0,
|
||||
1 if if_cache_gpu17 == i18n("是") else 0,
|
||||
1 if if_save_every_weights18 == i18n("是") else 0,
|
||||
@@ -1006,7 +1146,7 @@ def train1key(
|
||||
else:
|
||||
cmd = (
|
||||
config.python_cmd
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -te %s -se %s -pg %s -pd %s -l %s -c %s -sw %s -v %s"
|
||||
+ " train_nsf_sim_cache_sid_load_pretrain.py -e %s -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s"
|
||||
% (
|
||||
exp_dir1,
|
||||
sr2,
|
||||
@@ -1014,8 +1154,8 @@ def train1key(
|
||||
batch_size12,
|
||||
total_epoch11,
|
||||
save_epoch10,
|
||||
pretrained_G14,
|
||||
pretrained_D15,
|
||||
"-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
|
||||
"-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
|
||||
1 if if_save_latest13 == i18n("是") else 0,
|
||||
1 if if_cache_gpu17 == i18n("是") else 0,
|
||||
1 if if_save_every_weights18 == i18n("是") else 0,
|
||||
@@ -1037,6 +1177,29 @@ def train1key(
|
||||
big_npy_idx = np.arange(big_npy.shape[0])
|
||||
np.random.shuffle(big_npy_idx)
|
||||
big_npy = big_npy[big_npy_idx]
|
||||
|
||||
if big_npy.shape[0] > 2e5:
|
||||
# if(1):
|
||||
info = "Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0]
|
||||
print(info)
|
||||
yield get_info_str(info)
|
||||
try:
|
||||
big_npy = (
|
||||
MiniBatchKMeans(
|
||||
n_clusters=10000,
|
||||
verbose=True,
|
||||
batch_size=256 * config.n_cpu,
|
||||
compute_labels=False,
|
||||
init="random",
|
||||
)
|
||||
.fit(big_npy)
|
||||
.cluster_centers_
|
||||
)
|
||||
except:
|
||||
info = traceback.format_exc()
|
||||
print(info)
|
||||
yield get_info_str(info)
|
||||
|
||||
np.save("%s/total_fea.npy" % model_log_dir, big_npy)
|
||||
|
||||
# n_ivf = big_npy.shape[0] // 39
|
||||
@@ -1070,10 +1233,7 @@ def train1key(
|
||||
|
||||
# ckpt_path2.change(change_info_,[ckpt_path2],[sr__,if_f0__])
|
||||
def change_info_(ckpt_path):
|
||||
if (
|
||||
os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log"))
|
||||
== False
|
||||
):
|
||||
if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):
|
||||
return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
|
||||
try:
|
||||
with open(
|
||||
@@ -1088,15 +1248,12 @@ def change_info_(ckpt_path):
|
||||
return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
|
||||
|
||||
|
||||
from infer_pack.models_onnx import SynthesizerTrnMsNSFsidM
|
||||
|
||||
|
||||
def export_onnx(ModelPath, ExportedPath, MoeVS=True):
|
||||
def export_onnx(ModelPath, ExportedPath):
|
||||
cpt = torch.load(ModelPath, map_location="cpu")
|
||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
||||
hidden_channels = cpt["config"][-2] # hidden_channels,为768Vec做准备
|
||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0]
|
||||
vec_channels = 256 if cpt.get("version", "v1") == "v1" else 768
|
||||
|
||||
test_phone = torch.rand(1, 200, hidden_channels) # hidden unit
|
||||
test_phone = torch.rand(1, 200, vec_channels) # hidden unit
|
||||
test_phone_lengths = torch.tensor([200]).long() # hidden unit 长度(貌似没啥用)
|
||||
test_pitch = torch.randint(size=(1, 200), low=5, high=255) # 基频(单位赫兹)
|
||||
test_pitchf = torch.rand(1, 200) # nsf基频
|
||||
@@ -1106,7 +1263,7 @@ def export_onnx(ModelPath, ExportedPath, MoeVS=True):
|
||||
device = "cpu" # 导出时设备(不影响使用模型)
|
||||
|
||||
net_g = SynthesizerTrnMsNSFsidM(
|
||||
*cpt["config"], is_half=False
|
||||
*cpt["config"], is_half=False, version=cpt.get("version", "v1")
|
||||
) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16)
|
||||
net_g.load_state_dict(cpt["weight"], strict=False)
|
||||
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
|
||||
@@ -1132,7 +1289,7 @@ def export_onnx(ModelPath, ExportedPath, MoeVS=True):
|
||||
"rnd": [2],
|
||||
},
|
||||
do_constant_folding=False,
|
||||
opset_version=16,
|
||||
opset_version=13,
|
||||
verbose=False,
|
||||
input_names=input_names,
|
||||
output_names=output_names,
|
||||
@@ -1162,11 +1319,6 @@ with gr.Blocks() as app:
|
||||
interactive=True,
|
||||
)
|
||||
clean_button.click(fn=clean, inputs=[], outputs=[sid0])
|
||||
sid0.change(
|
||||
fn=get_vc,
|
||||
inputs=[sid0],
|
||||
outputs=[spk_item],
|
||||
)
|
||||
with gr.Group():
|
||||
gr.Markdown(
|
||||
value=i18n("男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ")
|
||||
@@ -1309,6 +1461,11 @@ with gr.Blocks() as app:
|
||||
choices=sorted(index_paths),
|
||||
interactive=True,
|
||||
)
|
||||
refresh_button.click(
|
||||
fn=lambda: change_choices()[1],
|
||||
inputs=[],
|
||||
outputs=file_index4,
|
||||
)
|
||||
# file_big_npy2 = gr.Textbox(
|
||||
# label=i18n("特征文件路径"),
|
||||
# value="E:\\codes\\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
|
||||
@@ -1385,6 +1542,11 @@ with gr.Blocks() as app:
|
||||
],
|
||||
[vc_output3],
|
||||
)
|
||||
sid0.change(
|
||||
fn=get_vc,
|
||||
inputs=[sid0, protect0, protect1],
|
||||
outputs=[spk_item, protect0, protect1],
|
||||
)
|
||||
with gr.TabItem(i18n("伴奏人声分离&去混响&去回声")):
|
||||
with gr.Group():
|
||||
gr.Markdown(
|
||||
@@ -1395,8 +1557,8 @@ with gr.Blocks() as app:
|
||||
"1、保留人声:不带和声的音频选这个,对主人声保留比HP5更好。内置HP2和HP3两个模型,HP3可能轻微漏伴奏但对主人声保留比HP2稍微好一丁点; <br>"
|
||||
"2、仅保留主人声:带和声的音频选这个,对主人声可能有削弱。内置HP5一个模型; <br> "
|
||||
"3、去混响、去延迟模型(by FoxJoy):<br>"
|
||||
" (1)MDX-Net:对于双通道混响是最好的选择,不能去除单通道混响;<br>"
|
||||
" (234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底,DeReverb额外去除混响,可去除单声道混响,但是对高频重的板式混响去不干净。<br>"
|
||||
" (1)MDX-Net(onnx_dereverb):对于双通道混响是最好的选择,不能去除单通道混响;<br>"
|
||||
" (234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底,DeReverb额外去除混响,可去除单声道混响,但是对高频重的板式混响去不干净。<br>"
|
||||
"去混响/去延迟,附:<br>"
|
||||
"1、DeEcho-DeReverb模型的耗时是另外2个DeEcho模型的接近2倍;<br>"
|
||||
"2、MDX-Net-Dereverb模型挺慢的;<br>"
|
||||
@@ -1471,7 +1633,7 @@ with gr.Blocks() as app:
|
||||
interactive=True,
|
||||
)
|
||||
version19 = gr.Radio(
|
||||
label=i18n("版本(目前仅40k支持了v2)"),
|
||||
label=i18n("版本"),
|
||||
choices=["v1", "v2"],
|
||||
value="v1",
|
||||
interactive=True,
|
||||
@@ -1482,7 +1644,7 @@ with gr.Blocks() as app:
|
||||
maximum=config.n_cpu,
|
||||
step=1,
|
||||
label=i18n("提取音高和处理数据使用的CPU进程数"),
|
||||
value=config.n_cpu,
|
||||
value=int(np.ceil(config.n_cpu / 1.5)),
|
||||
interactive=True,
|
||||
)
|
||||
with gr.Group(): # 暂时单人的, 后面支持最多4人的#数据处理
|
||||
@@ -1595,12 +1757,12 @@ with gr.Blocks() as app:
|
||||
sr2.change(
|
||||
change_sr2,
|
||||
[sr2, if_f0_3, version19],
|
||||
[pretrained_G14, pretrained_D15, version19],
|
||||
[pretrained_G14, pretrained_D15],
|
||||
)
|
||||
version19.change(
|
||||
change_version19,
|
||||
[sr2, if_f0_3, version19],
|
||||
[pretrained_G14, pretrained_D15],
|
||||
[pretrained_G14, pretrained_D15, sr2],
|
||||
)
|
||||
if_f0_3.change(
|
||||
change_f0,
|
||||
@@ -1677,7 +1839,7 @@ with gr.Blocks() as app:
|
||||
with gr.Row():
|
||||
sr_ = gr.Radio(
|
||||
label=i18n("目标采样率"),
|
||||
choices=["32k", "40k", "48k"],
|
||||
choices=["40k", "48k"],
|
||||
value="40k",
|
||||
interactive=True,
|
||||
)
|
||||
@@ -1777,7 +1939,7 @@ with gr.Blocks() as app:
|
||||
version_1 = gr.Radio(
|
||||
label=i18n("模型版本型号"),
|
||||
choices=["v1", "v2"],
|
||||
value="v1",
|
||||
value="v2",
|
||||
interactive=True,
|
||||
)
|
||||
info___ = gr.Textbox(
|
||||
@@ -1802,11 +1964,10 @@ with gr.Blocks() as app:
|
||||
label=i18n("Onnx输出路径"), value="", interactive=True
|
||||
)
|
||||
with gr.Row():
|
||||
moevs = gr.Checkbox(label=i18n("MoeVS模型"), value=True)
|
||||
infoOnnx = gr.Label(label="Null")
|
||||
infoOnnx = gr.Label(label="info")
|
||||
with gr.Row():
|
||||
butOnnx = gr.Button(i18n("导出Onnx模型"), variant="primary")
|
||||
butOnnx.click(export_onnx, [ckpt_dir, onnx_dir, moevs], infoOnnx)
|
||||
butOnnx.click(export_onnx, [ckpt_dir, onnx_dir], infoOnnx)
|
||||
|
||||
tab_faq = i18n("常见问题解答")
|
||||
with gr.TabItem(tab_faq):
|
||||
|
||||
217
infer_batch_rvc.py
Normal file
217
infer_batch_rvc.py
Normal file
@@ -0,0 +1,217 @@
|
||||
"""
|
||||
v1
|
||||
runtime\python.exe myinfer-v2-0528.py 0 "E:\codes\py39\RVC-beta\todo-songs" "E:\codes\py39\logs\mi-test\added_IVF677_Flat_nprobe_7.index" harvest "E:\codes\py39\RVC-beta\output" "E:\codes\py39\test-20230416b\weights\mi-test.pth" 0.66 cuda:0 True 3 0 1 0.33
|
||||
v2
|
||||
runtime\python.exe myinfer-v2-0528.py 0 "E:\codes\py39\RVC-beta\todo-songs" "E:\codes\py39\test-20230416b\logs\mi-test-v2\aadded_IVF677_Flat_nprobe_1_v2.index" harvest "E:\codes\py39\RVC-beta\output_v2" "E:\codes\py39\test-20230416b\weights\mi-test-v2.pth" 0.66 cuda:0 True 3 0 1 0.33
|
||||
"""
|
||||
import os, sys, pdb, torch
|
||||
|
||||
now_dir = os.getcwd()
|
||||
sys.path.append(now_dir)
|
||||
import argparse
|
||||
import glob
|
||||
import sys
|
||||
import torch
|
||||
import tqdm as tq
|
||||
from multiprocessing import cpu_count
|
||||
|
||||
|
||||
class Config:
|
||||
def __init__(self, device, is_half):
|
||||
self.device = device
|
||||
self.is_half = is_half
|
||||
self.n_cpu = 0
|
||||
self.gpu_name = None
|
||||
self.gpu_mem = None
|
||||
self.x_pad, self.x_query, self.x_center, self.x_max = self.device_config()
|
||||
|
||||
def device_config(self) -> tuple:
|
||||
if torch.cuda.is_available():
|
||||
i_device = int(self.device.split(":")[-1])
|
||||
self.gpu_name = torch.cuda.get_device_name(i_device)
|
||||
if (
|
||||
("16" in self.gpu_name and "V100" not in self.gpu_name.upper())
|
||||
or "P40" in self.gpu_name.upper()
|
||||
or "1060" in self.gpu_name
|
||||
or "1070" in self.gpu_name
|
||||
or "1080" in self.gpu_name
|
||||
):
|
||||
print("16系/10系显卡和P40强制单精度")
|
||||
self.is_half = False
|
||||
for config_file in ["32k.json", "40k.json", "48k.json"]:
|
||||
with open(f"configs/{config_file}", "r") as f:
|
||||
strr = f.read().replace("true", "false")
|
||||
with open(f"configs/{config_file}", "w") as f:
|
||||
f.write(strr)
|
||||
with open("trainset_preprocess_pipeline_print.py", "r") as f:
|
||||
strr = f.read().replace("3.7", "3.0")
|
||||
with open("trainset_preprocess_pipeline_print.py", "w") as f:
|
||||
f.write(strr)
|
||||
else:
|
||||
self.gpu_name = None
|
||||
self.gpu_mem = int(
|
||||
torch.cuda.get_device_properties(i_device).total_memory
|
||||
/ 1024
|
||||
/ 1024
|
||||
/ 1024
|
||||
+ 0.4
|
||||
)
|
||||
if self.gpu_mem <= 4:
|
||||
with open("trainset_preprocess_pipeline_print.py", "r") as f:
|
||||
strr = f.read().replace("3.7", "3.0")
|
||||
with open("trainset_preprocess_pipeline_print.py", "w") as f:
|
||||
f.write(strr)
|
||||
elif torch.backends.mps.is_available():
|
||||
print("没有发现支持的N卡, 使用MPS进行推理")
|
||||
self.device = "mps"
|
||||
else:
|
||||
print("没有发现支持的N卡, 使用CPU进行推理")
|
||||
self.device = "cpu"
|
||||
self.is_half = True
|
||||
|
||||
if self.n_cpu == 0:
|
||||
self.n_cpu = cpu_count()
|
||||
|
||||
if self.is_half:
|
||||
# 6G显存配置
|
||||
x_pad = 3
|
||||
x_query = 10
|
||||
x_center = 60
|
||||
x_max = 65
|
||||
else:
|
||||
# 5G显存配置
|
||||
x_pad = 1
|
||||
x_query = 6
|
||||
x_center = 38
|
||||
x_max = 41
|
||||
|
||||
if self.gpu_mem != None and self.gpu_mem <= 4:
|
||||
x_pad = 1
|
||||
x_query = 5
|
||||
x_center = 30
|
||||
x_max = 32
|
||||
|
||||
return x_pad, x_query, x_center, x_max
|
||||
|
||||
|
||||
f0up_key = sys.argv[1]
|
||||
input_path = sys.argv[2]
|
||||
index_path = sys.argv[3]
|
||||
f0method = sys.argv[4] # harvest or pm
|
||||
opt_path = sys.argv[5]
|
||||
model_path = sys.argv[6]
|
||||
index_rate = float(sys.argv[7])
|
||||
device = sys.argv[8]
|
||||
is_half = bool(sys.argv[9])
|
||||
filter_radius = int(sys.argv[10])
|
||||
resample_sr = int(sys.argv[11])
|
||||
rms_mix_rate = float(sys.argv[12])
|
||||
protect = float(sys.argv[13])
|
||||
print(sys.argv)
|
||||
config = Config(device, is_half)
|
||||
now_dir = os.getcwd()
|
||||
sys.path.append(now_dir)
|
||||
from vc_infer_pipeline import VC
|
||||
from infer_pack.models import (
|
||||
SynthesizerTrnMs256NSFsid,
|
||||
SynthesizerTrnMs256NSFsid_nono,
|
||||
SynthesizerTrnMs768NSFsid,
|
||||
SynthesizerTrnMs768NSFsid_nono,
|
||||
)
|
||||
from my_utils import load_audio
|
||||
from fairseq import checkpoint_utils
|
||||
from scipy.io import wavfile
|
||||
|
||||
hubert_model = None
|
||||
|
||||
|
||||
def load_hubert():
|
||||
global hubert_model
|
||||
models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
|
||||
["hubert_base.pt"],
|
||||
suffix="",
|
||||
)
|
||||
hubert_model = models[0]
|
||||
hubert_model = hubert_model.to(device)
|
||||
if is_half:
|
||||
hubert_model = hubert_model.half()
|
||||
else:
|
||||
hubert_model = hubert_model.float()
|
||||
hubert_model.eval()
|
||||
|
||||
|
||||
def vc_single(sid, input_audio, f0_up_key, f0_file, f0_method, file_index, index_rate):
|
||||
global tgt_sr, net_g, vc, hubert_model, version
|
||||
if input_audio is None:
|
||||
return "You need to upload an audio", None
|
||||
f0_up_key = int(f0_up_key)
|
||||
audio = load_audio(input_audio, 16000)
|
||||
times = [0, 0, 0]
|
||||
if hubert_model == None:
|
||||
load_hubert()
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
# audio_opt=vc.pipeline(hubert_model,net_g,sid,audio,times,f0_up_key,f0_method,file_index,file_big_npy,index_rate,if_f0,f0_file=f0_file)
|
||||
audio_opt = vc.pipeline(
|
||||
hubert_model,
|
||||
net_g,
|
||||
sid,
|
||||
audio,
|
||||
input_audio,
|
||||
times,
|
||||
f0_up_key,
|
||||
f0_method,
|
||||
file_index,
|
||||
index_rate,
|
||||
if_f0,
|
||||
filter_radius,
|
||||
tgt_sr,
|
||||
resample_sr,
|
||||
rms_mix_rate,
|
||||
version,
|
||||
protect,
|
||||
f0_file=f0_file,
|
||||
)
|
||||
print(times)
|
||||
return audio_opt
|
||||
|
||||
|
||||
def get_vc(model_path):
|
||||
global n_spk, tgt_sr, net_g, vc, cpt, device, is_half, version
|
||||
print("loading pth %s" % model_path)
|
||||
cpt = torch.load(model_path, map_location="cpu")
|
||||
tgt_sr = cpt["config"][-1]
|
||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
||||
if_f0 = cpt.get("f0", 1)
|
||||
version = cpt.get("version", "v1")
|
||||
if version == "v1":
|
||||
if if_f0 == 1:
|
||||
net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=is_half)
|
||||
else:
|
||||
net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
|
||||
elif version == "v2":
|
||||
if if_f0 == 1: #
|
||||
net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=is_half)
|
||||
else:
|
||||
net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
|
||||
del net_g.enc_q
|
||||
print(net_g.load_state_dict(cpt["weight"], strict=False)) # 不加这一行清不干净,真奇葩
|
||||
net_g.eval().to(device)
|
||||
if is_half:
|
||||
net_g = net_g.half()
|
||||
else:
|
||||
net_g = net_g.float()
|
||||
vc = VC(tgt_sr, config)
|
||||
n_spk = cpt["config"][-3]
|
||||
# return {"visible": True,"maximum": n_spk, "__type__": "update"}
|
||||
|
||||
|
||||
get_vc(model_path)
|
||||
audios = os.listdir(input_path)
|
||||
for file in tq.tqdm(audios):
|
||||
if file.endswith(".wav"):
|
||||
file_path = input_path + "/" + file
|
||||
wav_opt = vc_single(
|
||||
0, file_path, f0up_key, None, f0method, index_path, index_rate
|
||||
)
|
||||
out_path = opt_path + "/" + file
|
||||
wavfile.write(out_path, tgt_sr, wav_opt)
|
||||
File diff suppressed because it is too large
Load Diff
90
infer_pack/modules/F0Predictor/DioF0Predictor.py
Normal file
90
infer_pack/modules/F0Predictor/DioF0Predictor.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
|
||||
import pyworld
|
||||
import numpy as np
|
||||
|
||||
|
||||
class DioF0Predictor(F0Predictor):
|
||||
def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
|
||||
self.hop_length = hop_length
|
||||
self.f0_min = f0_min
|
||||
self.f0_max = f0_max
|
||||
self.sampling_rate = sampling_rate
|
||||
|
||||
def interpolate_f0(self, f0):
|
||||
"""
|
||||
对F0进行插值处理
|
||||
"""
|
||||
|
||||
data = np.reshape(f0, (f0.size, 1))
|
||||
|
||||
vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
|
||||
vuv_vector[data > 0.0] = 1.0
|
||||
vuv_vector[data <= 0.0] = 0.0
|
||||
|
||||
ip_data = data
|
||||
|
||||
frame_number = data.size
|
||||
last_value = 0.0
|
||||
for i in range(frame_number):
|
||||
if data[i] <= 0.0:
|
||||
j = i + 1
|
||||
for j in range(i + 1, frame_number):
|
||||
if data[j] > 0.0:
|
||||
break
|
||||
if j < frame_number - 1:
|
||||
if last_value > 0.0:
|
||||
step = (data[j] - data[i - 1]) / float(j - i)
|
||||
for k in range(i, j):
|
||||
ip_data[k] = data[i - 1] + step * (k - i + 1)
|
||||
else:
|
||||
for k in range(i, j):
|
||||
ip_data[k] = data[j]
|
||||
else:
|
||||
for k in range(i, frame_number):
|
||||
ip_data[k] = last_value
|
||||
else:
|
||||
ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
|
||||
last_value = data[i]
|
||||
|
||||
return ip_data[:, 0], vuv_vector[:, 0]
|
||||
|
||||
def resize_f0(self, x, target_len):
|
||||
source = np.array(x)
|
||||
source[source < 0.001] = np.nan
|
||||
target = np.interp(
|
||||
np.arange(0, len(source) * target_len, len(source)) / target_len,
|
||||
np.arange(0, len(source)),
|
||||
source,
|
||||
)
|
||||
res = np.nan_to_num(target)
|
||||
return res
|
||||
|
||||
def compute_f0(self, wav, p_len=None):
|
||||
if p_len is None:
|
||||
p_len = wav.shape[0] // self.hop_length
|
||||
f0, t = pyworld.dio(
|
||||
wav.astype(np.double),
|
||||
fs=self.sampling_rate,
|
||||
f0_floor=self.f0_min,
|
||||
f0_ceil=self.f0_max,
|
||||
frame_period=1000 * self.hop_length / self.sampling_rate,
|
||||
)
|
||||
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
|
||||
for index, pitch in enumerate(f0):
|
||||
f0[index] = round(pitch, 1)
|
||||
return self.interpolate_f0(self.resize_f0(f0, p_len))[0]
|
||||
|
||||
def compute_f0_uv(self, wav, p_len=None):
|
||||
if p_len is None:
|
||||
p_len = wav.shape[0] // self.hop_length
|
||||
f0, t = pyworld.dio(
|
||||
wav.astype(np.double),
|
||||
fs=self.sampling_rate,
|
||||
f0_floor=self.f0_min,
|
||||
f0_ceil=self.f0_max,
|
||||
frame_period=1000 * self.hop_length / self.sampling_rate,
|
||||
)
|
||||
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
|
||||
for index, pitch in enumerate(f0):
|
||||
f0[index] = round(pitch, 1)
|
||||
return self.interpolate_f0(self.resize_f0(f0, p_len))
|
||||
16
infer_pack/modules/F0Predictor/F0Predictor.py
Normal file
16
infer_pack/modules/F0Predictor/F0Predictor.py
Normal file
@@ -0,0 +1,16 @@
|
||||
class F0Predictor(object):
|
||||
def compute_f0(self, wav, p_len):
|
||||
"""
|
||||
input: wav:[signal_length]
|
||||
p_len:int
|
||||
output: f0:[signal_length//hop_length]
|
||||
"""
|
||||
pass
|
||||
|
||||
def compute_f0_uv(self, wav, p_len):
|
||||
"""
|
||||
input: wav:[signal_length]
|
||||
p_len:int
|
||||
output: f0:[signal_length//hop_length],uv:[signal_length//hop_length]
|
||||
"""
|
||||
pass
|
||||
86
infer_pack/modules/F0Predictor/HarvestF0Predictor.py
Normal file
86
infer_pack/modules/F0Predictor/HarvestF0Predictor.py
Normal file
@@ -0,0 +1,86 @@
|
||||
from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
|
||||
import pyworld
|
||||
import numpy as np
|
||||
|
||||
|
||||
class HarvestF0Predictor(F0Predictor):
|
||||
def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
|
||||
self.hop_length = hop_length
|
||||
self.f0_min = f0_min
|
||||
self.f0_max = f0_max
|
||||
self.sampling_rate = sampling_rate
|
||||
|
||||
def interpolate_f0(self, f0):
|
||||
"""
|
||||
对F0进行插值处理
|
||||
"""
|
||||
|
||||
data = np.reshape(f0, (f0.size, 1))
|
||||
|
||||
vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
|
||||
vuv_vector[data > 0.0] = 1.0
|
||||
vuv_vector[data <= 0.0] = 0.0
|
||||
|
||||
ip_data = data
|
||||
|
||||
frame_number = data.size
|
||||
last_value = 0.0
|
||||
for i in range(frame_number):
|
||||
if data[i] <= 0.0:
|
||||
j = i + 1
|
||||
for j in range(i + 1, frame_number):
|
||||
if data[j] > 0.0:
|
||||
break
|
||||
if j < frame_number - 1:
|
||||
if last_value > 0.0:
|
||||
step = (data[j] - data[i - 1]) / float(j - i)
|
||||
for k in range(i, j):
|
||||
ip_data[k] = data[i - 1] + step * (k - i + 1)
|
||||
else:
|
||||
for k in range(i, j):
|
||||
ip_data[k] = data[j]
|
||||
else:
|
||||
for k in range(i, frame_number):
|
||||
ip_data[k] = last_value
|
||||
else:
|
||||
ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
|
||||
last_value = data[i]
|
||||
|
||||
return ip_data[:, 0], vuv_vector[:, 0]
|
||||
|
||||
def resize_f0(self, x, target_len):
|
||||
source = np.array(x)
|
||||
source[source < 0.001] = np.nan
|
||||
target = np.interp(
|
||||
np.arange(0, len(source) * target_len, len(source)) / target_len,
|
||||
np.arange(0, len(source)),
|
||||
source,
|
||||
)
|
||||
res = np.nan_to_num(target)
|
||||
return res
|
||||
|
||||
def compute_f0(self, wav, p_len=None):
|
||||
if p_len is None:
|
||||
p_len = wav.shape[0] // self.hop_length
|
||||
f0, t = pyworld.harvest(
|
||||
wav.astype(np.double),
|
||||
fs=self.hop_length,
|
||||
f0_ceil=self.f0_max,
|
||||
f0_floor=self.f0_min,
|
||||
frame_period=1000 * self.hop_length / self.sampling_rate,
|
||||
)
|
||||
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.fs)
|
||||
return self.interpolate_f0(self.resize_f0(f0, p_len))[0]
|
||||
|
||||
def compute_f0_uv(self, wav, p_len=None):
|
||||
if p_len is None:
|
||||
p_len = wav.shape[0] // self.hop_length
|
||||
f0, t = pyworld.harvest(
|
||||
wav.astype(np.double),
|
||||
fs=self.sampling_rate,
|
||||
f0_floor=self.f0_min,
|
||||
f0_ceil=self.f0_max,
|
||||
frame_period=1000 * self.hop_length / self.sampling_rate,
|
||||
)
|
||||
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
|
||||
return self.interpolate_f0(self.resize_f0(f0, p_len))
|
||||
97
infer_pack/modules/F0Predictor/PMF0Predictor.py
Normal file
97
infer_pack/modules/F0Predictor/PMF0Predictor.py
Normal file
@@ -0,0 +1,97 @@
|
||||
from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
|
||||
import parselmouth
|
||||
import numpy as np
|
||||
|
||||
|
||||
class PMF0Predictor(F0Predictor):
|
||||
def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
|
||||
self.hop_length = hop_length
|
||||
self.f0_min = f0_min
|
||||
self.f0_max = f0_max
|
||||
self.sampling_rate = sampling_rate
|
||||
|
||||
def interpolate_f0(self, f0):
|
||||
"""
|
||||
对F0进行插值处理
|
||||
"""
|
||||
|
||||
data = np.reshape(f0, (f0.size, 1))
|
||||
|
||||
vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
|
||||
vuv_vector[data > 0.0] = 1.0
|
||||
vuv_vector[data <= 0.0] = 0.0
|
||||
|
||||
ip_data = data
|
||||
|
||||
frame_number = data.size
|
||||
last_value = 0.0
|
||||
for i in range(frame_number):
|
||||
if data[i] <= 0.0:
|
||||
j = i + 1
|
||||
for j in range(i + 1, frame_number):
|
||||
if data[j] > 0.0:
|
||||
break
|
||||
if j < frame_number - 1:
|
||||
if last_value > 0.0:
|
||||
step = (data[j] - data[i - 1]) / float(j - i)
|
||||
for k in range(i, j):
|
||||
ip_data[k] = data[i - 1] + step * (k - i + 1)
|
||||
else:
|
||||
for k in range(i, j):
|
||||
ip_data[k] = data[j]
|
||||
else:
|
||||
for k in range(i, frame_number):
|
||||
ip_data[k] = last_value
|
||||
else:
|
||||
ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
|
||||
last_value = data[i]
|
||||
|
||||
return ip_data[:, 0], vuv_vector[:, 0]
|
||||
|
||||
def compute_f0(self, wav, p_len=None):
|
||||
x = wav
|
||||
if p_len is None:
|
||||
p_len = x.shape[0] // self.hop_length
|
||||
else:
|
||||
assert abs(p_len - x.shape[0] // self.hop_length) < 4, "pad length error"
|
||||
time_step = self.hop_length / self.sampling_rate * 1000
|
||||
f0 = (
|
||||
parselmouth.Sound(x, self.sampling_rate)
|
||||
.to_pitch_ac(
|
||||
time_step=time_step / 1000,
|
||||
voicing_threshold=0.6,
|
||||
pitch_floor=self.f0_min,
|
||||
pitch_ceiling=self.f0_max,
|
||||
)
|
||||
.selected_array["frequency"]
|
||||
)
|
||||
|
||||
pad_size = (p_len - len(f0) + 1) // 2
|
||||
if pad_size > 0 or p_len - len(f0) - pad_size > 0:
|
||||
f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
|
||||
f0, uv = self.interpolate_f0(f0)
|
||||
return f0
|
||||
|
||||
def compute_f0_uv(self, wav, p_len=None):
|
||||
x = wav
|
||||
if p_len is None:
|
||||
p_len = x.shape[0] // self.hop_length
|
||||
else:
|
||||
assert abs(p_len - x.shape[0] // self.hop_length) < 4, "pad length error"
|
||||
time_step = self.hop_length / self.sampling_rate * 1000
|
||||
f0 = (
|
||||
parselmouth.Sound(x, self.sampling_rate)
|
||||
.to_pitch_ac(
|
||||
time_step=time_step / 1000,
|
||||
voicing_threshold=0.6,
|
||||
pitch_floor=self.f0_min,
|
||||
pitch_ceiling=self.f0_max,
|
||||
)
|
||||
.selected_array["frequency"]
|
||||
)
|
||||
|
||||
pad_size = (p_len - len(f0) + 1) // 2
|
||||
if pad_size > 0 or p_len - len(f0) - pad_size > 0:
|
||||
f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
|
||||
f0, uv = self.interpolate_f0(f0)
|
||||
return f0, uv
|
||||
0
infer_pack/modules/F0Predictor/__init__.py
Normal file
0
infer_pack/modules/F0Predictor/__init__.py
Normal file
143
infer_pack/onnx_inference.py
Normal file
143
infer_pack/onnx_inference.py
Normal file
@@ -0,0 +1,143 @@
|
||||
import onnxruntime
|
||||
import librosa
|
||||
import numpy as np
|
||||
import soundfile
|
||||
|
||||
|
||||
class ContentVec:
|
||||
def __init__(self, vec_path="pretrained/vec-768-layer-12.onnx", device=None):
|
||||
print("load model(s) from {}".format(vec_path))
|
||||
if device == "cpu" or device is None:
|
||||
providers = ["CPUExecutionProvider"]
|
||||
elif device == "cuda":
|
||||
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
|
||||
elif device == "dml":
|
||||
providers = ["DmlExecutionProvider"]
|
||||
else:
|
||||
raise RuntimeError("Unsportted Device")
|
||||
self.model = onnxruntime.InferenceSession(vec_path, providers=providers)
|
||||
|
||||
def __call__(self, wav):
|
||||
return self.forward(wav)
|
||||
|
||||
def forward(self, wav):
|
||||
feats = wav
|
||||
if feats.ndim == 2: # double channels
|
||||
feats = feats.mean(-1)
|
||||
assert feats.ndim == 1, feats.ndim
|
||||
feats = np.expand_dims(np.expand_dims(feats, 0), 0)
|
||||
onnx_input = {self.model.get_inputs()[0].name: feats}
|
||||
logits = self.model.run(None, onnx_input)[0]
|
||||
return logits.transpose(0, 2, 1)
|
||||
|
||||
|
||||
def get_f0_predictor(f0_predictor, hop_length, sampling_rate, **kargs):
|
||||
if f0_predictor == "pm":
|
||||
from infer_pack.modules.F0Predictor.PMF0Predictor import PMF0Predictor
|
||||
|
||||
f0_predictor_object = PMF0Predictor(
|
||||
hop_length=hop_length, sampling_rate=sampling_rate
|
||||
)
|
||||
elif f0_predictor == "harvest":
|
||||
from infer_pack.modules.F0Predictor.HarvestF0Predictor import HarvestF0Predictor
|
||||
|
||||
f0_predictor_object = HarvestF0Predictor(
|
||||
hop_length=hop_length, sampling_rate=sampling_rate
|
||||
)
|
||||
elif f0_predictor == "dio":
|
||||
from infer_pack.modules.F0Predictor.DioF0Predictor import DioF0Predictor
|
||||
|
||||
f0_predictor_object = DioF0Predictor(
|
||||
hop_length=hop_length, sampling_rate=sampling_rate
|
||||
)
|
||||
else:
|
||||
raise Exception("Unknown f0 predictor")
|
||||
return f0_predictor_object
|
||||
|
||||
|
||||
class OnnxRVC:
|
||||
def __init__(
|
||||
self,
|
||||
model_path,
|
||||
sr=40000,
|
||||
hop_size=512,
|
||||
vec_path="vec-768-layer-12",
|
||||
device="cpu",
|
||||
):
|
||||
vec_path = f"pretrained/{vec_path}.onnx"
|
||||
self.vec_model = ContentVec(vec_path, device)
|
||||
if device == "cpu" or device is None:
|
||||
providers = ["CPUExecutionProvider"]
|
||||
elif device == "cuda":
|
||||
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
|
||||
elif device == "dml":
|
||||
providers = ["DmlExecutionProvider"]
|
||||
else:
|
||||
raise RuntimeError("Unsportted Device")
|
||||
self.model = onnxruntime.InferenceSession(model_path, providers=providers)
|
||||
self.sampling_rate = sr
|
||||
self.hop_size = hop_size
|
||||
|
||||
def forward(self, hubert, hubert_length, pitch, pitchf, ds, rnd):
|
||||
onnx_input = {
|
||||
self.model.get_inputs()[0].name: hubert,
|
||||
self.model.get_inputs()[1].name: hubert_length,
|
||||
self.model.get_inputs()[2].name: pitch,
|
||||
self.model.get_inputs()[3].name: pitchf,
|
||||
self.model.get_inputs()[4].name: ds,
|
||||
self.model.get_inputs()[5].name: rnd,
|
||||
}
|
||||
return (self.model.run(None, onnx_input)[0] * 32767).astype(np.int16)
|
||||
|
||||
def inference(
|
||||
self,
|
||||
raw_path,
|
||||
sid,
|
||||
f0_method="dio",
|
||||
f0_up_key=0,
|
||||
pad_time=0.5,
|
||||
cr_threshold=0.02,
|
||||
):
|
||||
f0_min = 50
|
||||
f0_max = 1100
|
||||
f0_mel_min = 1127 * np.log(1 + f0_min / 700)
|
||||
f0_mel_max = 1127 * np.log(1 + f0_max / 700)
|
||||
f0_predictor = get_f0_predictor(
|
||||
f0_method,
|
||||
hop_length=self.hop_size,
|
||||
sampling_rate=self.sampling_rate,
|
||||
threshold=cr_threshold,
|
||||
)
|
||||
wav, sr = librosa.load(raw_path, sr=self.sampling_rate)
|
||||
org_length = len(wav)
|
||||
if org_length / sr > 50.0:
|
||||
raise RuntimeError("Reached Max Length")
|
||||
|
||||
wav16k = librosa.resample(wav, orig_sr=self.sampling_rate, target_sr=16000)
|
||||
wav16k = wav16k
|
||||
|
||||
hubert = self.vec_model(wav16k)
|
||||
hubert = np.repeat(hubert, 2, axis=2).transpose(0, 2, 1).astype(np.float32)
|
||||
hubert_length = hubert.shape[1]
|
||||
|
||||
pitchf = f0_predictor.compute_f0(wav, hubert_length)
|
||||
pitchf = pitchf * 2 ** (f0_up_key / 12)
|
||||
pitch = pitchf.copy()
|
||||
f0_mel = 1127 * np.log(1 + pitch / 700)
|
||||
f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - f0_mel_min) * 254 / (
|
||||
f0_mel_max - f0_mel_min
|
||||
) + 1
|
||||
f0_mel[f0_mel <= 1] = 1
|
||||
f0_mel[f0_mel > 255] = 255
|
||||
pitch = np.rint(f0_mel).astype(np.int64)
|
||||
|
||||
pitchf = pitchf.reshape(1, len(pitchf)).astype(np.float32)
|
||||
pitch = pitch.reshape(1, len(pitch))
|
||||
ds = np.array([sid]).astype(np.int64)
|
||||
|
||||
rnd = np.random.randn(1, 192, hubert_length).astype(np.float32)
|
||||
hubert_length = np.array([hubert_length]).astype(np.int64)
|
||||
|
||||
out_wav = self.forward(hubert, hubert_length, pitch, pitchf, ds, rnd).squeeze()
|
||||
out_wav = np.pad(out_wav, (0, 2 * self.hop_size), "constant")
|
||||
return out_wav[0:org_length]
|
||||
122
infer_uvr5.py
122
infer_uvr5.py
@@ -123,14 +123,29 @@ class _audio_pre_:
|
||||
else:
|
||||
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
|
||||
print("%s instruments done" % name)
|
||||
sf.write(
|
||||
os.path.join(
|
||||
ins_root,
|
||||
"instrument_{}_{}.{}".format(name, self.data["agg"], format),
|
||||
),
|
||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
) #
|
||||
if format in ["wav", "flac"]:
|
||||
sf.write(
|
||||
os.path.join(
|
||||
ins_root,
|
||||
"instrument_{}_{}.{}".format(name, self.data["agg"], format),
|
||||
),
|
||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
) #
|
||||
else:
|
||||
path = os.path.join(
|
||||
ins_root, "instrument_{}_{}.wav".format(name, self.data["agg"])
|
||||
)
|
||||
sf.write(
|
||||
path,
|
||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
if os.path.exists(path):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path, path[:-4] + ".%s" % format)
|
||||
)
|
||||
if vocal_root is not None:
|
||||
if self.data["high_end_process"].startswith("mirroring"):
|
||||
input_high_end_ = spec_utils.mirroring(
|
||||
@@ -142,13 +157,29 @@ class _audio_pre_:
|
||||
else:
|
||||
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
|
||||
print("%s vocals done" % name)
|
||||
sf.write(
|
||||
os.path.join(
|
||||
vocal_root, "vocal_{}_{}.{}".format(name, self.data["agg"], format)
|
||||
),
|
||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
if format in ["wav", "flac"]:
|
||||
sf.write(
|
||||
os.path.join(
|
||||
vocal_root,
|
||||
"vocal_{}_{}.{}".format(name, self.data["agg"], format),
|
||||
),
|
||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
else:
|
||||
path = os.path.join(
|
||||
vocal_root, "vocal_{}_{}.wav".format(name, self.data["agg"])
|
||||
)
|
||||
sf.write(
|
||||
path,
|
||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
if os.path.exists(path):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path, path[:-4] + ".%s" % format)
|
||||
)
|
||||
|
||||
|
||||
class _audio_pre_new:
|
||||
@@ -259,14 +290,29 @@ class _audio_pre_new:
|
||||
else:
|
||||
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
|
||||
print("%s instruments done" % name)
|
||||
sf.write(
|
||||
os.path.join(
|
||||
ins_root,
|
||||
"main_vocal_{}_{}.{}".format(name, self.data["agg"], format),
|
||||
),
|
||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
) #
|
||||
if format in ["wav", "flac"]:
|
||||
sf.write(
|
||||
os.path.join(
|
||||
ins_root,
|
||||
"instrument_{}_{}.{}".format(name, self.data["agg"], format),
|
||||
),
|
||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
) #
|
||||
else:
|
||||
path = os.path.join(
|
||||
ins_root, "instrument_{}_{}.wav".format(name, self.data["agg"])
|
||||
)
|
||||
sf.write(
|
||||
path,
|
||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
if os.path.exists(path):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path, path[:-4] + ".%s" % format)
|
||||
)
|
||||
if vocal_root is not None:
|
||||
if self.data["high_end_process"].startswith("mirroring"):
|
||||
input_high_end_ = spec_utils.mirroring(
|
||||
@@ -278,13 +324,29 @@ class _audio_pre_new:
|
||||
else:
|
||||
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
|
||||
print("%s vocals done" % name)
|
||||
sf.write(
|
||||
os.path.join(
|
||||
vocal_root, "others_{}_{}.{}".format(name, self.data["agg"], format)
|
||||
),
|
||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
if format in ["wav", "flac"]:
|
||||
sf.write(
|
||||
os.path.join(
|
||||
vocal_root,
|
||||
"vocal_{}_{}.{}".format(name, self.data["agg"], format),
|
||||
),
|
||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
else:
|
||||
path = os.path.join(
|
||||
vocal_root, "vocal_{}_{}.wav".format(name, self.data["agg"])
|
||||
)
|
||||
sf.write(
|
||||
path,
|
||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||
self.mp.param["sr"],
|
||||
)
|
||||
if os.path.exists(path):
|
||||
os.system(
|
||||
"ffmpeg -i %s -vn %s -q:a 2 -y"
|
||||
% (path, path[:-4] + ".%s" % format)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
20
onnx_inference_demo.py
Normal file
20
onnx_inference_demo.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import soundfile
|
||||
from infer_pack.onnx_inference import OnnxRVC
|
||||
|
||||
hop_size = 512
|
||||
sampling_rate = 40000 # 采样率
|
||||
f0_up_key = 0 # 升降调
|
||||
sid = 0 # 角色ID
|
||||
f0_method = "dio" # F0提取算法
|
||||
model_path = "ShirohaRVC.onnx" # 模型的完整路径
|
||||
vec_name = "vec-256-layer-9" # 内部自动补齐为 f"pretrained/{vec_name}.onnx" 需要onnx的vec模型
|
||||
wav_path = "123.wav" # 输入路径或ByteIO实例
|
||||
out_path = "out.wav" # 输出路径或ByteIO实例
|
||||
|
||||
model = OnnxRVC(
|
||||
model_path, vec_path=vec_name, sr=sampling_rate, hop_size=hop_size, device="cuda"
|
||||
)
|
||||
|
||||
audio = model.inference(wav_path, sid, f0_method=f0_method, f0_up_key=f0_up_key)
|
||||
|
||||
soundfile.write(out_path, audio, sampling_rate)
|
||||
16
poetry.lock
generated
16
poetry.lock
generated
@@ -813,19 +813,19 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "fastapi"
|
||||
version = "0.95.0"
|
||||
version = "0.95.2"
|
||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "fastapi-0.95.0-py3-none-any.whl", hash = "sha256:daf73bbe844180200be7966f68e8ec9fd8be57079dff1bacb366db32729e6eb5"},
|
||||
{file = "fastapi-0.95.0.tar.gz", hash = "sha256:99d4fdb10e9dd9a24027ac1d0bd4b56702652056ca17a6c8721eec4ad2f14e18"},
|
||||
{file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"},
|
||||
{file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
|
||||
starlette = ">=0.26.1,<0.27.0"
|
||||
starlette = ">=0.27.0,<0.28.0"
|
||||
|
||||
[package.extras]
|
||||
all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
||||
@@ -3376,14 +3376,14 @@ numpy = ["numpy"]
|
||||
|
||||
[[package]]
|
||||
name = "starlette"
|
||||
version = "0.26.1"
|
||||
version = "0.27.0"
|
||||
description = "The little ASGI library that shines."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "starlette-0.26.1-py3-none-any.whl", hash = "sha256:e87fce5d7cbdde34b76f0ac69013fd9d190d581d80681493016666e6f96c6d5e"},
|
||||
{file = "starlette-0.26.1.tar.gz", hash = "sha256:41da799057ea8620e4667a3e69a5b1923ebd32b1819c8fa75634bbe8d8bea9bd"},
|
||||
{file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
|
||||
{file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -4005,4 +4005,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.8,<3.11"
|
||||
content-hash = "82157a97aee3fd582e02f4ea0d7dd5c494a52d93e7cc62c3a4d1dffd39e50353"
|
||||
content-hash = "309a8ea8b898a89daf57e99dc285f7a36914aa7eb821b5a24253bc034277293e"
|
||||
|
||||
@@ -6,7 +6,7 @@ authors = ["lj1995"]
|
||||
license = "MIT"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8,<3.11"
|
||||
python = "^3.8"
|
||||
torch = "^2.0.0"
|
||||
torchaudio = "^2.0.1"
|
||||
Cython = "^0.29.34"
|
||||
@@ -34,7 +34,7 @@ Pillow = "9.3.0"
|
||||
pyworld = "^0.3.2"
|
||||
resampy = "^0.4.2"
|
||||
scikit-learn = "^1.2.2"
|
||||
starlette = "^0.26.1"
|
||||
starlette = "^0.27.0"
|
||||
tensorboard = "^2.12.1"
|
||||
tensorboard-data-server = "^0.7.0"
|
||||
tensorboard-plugin-wit = "^1.8.1"
|
||||
|
||||
@@ -2,11 +2,11 @@ joblib>=1.1.0
|
||||
numba==0.56.4
|
||||
numpy==1.23.5
|
||||
scipy==1.9.3
|
||||
librosa==0.9.2
|
||||
librosa==0.9.1
|
||||
llvmlite==0.39.0
|
||||
fairseq==0.12.2
|
||||
faiss-cpu==1.7.3
|
||||
gradio
|
||||
gradio==3.14.0
|
||||
Cython
|
||||
pydub>=0.25.1
|
||||
soundfile>=0.12.1
|
||||
@@ -40,4 +40,4 @@ colorama>=0.4.5
|
||||
pyworld>=0.3.2
|
||||
httpx==0.23.0
|
||||
onnxruntime-gpu
|
||||
torchcrepe
|
||||
torchcrepe==0.0.20
|
||||
|
||||
@@ -38,7 +38,7 @@ class TextAudioLoaderMultiNSFsid(torch.utils.data.Dataset):
|
||||
for audiopath, text, pitch, pitchf, dv in self.audiopaths_and_text:
|
||||
if self.min_text_len <= len(text) and len(text) <= self.max_text_len:
|
||||
audiopaths_and_text_new.append([audiopath, text, pitch, pitchf, dv])
|
||||
lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length))
|
||||
lengths.append(os.path.getsize(audiopath) // (3 * self.hop_length))
|
||||
self.audiopaths_and_text = audiopaths_and_text_new
|
||||
self.lengths = lengths
|
||||
|
||||
@@ -246,7 +246,7 @@ class TextAudioLoader(torch.utils.data.Dataset):
|
||||
for audiopath, text, dv in self.audiopaths_and_text:
|
||||
if self.min_text_len <= len(text) and len(text) <= self.max_text_len:
|
||||
audiopaths_and_text_new.append([audiopath, text, dv])
|
||||
lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length))
|
||||
lengths.append(os.path.getsize(audiopath) // (3 * self.hop_length))
|
||||
self.audiopaths_and_text = audiopaths_and_text_new
|
||||
self.lengths = lengths
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from i18n import I18nAuto
|
||||
i18n = I18nAuto()
|
||||
|
||||
|
||||
def savee(ckpt, sr, if_f0, name, epoch, version):
|
||||
def savee(ckpt, sr, if_f0, name, epoch, version, hps):
|
||||
try:
|
||||
opt = OrderedDict()
|
||||
opt["weight"] = {}
|
||||
@@ -16,69 +16,26 @@ def savee(ckpt, sr, if_f0, name, epoch, version):
|
||||
if "enc_q" in key:
|
||||
continue
|
||||
opt["weight"][key] = ckpt[key].half()
|
||||
if sr == "40k":
|
||||
opt["config"] = [
|
||||
1025,
|
||||
32,
|
||||
192,
|
||||
192,
|
||||
768,
|
||||
2,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
"1",
|
||||
[3, 7, 11],
|
||||
[[1, 3, 5], [1, 3, 5], [1, 3, 5]],
|
||||
[10, 10, 2, 2],
|
||||
512,
|
||||
[16, 16, 4, 4],
|
||||
109,
|
||||
256,
|
||||
40000,
|
||||
]
|
||||
elif sr == "48k":
|
||||
opt["config"] = [
|
||||
1025,
|
||||
32,
|
||||
192,
|
||||
192,
|
||||
768,
|
||||
2,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
"1",
|
||||
[3, 7, 11],
|
||||
[[1, 3, 5], [1, 3, 5], [1, 3, 5]],
|
||||
[10, 6, 2, 2, 2],
|
||||
512,
|
||||
[16, 16, 4, 4, 4],
|
||||
109,
|
||||
256,
|
||||
48000,
|
||||
]
|
||||
elif sr == "32k":
|
||||
opt["config"] = [
|
||||
513,
|
||||
32,
|
||||
192,
|
||||
192,
|
||||
768,
|
||||
2,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
"1",
|
||||
[3, 7, 11],
|
||||
[[1, 3, 5], [1, 3, 5], [1, 3, 5]],
|
||||
[10, 4, 2, 2, 2],
|
||||
512,
|
||||
[16, 16, 4, 4, 4],
|
||||
109,
|
||||
256,
|
||||
32000,
|
||||
]
|
||||
opt["config"] = [
|
||||
hps.data.filter_length // 2 + 1,
|
||||
32,
|
||||
hps.model.inter_channels,
|
||||
hps.model.hidden_channels,
|
||||
hps.model.filter_channels,
|
||||
hps.model.n_heads,
|
||||
hps.model.n_layers,
|
||||
hps.model.kernel_size,
|
||||
hps.model.p_dropout,
|
||||
hps.model.resblock,
|
||||
hps.model.resblock_kernel_sizes,
|
||||
hps.model.resblock_dilation_sizes,
|
||||
hps.model.upsample_rates,
|
||||
hps.model.upsample_initial_channel,
|
||||
hps.model.upsample_kernel_sizes,
|
||||
hps.model.spk_embed_dim,
|
||||
hps.model.gin_channels,
|
||||
hps.data.sampling_rate,
|
||||
]
|
||||
opt["info"] = "%sepoch" % epoch
|
||||
opt["sr"] = sr
|
||||
opt["f0"] = if_f0
|
||||
|
||||
@@ -360,7 +360,10 @@ def get_hparams(init=True):
|
||||
if not os.path.exists(experiment_dir):
|
||||
os.makedirs(experiment_dir)
|
||||
|
||||
config_path = "configs/%s.json" % args.sample_rate
|
||||
if args.version == "v1" or args.sample_rate == "40k":
|
||||
config_path = "configs/%s.json" % args.sample_rate
|
||||
else:
|
||||
config_path = "configs/%s_v2.json" % args.sample_rate
|
||||
config_save_path = os.path.join(experiment_dir, "config.json")
|
||||
if init:
|
||||
with open(config_path, "r") as f:
|
||||
|
||||
@@ -9,7 +9,7 @@ import datetime
|
||||
hps = utils.get_hparams()
|
||||
os.environ["CUDA_VISIBLE_DEVICES"] = hps.gpus.replace("-", ",")
|
||||
n_gpus = len(hps.gpus.split("-"))
|
||||
from random import shuffle
|
||||
from random import shuffle, randint
|
||||
import traceback, json, argparse, itertools, math, torch, pdb
|
||||
|
||||
torch.backends.cudnn.deterministic = False
|
||||
@@ -67,9 +67,10 @@ class EpochRecorder:
|
||||
|
||||
def main():
|
||||
n_gpus = torch.cuda.device_count()
|
||||
if torch.cuda.is_available() == False and torch.backends.mps.is_available() == True:
|
||||
n_gpus = 1
|
||||
os.environ["MASTER_ADDR"] = "localhost"
|
||||
os.environ["MASTER_PORT"] = "51545"
|
||||
|
||||
os.environ["MASTER_PORT"] = str(randint(20000, 55555))
|
||||
children = []
|
||||
for i in range(n_gpus):
|
||||
subproc = mp.Process(
|
||||
@@ -190,18 +191,22 @@ def run(rank, n_gpus, hps):
|
||||
# traceback.print_exc()
|
||||
epoch_str = 1
|
||||
global_step = 0
|
||||
if rank == 0:
|
||||
logger.info("loaded pretrained %s %s" % (hps.pretrainG, hps.pretrainD))
|
||||
print(
|
||||
net_g.module.load_state_dict(
|
||||
torch.load(hps.pretrainG, map_location="cpu")["model"]
|
||||
if hps.pretrainG != "":
|
||||
if rank == 0:
|
||||
logger.info("loaded pretrained %s" % (hps.pretrainG))
|
||||
print(
|
||||
net_g.module.load_state_dict(
|
||||
torch.load(hps.pretrainG, map_location="cpu")["model"]
|
||||
)
|
||||
) ##测试不加载优化器
|
||||
if hps.pretrainD != "":
|
||||
if rank == 0:
|
||||
logger.info("loaded pretrained %s" % (hps.pretrainD))
|
||||
print(
|
||||
net_d.module.load_state_dict(
|
||||
torch.load(hps.pretrainD, map_location="cpu")["model"]
|
||||
)
|
||||
)
|
||||
) ##测试不加载优化器
|
||||
print(
|
||||
net_d.module.load_state_dict(
|
||||
torch.load(hps.pretrainD, map_location="cpu")["model"]
|
||||
)
|
||||
)
|
||||
|
||||
scheduler_g = torch.optim.lr_scheduler.ExponentialLR(
|
||||
optim_g, gamma=hps.train.lr_decay, last_epoch=epoch_str - 2
|
||||
@@ -556,9 +561,10 @@ def train_and_evaluate(
|
||||
ckpt,
|
||||
hps.sample_rate,
|
||||
hps.if_f0,
|
||||
hps.name + "_e%s" % epoch,
|
||||
hps.name + "_e%s_s%s" % (epoch, global_step),
|
||||
epoch,
|
||||
hps.version,
|
||||
hps,
|
||||
),
|
||||
)
|
||||
)
|
||||
@@ -574,7 +580,11 @@ def train_and_evaluate(
|
||||
ckpt = net_g.state_dict()
|
||||
logger.info(
|
||||
"saving final ckpt:%s"
|
||||
% (savee(ckpt, hps.sample_rate, hps.if_f0, hps.name, epoch, hps.version))
|
||||
% (
|
||||
savee(
|
||||
ckpt, hps.sample_rate, hps.if_f0, hps.name, epoch, hps.version, hps
|
||||
)
|
||||
)
|
||||
)
|
||||
sleep(1)
|
||||
os._exit(2333333)
|
||||
|
||||
@@ -53,7 +53,11 @@ class PreProcess:
|
||||
os.makedirs(self.wavs16k_dir, exist_ok=True)
|
||||
|
||||
def norm_write(self, tmp_audio, idx0, idx1):
|
||||
tmp_audio = (tmp_audio / np.abs(tmp_audio).max() * (self.max * self.alpha)) + (
|
||||
tmp_max = np.abs(tmp_audio).max()
|
||||
if tmp_max > 2.5:
|
||||
print("%s-%s-%s-filtered" % (idx0, idx1, tmp_max))
|
||||
return
|
||||
tmp_audio = (tmp_audio / tmp_max * (self.max * self.alpha)) + (
|
||||
1 - self.alpha
|
||||
) * tmp_audio
|
||||
wavfile.write(
|
||||
|
||||
@@ -184,7 +184,7 @@ class VC(object):
|
||||
with torch.no_grad():
|
||||
logits = model.extract_features(**inputs)
|
||||
feats = model.final_proj(logits[0]) if version == "v1" else logits[0]
|
||||
if protect < 0.5:
|
||||
if protect < 0.5 and pitch != None and pitchf != None:
|
||||
feats0 = feats.clone()
|
||||
if (
|
||||
isinstance(index, type(None)) == False
|
||||
@@ -211,7 +211,7 @@ class VC(object):
|
||||
)
|
||||
|
||||
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
||||
if protect < 0.5:
|
||||
if protect < 0.5 and pitch != None and pitchf != None:
|
||||
feats0 = F.interpolate(feats0.permute(0, 2, 1), scale_factor=2).permute(
|
||||
0, 2, 1
|
||||
)
|
||||
@@ -223,7 +223,7 @@ class VC(object):
|
||||
pitch = pitch[:, :p_len]
|
||||
pitchf = pitchf[:, :p_len]
|
||||
|
||||
if protect < 0.5:
|
||||
if protect < 0.5 and pitch != None and pitchf != None:
|
||||
pitchff = pitchf.clone()
|
||||
pitchff[pitchf > 0] = 1
|
||||
pitchff[pitchf < 1] = protect
|
||||
|
||||
Reference in New Issue
Block a user