WIP: integrate vcs to new gui 2
This commit is contained in:
parent
c7e72e52db
commit
06a5250f61
@ -10,6 +10,11 @@ import json
|
|||||||
@dataclass
|
@dataclass
|
||||||
class ModelSlot:
|
class ModelSlot:
|
||||||
voiceChangerType: VoiceChangerType | None = None
|
voiceChangerType: VoiceChangerType | None = None
|
||||||
|
name: str = ""
|
||||||
|
description: str = ""
|
||||||
|
credit: str = ""
|
||||||
|
termsOfUseUrl: str = ""
|
||||||
|
iconFile: str = ""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -30,12 +35,7 @@ class RVCModelSlot(ModelSlot):
|
|||||||
deprecated: bool = False
|
deprecated: bool = False
|
||||||
embedder: str = EnumEmbedderTypes.hubert.value
|
embedder: str = EnumEmbedderTypes.hubert.value
|
||||||
|
|
||||||
name: str = ""
|
|
||||||
description: str = ""
|
|
||||||
credit: str = ""
|
|
||||||
termsOfUseUrl: str = ""
|
|
||||||
sampleId: str = ""
|
sampleId: str = ""
|
||||||
iconFile: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -48,10 +48,6 @@ class MMVCv13ModelSlot(ModelSlot):
|
|||||||
isONNX: bool = False
|
isONNX: bool = False
|
||||||
samplingRate: int = 24000
|
samplingRate: int = 24000
|
||||||
|
|
||||||
name: str = ""
|
|
||||||
description: str = ""
|
|
||||||
iconFile: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class MMVCv15ModelSlot(ModelSlot):
|
class MMVCv15ModelSlot(ModelSlot):
|
||||||
@ -60,13 +56,10 @@ class MMVCv15ModelSlot(ModelSlot):
|
|||||||
configFile: str = ""
|
configFile: str = ""
|
||||||
srcId: int = 0
|
srcId: int = 0
|
||||||
dstId: int = 101
|
dstId: int = 101
|
||||||
|
f0Factor: float = 1.0
|
||||||
isONNX: bool = False
|
isONNX: bool = False
|
||||||
samplingRate: int = 24000
|
samplingRate: int = 24000
|
||||||
|
|
||||||
name: str = ""
|
|
||||||
description: str = ""
|
|
||||||
iconFile: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SoVitsSvc40ModelSlot(ModelSlot):
|
class SoVitsSvc40ModelSlot(ModelSlot):
|
||||||
@ -77,12 +70,11 @@ class SoVitsSvc40ModelSlot(ModelSlot):
|
|||||||
dstId: int = 0
|
dstId: int = 0
|
||||||
isONNX: bool = False
|
isONNX: bool = False
|
||||||
|
|
||||||
name: str = ""
|
|
||||||
description: str = ""
|
|
||||||
credit: str = ""
|
|
||||||
termsOfUseUrl: str = ""
|
|
||||||
sampleId: str = ""
|
sampleId: str = ""
|
||||||
iconFile: str = ""
|
|
||||||
|
defaultTune: int = 0
|
||||||
|
defaultClusterInferRatio: float = 0.0
|
||||||
|
noiseScale: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -95,12 +87,12 @@ class DDSPSVCModelSlot(ModelSlot):
|
|||||||
dstId: int = 0
|
dstId: int = 0
|
||||||
isONNX: bool = False
|
isONNX: bool = False
|
||||||
|
|
||||||
name: str = ""
|
|
||||||
description: str = ""
|
|
||||||
credit: str = ""
|
|
||||||
termsOfUseUrl: str = ""
|
|
||||||
sampleId: str = ""
|
sampleId: str = ""
|
||||||
iconFile: str = ""
|
defaultTune: int = 0
|
||||||
|
enhancer: bool = False
|
||||||
|
diffusion: bool = True
|
||||||
|
acc: int = 20
|
||||||
|
kstep: int = 100
|
||||||
|
|
||||||
|
|
||||||
ModelSlots: TypeAlias = Union[ModelSlot, RVCModelSlot, MMVCv13ModelSlot, MMVCv15ModelSlot, SoVitsSvc40ModelSlot, DDSPSVCModelSlot]
|
ModelSlots: TypeAlias = Union[ModelSlot, RVCModelSlot, MMVCv13ModelSlot, MMVCv15ModelSlot, SoVitsSvc40ModelSlot, DDSPSVCModelSlot]
|
||||||
|
@ -15,7 +15,7 @@ def downloadInitialSamples(mode: RVCSampleMode, model_dir: str):
|
|||||||
sampleJsonUrls, sampleModels = getSampleJsonAndModelIds(mode)
|
sampleJsonUrls, sampleModels = getSampleJsonAndModelIds(mode)
|
||||||
sampleJsons = _downloadSampleJsons(sampleJsonUrls)
|
sampleJsons = _downloadSampleJsons(sampleJsonUrls)
|
||||||
if os.path.exists(model_dir):
|
if os.path.exists(model_dir):
|
||||||
print("[Voice Changer] model_dir is already exists. skil download samples.")
|
print("[Voice Changer] model_dir is already exists. skip download samples.")
|
||||||
return
|
return
|
||||||
samples = _generateSampleList(sampleJsons)
|
samples = _generateSampleList(sampleJsons)
|
||||||
slotIndex = list(range(len(sampleModels)))
|
slotIndex = list(range(len(sampleModels)))
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from typing import cast
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
import torchaudio
|
import torchaudio
|
||||||
from data.ModelSlot import RVCModelSlot
|
from data.ModelSlot import RVCModelSlot
|
||||||
from voice_changer.ModelSlotManager import ModelSlotManager
|
|
||||||
|
|
||||||
|
|
||||||
# avoiding parse arg error in RVC
|
# avoiding parse arg error in RVC
|
||||||
@ -22,15 +20,13 @@ if sys.platform.startswith("darwin"):
|
|||||||
else:
|
else:
|
||||||
sys.path.append("RVC")
|
sys.path.append("RVC")
|
||||||
|
|
||||||
from voice_changer.RVC.modelMerger.MergeModel import merge_model
|
|
||||||
from voice_changer.RVC.modelMerger.MergeModelRequest import MergeModelRequest
|
|
||||||
from voice_changer.RVC.ModelSlotGenerator import (
|
from voice_changer.RVC.ModelSlotGenerator import (
|
||||||
_setInfoByONNX,
|
_setInfoByONNX,
|
||||||
_setInfoByPytorch,
|
_setInfoByPytorch,
|
||||||
)
|
)
|
||||||
from voice_changer.RVC.RVCSettings import RVCSettings
|
from voice_changer.RVC.RVCSettings import RVCSettings
|
||||||
from voice_changer.RVC.embedder.EmbedderManager import EmbedderManager
|
from voice_changer.RVC.embedder.EmbedderManager import EmbedderManager
|
||||||
from voice_changer.utils.LoadModelParams import LoadModelParams, LoadModelParams2
|
from voice_changer.utils.LoadModelParams import LoadModelParams2
|
||||||
from voice_changer.utils.VoiceChangerModel import AudioInOut
|
from voice_changer.utils.VoiceChangerModel import AudioInOut
|
||||||
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
||||||
from voice_changer.RVC.onnxExporter.export2onnx import export2onnx
|
from voice_changer.RVC.onnxExporter.export2onnx import export2onnx
|
||||||
@ -40,11 +36,6 @@ from voice_changer.RVC.deviceManager.DeviceManager import DeviceManager
|
|||||||
from voice_changer.RVC.pipeline.Pipeline import Pipeline
|
from voice_changer.RVC.pipeline.Pipeline import Pipeline
|
||||||
|
|
||||||
from Exceptions import DeviceCannotSupportHalfPrecisionException, NoModeLoadedException
|
from Exceptions import DeviceCannotSupportHalfPrecisionException, NoModeLoadedException
|
||||||
from const import (
|
|
||||||
UPLOAD_DIR,
|
|
||||||
)
|
|
||||||
import shutil
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
class RVC:
|
class RVC:
|
||||||
@ -61,34 +52,29 @@ class RVC:
|
|||||||
currentSlot: int = 0
|
currentSlot: int = 0
|
||||||
needSwitch: bool = False
|
needSwitch: bool = False
|
||||||
|
|
||||||
def __init__(self, params: VoiceChangerParams):
|
def __init__(self, params: VoiceChangerParams, slotInfo: RVCModelSlot):
|
||||||
self.pitchExtractor = PitchExtractorManager.getPitchExtractor(self.settings.f0Detector)
|
print("[Voice Changer][RVC] Creating instance ")
|
||||||
self.params = params
|
|
||||||
EmbedderManager.initialize(params)
|
EmbedderManager.initialize(params)
|
||||||
print("[Voice Changer] RVC initialization: ", params)
|
|
||||||
self.modelSlotManager = ModelSlotManager.get_instance(self.params.model_dir)
|
|
||||||
|
|
||||||
# 起動時にスロットにモデルがある場合はロードしておく
|
self.params = params
|
||||||
allSlots = self.modelSlotManager.getAllSlotInfo()
|
self.pitchExtractor = PitchExtractorManager.getPitchExtractor(self.settings.f0Detector)
|
||||||
availableIndex = -1
|
|
||||||
for i, slot in enumerate(allSlots):
|
|
||||||
if slot.modelFile is not None and slot.modelFile != "":
|
|
||||||
availableIndex = i
|
|
||||||
break
|
|
||||||
if availableIndex >= 0:
|
|
||||||
self.prepareModel(availableIndex)
|
|
||||||
self.settings.modelSlotIndex = availableIndex
|
|
||||||
self.switchModel(self.settings.modelSlotIndex)
|
|
||||||
self.initialLoad = False
|
|
||||||
|
|
||||||
self.prevVol = 0.0
|
self.prevVol = 0.0
|
||||||
|
self.slotInfo = slotInfo
|
||||||
|
self.initialize()
|
||||||
|
|
||||||
def moveToModelDir(self, file: str, dstDir: str):
|
def initialize(self):
|
||||||
dst = os.path.join(dstDir, os.path.basename(file))
|
print("[Voice Changer][RVC] Initializing... ")
|
||||||
if os.path.exists(dst):
|
|
||||||
os.remove(dst)
|
# pipelineの生成
|
||||||
shutil.move(file, dst)
|
self.pipeline = createPipeline(self.slotInfo, self.settings.gpu, self.settings.f0Detector)
|
||||||
return dst
|
|
||||||
|
# その他の設定
|
||||||
|
self.trans = self.slotInfo.defaultTune
|
||||||
|
self.index_ratio = self.slotInfo.defaultIndexRatio
|
||||||
|
self.protect = self.slotInfo.defaultProtect
|
||||||
|
self.samplingRate = self.slotInfo.samplingRate
|
||||||
|
print("[Voice Changer][RVC] Initializing... done")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def loadModel2(cls, props: LoadModelParams2):
|
def loadModel2(cls, props: LoadModelParams2):
|
||||||
@ -111,70 +97,13 @@ class RVC:
|
|||||||
_setInfoByPytorch(slotInfo)
|
_setInfoByPytorch(slotInfo)
|
||||||
return slotInfo
|
return slotInfo
|
||||||
|
|
||||||
def loadModel(self, props: LoadModelParams):
|
|
||||||
target_slot_idx = props.slot
|
|
||||||
params = props.params
|
|
||||||
slotInfo: RVCModelSlot = RVCModelSlot()
|
|
||||||
|
|
||||||
print("loadModel", params)
|
|
||||||
slotInfo.modelFile = params["files"]["rvcModel"]
|
|
||||||
slotInfo.indexFile = params["files"]["rvcIndex"] if "rvcIndex" in params["files"] else None
|
|
||||||
|
|
||||||
slotInfo.defaultTune = params["defaultTune"]
|
|
||||||
slotInfo.defaultIndexRatio = params["defaultIndexRatio"]
|
|
||||||
slotInfo.defaultProtect = params["defaultProtect"]
|
|
||||||
slotInfo.voiceChangerType = "RVC"
|
|
||||||
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
|
|
||||||
|
|
||||||
if slotInfo.isONNX:
|
|
||||||
_setInfoByONNX(slotInfo)
|
|
||||||
else:
|
|
||||||
_setInfoByPytorch(slotInfo)
|
|
||||||
|
|
||||||
# メタデータを見て、永続化モデルフォルダに移動させる
|
|
||||||
# その際に、メタデータのファイル格納場所も書き換える
|
|
||||||
slotDir = os.path.join(self.params.model_dir, str(target_slot_idx))
|
|
||||||
os.makedirs(slotDir, exist_ok=True)
|
|
||||||
slotInfo.modelFile = self.moveToModelDir(slotInfo.modelFile, slotDir)
|
|
||||||
if slotInfo.indexFile is not None and len(slotInfo.indexFile) > 0:
|
|
||||||
slotInfo.indexFile = self.moveToModelDir(slotInfo.indexFile, slotDir)
|
|
||||||
if slotInfo.iconFile is not None and len(slotInfo.iconFile) > 0:
|
|
||||||
slotInfo.iconFile = self.moveToModelDir(slotInfo.iconFile, slotDir)
|
|
||||||
# json.dump(asdict(slotInfo), open(os.path.join(slotDir, "params.json"), "w"))
|
|
||||||
self.modelSlotManager.save_model_slot(target_slot_idx, slotInfo)
|
|
||||||
|
|
||||||
# 初回のみロード(起動時にスロットにモデルがあった場合はinitialLoadはFalseになっている)
|
|
||||||
if self.initialLoad:
|
|
||||||
self.prepareModel(target_slot_idx)
|
|
||||||
self.settings.modelSlotIndex = target_slot_idx
|
|
||||||
self.switchModel(self.settings.modelSlotIndex)
|
|
||||||
self.initialLoad = False
|
|
||||||
elif target_slot_idx == self.currentSlot:
|
|
||||||
self.prepareModel(target_slot_idx)
|
|
||||||
|
|
||||||
return self.get_info()
|
|
||||||
|
|
||||||
def update_settings(self, key: str, val: int | float | str):
|
def update_settings(self, key: str, val: int | float | str):
|
||||||
|
print("[Voice Changer][RVC]: update_settings", key, val)
|
||||||
if key in self.settings.intData:
|
if key in self.settings.intData:
|
||||||
# 設定前処理
|
setattr(self.settings, key, int(val))
|
||||||
val = cast(int, val)
|
|
||||||
if key == "modelSlotIndex":
|
|
||||||
if val < 0:
|
|
||||||
return True
|
|
||||||
val = val % 1000 # Quick hack for same slot is selected
|
|
||||||
allModelSlots = self.modelSlotManager.getAllSlotInfo()
|
|
||||||
if allModelSlots[val].modelFile is None or allModelSlots[val].modelFile == "":
|
|
||||||
print("[Voice Changer] slot does not have model.")
|
|
||||||
return True
|
|
||||||
self.prepareModel(val)
|
|
||||||
|
|
||||||
# 設定
|
|
||||||
setattr(self.settings, key, val)
|
|
||||||
|
|
||||||
if key == "gpu":
|
if key == "gpu":
|
||||||
self.deviceManager.setForceTensor(False)
|
self.deviceManager.setForceTensor(False)
|
||||||
self.prepareModel(self.settings.modelSlotIndex)
|
self.initialize()
|
||||||
|
|
||||||
elif key in self.settings.floatData:
|
elif key in self.settings.floatData:
|
||||||
setattr(self.settings, key, float(val))
|
setattr(self.settings, key, float(val))
|
||||||
elif key in self.settings.strData:
|
elif key in self.settings.strData:
|
||||||
@ -186,44 +115,6 @@ class RVC:
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def prepareModel(self, slot: int):
|
|
||||||
if slot < 0:
|
|
||||||
print("[Voice Changer] Prepare Model of slot skip:", slot)
|
|
||||||
return self.get_info()
|
|
||||||
allModelSlots = self.modelSlotManager.getAllSlotInfo()
|
|
||||||
modelSlot = allModelSlots[slot]
|
|
||||||
|
|
||||||
print("[Voice Changer] Prepare Model of slot:", slot)
|
|
||||||
|
|
||||||
# pipelineの生成
|
|
||||||
self.next_pipeline = createPipeline(modelSlot, self.settings.gpu, self.settings.f0Detector)
|
|
||||||
|
|
||||||
# その他の設定
|
|
||||||
self.next_trans = modelSlot.defaultTune
|
|
||||||
self.next_index_ratio = modelSlot.defaultIndexRatio
|
|
||||||
self.next_protect = modelSlot.defaultProtect
|
|
||||||
self.next_samplingRate = modelSlot.samplingRate
|
|
||||||
self.next_framework = "ONNX" if modelSlot.isONNX else "PyTorch"
|
|
||||||
# self.needSwitch = True
|
|
||||||
print("[Voice Changer] Prepare done.")
|
|
||||||
self.switchModel(slot)
|
|
||||||
return self.get_info()
|
|
||||||
|
|
||||||
def switchModel(self, slot: int):
|
|
||||||
print("[Voice Changer] Switching model..")
|
|
||||||
self.pipeline = self.next_pipeline
|
|
||||||
self.settings.tran = self.next_trans
|
|
||||||
self.settings.indexRatio = self.next_index_ratio
|
|
||||||
self.settings.protect = self.next_protect
|
|
||||||
self.settings.modelSamplingRate = self.next_samplingRate
|
|
||||||
self.settings.framework = self.next_framework
|
|
||||||
|
|
||||||
# self.currentSlot = self.settings.modelSlotIndex # prepareModelから呼ばれるということはupdate_settingsの中で呼ばれるということなので、まだmodelSlotIndexは更新されていない
|
|
||||||
self.currentSlot = slot
|
|
||||||
print(
|
|
||||||
"[Voice Changer] Switching model..done",
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
data = asdict(self.settings)
|
data = asdict(self.settings)
|
||||||
if self.pipeline is not None:
|
if self.pipeline is not None:
|
||||||
@ -279,22 +170,13 @@ class RVC:
|
|||||||
return (audio_buffer, convertSize, vol)
|
return (audio_buffer, convertSize, vol)
|
||||||
|
|
||||||
def inference(self, data):
|
def inference(self, data):
|
||||||
if self.settings.modelSlotIndex < 0:
|
# if self.settings.modelSlotIndex < 0:
|
||||||
print(
|
|
||||||
"[Voice Changer] wait for loading model...",
|
|
||||||
self.settings.modelSlotIndex,
|
|
||||||
self.currentSlot,
|
|
||||||
)
|
|
||||||
raise NoModeLoadedException("model_common")
|
|
||||||
# if self.needSwitch:
|
|
||||||
# print(
|
# print(
|
||||||
# f"[Voice Changer] Switch model {self.currentSlot} -> {self.settings.modelSlotIndex}"
|
# "[Voice Changer] wait for loading model...",
|
||||||
|
# self.settings.modelSlotIndex,
|
||||||
|
# self.currentSlot,
|
||||||
# )
|
# )
|
||||||
# self.switchModel()
|
# raise NoModeLoadedException("model_common")
|
||||||
# self.needSwitch = False
|
|
||||||
|
|
||||||
# half = self.deviceManager.halfPrecisionAvailable(self.settings.gpu)
|
|
||||||
# half = self.pipeline.isHalf
|
|
||||||
|
|
||||||
audio = data[0]
|
audio = data[0]
|
||||||
convertSize = data[1]
|
convertSize = data[1]
|
||||||
@ -314,9 +196,9 @@ class RVC:
|
|||||||
# embOutputLayer = self.settings.modelSlots[self.currentSlot].embOutputLayer
|
# embOutputLayer = self.settings.modelSlots[self.currentSlot].embOutputLayer
|
||||||
# useFinalProj = self.settings.modelSlots[self.currentSlot].useFinalProj
|
# useFinalProj = self.settings.modelSlots[self.currentSlot].useFinalProj
|
||||||
|
|
||||||
if_f0 = 1 if self.modelSlotManager.get_slot_info(self.currentSlot).f0 else 0
|
if_f0 = 1 if self.slotInfo.f0 else 0
|
||||||
embOutputLayer = self.modelSlotManager.get_slot_info(self.currentSlot).embOutputLayer
|
embOutputLayer = self.slotInfo.embOutputLayer
|
||||||
useFinalProj = self.modelSlotManager.get_slot_info(self.currentSlot).useFinalProj
|
useFinalProj = self.slotInfo.useFinalProj
|
||||||
|
|
||||||
try:
|
try:
|
||||||
audio_out = self.pipeline.exec(
|
audio_out = self.pipeline.exec(
|
||||||
@ -345,7 +227,7 @@ class RVC:
|
|||||||
def __del__(self):
|
def __del__(self):
|
||||||
del self.pipeline
|
del self.pipeline
|
||||||
|
|
||||||
# print("---------- REMOVING ---------------")
|
print("---------- REMOVING ---------------")
|
||||||
|
|
||||||
remove_path = os.path.join("RVC")
|
remove_path = os.path.join("RVC")
|
||||||
sys.path = [x for x in sys.path if x.endswith(remove_path) is False]
|
sys.path = [x for x in sys.path if x.endswith(remove_path) is False]
|
||||||
@ -378,70 +260,86 @@ class RVC:
|
|||||||
|
|
||||||
def merge_models(self, request: str):
|
def merge_models(self, request: str):
|
||||||
print("[Voice Changer] MergeRequest:", request)
|
print("[Voice Changer] MergeRequest:", request)
|
||||||
req: MergeModelRequest = MergeModelRequest.from_json(request)
|
# req: MergeModelRequest = MergeModelRequest.from_json(request)
|
||||||
merged = merge_model(req)
|
# merged = merge_model(req)
|
||||||
targetSlot = 0
|
# targetSlot = 0
|
||||||
if req.slot < 0:
|
# if req.slot < 0:
|
||||||
# 最後尾のスロット番号を格納先とする。
|
# # 最後尾のスロット番号を格納先とする。
|
||||||
allModelSlots = self.modelSlotManager.getAllSlotInfo()
|
# allModelSlots = self.modelSlotManager.getAllSlotInfo()
|
||||||
targetSlot = len(allModelSlots) - 1
|
# targetSlot = len(allModelSlots) - 1
|
||||||
else:
|
# else:
|
||||||
targetSlot = req.slot
|
# targetSlot = req.slot
|
||||||
|
|
||||||
# いったんは、アップロードフォルダに格納する。(歴史的経緯)
|
# # いったんは、アップロードフォルダに格納する。(歴史的経緯)
|
||||||
# 後続のloadmodelを呼び出すことで永続化モデルフォルダに移動させられる。
|
# # 後続のloadmodelを呼び出すことで永続化モデルフォルダに移動させられる。
|
||||||
storeDir = os.path.join(UPLOAD_DIR, f"{targetSlot}")
|
# storeDir = os.path.join(UPLOAD_DIR, f"{targetSlot}")
|
||||||
print("[Voice Changer] store merged model to:", storeDir)
|
# print("[Voice Changer] store merged model to:", storeDir)
|
||||||
os.makedirs(storeDir, exist_ok=True)
|
# os.makedirs(storeDir, exist_ok=True)
|
||||||
storeFile = os.path.join(storeDir, "merged.pth")
|
# storeFile = os.path.join(storeDir, "merged.pth")
|
||||||
torch.save(merged, storeFile)
|
# torch.save(merged, storeFile)
|
||||||
|
|
||||||
# loadmodelを呼び出して永続化モデルフォルダに移動させる。
|
# # loadmodelを呼び出して永続化モデルフォルダに移動させる。
|
||||||
params = {
|
# params = {
|
||||||
"defaultTune": req.defaultTune,
|
# "defaultTune": req.defaultTune,
|
||||||
"defaultIndexRatio": req.defaultIndexRatio,
|
# "defaultIndexRatio": req.defaultIndexRatio,
|
||||||
"defaultProtect": req.defaultProtect,
|
# "defaultProtect": req.defaultProtect,
|
||||||
"sampleId": "",
|
# "sampleId": "",
|
||||||
"files": {"rvcModel": storeFile},
|
# "files": {"rvcModel": storeFile},
|
||||||
}
|
# }
|
||||||
props: LoadModelParams = LoadModelParams(slot=targetSlot, isHalf=True, params=params)
|
# props: LoadModelParams = LoadModelParams(slot=targetSlot, isHalf=True, params=params)
|
||||||
self.loadModel(props)
|
# self.loadModel(props)
|
||||||
self.prepareModel(targetSlot)
|
# self.prepareModel(targetSlot)
|
||||||
self.settings.modelSlotIndex = targetSlot
|
# self.settings.modelSlotIndex = targetSlot
|
||||||
self.currentSlot = self.settings.modelSlotIndex
|
# self.currentSlot = self.settings.modelSlotIndex
|
||||||
|
|
||||||
def update_model_default(self):
|
# def update_model_default(self):
|
||||||
# {"slot":9,"key":"name","val":"dogsdododg"}
|
# # {"slot":9,"key":"name","val":"dogsdododg"}
|
||||||
self.modelSlotManager.update_model_info(
|
# self.modelSlotManager.update_model_info(
|
||||||
json.dumps(
|
# json.dumps(
|
||||||
|
# {
|
||||||
|
# "slot": self.currentSlot,
|
||||||
|
# "key": "defaultTune",
|
||||||
|
# "val": self.settings.tran,
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# self.modelSlotManager.update_model_info(
|
||||||
|
# json.dumps(
|
||||||
|
# {
|
||||||
|
# "slot": self.currentSlot,
|
||||||
|
# "key": "defaultIndexRatio",
|
||||||
|
# "val": self.settings.indexRatio,
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# self.modelSlotManager.update_model_info(
|
||||||
|
# json.dumps(
|
||||||
|
# {
|
||||||
|
# "slot": self.currentSlot,
|
||||||
|
# "key": "defaultProtect",
|
||||||
|
# "val": self.settings.protect,
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
|
||||||
|
def get_model_current(self):
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
"slot": self.currentSlot,
|
|
||||||
"key": "defaultTune",
|
"key": "defaultTune",
|
||||||
"val": self.settings.tran,
|
"val": self.settings.tran,
|
||||||
}
|
},
|
||||||
)
|
|
||||||
)
|
|
||||||
self.modelSlotManager.update_model_info(
|
|
||||||
json.dumps(
|
|
||||||
{
|
{
|
||||||
"slot": self.currentSlot,
|
|
||||||
"key": "defaultIndexRatio",
|
"key": "defaultIndexRatio",
|
||||||
"val": self.settings.indexRatio,
|
"val": self.settings.indexRatio,
|
||||||
}
|
},
|
||||||
)
|
|
||||||
)
|
|
||||||
self.modelSlotManager.update_model_info(
|
|
||||||
json.dumps(
|
|
||||||
{
|
{
|
||||||
"slot": self.currentSlot,
|
|
||||||
"key": "defaultProtect",
|
"key": "defaultProtect",
|
||||||
"val": self.settings.protect,
|
"val": self.settings.protect,
|
||||||
}
|
},
|
||||||
)
|
]
|
||||||
)
|
|
||||||
|
|
||||||
def update_model_info(self, newData: str):
|
# def update_model_info(self, newData: str):
|
||||||
self.modelSlotManager.update_model_info(newData)
|
# self.modelSlotManager.update_model_info(newData)
|
||||||
|
|
||||||
def upload_model_assets(self, params: str):
|
# def upload_model_assets(self, params: str):
|
||||||
self.modelSlotManager.store_model_assets(params)
|
# self.modelSlotManager.store_model_assets(params)
|
||||||
|
@ -19,7 +19,6 @@ class RVCSettings:
|
|||||||
rvcQuality: int = 0
|
rvcQuality: int = 0
|
||||||
silenceFront: int = 1 # 0:off, 1:on
|
silenceFront: int = 1 # 0:off, 1:on
|
||||||
modelSamplingRate: int = 48000
|
modelSamplingRate: int = 48000
|
||||||
modelSlotIndex: int = -1
|
|
||||||
|
|
||||||
speakers: dict[str, int] = field(default_factory=lambda: {})
|
speakers: dict[str, int] = field(default_factory=lambda: {})
|
||||||
isHalf: int = 1 # 0:off, 1:on
|
isHalf: int = 1 # 0:off, 1:on
|
||||||
|
@ -80,48 +80,51 @@ class VoiceChanger:
|
|||||||
|
|
||||||
print(f"VoiceChanger Initialized (GPU_NUM:{self.gpu_num}, mps_enabled:{self.mps_enabled})")
|
print(f"VoiceChanger Initialized (GPU_NUM:{self.gpu_num}, mps_enabled:{self.mps_enabled})")
|
||||||
|
|
||||||
def switchModelType(self, modelType: ModelType):
|
def setModel(self, model: Any):
|
||||||
print("Switch Model Type:", modelType)
|
self.voiceChanger = model
|
||||||
try:
|
|
||||||
if self.voiceChanger is not None:
|
|
||||||
# return {"status": "ERROR", "msg": "vc is already selected. currently re-select is not implemented"}
|
|
||||||
del self.voiceChanger
|
|
||||||
self.voiceChanger = None
|
|
||||||
|
|
||||||
self.modelType = modelType
|
# def switchModelType(self, modelType: ModelType):
|
||||||
if self.modelType == "MMVCv15":
|
# print("Switch Model Type:", modelType)
|
||||||
from voice_changer.MMVCv15.MMVCv15 import MMVCv15
|
# try:
|
||||||
|
# if self.voiceChanger is not None:
|
||||||
|
# # return {"status": "ERROR", "msg": "vc is already selected. currently re-select is not implemented"}
|
||||||
|
# del self.voiceChanger
|
||||||
|
# self.voiceChanger = None
|
||||||
|
|
||||||
self.voiceChanger = MMVCv15() # type: ignore
|
# self.modelType = modelType
|
||||||
elif self.modelType == "MMVCv13":
|
# if self.modelType == "MMVCv15":
|
||||||
from voice_changer.MMVCv13.MMVCv13 import MMVCv13
|
# from voice_changer.MMVCv15.MMVCv15 import MMVCv15
|
||||||
|
|
||||||
self.voiceChanger = MMVCv13()
|
# self.voiceChanger = MMVCv15() # type: ignore
|
||||||
elif self.modelType == "so-vits-svc-40v2":
|
# elif self.modelType == "MMVCv13":
|
||||||
from voice_changer.SoVitsSvc40v2.SoVitsSvc40v2 import SoVitsSvc40v2
|
# from voice_changer.MMVCv13.MMVCv13 import MMVCv13
|
||||||
|
|
||||||
self.voiceChanger = SoVitsSvc40v2(self.params)
|
# self.voiceChanger = MMVCv13()
|
||||||
elif self.modelType == "so-vits-svc-40" or self.modelType == "so-vits-svc-40_c":
|
# elif self.modelType == "so-vits-svc-40v2":
|
||||||
from voice_changer.SoVitsSvc40.SoVitsSvc40 import SoVitsSvc40
|
# from voice_changer.SoVitsSvc40v2.SoVitsSvc40v2 import SoVitsSvc40v2
|
||||||
|
|
||||||
self.voiceChanger = SoVitsSvc40(self.params)
|
# self.voiceChanger = SoVitsSvc40v2(self.params)
|
||||||
elif self.modelType == "DDSP-SVC":
|
# elif self.modelType == "so-vits-svc-40" or self.modelType == "so-vits-svc-40_c":
|
||||||
from voice_changer.DDSP_SVC.DDSP_SVC import DDSP_SVC
|
# from voice_changer.SoVitsSvc40.SoVitsSvc40 import SoVitsSvc40
|
||||||
|
|
||||||
self.voiceChanger = DDSP_SVC(self.params)
|
# self.voiceChanger = SoVitsSvc40(self.params)
|
||||||
elif self.modelType == "RVC":
|
# elif self.modelType == "DDSP-SVC":
|
||||||
from voice_changer.RVC.RVC import RVC
|
# from voice_changer.DDSP_SVC.DDSP_SVC import DDSP_SVC
|
||||||
|
|
||||||
self.voiceChanger = RVC(self.params)
|
# self.voiceChanger = DDSP_SVC(self.params)
|
||||||
else:
|
# elif self.modelType == "RVC":
|
||||||
from voice_changer.MMVCv13.MMVCv13 import MMVCv13
|
# from voice_changer.RVC.RVC import RVC
|
||||||
|
|
||||||
self.voiceChanger = MMVCv13()
|
# self.voiceChanger = RVC(self.params)
|
||||||
except Exception as e:
|
# else:
|
||||||
print(e)
|
# from voice_changer.MMVCv13.MMVCv13 import MMVCv13
|
||||||
print(traceback.format_exc())
|
|
||||||
print("Switch Model Type:", self.voiceChanger)
|
# self.voiceChanger = MMVCv13()
|
||||||
return {"status": "OK", "msg": "vc is switched."}
|
# except Exception as e:
|
||||||
|
# print(e)
|
||||||
|
# print(traceback.format_exc())
|
||||||
|
# print("Switch Model Type:", self.voiceChanger)
|
||||||
|
# return {"status": "OK", "msg": "vc is switched."}
|
||||||
|
|
||||||
def getModelType(self):
|
def getModelType(self):
|
||||||
if self.modelType is not None:
|
if self.modelType is not None:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -9,9 +10,10 @@ from const import UPLOAD_DIR, ModelType
|
|||||||
from voice_changer.utils.LoadModelParams import LoadModelParamFile, LoadModelParams, LoadModelParams2
|
from voice_changer.utils.LoadModelParams import LoadModelParamFile, LoadModelParams, LoadModelParams2
|
||||||
from voice_changer.utils.VoiceChangerModel import AudioInOut
|
from voice_changer.utils.VoiceChangerModel import AudioInOut
|
||||||
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
|
||||||
from dataclasses import dataclass, asdict
|
from dataclasses import dataclass, asdict, field
|
||||||
import torch
|
import torch
|
||||||
import threading
|
|
||||||
|
# import threading
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@ -26,8 +28,9 @@ class GPUInfo:
|
|||||||
@dataclass()
|
@dataclass()
|
||||||
class VoiceChangerManagerSettings:
|
class VoiceChangerManagerSettings:
|
||||||
dummy: int
|
dummy: int
|
||||||
|
modelSlotIndex: int = -1
|
||||||
# intData: list[str] = field(default_factory=lambda: ["slotIndex"])
|
# ↓mutableな物だけ列挙
|
||||||
|
intData: list[str] = field(default_factory=lambda: ["modelSlotIndex"])
|
||||||
|
|
||||||
|
|
||||||
class VoiceChangerManager(ServerDeviceCallbacks):
|
class VoiceChangerManager(ServerDeviceCallbacks):
|
||||||
@ -62,8 +65,8 @@ class VoiceChangerManager(ServerDeviceCallbacks):
|
|||||||
|
|
||||||
self.serverDevice = ServerDevice(self)
|
self.serverDevice = ServerDevice(self)
|
||||||
|
|
||||||
thread = threading.Thread(target=self.serverDevice.start, args=())
|
# thread = threading.Thread(target=self.serverDevice.start, args=())
|
||||||
thread.start()
|
# thread.start()
|
||||||
|
|
||||||
def _get_gpuInfos(self):
|
def _get_gpuInfos(self):
|
||||||
devCount = torch.cuda.device_count()
|
devCount = torch.cuda.device_count()
|
||||||
@ -174,12 +177,38 @@ class VoiceChangerManager(ServerDeviceCallbacks):
|
|||||||
else:
|
else:
|
||||||
return {"status": "ERROR", "msg": "no model loaded"}
|
return {"status": "ERROR", "msg": "no model loaded"}
|
||||||
|
|
||||||
|
def generateVoiceChanger(self, val: int):
|
||||||
|
slotInfo = self.modelSlotManager.get_slot_info(val)
|
||||||
|
if slotInfo is None:
|
||||||
|
print(f"[Voice Changer] model slot is not found {val}")
|
||||||
|
return
|
||||||
|
elif slotInfo.voiceChangerType == "RVC":
|
||||||
|
print("................RVC")
|
||||||
|
from voice_changer.RVC.RVC import RVC
|
||||||
|
|
||||||
|
self.voiceChangerModel = RVC(self.params, slotInfo)
|
||||||
|
self.voiceChanger = VoiceChanger(self.params)
|
||||||
|
self.voiceChanger.setModel(self.voiceChangerModel)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(f"[Voice Changer] unknown voice changer model: {slotInfo.voiceChangerType}")
|
||||||
|
del self.voiceChangerModel
|
||||||
|
return
|
||||||
|
|
||||||
def update_settings(self, key: str, val: str | int | float):
|
def update_settings(self, key: str, val: str | int | float):
|
||||||
|
if key in self.settings.intData:
|
||||||
|
newVal = int(val)
|
||||||
|
if key == "modelSlotIndex":
|
||||||
|
newVal = newVal % 1000
|
||||||
|
print(f"[Voice Changer] model slot is changed {self.settings.modelSlotIndex} -> {newVal}")
|
||||||
|
self.generateVoiceChanger(newVal)
|
||||||
|
setattr(self.settings, key, newVal)
|
||||||
|
|
||||||
|
else:
|
||||||
self.serverDevice.update_settings(key, val)
|
self.serverDevice.update_settings(key, val)
|
||||||
if hasattr(self, "voiceChanger"):
|
if hasattr(self, "voiceChanger"):
|
||||||
self.voiceChanger.update_settings(key, val)
|
self.voiceChanger.update_settings(key, val)
|
||||||
else:
|
|
||||||
return {"status": "ERROR", "msg": "no model loaded"}
|
|
||||||
return self.get_info()
|
return self.get_info()
|
||||||
|
|
||||||
def changeVoice(self, receivedData: AudioInOut):
|
def changeVoice(self, receivedData: AudioInOut):
|
||||||
@ -206,13 +235,19 @@ class VoiceChangerManager(ServerDeviceCallbacks):
|
|||||||
self.emitToFunc = emitTo
|
self.emitToFunc = emitTo
|
||||||
|
|
||||||
def update_model_default(self):
|
def update_model_default(self):
|
||||||
self.voiceChanger.update_model_default()
|
# self.voiceChanger.update_model_default()
|
||||||
|
current_settings = self.voiceChangerModel.get_model_current()
|
||||||
|
for current_setting in current_settings:
|
||||||
|
current_setting["slot"] = self.settings.modelSlotIndex
|
||||||
|
self.modelSlotManager.update_model_info(json.dumps(current_setting))
|
||||||
return self.get_info()
|
return self.get_info()
|
||||||
|
|
||||||
def update_model_info(self, newData: str):
|
def update_model_info(self, newData: str):
|
||||||
self.voiceChanger.update_model_info(newData)
|
# self.voiceChanger.update_model_info(newData)
|
||||||
|
self.modelSlotManager.update_model_info(newData)
|
||||||
return self.get_info()
|
return self.get_info()
|
||||||
|
|
||||||
def upload_model_assets(self, params: str):
|
def upload_model_assets(self, params: str):
|
||||||
self.voiceChanger.upload_model_assets(params)
|
# self.voiceChanger.upload_model_assets(params)
|
||||||
|
self.modelSlotManager.store_model_assets(params)
|
||||||
return self.get_info()
|
return self.get_info()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user