2023-06-19 05:40:16 +03:00
|
|
|
import os
|
|
|
|
import shutil
|
2022-12-31 10:02:53 +03:00
|
|
|
import numpy as np
|
2023-06-17 09:35:43 +03:00
|
|
|
from downloader.SampleDownloader import downloadSample, getSampleInfos
|
2023-06-16 09:06:35 +03:00
|
|
|
from voice_changer.Local.ServerDevice import ServerDevice, ServerDeviceCallbacks
|
2023-06-17 08:16:29 +03:00
|
|
|
from voice_changer.ModelSlotManager import ModelSlotManager
|
2022-12-31 10:08:14 +03:00
|
|
|
from voice_changer.VoiceChanger import VoiceChanger
|
2023-06-19 05:40:16 +03:00
|
|
|
from const import UPLOAD_DIR, ModelType
|
|
|
|
from voice_changer.utils.LoadModelParams import LoadModelParamFile, LoadModelParams, LoadModelParams2
|
2023-04-28 00:39:51 +03:00
|
|
|
from voice_changer.utils.VoiceChangerModel import AudioInOut
|
2023-04-27 17:38:25 +03:00
|
|
|
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
2023-06-15 20:50:05 +03:00
|
|
|
from dataclasses import dataclass, asdict
|
|
|
|
import torch
|
2023-06-16 09:06:35 +03:00
|
|
|
import threading
|
2023-06-16 10:10:46 +03:00
|
|
|
from typing import Callable
|
|
|
|
from typing import Any
|
2023-06-15 20:50:05 +03:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass()
|
|
|
|
class GPUInfo:
|
|
|
|
id: int
|
|
|
|
name: str
|
|
|
|
memory: int
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass()
|
|
|
|
class VoiceChangerManagerSettings:
|
|
|
|
dummy: int
|
|
|
|
|
|
|
|
# intData: list[str] = field(default_factory=lambda: ["slotIndex"])
|
2022-12-31 10:02:53 +03:00
|
|
|
|
2023-01-29 03:42:45 +03:00
|
|
|
|
2023-06-16 09:06:35 +03:00
|
|
|
class VoiceChangerManager(ServerDeviceCallbacks):
|
2023-04-27 17:38:25 +03:00
|
|
|
_instance = None
|
2023-06-15 20:50:05 +03:00
|
|
|
|
2023-06-16 09:06:35 +03:00
|
|
|
############################
|
|
|
|
# ServerDeviceCallbacks
|
|
|
|
############################
|
|
|
|
def on_request(self, unpackedData: AudioInOut):
|
|
|
|
return self.changeVoice(unpackedData)
|
|
|
|
|
|
|
|
def emitTo(self, performance: list[float]):
|
2023-06-16 10:10:46 +03:00
|
|
|
self.emitToFunc(performance)
|
2023-06-16 09:06:35 +03:00
|
|
|
|
|
|
|
def get_processing_sampling_rate(self):
|
|
|
|
return self.voiceChanger.get_processing_sampling_rate()
|
|
|
|
|
|
|
|
def setSamplingRate(self, sr: int):
|
|
|
|
self.voiceChanger.settings.inputSampleRate = sr
|
|
|
|
|
|
|
|
############################
|
|
|
|
# VoiceChangerManager
|
|
|
|
############################
|
2023-06-15 20:50:05 +03:00
|
|
|
def __init__(self, params: VoiceChangerParams):
|
2023-06-16 11:51:46 +03:00
|
|
|
self.params = params
|
2023-06-15 20:50:05 +03:00
|
|
|
self.voiceChanger: VoiceChanger = None
|
|
|
|
self.settings: VoiceChangerManagerSettings = VoiceChangerManagerSettings(dummy=0)
|
2023-06-17 08:16:29 +03:00
|
|
|
|
|
|
|
self.modelSlotManager = ModelSlotManager.get_instance(self.params.model_dir)
|
2023-06-15 20:50:05 +03:00
|
|
|
# スタティックな情報を収集
|
|
|
|
self.gpus: list[GPUInfo] = self._get_gpuInfos()
|
|
|
|
|
2023-06-16 09:06:35 +03:00
|
|
|
self.serverDevice = ServerDevice(self)
|
|
|
|
|
|
|
|
thread = threading.Thread(target=self.serverDevice.start, args=())
|
|
|
|
thread.start()
|
|
|
|
|
2023-06-15 20:50:05 +03:00
|
|
|
def _get_gpuInfos(self):
|
|
|
|
devCount = torch.cuda.device_count()
|
|
|
|
gpus = []
|
|
|
|
for id in range(devCount):
|
|
|
|
name = torch.cuda.get_device_name(id)
|
|
|
|
memory = torch.cuda.get_device_properties(id).total_memory
|
|
|
|
gpu = {"id": id, "name": name, "memory": memory}
|
|
|
|
gpus.append(gpu)
|
|
|
|
return gpus
|
2023-04-27 17:38:25 +03:00
|
|
|
|
2022-12-31 10:02:53 +03:00
|
|
|
@classmethod
|
2023-04-27 17:38:25 +03:00
|
|
|
def get_instance(cls, params: VoiceChangerParams):
|
|
|
|
if cls._instance is None:
|
2023-06-15 20:50:05 +03:00
|
|
|
cls._instance = cls(params)
|
2023-03-16 02:11:38 +03:00
|
|
|
cls._instance.voiceChanger = VoiceChanger(params)
|
2022-12-31 10:02:53 +03:00
|
|
|
return cls._instance
|
|
|
|
|
2023-04-28 00:39:51 +03:00
|
|
|
def loadModel(self, props: LoadModelParams):
|
2023-06-16 11:51:46 +03:00
|
|
|
paramDict = props.params
|
2023-06-19 05:40:16 +03:00
|
|
|
if paramDict["sampleId"] is not None:
|
|
|
|
# サンプルダウンロード
|
2023-06-16 11:51:46 +03:00
|
|
|
downloadSample(self.params.sample_mode, paramDict["sampleId"], self.params.model_dir, props.slot, {"useIndex": paramDict["rvcIndexDownload"]})
|
2023-06-17 08:16:29 +03:00
|
|
|
self.modelSlotManager.getAllSlotInfo(reload=True)
|
2023-06-16 11:51:46 +03:00
|
|
|
info = {"status": "OK"}
|
2023-04-14 05:03:52 +03:00
|
|
|
return info
|
2023-06-19 05:40:16 +03:00
|
|
|
elif paramDict["voiceChangerType"]:
|
|
|
|
# 新しいアップローダ
|
|
|
|
# Dataを展開
|
|
|
|
params = LoadModelParams2(**paramDict)
|
|
|
|
params.files = [LoadModelParamFile(**x) for x in paramDict["files"]]
|
2023-06-20 00:39:39 +03:00
|
|
|
|
2023-06-19 05:40:16 +03:00
|
|
|
# ファイルをslotにコピー
|
|
|
|
for file in params.files:
|
|
|
|
print("FILE", file)
|
2023-06-20 00:39:39 +03:00
|
|
|
srcPath = os.path.join(UPLOAD_DIR, file.dir, file.name)
|
|
|
|
dstDir = os.path.join(
|
|
|
|
self.params.model_dir,
|
|
|
|
str(params.slot),
|
|
|
|
file.dir,
|
|
|
|
)
|
2023-06-19 05:40:16 +03:00
|
|
|
dstPath = os.path.join(dstDir, file.name)
|
|
|
|
os.makedirs(dstDir, exist_ok=True)
|
|
|
|
print(f"move to {srcPath} -> {dstPath}")
|
|
|
|
shutil.move(srcPath, dstPath)
|
|
|
|
file.name = dstPath
|
2023-06-20 00:39:39 +03:00
|
|
|
|
2023-06-19 05:40:16 +03:00
|
|
|
# メタデータ作成(各VCで定義)
|
|
|
|
if params.voiceChangerType == "RVC":
|
|
|
|
from voice_changer.RVC.RVC import RVC # 起動時にインポートするとパラメータが取れない。
|
|
|
|
|
|
|
|
slotInfo = RVC.loadModel2(params)
|
|
|
|
self.modelSlotManager.save_model_slot(params.slot, slotInfo)
|
2023-06-20 00:39:39 +03:00
|
|
|
elif params.voiceChangerType == "MMVCv13":
|
|
|
|
from voice_changer.MMVCv13.MMVCv13 import MMVCv13
|
|
|
|
|
|
|
|
slotInfo = MMVCv13.loadModel2(params)
|
|
|
|
self.modelSlotManager.save_model_slot(params.slot, slotInfo)
|
|
|
|
elif params.voiceChangerType == "MMVCv15":
|
|
|
|
from voice_changer.MMVCv15.MMVCv15 import MMVCv15
|
|
|
|
|
|
|
|
slotInfo = MMVCv15.loadModel2(params)
|
|
|
|
self.modelSlotManager.save_model_slot(params.slot, slotInfo)
|
|
|
|
elif params.voiceChangerType == "so-vits-svc-40":
|
|
|
|
from voice_changer.SoVitsSvc40.SoVitsSvc40 import SoVitsSvc40
|
|
|
|
|
|
|
|
slotInfo = SoVitsSvc40.loadModel2(params)
|
|
|
|
self.modelSlotManager.save_model_slot(params.slot, slotInfo)
|
|
|
|
elif params.voiceChangerType == "DDSP-SVC":
|
|
|
|
from voice_changer.DDSP_SVC.DDSP_SVC import DDSP_SVC
|
|
|
|
|
|
|
|
slotInfo = DDSP_SVC.loadModel2(params)
|
|
|
|
self.modelSlotManager.save_model_slot(params.slot, slotInfo)
|
2023-06-19 05:40:16 +03:00
|
|
|
print("params", params)
|
|
|
|
|
2023-04-14 05:03:52 +03:00
|
|
|
else:
|
2023-06-19 05:40:16 +03:00
|
|
|
# 古いアップローダ
|
2023-06-16 11:51:46 +03:00
|
|
|
print("[Voice Canger]: upload models........")
|
|
|
|
info = self.voiceChanger.loadModel(props)
|
|
|
|
if hasattr(info, "status") and info["status"] == "NG":
|
|
|
|
return info
|
|
|
|
else:
|
|
|
|
info["status"] = "OK"
|
|
|
|
return info
|
2022-12-31 10:02:53 +03:00
|
|
|
|
2023-01-07 18:25:21 +03:00
|
|
|
def get_info(self):
|
2023-06-15 20:50:05 +03:00
|
|
|
data = asdict(self.settings)
|
|
|
|
data["gpus"] = self.gpus
|
2023-06-17 08:16:29 +03:00
|
|
|
data["modelSlots"] = self.modelSlotManager.getAllSlotInfo(reload=True)
|
|
|
|
data["sampleModels"] = getSampleInfos(self.params.sample_mode)
|
2023-06-15 20:50:05 +03:00
|
|
|
|
|
|
|
data["status"] = "OK"
|
|
|
|
|
2023-06-16 09:06:35 +03:00
|
|
|
info = self.serverDevice.get_info()
|
|
|
|
data.update(info)
|
|
|
|
|
2023-04-27 17:38:25 +03:00
|
|
|
if hasattr(self, "voiceChanger"):
|
2023-01-10 16:49:16 +03:00
|
|
|
info = self.voiceChanger.get_info()
|
2023-06-15 20:50:05 +03:00
|
|
|
data.update(info)
|
|
|
|
return data
|
2023-01-07 18:25:21 +03:00
|
|
|
else:
|
2023-01-29 03:42:45 +03:00
|
|
|
return {"status": "ERROR", "msg": "no model loaded"}
|
2023-05-06 22:18:18 +03:00
|
|
|
|
|
|
|
def get_performance(self):
|
|
|
|
if hasattr(self, "voiceChanger"):
|
|
|
|
info = self.voiceChanger.get_performance()
|
|
|
|
return info
|
|
|
|
else:
|
|
|
|
return {"status": "ERROR", "msg": "no model loaded"}
|
2023-01-07 18:25:21 +03:00
|
|
|
|
2023-04-28 00:39:51 +03:00
|
|
|
def update_settings(self, key: str, val: str | int | float):
|
2023-06-16 09:06:35 +03:00
|
|
|
self.serverDevice.update_settings(key, val)
|
2023-04-27 17:38:25 +03:00
|
|
|
if hasattr(self, "voiceChanger"):
|
2023-06-15 20:50:05 +03:00
|
|
|
self.voiceChanger.update_settings(key, val)
|
2023-01-07 18:25:21 +03:00
|
|
|
else:
|
2023-01-29 03:42:45 +03:00
|
|
|
return {"status": "ERROR", "msg": "no model loaded"}
|
2023-06-15 20:50:05 +03:00
|
|
|
return self.get_info()
|
2023-01-08 10:18:20 +03:00
|
|
|
|
2023-04-28 00:39:51 +03:00
|
|
|
def changeVoice(self, receivedData: AudioInOut):
|
2023-04-27 17:38:25 +03:00
|
|
|
if hasattr(self, "voiceChanger") is True:
|
2023-03-07 17:14:14 +03:00
|
|
|
return self.voiceChanger.on_request(receivedData)
|
2023-01-04 20:28:36 +03:00
|
|
|
else:
|
|
|
|
print("Voice Change is not loaded. Did you load a correct model?")
|
2023-02-20 22:07:43 +03:00
|
|
|
return np.zeros(1).astype(np.int16), []
|
2023-04-10 18:21:17 +03:00
|
|
|
|
|
|
|
def switchModelType(self, modelType: ModelType):
|
|
|
|
return self.voiceChanger.switchModelType(modelType)
|
|
|
|
|
|
|
|
def getModelType(self):
|
|
|
|
return self.voiceChanger.getModelType()
|
2023-04-13 02:00:28 +03:00
|
|
|
|
|
|
|
def export2onnx(self):
|
|
|
|
return self.voiceChanger.export2onnx()
|
2023-04-30 20:34:01 +03:00
|
|
|
|
|
|
|
def merge_models(self, request: str):
|
2023-06-16 15:58:46 +03:00
|
|
|
self.voiceChanger.merge_models(request)
|
|
|
|
return self.get_info()
|
2023-05-20 22:21:54 +03:00
|
|
|
|
2023-06-17 04:08:32 +03:00
|
|
|
def setEmitTo(self, emitTo: Callable[[Any], None]):
|
|
|
|
self.emitToFunc = emitTo
|
|
|
|
|
2023-05-20 22:21:54 +03:00
|
|
|
def update_model_default(self):
|
2023-06-16 15:58:46 +03:00
|
|
|
self.voiceChanger.update_model_default()
|
|
|
|
return self.get_info()
|
2023-06-07 21:08:59 +03:00
|
|
|
|
|
|
|
def update_model_info(self, newData: str):
|
2023-06-16 15:58:46 +03:00
|
|
|
self.voiceChanger.update_model_info(newData)
|
|
|
|
return self.get_info()
|
2023-06-07 21:08:59 +03:00
|
|
|
|
|
|
|
def upload_model_assets(self, params: str):
|
2023-06-16 15:58:46 +03:00
|
|
|
self.voiceChanger.upload_model_assets(params)
|
|
|
|
return self.get_info()
|