2023-06-16 10:49:55 +03:00
|
|
|
import json
|
|
|
|
import os
|
2023-07-28 22:24:36 +03:00
|
|
|
import sys
|
2023-06-16 10:49:55 +03:00
|
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
from typing import Any, Tuple
|
|
|
|
|
|
|
|
from const import RVCSampleMode, getSampleJsonAndModelIds
|
|
|
|
from data.ModelSample import ModelSamples, generateModelSample
|
2023-07-21 12:25:28 +03:00
|
|
|
from data.ModelSlot import DiffusionSVCModelSlot, ModelSlot, RVCModelSlot
|
2023-07-26 22:06:25 +03:00
|
|
|
from mods.log_control import VoiceChangaerLogger
|
2023-06-17 08:16:29 +03:00
|
|
|
from voice_changer.ModelSlotManager import ModelSlotManager
|
2023-06-21 03:18:51 +03:00
|
|
|
from voice_changer.RVC.RVCModelSlotGenerator import RVCModelSlotGenerator
|
2023-06-17 09:35:43 +03:00
|
|
|
from downloader.Downloader import download, download_no_tqdm
|
2023-06-16 10:49:55 +03:00
|
|
|
|
2023-07-26 22:06:25 +03:00
|
|
|
logger = VoiceChangaerLogger.get_instance().getLogger()
|
|
|
|
|
2023-06-16 10:49:55 +03:00
|
|
|
|
|
|
|
def downloadInitialSamples(mode: RVCSampleMode, model_dir: str):
|
|
|
|
sampleJsonUrls, sampleModels = getSampleJsonAndModelIds(mode)
|
|
|
|
sampleJsons = _downloadSampleJsons(sampleJsonUrls)
|
|
|
|
if os.path.exists(model_dir):
|
2023-07-26 22:06:25 +03:00
|
|
|
logger.info("[Voice Changer] model_dir is already exists. skip download samples.")
|
2023-06-16 10:49:55 +03:00
|
|
|
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)
|
2023-06-17 08:16:29 +03:00
|
|
|
_downloadSamples(samples, [(modelId, params)], model_dir, [slotIndex], withoutTqdm=True)
|
2023-06-16 10:49:55 +03:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2023-06-17 08:16:29 +03:00
|
|
|
def _downloadSamples(samples: list[ModelSamples], sampleModelIds: list[Tuple[str, Any]], model_dir: str, slotIndex: list[int], withoutTqdm=False):
|
2023-06-16 10:49:55 +03:00
|
|
|
downloadParams = []
|
|
|
|
line_num = 0
|
2023-06-17 08:16:29 +03:00
|
|
|
modelSlotManager = ModelSlotManager.get_instance(model_dir)
|
2023-06-16 10:49:55 +03:00
|
|
|
|
|
|
|
for i, initSampleId in enumerate(sampleModelIds):
|
|
|
|
targetSampleId = initSampleId[0]
|
|
|
|
targetSampleParams = initSampleId[1]
|
2023-06-18 03:24:47 +03:00
|
|
|
targetSlotIndex = slotIndex[i]
|
2023-06-16 10:49:55 +03:00
|
|
|
|
|
|
|
# 初期サンプルをサーチ
|
|
|
|
match = False
|
|
|
|
for sample in samples:
|
|
|
|
if sample.id == targetSampleId:
|
|
|
|
match = True
|
|
|
|
break
|
|
|
|
if match is False:
|
2023-07-26 22:06:25 +03:00
|
|
|
logger.warn(f"[Voice Changer] initiail sample not found. {targetSampleId}")
|
2023-06-16 10:49:55 +03:00
|
|
|
continue
|
|
|
|
|
|
|
|
# 検出されたら、、、
|
2023-06-18 03:24:47 +03:00
|
|
|
slotDir = os.path.join(model_dir, str(targetSlotIndex))
|
2023-07-21 12:25:28 +03:00
|
|
|
slotInfo: ModelSlot = ModelSlot()
|
2023-06-16 10:49:55 +03:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
)
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo.modelFile = os.path.basename(sample.modelUrl)
|
2023-06-16 10:49:55 +03:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
)
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo.indexFile = os.path.basename(sample.indexUrl)
|
2023-06-16 10:49:55 +03:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
)
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo.iconFile = os.path.basename(sample.icon)
|
2023-06-16 10:49:55 +03:00
|
|
|
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
|
2023-06-23 16:34:09 +03:00
|
|
|
slotInfo.defaultIndexRatio = 0
|
2023-06-16 10:49:55 +03:00
|
|
|
slotInfo.defaultProtect = 0.5
|
|
|
|
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
|
2023-06-18 03:24:47 +03:00
|
|
|
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
|
2023-07-21 12:25:28 +03:00
|
|
|
elif sample.voiceChangerType == "Diffusion-SVC":
|
2023-07-28 23:21:06 +03:00
|
|
|
if sys.platform.startswith("darwin") is True:
|
|
|
|
continue
|
2023-07-21 12:25:28 +03:00
|
|
|
slotInfo: DiffusionSVCModelSlot = DiffusionSVCModelSlot()
|
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
)
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo.modelFile = os.path.basename(sample.modelUrl)
|
2023-07-21 12:25:28 +03:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
)
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo.iconFile = os.path.basename(sample.icon)
|
2023-07-21 12:25:28 +03:00
|
|
|
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.defaultKstep = 0
|
|
|
|
slotInfo.defaultSpeedup = 0
|
|
|
|
slotInfo.kStepMax = 0
|
|
|
|
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
|
|
|
|
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
|
2023-06-16 10:49:55 +03:00
|
|
|
else:
|
2023-07-26 22:06:25 +03:00
|
|
|
logger.warn(f"[Voice Changer] {sample.voiceChangerType} is not supported.")
|
2023-06-16 10:49:55 +03:00
|
|
|
|
|
|
|
# ダウンロード
|
2023-07-26 22:06:25 +03:00
|
|
|
logger.info("[Voice Changer] Downloading model files...")
|
2023-06-17 08:16:29 +03:00
|
|
|
if withoutTqdm:
|
|
|
|
with ThreadPoolExecutor() as pool:
|
|
|
|
pool.map(download_no_tqdm, downloadParams)
|
|
|
|
else:
|
|
|
|
with ThreadPoolExecutor() as pool:
|
|
|
|
pool.map(download, downloadParams)
|
2023-06-16 10:49:55 +03:00
|
|
|
|
|
|
|
# メタデータ作成
|
2023-07-26 22:06:25 +03:00
|
|
|
logger.info("[Voice Changer] Generating metadata...")
|
2023-06-16 10:49:55 +03:00
|
|
|
for targetSlotIndex in slotIndex:
|
2023-06-17 08:16:29 +03:00
|
|
|
slotInfo = modelSlotManager.get_slot_info(targetSlotIndex)
|
2023-08-05 06:33:31 +03:00
|
|
|
modelPath = os.path.join(model_dir, str(slotInfo.slotIndex), os.path.basename(slotInfo.modelFile))
|
2023-06-16 10:49:55 +03:00
|
|
|
if slotInfo.voiceChangerType == "RVC":
|
|
|
|
if slotInfo.isONNX:
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo = RVCModelSlotGenerator._setInfoByONNX(modelPath, slotInfo)
|
2023-06-16 10:49:55 +03:00
|
|
|
else:
|
2023-08-05 06:33:31 +03:00
|
|
|
slotInfo = RVCModelSlotGenerator._setInfoByPytorch(modelPath, slotInfo)
|
2023-07-07 21:18:23 +03:00
|
|
|
|
2023-06-18 03:24:47 +03:00
|
|
|
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
|
2023-07-21 12:25:28 +03:00
|
|
|
elif slotInfo.voiceChangerType == "Diffusion-SVC":
|
2023-07-28 22:24:36 +03:00
|
|
|
if sys.platform.startswith("darwin") is False:
|
|
|
|
from voice_changer.DiffusionSVC.DiffusionSVCModelSlotGenerator import DiffusionSVCModelSlotGenerator
|
|
|
|
if slotInfo.isONNX:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
slotInfo = DiffusionSVCModelSlotGenerator._setInfoByPytorch(slotInfo)
|
|
|
|
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
|