from typing import TypeAlias, Union from const import MAX_SLOT_NUM, MODEL_DIR_STATIC, DiffusionSVCInferenceType, EnumInferenceTypes, EmbedderType, StaticSlot, VoiceChangerType from dataclasses import dataclass, asdict, field import os import json @dataclass class ModelSlot: slotIndex: int | StaticSlot = -1 voiceChangerType: VoiceChangerType | None = None name: str = "" description: str = "" credit: str = "" termsOfUseUrl: str = "" iconFile: str = "" speakers: dict = field(default_factory=lambda: {}) @dataclass class RVCModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "RVC" modelFile: str = "" indexFile: str = "" defaultTune: int = 0 defaultIndexRatio: int = 0 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: EmbedderType = "hubert_base" sampleId: str = "" speakers: dict = field(default_factory=lambda: {0: "target"}) version: str = "v2" @dataclass class MMVCv13ModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "MMVCv13" modelFile: str = "" configFile: str = "" srcId: int = 107 dstId: int = 100 isONNX: bool = False samplingRate: int = 24000 speakers: dict = field(default_factory=lambda: {107: "user", 100: "zundamon", 101: "sora", 102: "methane", 103: "tsumugi"}) @dataclass class MMVCv15ModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "MMVCv15" modelFile: str = "" configFile: str = "" srcId: int = 0 dstId: int = 101 f0Factor: float = 1.0 isONNX: bool = False samplingRate: int = 24000 speakers: dict = field(default_factory=lambda: {}) f0: dict = field(default_factory=lambda: {}) @dataclass class SoVitsSvc40ModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "so-vits-svc-40" modelFile: str = "" configFile: str = "" clusterFile: str = "" dstId: int = 0 isONNX: bool = False sampleId: str = "" defaultTune: int = 0 defaultClusterInferRatio: float = 0.0 noiseScale: float = 0.0 speakers: dict = field(default_factory=lambda: {1: "user"}) @dataclass class DDSPSVCModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "DDSP-SVC" modelFile: str = "" configFile: str = "" diffModelFile: str = "" diffConfigFile: str = "" dstId: int = 0 isONNX: bool = False sampleId: str = "" defaultTune: int = 0 enhancer: bool = False diffusion: bool = True acc: int = 20 kstep: int = 100 speakers: dict = field(default_factory=lambda: {1: "user"}) @dataclass class DiffusionSVCModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "Diffusion-SVC" modelFile: str = "" isONNX: bool = False modelType: DiffusionSVCInferenceType = "combo" dstId: int = 1 sampleId: str = "" defaultTune: int = 0 defaultKstep: int = 20 defaultSpeedup: int = 10 kStepMax: int = 100 nLayers: int = 20 nnLayers: int = 20 speakers: dict = field(default_factory=lambda: {1: "user"}) embedder: EmbedderType = "hubert_base" samplingRate: int = 44100 embChannels: int = 768 @dataclass class BeatriceModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "Beatrice" modelFile: str = "" dstId: int = 1 speakers: dict = field(default_factory=lambda: {1: "user1", 2: "user2"}) @dataclass class LLVCModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "LLVC" modelFile: str = "" configFile: str = "" @dataclass class EasyVCModelSlot(ModelSlot): voiceChangerType: VoiceChangerType = "EasyVC" modelFile: str = "" version: str = "" samplingRate: int = -1 ModelSlots: TypeAlias = Union[ ModelSlot, RVCModelSlot, MMVCv13ModelSlot, MMVCv15ModelSlot, SoVitsSvc40ModelSlot, DDSPSVCModelSlot, DiffusionSVCModelSlot, BeatriceModelSlot, LLVCModelSlot, EasyVCModelSlot, ] def loadSlotInfo(model_dir: str, slotIndex: int | StaticSlot) -> 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(jsonFile, encoding="utf-8")) slotInfoKey = list(ModelSlot.__annotations__.keys()) slotInfo = ModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) if slotInfo.voiceChangerType == "RVC": slotInfoKey.extend(list(RVCModelSlot.__annotations__.keys())) return RVCModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "MMVCv13": slotInfoKey.extend(list(MMVCv13ModelSlot.__annotations__.keys())) return MMVCv13ModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "MMVCv15": slotInfoKey.extend(list(MMVCv15ModelSlot.__annotations__.keys())) return MMVCv15ModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "so-vits-svc-40": slotInfoKey.extend(list(SoVitsSvc40ModelSlot.__annotations__.keys())) return SoVitsSvc40ModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "DDSP-SVC": slotInfoKey.extend(list(DDSPSVCModelSlot.__annotations__.keys())) return DDSPSVCModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "Diffusion-SVC": slotInfoKey.extend(list(DiffusionSVCModelSlot.__annotations__.keys())) return DiffusionSVCModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "Beatrice": slotInfoKey.extend(list(BeatriceModelSlot.__annotations__.keys())) if slotIndex == "Beatrice-JVS": # STATIC Model return BeatriceModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) return BeatriceModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "LLVC": slotInfoKey.extend(list(LLVCModelSlot.__annotations__.keys())) return LLVCModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) elif slotInfo.voiceChangerType == "EasyVC": slotInfoKey.extend(list(EasyVCModelSlot.__annotations__.keys())) return EasyVCModelSlot(**{k: v for k, v in jsonDict.items() if k in slotInfoKey}) else: return ModelSlot() def loadAllSlotInfo(model_dir: str): slotInfos: list[ModelSlots] = [] for slotIndex in range(MAX_SLOT_NUM): slotInfo = loadSlotInfo(model_dir, slotIndex) slotInfo.slotIndex = slotIndex # スロットインデックスは動的に注入 slotInfos.append(slotInfo) slotInfo = loadSlotInfo(MODEL_DIR_STATIC, "Beatrice-JVS") slotInfos.append(slotInfo) return slotInfos def saveSlotInfo(model_dir: str, slotIndex: int, slotInfo: ModelSlots): slotDir = os.path.join(model_dir, str(slotIndex)) print("SlotInfo:::", slotInfo) slotInfoDict = asdict(slotInfo) slotInfo.slotIndex = -1 # スロットインデックスは動的に注入 json.dump(slotInfoDict, open(os.path.join(slotDir, "params.json"), "w"), indent=4)