mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-02-02 16:23:58 +03:00
common sample
This commit is contained in:
parent
4d55e19bd0
commit
99cf22041f
@ -3,9 +3,7 @@ class NoModeLoadedException(Exception):
|
||||
self.framework = framework
|
||||
|
||||
def __str__(self):
|
||||
return repr(
|
||||
f"No model for {self.framework} loaded. Please confirm the model uploaded."
|
||||
)
|
||||
return repr(f"No model for {self.framework} loaded. Please confirm the model uploaded.")
|
||||
|
||||
|
||||
class HalfPrecisionChangingException(Exception):
|
||||
@ -36,3 +34,8 @@ class DeviceCannotSupportHalfPrecisionException(Exception):
|
||||
class VoiceChangerIsNotSelectedException(Exception):
|
||||
def __str__(self):
|
||||
return repr("Voice Changer is not selected.")
|
||||
|
||||
|
||||
class WeightDownladException(Exception):
|
||||
def __str__(self):
|
||||
return repr("Failed to download weight.")
|
||||
|
@ -1,4 +1,3 @@
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import sys
|
||||
|
||||
from distutils.util import strtobool
|
||||
@ -7,11 +6,9 @@ import socket
|
||||
import platform
|
||||
import os
|
||||
import argparse
|
||||
from Downloader import download, download_no_tqdm
|
||||
from voice_changer.RVC.SampleDownloader import (
|
||||
checkRvcModelExist,
|
||||
downloadInitialSampleModels,
|
||||
)
|
||||
from Exceptions import WeightDownladException
|
||||
from utils.downloader.SampleDownloader import downloadInitialSamples
|
||||
from utils.downloader.WeightDownloader import downloadWeight
|
||||
|
||||
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
||||
|
||||
@ -24,7 +21,6 @@ from const import (
|
||||
NATIVE_CLIENT_FILE_MAC,
|
||||
NATIVE_CLIENT_FILE_WIN,
|
||||
SSL_KEY_DIR,
|
||||
getRVCSampleJsonAndModelIds,
|
||||
)
|
||||
import subprocess
|
||||
import multiprocessing as mp
|
||||
@ -35,56 +31,23 @@ setup_loggers()
|
||||
|
||||
def setupArgParser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--logLevel",
|
||||
type=str,
|
||||
default="critical",
|
||||
help="Log level info|critical. (default: critical)",
|
||||
)
|
||||
parser.add_argument("--logLevel", type=str, default="critical", help="Log level info|critical. (default: critical)")
|
||||
parser.add_argument("-p", type=int, default=18888, help="port")
|
||||
parser.add_argument("--https", type=strtobool, default=False, help="use https")
|
||||
parser.add_argument(
|
||||
"--httpsKey", type=str, default="ssl.key", help="path for the key of https"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--httpsCert", type=str, default="ssl.cert", help="path for the cert of https"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--httpsSelfSigned",
|
||||
type=strtobool,
|
||||
default=True,
|
||||
help="generate self-signed certificate",
|
||||
)
|
||||
parser.add_argument("--httpsKey", type=str, default="ssl.key", help="path for the key of https")
|
||||
parser.add_argument("--httpsCert", type=str, default="ssl.cert", help="path for the cert of https")
|
||||
parser.add_argument("--httpsSelfSigned", type=strtobool, default=True, help="generate self-signed certificate")
|
||||
|
||||
parser.add_argument("--model_dir", type=str, help="path to model files")
|
||||
parser.add_argument(
|
||||
"--rvc_sample_mode", type=str, default="production", help="rvc_sample_mode"
|
||||
)
|
||||
parser.add_argument("--sample_mode", type=str, default="production", help="rvc_sample_mode")
|
||||
|
||||
parser.add_argument(
|
||||
"--content_vec_500", type=str, help="path to content_vec_500 model(pytorch)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--content_vec_500_onnx", type=str, help="path to content_vec_500 model(onnx)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--content_vec_500_onnx_on",
|
||||
type=strtobool,
|
||||
default=False,
|
||||
help="use or not onnx for content_vec_500",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--hubert_base", type=str, help="path to hubert_base model(pytorch)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--hubert_base_jp", type=str, help="path to hubert_base_jp model(pytorch)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--hubert_soft", type=str, help="path to hubert_soft model(pytorch)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--nsf_hifigan", type=str, help="path to nsf_hifigan model(pytorch)"
|
||||
)
|
||||
parser.add_argument("--content_vec_500", type=str, help="path to content_vec_500 model(pytorch)")
|
||||
parser.add_argument("--content_vec_500_onnx", type=str, help="path to content_vec_500 model(onnx)")
|
||||
parser.add_argument("--content_vec_500_onnx_on", type=strtobool, default=False, help="use or not onnx for content_vec_500")
|
||||
parser.add_argument("--hubert_base", type=str, help="path to hubert_base model(pytorch)")
|
||||
parser.add_argument("--hubert_base_jp", type=str, help="path to hubert_base_jp model(pytorch)")
|
||||
parser.add_argument("--hubert_soft", type=str, help="path to hubert_soft model(pytorch)")
|
||||
parser.add_argument("--nsf_hifigan", type=str, help="path to nsf_hifigan model(pytorch)")
|
||||
|
||||
return parser
|
||||
|
||||
@ -111,76 +74,19 @@ def printMessage(message, level=0):
|
||||
print(f"\033[47m {message}\033[0m")
|
||||
|
||||
|
||||
def downloadWeight():
|
||||
# content_vec_500 = (args.content_vec_500,)
|
||||
# content_vec_500_onnx = (args.content_vec_500_onnx,)
|
||||
# content_vec_500_onnx_on = (args.content_vec_500_onnx_on,)
|
||||
hubert_base = args.hubert_base
|
||||
hubert_base_jp = args.hubert_base_jp
|
||||
hubert_soft = args.hubert_soft
|
||||
nsf_hifigan = args.nsf_hifigan
|
||||
|
||||
# file exists check (currently only for rvc)
|
||||
downloadParams = []
|
||||
if os.path.exists(hubert_base) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/ddPn08/rvc-webui-models/resolve/main/embeddings/hubert_base.pt",
|
||||
"saveTo": hubert_base,
|
||||
"position": 0,
|
||||
}
|
||||
)
|
||||
if os.path.exists(hubert_base_jp) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/rinna/japanese-hubert-base/resolve/main/fairseq/model.pt",
|
||||
"saveTo": hubert_base_jp,
|
||||
"position": 1,
|
||||
}
|
||||
)
|
||||
if os.path.exists(hubert_soft) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/wok000/weights/resolve/main/ddsp-svc30/embedder/hubert-soft-0d54a1f4.pt",
|
||||
"saveTo": hubert_soft,
|
||||
"position": 2,
|
||||
}
|
||||
)
|
||||
if os.path.exists(nsf_hifigan) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/wok000/weights/resolve/main/ddsp-svc30/nsf_hifigan_20221211/model.bin",
|
||||
"saveTo": nsf_hifigan,
|
||||
"position": 3,
|
||||
}
|
||||
)
|
||||
nsf_hifigan_config = os.path.join(os.path.dirname(nsf_hifigan), "config.json")
|
||||
|
||||
if os.path.exists(nsf_hifigan_config) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/wok000/weights/raw/main/ddsp-svc30/nsf_hifigan_20221211/config.json",
|
||||
"saveTo": nsf_hifigan_config,
|
||||
"position": 4,
|
||||
}
|
||||
)
|
||||
|
||||
with ThreadPoolExecutor() as pool:
|
||||
pool.map(download, downloadParams)
|
||||
|
||||
if (
|
||||
os.path.exists(hubert_base) is False
|
||||
or os.path.exists(hubert_base_jp) is False
|
||||
or os.path.exists(hubert_soft) is False
|
||||
or os.path.exists(nsf_hifigan) is False
|
||||
or os.path.exists(nsf_hifigan_config) is False
|
||||
):
|
||||
printMessage("RVC用のモデルファイルのダウンロードに失敗しました。", level=2)
|
||||
printMessage("failed to download weight for rvc", level=2)
|
||||
|
||||
|
||||
parser = setupArgParser()
|
||||
args, unknown = parser.parse_known_args()
|
||||
voiceChangerParams = VoiceChangerParams(
|
||||
model_dir=args.model_dir,
|
||||
content_vec_500=args.content_vec_500,
|
||||
content_vec_500_onnx=args.content_vec_500_onnx,
|
||||
content_vec_500_onnx_on=args.content_vec_500_onnx_on,
|
||||
hubert_base=args.hubert_base,
|
||||
hubert_base_jp=args.hubert_base_jp,
|
||||
hubert_soft=args.hubert_soft,
|
||||
nsf_hifigan=args.nsf_hifigan,
|
||||
sample_mode=args.sample_mode,
|
||||
)
|
||||
|
||||
printMessage(f"Booting PHASE :{__name__}", level=2)
|
||||
|
||||
@ -199,24 +105,6 @@ def localServer(logLevel: str = "critical"):
|
||||
|
||||
if __name__ == "MMVCServerSIO":
|
||||
mp.freeze_support()
|
||||
voiceChangerParams = VoiceChangerParams(
|
||||
model_dir=args.model_dir,
|
||||
content_vec_500=args.content_vec_500,
|
||||
content_vec_500_onnx=args.content_vec_500_onnx,
|
||||
content_vec_500_onnx_on=args.content_vec_500_onnx_on,
|
||||
hubert_base=args.hubert_base,
|
||||
hubert_base_jp=args.hubert_base_jp,
|
||||
hubert_soft=args.hubert_soft,
|
||||
nsf_hifigan=args.nsf_hifigan,
|
||||
rvc_sample_mode=args.rvc_sample_mode,
|
||||
)
|
||||
|
||||
if (
|
||||
os.path.exists(voiceChangerParams.hubert_base) is False
|
||||
or os.path.exists(voiceChangerParams.hubert_base_jp) is False
|
||||
):
|
||||
printMessage("RVC用のモデルファイルのダウンロードに失敗しました。", level=2)
|
||||
printMessage("failed to download weight for rvc", level=2)
|
||||
|
||||
voiceChangerManager = VoiceChangerManager.get_instance(voiceChangerParams)
|
||||
app_fastapi = MMVC_Rest.get_instance(voiceChangerManager, voiceChangerParams)
|
||||
@ -230,24 +118,20 @@ if __name__ == "__main__":
|
||||
mp.freeze_support()
|
||||
|
||||
printMessage("Voice Changerを起動しています。", level=2)
|
||||
|
||||
# ダウンロード
|
||||
downloadWeight()
|
||||
os.makedirs(args.model_dir, exist_ok=True)
|
||||
|
||||
# ダウンロード(Weight)
|
||||
try:
|
||||
sampleJsons = []
|
||||
sampleJsonUrls, sampleModels = getRVCSampleJsonAndModelIds(args.rvc_sample_mode)
|
||||
for url in sampleJsonUrls:
|
||||
filename = os.path.basename(url)
|
||||
download_no_tqdm({"url": url, "saveTo": filename, "position": 0})
|
||||
sampleJsons.append(filename)
|
||||
if checkRvcModelExist(args.model_dir) is False:
|
||||
downloadInitialSampleModels(sampleJsons, sampleModels, args.model_dir)
|
||||
downloadWeight(voiceChangerParams)
|
||||
except WeightDownladException:
|
||||
printMessage("RVC用のモデルファイルのダウンロードに失敗しました。", level=2)
|
||||
printMessage("failed to download weight for rvc", level=2)
|
||||
|
||||
# ダウンロード(Sample)
|
||||
try:
|
||||
downloadInitialSamples(args.sample_mode, args.model_dir)
|
||||
except Exception as e:
|
||||
print("[Voice Changer] loading sample failed", e)
|
||||
|
||||
PORT = args.p
|
||||
# PORT = args.p
|
||||
|
||||
if os.getenv("EX_PORT"):
|
||||
EX_PORT = os.environ["EX_PORT"]
|
||||
@ -280,9 +164,7 @@ if __name__ == "__main__":
|
||||
)
|
||||
key_path = os.path.join(SSL_KEY_DIR, keyname)
|
||||
cert_path = os.path.join(SSL_KEY_DIR, certname)
|
||||
printMessage(
|
||||
f"protocol: HTTPS(self-signed), key:{key_path}, cert:{cert_path}", level=1
|
||||
)
|
||||
printMessage(f"protocol: HTTPS(self-signed), key:{key_path}, cert:{cert_path}", level=1)
|
||||
|
||||
elif args.https and args.httpsSelfSigned == 0:
|
||||
# HTTPS
|
||||
@ -336,16 +218,12 @@ if __name__ == "__main__":
|
||||
p.start()
|
||||
try:
|
||||
if sys.platform.startswith("win"):
|
||||
process = subprocess.Popen(
|
||||
[NATIVE_CLIENT_FILE_WIN, "-u", f"http://localhost:{PORT}/"]
|
||||
)
|
||||
process = subprocess.Popen([NATIVE_CLIENT_FILE_WIN, "-u", f"http://localhost:{PORT}/"])
|
||||
return_code = process.wait()
|
||||
print("client closed.")
|
||||
p.terminate()
|
||||
elif sys.platform.startswith("darwin"):
|
||||
process = subprocess.Popen(
|
||||
[NATIVE_CLIENT_FILE_MAC, "-u", f"http://localhost:{PORT}/"]
|
||||
)
|
||||
process = subprocess.Popen([NATIVE_CLIENT_FILE_MAC, "-u", f"http://localhost:{PORT}/"])
|
||||
return_code = process.wait()
|
||||
print("client closed.")
|
||||
p.terminate()
|
||||
|
133
server/const.py
133
server/const.py
@ -5,6 +5,14 @@ import tempfile
|
||||
from typing import Literal, TypeAlias
|
||||
|
||||
|
||||
VoiceChangerType: TypeAlias = Literal[
|
||||
"MMVCv13",
|
||||
"MMVCv15",
|
||||
"so-vits-svc-40",
|
||||
"DDSP-SVC",
|
||||
"RVC",
|
||||
]
|
||||
|
||||
ModelType: TypeAlias = Literal[
|
||||
"MMVCv15",
|
||||
"MMVCv13",
|
||||
@ -22,16 +30,8 @@ tmpdir = tempfile.TemporaryDirectory()
|
||||
# print("generate tmpdir:::",tmpdir)
|
||||
SSL_KEY_DIR = os.path.join(tmpdir.name, "keys") if hasattr(sys, "_MEIPASS") else "keys"
|
||||
MODEL_DIR = os.path.join(tmpdir.name, "logs") if hasattr(sys, "_MEIPASS") else "logs"
|
||||
UPLOAD_DIR = (
|
||||
os.path.join(tmpdir.name, "upload_dir")
|
||||
if hasattr(sys, "_MEIPASS")
|
||||
else "upload_dir"
|
||||
)
|
||||
NATIVE_CLIENT_FILE_WIN = (
|
||||
os.path.join(sys._MEIPASS, "voice-changer-native-client.exe") # type: ignore
|
||||
if hasattr(sys, "_MEIPASS")
|
||||
else "voice-changer-native-client"
|
||||
)
|
||||
UPLOAD_DIR = os.path.join(tmpdir.name, "upload_dir") if hasattr(sys, "_MEIPASS") else "upload_dir"
|
||||
NATIVE_CLIENT_FILE_WIN = os.path.join(sys._MEIPASS, "voice-changer-native-client.exe") if hasattr(sys, "_MEIPASS") else "voice-changer-native-client" # type: ignore
|
||||
NATIVE_CLIENT_FILE_MAC = (
|
||||
os.path.join(
|
||||
sys._MEIPASS, # type: ignore
|
||||
@ -44,25 +44,15 @@ NATIVE_CLIENT_FILE_MAC = (
|
||||
else "voice-changer-native-client"
|
||||
)
|
||||
|
||||
HUBERT_ONNX_MODEL_PATH = (
|
||||
os.path.join(sys._MEIPASS, "model_hubert/hubert_simple.onnx") # type: ignore
|
||||
if hasattr(sys, "_MEIPASS")
|
||||
else "model_hubert/hubert_simple.onnx"
|
||||
)
|
||||
HUBERT_ONNX_MODEL_PATH = os.path.join(sys._MEIPASS, "model_hubert/hubert_simple.onnx") if hasattr(sys, "_MEIPASS") else "model_hubert/hubert_simple.onnx" # type: ignore
|
||||
|
||||
|
||||
TMP_DIR = (
|
||||
os.path.join(tmpdir.name, "tmp_dir") if hasattr(sys, "_MEIPASS") else "tmp_dir"
|
||||
)
|
||||
TMP_DIR = os.path.join(tmpdir.name, "tmp_dir") if hasattr(sys, "_MEIPASS") else "tmp_dir"
|
||||
os.makedirs(TMP_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def getFrontendPath():
|
||||
frontend_path = (
|
||||
os.path.join(sys._MEIPASS, "dist")
|
||||
if hasattr(sys, "_MEIPASS")
|
||||
else "../client/demo/dist"
|
||||
)
|
||||
frontend_path = os.path.join(sys._MEIPASS, "dist") if hasattr(sys, "_MEIPASS") else "../client/demo/dist"
|
||||
return frontend_path
|
||||
|
||||
|
||||
@ -100,80 +90,81 @@ class ServerAudioDeviceTypes(Enum):
|
||||
audiooutput = "audiooutput"
|
||||
|
||||
|
||||
class RVCSampleMode(Enum):
|
||||
production = "production"
|
||||
testOfficial = "testOfficial"
|
||||
testDDPNTorch = "testDDPNTorch"
|
||||
testDDPNONNX = "testDDPNONNX"
|
||||
testONNXFull = "testONNXFull"
|
||||
RVCSampleMode: TypeAlias = Literal[
|
||||
"production",
|
||||
"testOfficial",
|
||||
"testDDPNTorch",
|
||||
"testDDPNONNX",
|
||||
"testONNXFull",
|
||||
]
|
||||
|
||||
|
||||
def getRVCSampleJsonAndModelIds(mode: RVCSampleMode):
|
||||
if mode == RVCSampleMode.production.value:
|
||||
def getSampleJsonAndModelIds(mode: RVCSampleMode):
|
||||
if mode == "production":
|
||||
return [
|
||||
# "https://huggingface.co/wok000/vcclient_model/raw/main/samples_0001.json",
|
||||
# "https://huggingface.co/wok000/vcclient_model/raw/main/samples_0002.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_t.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_o.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_t2.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_o2.json",
|
||||
], [
|
||||
("TokinaShigure_o", True),
|
||||
("KikotoMahiro_o", False),
|
||||
("Amitaro_o", False),
|
||||
("Tsukuyomi-chan_o", False),
|
||||
("TokinaShigure_o", {"useIndex": True}),
|
||||
("KikotoMahiro_o", {"useIndex": False}),
|
||||
("Amitaro_o", {"useIndex": False}),
|
||||
("Tsukuyomi-chan_o", {"useIndex": False}),
|
||||
]
|
||||
elif mode == RVCSampleMode.testOfficial.value:
|
||||
elif mode == "testOfficial":
|
||||
return [
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_official_v1_v2.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_ddpn_v1_v2.json",
|
||||
], [
|
||||
("test-official-v1-f0-48k-l9-hubert_t", True),
|
||||
("test-official-v1-nof0-48k-l9-hubert_t", False),
|
||||
("test-official-v2-f0-40k-l12-hubert_t", False),
|
||||
("test-official-v2-nof0-40k-l12-hubert_t", False),
|
||||
("test-official-v1-f0-48k-l9-hubert_o", True),
|
||||
("test-official-v1-nof0-48k-l9-hubert_o", False),
|
||||
("test-official-v2-f0-40k-l12-hubert_o", False),
|
||||
("test-official-v2-nof0-40k-l12-hubert_o", False),
|
||||
("test-official-v1-f0-48k-l9-hubert_t", {"useIndex": True}),
|
||||
("test-official-v1-nof0-48k-l9-hubert_t", {"useIndex": False}),
|
||||
("test-official-v2-f0-40k-l12-hubert_t", {"useIndex": False}),
|
||||
("test-official-v2-nof0-40k-l12-hubert_t", {"useIndex": False}),
|
||||
("test-official-v1-f0-48k-l9-hubert_o", {"useIndex": True}),
|
||||
("test-official-v1-nof0-48k-l9-hubert_o", {"useIndex": False}),
|
||||
("test-official-v2-f0-40k-l12-hubert_o", {"useIndex": False}),
|
||||
("test-official-v2-nof0-40k-l12-hubert_o", {"useIndex": False}),
|
||||
]
|
||||
elif mode == RVCSampleMode.testDDPNTorch.value:
|
||||
elif mode == "testDDPNTorch":
|
||||
return [
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_official_v1_v2.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_ddpn_v1_v2.json",
|
||||
], [
|
||||
("test-ddpn-v1-f0-48k-l9-hubert_t", False),
|
||||
("test-ddpn-v1-nof0-48k-l9-hubert_t", False),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_t", False),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_t", False),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_jp_t", False),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_jp_t", False),
|
||||
("test-ddpn-v1-f0-48k-l9-hubert_t", {"useIndex": False}),
|
||||
("test-ddpn-v1-nof0-48k-l9-hubert_t", {"useIndex": False}),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_t", {"useIndex": False}),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_t", {"useIndex": False}),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_jp_t", {"useIndex": False}),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_jp_t", {"useIndex": False}),
|
||||
]
|
||||
elif mode == RVCSampleMode.testDDPNONNX.value:
|
||||
elif mode == "testDDPNONNX":
|
||||
return [
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_official_v1_v2.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_ddpn_v1_v2.json",
|
||||
], [
|
||||
("test-ddpn-v1-f0-48k-l9-hubert_o", False),
|
||||
("test-ddpn-v1-nof0-48k-l9-hubert_o", False),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_o", False),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_o", False),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_jp_o", False),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_jp_o", False),
|
||||
("test-ddpn-v1-f0-48k-l9-hubert_o", {"useIndex": False}),
|
||||
("test-ddpn-v1-nof0-48k-l9-hubert_o", {"useIndex": False}),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_o", {"useIndex": False}),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_o", {"useIndex": False}),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_jp_o", {"useIndex": False}),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_jp_o", {"useIndex": False}),
|
||||
]
|
||||
elif mode == RVCSampleMode.testONNXFull.value:
|
||||
elif mode == "testONNXFull":
|
||||
return [
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_official_v1_v2.json",
|
||||
"https://huggingface.co/wok000/vcclient_model/raw/main/test/test_ddpn_v1_v2.json",
|
||||
], [
|
||||
("test-official-v1-f0-48k-l9-hubert_o_full", False),
|
||||
("test-official-v1-nof0-48k-l9-hubert_o_full", False),
|
||||
("test-official-v2-f0-40k-l12-hubert_o_full", False),
|
||||
("test-official-v2-nof0-40k-l12-hubert_o_full", False),
|
||||
("test-ddpn-v1-f0-48k-l9-hubert_o_full", False),
|
||||
("test-ddpn-v1-nof0-48k-l9-hubert_o_full", False),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_o_full", False),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_o_full", False),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_jp_o_full", False),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_jp_o_full", False),
|
||||
("test-official-v1-f0-48k-l9-hubert_o_full", {"useIndex": False}),
|
||||
("test-official-v1-nof0-48k-l9-hubert_o_full", {"useIndex": False}),
|
||||
("test-official-v2-f0-40k-l12-hubert_o_full", {"useIndex": False}),
|
||||
("test-official-v2-nof0-40k-l12-hubert_o_full", {"useIndex": False}),
|
||||
("test-ddpn-v1-f0-48k-l9-hubert_o_full", {"useIndex": False}),
|
||||
("test-ddpn-v1-nof0-48k-l9-hubert_o_full", {"useIndex": False}),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_o_full", {"useIndex": False}),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_o_full", {"useIndex": False}),
|
||||
("test-ddpn-v2-f0-40k-l12-hubert_jp_o_full", {"useIndex": False}),
|
||||
("test-ddpn-v2-nof0-40k-l12-hubert_jp_o_full", {"useIndex": False}),
|
||||
]
|
||||
else:
|
||||
return [], []
|
||||
|
37
server/data/ModelSample.py
Normal file
37
server/data/ModelSample.py
Normal file
@ -0,0 +1,37 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TypeAlias, Union, Any
|
||||
from const import VoiceChangerType
|
||||
|
||||
|
||||
@dataclass
|
||||
class ModelSample:
|
||||
id: str = ""
|
||||
voiceChangerType: VoiceChangerType | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class RVCModelSample(ModelSample):
|
||||
voiceChangerType: VoiceChangerType = "RVC"
|
||||
lang: str = ""
|
||||
tag: list[str] = field(default_factory=lambda: [])
|
||||
name: str = ""
|
||||
modelUrl: str = ""
|
||||
indexUrl: str = ""
|
||||
termsOfUseUrl: str = ""
|
||||
icon: str = ""
|
||||
credit: str = ""
|
||||
description: str = ""
|
||||
|
||||
sampleRate: int = 48000
|
||||
modelType: str = ""
|
||||
f0: bool = True
|
||||
|
||||
|
||||
ModelSamples: TypeAlias = Union[ModelSample, RVCModelSample]
|
||||
|
||||
|
||||
def generateModelSample(params: Any) -> ModelSamples:
|
||||
if params["voiceChangerType"] == "RVC":
|
||||
return RVCModelSample(**params)
|
||||
else:
|
||||
return ModelSample(**{k: v for k, v in params.items() if k in ModelSample.__annotations__})
|
59
server/data/ModelSlot.py
Normal file
59
server/data/ModelSlot.py
Normal file
@ -0,0 +1,59 @@
|
||||
from typing import TypeAlias, Union
|
||||
from const import EnumInferenceTypes, EnumEmbedderTypes, VoiceChangerType
|
||||
|
||||
from dataclasses import dataclass, asdict
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
|
||||
@dataclass
|
||||
class ModelSlot:
|
||||
voiceChangerType: VoiceChangerType | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class RVCModelSlot(ModelSlot):
|
||||
voiceChangerType: VoiceChangerType = "RVC"
|
||||
modelFile: str = ""
|
||||
indexFile: str = ""
|
||||
defaultTune: int = 0
|
||||
defaultIndexRatio: int = 1
|
||||
defaultProtect: float = 0.5
|
||||
isONNX: bool = False
|
||||
modelType: str = EnumInferenceTypes.pyTorchRVC.value
|
||||
samplingRate: int = -1
|
||||
f0: bool = True
|
||||
embChannels: int = 256
|
||||
embOutputLayer: int = 9
|
||||
useFinalProj: bool = True
|
||||
deprecated: bool = False
|
||||
embedder: str = EnumEmbedderTypes.hubert.value
|
||||
|
||||
name: str = ""
|
||||
description: str = ""
|
||||
credit: str = ""
|
||||
termsOfUseUrl: str = ""
|
||||
sampleId: str = ""
|
||||
iconFile: str = ""
|
||||
|
||||
|
||||
ModelSlots: TypeAlias = Union[ModelSlot, RVCModelSlot]
|
||||
|
||||
|
||||
def loadSlotInfo(model_dir: str, slotIndex: int) -> ModelSlots:
|
||||
slotDir = os.path.join(model_dir, str(slotIndex))
|
||||
jsonFile = os.path.join(slotDir, "params.json")
|
||||
if not os.path.exists(jsonFile):
|
||||
return ModelSlot()
|
||||
jsonDict = json.load(open(os.path.join(slotDir, "params.json")))
|
||||
slotInfo = ModelSlot(**{k: v for k, v in jsonDict.items() if k in ModelSlot.__annotations__})
|
||||
if slotInfo.voiceChangerType == "RVC":
|
||||
return RVCModelSlot(**jsonDict)
|
||||
else:
|
||||
return ModelSlot()
|
||||
|
||||
|
||||
def saveSlotInfo(model_dir: str, slotIndex: int, slotInfo: ModelSlots):
|
||||
slotDir = os.path.join(model_dir, str(slotIndex))
|
||||
json.dump(asdict(slotInfo), open(os.path.join(slotDir, "params.json"), "w"))
|
@ -1,79 +0,0 @@
|
||||
{
|
||||
"RVC": [
|
||||
{
|
||||
"id": "KikotoKurage_o",
|
||||
"lang": "ja-JP",
|
||||
"tag": ["v2", "onnx"],
|
||||
"name": "黄琴海月(onnx)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/kikoto_kurage_v2_40k_e100_simple.onnx",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/added_IVF5181_Flat_nprobe_1_v2.index.bin",
|
||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/kikoto_kurage/terms_of_use.txt",
|
||||
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/kikoto_kurage.png",
|
||||
"credit": "黄琴海月",
|
||||
"description": "",
|
||||
"sampleRate": 40000,
|
||||
"modelType": "rvc_v2",
|
||||
"f0": true
|
||||
},
|
||||
{
|
||||
"id": "KikotoMahiro_o",
|
||||
"lang": "ja-JP",
|
||||
"tag": ["v2", "onnx"],
|
||||
"name": "黄琴まひろ(onnx)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/kikoto_mahiro_v2_40k_simple.onnx",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/added_IVF6881_Flat_nprobe_1_v2.index.bin",
|
||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/kikoto_mahiro/terms_of_use.txt",
|
||||
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/kikoto_mahiro.png",
|
||||
"credit": "黄琴まひろ",
|
||||
"description": "",
|
||||
"sampleRate": 40000,
|
||||
"modelType": "rvc_v2",
|
||||
"f0": true
|
||||
},
|
||||
{
|
||||
"id": "TokinaShigure_o",
|
||||
"lang": "ja-JP",
|
||||
"tag": ["v2", "onnx"],
|
||||
"name": "刻鳴時雨(onnx)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/tokina_shigure_v2_40k_e100_simple.onnx",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/added_IVF2736_Flat_nprobe_1_v2.index.bin",
|
||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/tokina_shigure/terms_of_use.txt",
|
||||
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/tokina_shigure.png",
|
||||
"credit": "刻鳴時雨",
|
||||
"description": "",
|
||||
"sampleRate": 40000,
|
||||
"modelType": "rvc_v2",
|
||||
"f0": true
|
||||
},
|
||||
{
|
||||
"id": "Amitaro_o",
|
||||
"lang": "ja-JP",
|
||||
"tag": ["v2", "onnx"],
|
||||
"name": "あみたろ(onnx)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/amitaro_v2_40k_e100_simple.onnx",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/added_IVF3139_Flat_nprobe_1_v2.index.bin",
|
||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/amitaro/terms_of_use.txt",
|
||||
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/amitaro.png",
|
||||
"credit": "あみたろ",
|
||||
"description": "",
|
||||
"sampleRate": 40000,
|
||||
"modelType": "rvc_v2",
|
||||
"f0": true
|
||||
},
|
||||
{
|
||||
"id": "Tsukuyomi-chan_o",
|
||||
"lang": "ja-JP",
|
||||
"tag": ["v2", "onnx"],
|
||||
"name": "つくよみちゃん(onnx)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/tsukuyomi_v2_40k_e100_simple.onnx",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/added_IVF7852_Flat_nprobe_1_v2.index.bin",
|
||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/tsukuyomi-chan/terms_of_use.txt",
|
||||
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/tsukuyomi-chan.png",
|
||||
"credit": "つくよみちゃん",
|
||||
"description": "",
|
||||
"sampleRate": 40000,
|
||||
"modelType": "rvc_v2",
|
||||
"f0": true
|
||||
}
|
||||
]
|
||||
}
|
56
server/utils/downloader/Downloader.py
Normal file
56
server/utils/downloader/Downloader.py
Normal file
@ -0,0 +1,56 @@
|
||||
import requests # type: ignore
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
def download(params):
|
||||
url = params["url"]
|
||||
saveTo = params["saveTo"]
|
||||
position = params["position"]
|
||||
dirname = os.path.dirname(saveTo)
|
||||
if dirname != "":
|
||||
os.makedirs(dirname, exist_ok=True)
|
||||
|
||||
try:
|
||||
req = requests.get(url, stream=True, allow_redirects=True)
|
||||
content_length = req.headers.get("content-length")
|
||||
progress_bar = tqdm(
|
||||
total=int(content_length) if content_length is not None else None,
|
||||
leave=False,
|
||||
unit="B",
|
||||
unit_scale=True,
|
||||
unit_divisor=1024,
|
||||
position=position,
|
||||
)
|
||||
|
||||
# with tqdm
|
||||
with open(saveTo, "wb") as f:
|
||||
for chunk in req.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
progress_bar.update(len(chunk))
|
||||
f.write(chunk)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
def download_no_tqdm(params):
|
||||
url = params["url"]
|
||||
saveTo = params["saveTo"]
|
||||
dirname = os.path.dirname(saveTo)
|
||||
if dirname != "":
|
||||
os.makedirs(dirname, exist_ok=True)
|
||||
try:
|
||||
req = requests.get(url, stream=True, allow_redirects=True)
|
||||
with open(saveTo, "wb") as f:
|
||||
countToDot = 0
|
||||
for chunk in req.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
countToDot += 1
|
||||
if countToDot % 1024 == 0:
|
||||
print(".", end="", flush=True)
|
||||
|
||||
print("+", end="", flush=True)
|
||||
except Exception as e:
|
||||
print(e)
|
166
server/utils/downloader/SampleDownloader.py
Normal file
166
server/utils/downloader/SampleDownloader.py
Normal file
@ -0,0 +1,166 @@
|
||||
import json
|
||||
import os
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Any, Tuple
|
||||
|
||||
from const import RVCSampleMode, getSampleJsonAndModelIds
|
||||
from data.ModelSample import ModelSamples, generateModelSample
|
||||
from data.ModelSlot import RVCModelSlot, loadSlotInfo, saveSlotInfo
|
||||
from voice_changer.RVC.ModelSlotGenerator import _setInfoByONNX, _setInfoByPytorch
|
||||
from utils.downloader.Downloader import download, download_no_tqdm
|
||||
|
||||
|
||||
def downloadInitialSamples(mode: RVCSampleMode, model_dir: str):
|
||||
sampleJsonUrls, sampleModels = getSampleJsonAndModelIds(mode)
|
||||
sampleJsons = _downloadSampleJsons(sampleJsonUrls)
|
||||
if os.path.exists(model_dir):
|
||||
print("[Voice Changer] model_dir is already exists. skil download samples.")
|
||||
return
|
||||
samples = _generateSampleList(sampleJsons)
|
||||
slotIndex = list(range(len(sampleModels)))
|
||||
_downloadSamples(samples, sampleModels, model_dir, slotIndex)
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def downloadSample(mode: RVCSampleMode, modelId: str, model_dir: str, slotIndex: int, params: Any):
|
||||
sampleJsonUrls, _sampleModels = getSampleJsonAndModelIds(mode)
|
||||
sampleJsons = _generateSampleJsons(sampleJsonUrls)
|
||||
samples = _generateSampleList(sampleJsons)
|
||||
_downloadSamples(samples, [(modelId, params)], model_dir, [slotIndex])
|
||||
pass
|
||||
|
||||
|
||||
def getSampleInfos(mode: RVCSampleMode):
|
||||
sampleJsonUrls, _sampleModels = getSampleJsonAndModelIds(mode)
|
||||
sampleJsons = _generateSampleJsons(sampleJsonUrls)
|
||||
samples = _generateSampleList(sampleJsons)
|
||||
return samples
|
||||
|
||||
|
||||
def _downloadSampleJsons(sampleJsonUrls: list[str]):
|
||||
sampleJsons = []
|
||||
for url in sampleJsonUrls:
|
||||
filename = os.path.basename(url)
|
||||
download_no_tqdm({"url": url, "saveTo": filename, "position": 0})
|
||||
sampleJsons.append(filename)
|
||||
return sampleJsons
|
||||
|
||||
|
||||
def _generateSampleJsons(sampleJsonUrls: list[str]):
|
||||
sampleJsons = []
|
||||
for url in sampleJsonUrls:
|
||||
filename = os.path.basename(url)
|
||||
sampleJsons.append(filename)
|
||||
return sampleJsons
|
||||
|
||||
|
||||
def _generateSampleList(sampleJsons: list[str]):
|
||||
samples: list[ModelSamples] = []
|
||||
for file in sampleJsons:
|
||||
with open(file, "r", encoding="utf-8") as f:
|
||||
jsonDict = json.load(f)
|
||||
for vcType in jsonDict:
|
||||
for sampleParams in jsonDict[vcType]:
|
||||
sample = generateModelSample(sampleParams)
|
||||
samples.append(sample)
|
||||
return samples
|
||||
|
||||
|
||||
def _downloadSamples(samples: list[ModelSamples], sampleModelIds: list[Tuple[str, Any]], model_dir: str, slotIndex: list[int]):
|
||||
downloadParams = []
|
||||
line_num = 0
|
||||
|
||||
for i, initSampleId in enumerate(sampleModelIds):
|
||||
targetSampleId = initSampleId[0]
|
||||
targetSampleParams = initSampleId[1]
|
||||
tagetSlotIndex = slotIndex[i]
|
||||
|
||||
# 初期サンプルをサーチ
|
||||
match = False
|
||||
for sample in samples:
|
||||
if sample.id == targetSampleId:
|
||||
match = True
|
||||
break
|
||||
if match is False:
|
||||
print(f"[Voice Changer] initiail sample not found. {targetSampleId}")
|
||||
continue
|
||||
|
||||
# 検出されたら、、、
|
||||
slotDir = os.path.join(model_dir, str(tagetSlotIndex))
|
||||
if sample.voiceChangerType == "RVC":
|
||||
slotInfo: RVCModelSlot = RVCModelSlot()
|
||||
|
||||
os.makedirs(slotDir, exist_ok=True)
|
||||
modelFilePath = os.path.join(
|
||||
slotDir,
|
||||
os.path.basename(sample.modelUrl),
|
||||
)
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": sample.modelUrl,
|
||||
"saveTo": modelFilePath,
|
||||
"position": line_num,
|
||||
}
|
||||
)
|
||||
slotInfo.modelFile = modelFilePath
|
||||
line_num += 1
|
||||
|
||||
if targetSampleParams["useIndex"] is True and hasattr(sample, "indexUrl") and sample.indexUrl != "":
|
||||
indexPath = os.path.join(
|
||||
slotDir,
|
||||
os.path.basename(sample.indexUrl),
|
||||
)
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": sample.indexUrl,
|
||||
"saveTo": indexPath,
|
||||
"position": line_num,
|
||||
}
|
||||
)
|
||||
slotInfo.indexFile = indexPath
|
||||
line_num += 1
|
||||
|
||||
if hasattr(sample, "icon") and sample.icon != "":
|
||||
iconPath = os.path.join(
|
||||
slotDir,
|
||||
os.path.basename(sample.icon),
|
||||
)
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": sample.icon,
|
||||
"saveTo": iconPath,
|
||||
"position": line_num,
|
||||
}
|
||||
)
|
||||
slotInfo.iconFile = iconPath
|
||||
line_num += 1
|
||||
|
||||
slotInfo.sampleId = sample.id
|
||||
slotInfo.credit = sample.credit
|
||||
slotInfo.description = sample.description
|
||||
slotInfo.name = sample.name
|
||||
slotInfo.termsOfUseUrl = sample.termsOfUseUrl
|
||||
slotInfo.defaultTune = 0
|
||||
slotInfo.defaultIndexRatio = 1
|
||||
slotInfo.defaultProtect = 0.5
|
||||
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
|
||||
saveSlotInfo(model_dir, tagetSlotIndex, slotInfo)
|
||||
else:
|
||||
print(f"[Voice Changer] {sample.voiceChangerType} is not supported.")
|
||||
|
||||
# ダウンロード
|
||||
print("[Voice Changer] Downloading model files...")
|
||||
with ThreadPoolExecutor() as pool:
|
||||
pool.map(download, downloadParams)
|
||||
|
||||
# メタデータ作成
|
||||
print("[Voice Changer] Generating metadata...")
|
||||
for targetSlotIndex in slotIndex:
|
||||
slotInfo = loadSlotInfo(model_dir, targetSlotIndex)
|
||||
if slotInfo.voiceChangerType == "RVC":
|
||||
if slotInfo.isONNX:
|
||||
_setInfoByONNX(slotInfo)
|
||||
else:
|
||||
_setInfoByPytorch(slotInfo)
|
||||
saveSlotInfo(model_dir, targetSlotIndex, slotInfo)
|
64
server/utils/downloader/WeightDownloader.py
Normal file
64
server/utils/downloader/WeightDownloader.py
Normal file
@ -0,0 +1,64 @@
|
||||
import os
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from utils.downloader.Downloader import download
|
||||
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
||||
from Exceptions import WeightDownladException
|
||||
|
||||
|
||||
def downloadWeight(voiceChangerParams: VoiceChangerParams):
|
||||
hubert_base = voiceChangerParams.hubert_base
|
||||
hubert_base_jp = voiceChangerParams.hubert_base_jp
|
||||
hubert_soft = voiceChangerParams.hubert_soft
|
||||
nsf_hifigan = voiceChangerParams.nsf_hifigan
|
||||
|
||||
# file exists check (currently only for rvc)
|
||||
downloadParams = []
|
||||
if os.path.exists(hubert_base) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/ddPn08/rvc-webui-models/resolve/main/embeddings/hubert_base.pt",
|
||||
"saveTo": hubert_base,
|
||||
"position": 0,
|
||||
}
|
||||
)
|
||||
if os.path.exists(hubert_base_jp) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/rinna/japanese-hubert-base/resolve/main/fairseq/model.pt",
|
||||
"saveTo": hubert_base_jp,
|
||||
"position": 1,
|
||||
}
|
||||
)
|
||||
if os.path.exists(hubert_soft) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/wok000/weights/resolve/main/ddsp-svc30/embedder/hubert-soft-0d54a1f4.pt",
|
||||
"saveTo": hubert_soft,
|
||||
"position": 2,
|
||||
}
|
||||
)
|
||||
if os.path.exists(nsf_hifigan) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/wok000/weights/resolve/main/ddsp-svc30/nsf_hifigan_20221211/model.bin",
|
||||
"saveTo": nsf_hifigan,
|
||||
"position": 3,
|
||||
}
|
||||
)
|
||||
nsf_hifigan_config = os.path.join(os.path.dirname(nsf_hifigan), "config.json")
|
||||
|
||||
if os.path.exists(nsf_hifigan_config) is False:
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": "https://huggingface.co/wok000/weights/raw/main/ddsp-svc30/nsf_hifigan_20221211/config.json",
|
||||
"saveTo": nsf_hifigan_config,
|
||||
"position": 4,
|
||||
}
|
||||
)
|
||||
|
||||
with ThreadPoolExecutor() as pool:
|
||||
pool.map(download, downloadParams)
|
||||
|
||||
if os.path.exists(hubert_base) is False or os.path.exists(hubert_base_jp) is False or os.path.exists(hubert_soft) is False or os.path.exists(nsf_hifigan) is False or os.path.exists(nsf_hifigan_config) is False:
|
||||
raise WeightDownladException()
|
@ -11,4 +11,4 @@ class VoiceChangerParams:
|
||||
hubert_base_jp: str
|
||||
hubert_soft: str
|
||||
nsf_hifigan: str
|
||||
rvc_sample_mode: str
|
||||
sample_mode: str
|
||||
|
Loading…
Reference in New Issue
Block a user