add sample diffusion svc

This commit is contained in:
w-okada 2023-07-21 18:25:28 +09:00
parent a0e890a438
commit d3e49efd69
15 changed files with 324 additions and 105 deletions

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.161", "@dannadori/voice-changer-client-js": "^1.0.163",
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0", "@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0", "@fortawesome/free-regular-svg-icons": "^6.4.0",
@ -35,7 +35,7 @@
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react": "^7.32.2", "eslint-plugin-react": "^7.33.0",
"eslint-webpack-plugin": "^4.0.1", "eslint-webpack-plugin": "^4.0.1",
"html-loader": "^4.2.0", "html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.3", "html-webpack-plugin": "^5.5.3",
@ -48,7 +48,7 @@
"ts-loader": "^9.4.4", "ts-loader": "^9.4.4",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"typescript": "^5.1.6", "typescript": "^5.1.6",
"webpack": "^5.88.1", "webpack": "^5.88.2",
"webpack-cli": "^5.1.4", "webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1" "webpack-dev-server": "^4.15.1"
} }
@ -2708,9 +2708,9 @@
} }
}, },
"node_modules/@dannadori/voice-changer-client-js": { "node_modules/@dannadori/voice-changer-client-js": {
"version": "1.0.161", "version": "1.0.163",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.161.tgz", "resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.163.tgz",
"integrity": "sha512-09TncUiM+NTnU3F8FnPuVqI/OQcQ6KEvUW0ErSuZtXLWIn6M7Ol+F+tvdlIa+5/fahsZle40Ujaz+5oq1g6uXQ==", "integrity": "sha512-ZSY+ppO96pEe6ouwBI9vCkOY7PjnWcxpGmW5ZyuHZTyhIZK4ArBrKyRs+hfo4oJIqVfkgvrv3RblFDV3BNnNow==",
"dependencies": { "dependencies": {
"@types/readable-stream": "^2.3.15", "@types/readable-stream": "^2.3.15",
"amazon-chime-sdk-js": "^3.15.0", "amazon-chime-sdk-js": "^3.15.0",
@ -6232,9 +6232,9 @@
} }
}, },
"node_modules/eslint-plugin-react": { "node_modules/eslint-plugin-react": {
"version": "7.32.2", "version": "7.33.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.0.tgz",
"integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "integrity": "sha512-qewL/8P34WkY8jAqdQxsiL82pDUeT7nhs8IsuXgfgnsEloKCT4miAV9N9kGtx7/KM9NH/NCGUE7Edt9iGxLXFw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"array-includes": "^3.1.6", "array-includes": "^3.1.6",
@ -6250,7 +6250,7 @@
"object.values": "^1.1.6", "object.values": "^1.1.6",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"resolve": "^2.0.0-next.4", "resolve": "^2.0.0-next.4",
"semver": "^6.3.0", "semver": "^6.3.1",
"string.prototype.matchall": "^4.0.8" "string.prototype.matchall": "^4.0.8"
}, },
"engines": { "engines": {
@ -11748,9 +11748,9 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.88.1", "version": "5.88.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
"integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",

View File

@ -36,7 +36,7 @@
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react": "^7.32.2", "eslint-plugin-react": "^7.33.0",
"eslint-webpack-plugin": "^4.0.1", "eslint-webpack-plugin": "^4.0.1",
"html-loader": "^4.2.0", "html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.3", "html-webpack-plugin": "^5.5.3",
@ -54,7 +54,7 @@
"webpack-dev-server": "^4.15.1" "webpack-dev-server": "^4.15.1"
}, },
"dependencies": { "dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.162", "@dannadori/voice-changer-client-js": "^1.0.163",
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0", "@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0", "@fortawesome/free-regular-svg-icons": "^6.4.0",

View File

@ -223,7 +223,7 @@ export const MainScreen = (props: MainScreenProps) => {
iconArea = generateIconArea(index, slotInfo.iconFile, true); iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl); nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
fileRows.push(generateFileRow("model", slotInfo.modelFile)); fileRows.push(generateFileRow("model", slotInfo.modelFile));
infoRow = generateInfoRow(`tune:${slotInfo.defaultTune},ks(max):${slotInfo.kStepMax},ks:${slotInfo.defaultKstep}, sp:${slotInfo.defaultSpeedup}, l:${slotInfo.nLayers},${slotInfo.nnLayers},`); infoRow = generateInfoRow(`tune:${slotInfo.defaultTune},mks:${slotInfo.kStepMax},ks:${slotInfo.defaultKstep}, sp:${slotInfo.defaultSpeedup}, l:${slotInfo.nLayers},${slotInfo.nnLayers},`);
} else { } else {
iconArea = generateIconArea(index, "/assets/icons/blank.png", false); iconArea = generateIconArea(index, "/assets/icons/blank.png", false);
nameRow = generateNameRow(index, "", ""); nameRow = generateNameRow(index, "", "");

View File

@ -1,78 +1,94 @@
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { useAppState } from "../../001_provider/001_AppStateProvider"; import { useAppState } from "../../001_provider/001_AppStateProvider";
import { ModelUploadSetting } from "@dannadori/voice-changer-client-js"; import { DiffusionSVCSampleModel, ModelUploadSetting, RVCSampleModel, VoiceChangerType } from "@dannadori/voice-changer-client-js";
import { useMessageBuilder } from "../../hooks/useMessageBuilder"; import { useMessageBuilder } from "../../hooks/useMessageBuilder";
import { ModelSlotManagerDialogScreen } from "./904_ModelSlotManagerDialog"; import { ModelSlotManagerDialogScreen } from "./904_ModelSlotManagerDialog";
export type SampleDownloaderScreenProps = { export type SampleDownloaderScreenProps = {
screen: ModelSlotManagerDialogScreen screen: ModelSlotManagerDialogScreen;
targetIndex: number targetIndex: number;
close: () => void close: () => void;
backToSlotManager: () => void backToSlotManager: () => void;
};
}
export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => { export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => {
const { serverSetting } = useAppState() const { serverSetting } = useAppState();
const [lang, setLang] = useState<string>("All") const [lang, setLang] = useState<string>("All");
const messageBuilderState = useMessageBuilder() const messageBuilderState = useMessageBuilder();
useMemo(() => { useMemo(() => {
messageBuilderState.setMessage(__filename, "header_message", { "ja": "サンプルをダウンロードしてください. 対象:", "en": "Download Sample for" }) messageBuilderState.setMessage(__filename, "header_message", { ja: "サンプルをダウンロードしてください. 対象:", en: "Download Sample for" });
messageBuilderState.setMessage(__filename, "lang", { "ja": "言語", "en": "Lang" }) messageBuilderState.setMessage(__filename, "lang", { ja: "言語", en: "Lang" });
messageBuilderState.setMessage(__filename, "back", { "ja": "戻る", "en": "back" }) messageBuilderState.setMessage(__filename, "back", { ja: "戻る", en: "back" });
messageBuilderState.setMessage(__filename, "terms_of_use", { "ja": "利用規約", "en": "terms of use" }) messageBuilderState.setMessage(__filename, "terms_of_use", { ja: "利用規約", en: "terms of use" });
messageBuilderState.setMessage(__filename, "download", { "ja": "ダウンロード", "en": "download" }) messageBuilderState.setMessage(__filename, "download", { ja: "ダウンロード", en: "download" });
}, []) }, []);
///////////////////////////////////////// /////////////////////////////////////////
// Sample Downloader // Sample Downloader
///////////////////////////////////////// /////////////////////////////////////////
const screen = useMemo(() => { const screen = useMemo(() => {
if (props.screen != "SampleDownloader") { if (props.screen != "SampleDownloader") {
return <></> return <></>;
} }
if (!serverSetting.serverSetting.modelSlots) { if (!serverSetting.serverSetting.modelSlots) {
return <></> return <></>;
} }
const langs = serverSetting.serverSetting.sampleModels.reduce((prev, cur) => { const langs = serverSetting.serverSetting.sampleModels.reduce(
(prev, cur) => {
if (prev.includes(cur.lang) == false) { if (prev.includes(cur.lang) == false) {
prev.push(cur.lang) prev.push(cur.lang);
} }
return prev return prev;
}, ["All"] as string[]) },
const langOptions = ( ["All"] as string[],
langs.map(x => { );
return <option key={x} value={x}>{x}</option> const langOptions = langs.map((x) => {
}) return (
) <option key={x} value={x}>
{x}
const onDownloadSampleClicked = async (id: string) => { </option>
);
});
const onDownloadSampleClicked = async (id: string, voiceChangerType: VoiceChangerType, params: any) => {
const uploadParams: ModelUploadSetting = { const uploadParams: ModelUploadSetting = {
voiceChangerType: "RVC", voiceChangerType: voiceChangerType,
slot: props.targetIndex, slot: props.targetIndex,
isSampleMode: true, isSampleMode: true,
sampleId: id, sampleId: id,
files: [], files: [],
params: { params: params,
rvcIndexDownload: true };
}
}
try { try {
await serverSetting.uploadModel(uploadParams) await serverSetting.uploadModel(uploadParams);
} catch (e) { } catch (e) {
alert(e) alert(e);
} }
props.backToSlotManager() props.backToSlotManager();
// setMode("localFile") // setMode("localFile")
} };
const options = ( const options = serverSetting.serverSetting.sampleModels
serverSetting.serverSetting.sampleModels.filter(x => { return lang == "All" ? true : x.lang == lang }).map((x, index) => { .filter((x) => {
const termOfUseUrlLink = x.termsOfUseUrl && x.termsOfUseUrl.length > 0 ? <a href={x.termsOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[{messageBuilderState.getMessage(__filename, "terms_of_use")}]</a> : <></> return lang == "All" ? true : x.lang == lang;
})
.map((x, index) => {
const termOfUseUrlLink =
x.termsOfUseUrl && x.termsOfUseUrl.length > 0 ? (
<a href={x.termsOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">
[{messageBuilderState.getMessage(__filename, "terms_of_use")}]
</a>
) : (
<></>
);
let info = ``;
if (x.voiceChangerType == "RVC") {
const sampleInfo = x as RVCSampleModel;
info = `type:${sampleInfo.modelType}, f0:${sampleInfo.f0 ? "f0" : "nof0"}, sr:${sampleInfo.sampleRate}`;
} else if (x.voiceChangerType == "Diffusion-SVC") {
const sampleInfo = x as DiffusionSVCSampleModel;
info = `native_l:${sampleInfo.numOfNativeLayers}, diff_l:${sampleInfo.numOfDiffLayers}, max_kstep:${sampleInfo.maxKStep}`;
}
return ( return (
<div key={index} className="model-slot"> <div key={index} className="model-slot">
<img src={x.icon} className="model-slot-icon"></img> <img src={x.icon} className="model-slot-icon"></img>
@ -82,21 +98,36 @@ export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => {
<div className="model-slot-detail-row-value">{x.name}</div> <div className="model-slot-detail-row-value">{x.name}</div>
<div className="">{termOfUseUrlLink}</div> <div className="">{termOfUseUrlLink}</div>
</div> </div>
<div className="model-slot-detail-row">
<div className="model-slot-detail-row-label">VC Type: </div>
<div className="model-slot-detail-row-value">{x.voiceChangerType}</div>
<div className=""></div>
</div>
<div className="model-slot-detail-row"> <div className="model-slot-detail-row">
<div className="model-slot-detail-row-label">info: </div> <div className="model-slot-detail-row-label">info: </div>
<div className="model-slot-detail-row-value">{x.modelType},{x.f0 ? "f0" : "nof0"},{x.sampleRate}</div> <div className="model-slot-detail-row-value">{info}</div>
<div className=""></div> <div className=""></div>
</div> </div>
</div> </div>
<div className="model-slot-buttons"> <div className="model-slot-buttons">
<div className="model-slot-button" onClick={() => { onDownloadSampleClicked(x.id) }}> <div
className="model-slot-button"
onClick={() => {
if (x.voiceChangerType == "RVC") {
onDownloadSampleClicked(x.id, x.voiceChangerType, {
rvcIndexDownload: true,
});
} else if (x.voiceChangerType == "Diffusion-SVC") {
onDownloadSampleClicked(x.id, x.voiceChangerType, {});
}
}}
>
{messageBuilderState.getMessage(__filename, "download")} {messageBuilderState.getMessage(__filename, "download")}
</div> </div>
</div> </div>
</div> </div>
) );
}) });
)
return ( return (
<div className="dialog-frame"> <div className="dialog-frame">
@ -104,32 +135,32 @@ export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => {
<div className="dialog-fixed-size-content"> <div className="dialog-fixed-size-content">
<div className="model-slot-header"> <div className="model-slot-header">
{messageBuilderState.getMessage(__filename, "header_message")} Slot[{props.targetIndex}] {messageBuilderState.getMessage(__filename, "header_message")} Slot[{props.targetIndex}]
<span onClick={() => { props.backToSlotManager() }} className="model-slot-header-button"> <span
onClick={() => {
props.backToSlotManager();
}}
className="model-slot-header-button"
>
&lt;&lt;{messageBuilderState.getMessage(__filename, "back")} &lt;&lt;{messageBuilderState.getMessage(__filename, "back")}
</span> </span>
</div> </div>
<div>{messageBuilderState.getMessage(__filename, "lang")}: <div>
<select value={lang} onChange={(e) => { setLang(e.target.value) }}> {messageBuilderState.getMessage(__filename, "lang")}:
<select
value={lang}
onChange={(e) => {
setLang(e.target.value);
}}
>
{langOptions} {langOptions}
</select> </select>
</div> </div>
<div className="model-slot-container"> <div className="model-slot-container">{options}</div>
{options}
</div> </div>
</div> </div>
</div> );
) }, [props.screen, props.targetIndex, lang, serverSetting.serverSetting]);
}, [
props.screen,
props.targetIndex,
lang,
serverSetting.serverSetting
])
return screen; return screen;
}; };

View File

@ -1,12 +1,12 @@
{ {
"name": "@dannadori/voice-changer-client-js", "name": "@dannadori/voice-changer-client-js",
"version": "1.0.162", "version": "1.0.163",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@dannadori/voice-changer-client-js", "name": "@dannadori/voice-changer-client-js",
"version": "1.0.162", "version": "1.0.163",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/readable-stream": "^2.3.15", "@types/readable-stream": "^2.3.15",

View File

@ -1,6 +1,6 @@
{ {
"name": "@dannadori/voice-changer-client-js", "name": "@dannadori/voice-changer-client-js",
"version": "1.0.162", "version": "1.0.163",
"description": "", "description": "",
"main": "dist/index.js", "main": "dist/index.js",
"directories": { "directories": {

View File

@ -296,7 +296,7 @@ export type ServerInfo = VoiceChangerServerSetting & {
modelSlots: ModelSlotUnion[] modelSlots: ModelSlotUnion[]
serverAudioInputDevices: ServerAudioDevice[] serverAudioInputDevices: ServerAudioDevice[]
serverAudioOutputDevices: ServerAudioDevice[] serverAudioOutputDevices: ServerAudioDevice[]
sampleModels: RVCSampleModel[] sampleModels: (RVCSampleModel|DiffusionSVCSampleModel)[]
gpus: { gpus: {
id: number, id: number,
name: string, name: string,
@ -306,24 +306,37 @@ export type ServerInfo = VoiceChangerServerSetting & {
} }
export type SampleModel = {
export type RVCSampleModel = {
id: string id: string
name: string voiceChangerType: VoiceChangerType
modelUrl: string
indexUrl: string
featureUrl: string
termsOfUseUrl: string
credit: string
description: string
lang: string lang: string
tag: string[] tag: string[]
name: string
modelUrl: string
termsOfUseUrl: string
icon: string icon: string
f0: boolean credit: string
description: string
sampleRate: number sampleRate: number
modelType: string modelType: string
f0: boolean
} }
export type RVCSampleModel =SampleModel & {
indexUrl: string
featureUrl: string
}
export type DiffusionSVCSampleModel =SampleModel & {
numOfDiffLayers: number
numOfNativeLayers: number
maxKStep: number
}
export const DefaultServerSetting: ServerInfo = { export const DefaultServerSetting: ServerInfo = {
// VC Common // VC Common
inputSampleRate: 48000, inputSampleRate: 48000,

View File

@ -101,11 +101,14 @@ def getSampleJsonAndModelIds(mode: RVCSampleMode):
# "https://huggingface.co/wok000/vcclient_model/raw/main/samples_0002.json", # "https://huggingface.co/wok000/vcclient_model/raw/main/samples_0002.json",
"https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_t2.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", "https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_o2.json",
"https://huggingface.co/wok000/vcclient_model/raw/main/samples_0003_d2.json",
], [ ], [
("Tsukuyomi-chan_o", {"useIndex": False}), ("Tsukuyomi-chan_o", {"useIndex": False}),
("Amitaro_o", {"useIndex": False}), ("Amitaro_o", {"useIndex": False}),
("KikotoMahiro_o", {"useIndex": False}), ("KikotoMahiro_o", {"useIndex": False}),
("TokinaShigure_o", {"useIndex": True}), ("TokinaShigure_o", {"useIndex": True}),
("diffusion_combo_spk5_nl3_dl20_k50_500ep", {}),
("diffusion_combo_spk5_nl3_dl1_k50_500ep", {}),
] ]
elif mode == "testOfficial": elif mode == "testOfficial":
return [ return [

View File

@ -11,6 +11,7 @@ class ModelSample:
@dataclass @dataclass
class RVCModelSample(ModelSample): class RVCModelSample(ModelSample):
id: str = ""
voiceChangerType: VoiceChangerType = "RVC" voiceChangerType: VoiceChangerType = "RVC"
lang: str = "" lang: str = ""
tag: list[str] = field(default_factory=lambda: []) tag: list[str] = field(default_factory=lambda: [])
@ -27,11 +28,34 @@ class RVCModelSample(ModelSample):
f0: bool = True f0: bool = True
ModelSamples: TypeAlias = Union[ModelSample, RVCModelSample] @dataclass
class DiffusionSVCModelSample(ModelSample):
id: str = ""
voiceChangerType: VoiceChangerType = "Diffusion-SVC"
lang: str = ""
tag: list[str] = field(default_factory=lambda: [])
name: str = ""
modelUrl: str = ""
termsOfUseUrl: str = ""
icon: str = ""
credit: str = ""
description: str = ""
sampleRate: int = 48000
modelType: str = ""
f0: bool = True
numOfDiffLayers: int = 20
numOfNativeLayers: int = 3
maxKStep: int = 50
ModelSamples: TypeAlias = Union[ModelSample, RVCModelSample, DiffusionSVCModelSample]
def generateModelSample(params: Any) -> ModelSamples: def generateModelSample(params: Any) -> ModelSamples:
if params["voiceChangerType"] == "RVC": if params["voiceChangerType"] == "RVC":
return RVCModelSample(**params) return RVCModelSample(**{k: v for k, v in params.items() if k in RVCModelSample.__annotations__})
elif params["voiceChangerType"] == "Diffusion-SVC":
return DiffusionSVCModelSample(**{k: v for k, v in params.items() if k in DiffusionSVCModelSample.__annotations__})
else: else:
return ModelSample(**{k: v for k, v in params.items() if k in ModelSample.__annotations__}) return ModelSample(**{k: v for k, v in params.items() if k in ModelSample.__annotations__})

View File

@ -5,21 +5,29 @@ from typing import Any, Tuple
from const import RVCSampleMode, getSampleJsonAndModelIds from const import RVCSampleMode, getSampleJsonAndModelIds
from data.ModelSample import ModelSamples, generateModelSample from data.ModelSample import ModelSamples, generateModelSample
from data.ModelSlot import RVCModelSlot from data.ModelSlot import DiffusionSVCModelSlot, ModelSlot, RVCModelSlot
from voice_changer.DiffusionSVC.DiffusionSVCModelSlotGenerator import DiffusionSVCModelSlotGenerator
from voice_changer.ModelSlotManager import ModelSlotManager from voice_changer.ModelSlotManager import ModelSlotManager
from voice_changer.RVC.RVCModelSlotGenerator import RVCModelSlotGenerator from voice_changer.RVC.RVCModelSlotGenerator import RVCModelSlotGenerator
from downloader.Downloader import download, download_no_tqdm from downloader.Downloader import download, download_no_tqdm
def downloadInitialSamples(mode: RVCSampleMode, model_dir: str): def downloadInitialSamples(mode: RVCSampleMode, model_dir: str):
print("1111111111111")
sampleJsonUrls, sampleModels = getSampleJsonAndModelIds(mode) sampleJsonUrls, sampleModels = getSampleJsonAndModelIds(mode)
print("11111111111112")
sampleJsons = _downloadSampleJsons(sampleJsonUrls) sampleJsons = _downloadSampleJsons(sampleJsonUrls)
print("11111111111113")
if os.path.exists(model_dir): if os.path.exists(model_dir):
print("[Voice Changer] model_dir is already exists. skip download samples.") print("[Voice Changer] model_dir is already exists. skip download samples.")
return return
print("11111111111114")
samples = _generateSampleList(sampleJsons) samples = _generateSampleList(sampleJsons)
print("11111111111115")
slotIndex = list(range(len(sampleModels))) slotIndex = list(range(len(sampleModels)))
print("11111111111116")
_downloadSamples(samples, sampleModels, model_dir, slotIndex) _downloadSamples(samples, sampleModels, model_dir, slotIndex)
print("11111111111117")
pass pass
@ -90,6 +98,7 @@ def _downloadSamples(samples: list[ModelSamples], sampleModelIds: list[Tuple[str
# 検出されたら、、、 # 検出されたら、、、
slotDir = os.path.join(model_dir, str(targetSlotIndex)) slotDir = os.path.join(model_dir, str(targetSlotIndex))
slotInfo: ModelSlot = ModelSlot()
if sample.voiceChangerType == "RVC": if sample.voiceChangerType == "RVC":
slotInfo: RVCModelSlot = RVCModelSlot() slotInfo: RVCModelSlot = RVCModelSlot()
@ -148,6 +157,50 @@ def _downloadSamples(samples: list[ModelSamples], sampleModelIds: list[Tuple[str
slotInfo.defaultProtect = 0.5 slotInfo.defaultProtect = 0.5
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx") slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo) modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
elif sample.voiceChangerType == "Diffusion-SVC":
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,
}
)
slotInfo.modelFile = modelFilePath
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.defaultKstep = 0
slotInfo.defaultSpeedup = 0
slotInfo.kStepMax = 0
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
else: else:
print(f"[Voice Changer] {sample.voiceChangerType} is not supported.") print(f"[Voice Changer] {sample.voiceChangerType} is not supported.")
@ -171,3 +224,9 @@ def _downloadSamples(samples: list[ModelSamples], sampleModelIds: list[Tuple[str
slotInfo = RVCModelSlotGenerator._setInfoByPytorch(slotInfo) slotInfo = RVCModelSlotGenerator._setInfoByPytorch(slotInfo)
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo) modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)
elif slotInfo.voiceChangerType == "Diffusion-SVC":
if slotInfo.isONNX:
pass
else:
slotInfo = DiffusionSVCModelSlotGenerator._setInfoByPytorch(slotInfo)
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)

View File

@ -0,0 +1,76 @@
{
"Diffusion-SVC": [
{
"id": "diffusion_combo_spk5_nl3_dl20_k50_500ep",
"voiceChangerType": "Diffusion-SVC",
"lang": "ja-JP",
"tag": ["diffsuion-svc", "torch"],
"name": "初期メン(3,20)",
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/combo_spk5_nl3_dl20_k50_500ep.ptc.bin",
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/diffusion-svc/term_of_use.txt",
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/diffusion-svc.png",
"credit": "あみたろ,つくよみちゃん,黄琴海月,黄琴まひろ,刻鳴時雨",
"description": "",
"sampleRate": 44100,
"modelType": "combo",
"f0": true,
"numOfDiffLayers":20,
"numOfNativeLayers":3,
"maxKStep":50
},
{
"id": "diffusion_combo_spk5_nl3_dl10_k50_500ep",
"voiceChangerType": "Diffusion-SVC",
"lang": "ja-JP",
"tag": ["diffsuion-svc", "torch"],
"name": "初期メン(3,10)",
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/combo_spk5_nl3_dl10_k50_500ep.ptc.bin",
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/diffusion-svc/term_of_use.txt",
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/diffusion-svc.png",
"credit": "あみたろ,つくよみちゃん,黄琴海月,黄琴まひろ,刻鳴時雨",
"description": "",
"sampleRate": 44100,
"modelType": "combo",
"f0": true,
"numOfDiffLayers":10,
"numOfNativeLayers":3,
"maxKStep":50
},
{
"id": "diffusion_combo_spk5_nl3_dl1_k50_500ep",
"voiceChangerType": "Diffusion-SVC",
"lang": "ja-JP",
"tag": ["diffsuion-svc", "torch"],
"name": "初期メン(3,1)",
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/combo_spk5_nl3_dl1_k50_500ep.ptc.bin",
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/diffusion-svc/term_of_use.txt",
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/diffusion-svc.png",
"credit": "あみたろ,つくよみちゃん,黄琴海月,黄琴まひろ,刻鳴時雨",
"description": "",
"sampleRate": 44100,
"modelType": "combo",
"f0": true,
"numOfDiffLayers":1,
"numOfNativeLayers":3,
"maxKStep":50
},
{
"id": "diffusion_combo_spk5_nl1_dl1_k50_500ep",
"voiceChangerType": "Diffusion-SVC",
"lang": "ja-JP",
"tag": ["diffsuion-svc", "torch"],
"name": "初期メン(1,1)",
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/combo_spk5_nl1_dl1_k50_500ep.ptc.bin",
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/diffusion-svc/term_of_use.txt",
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/diffusion-svc/diffusion-svc.png",
"credit": "あみたろ,つくよみちゃん,黄琴海月,黄琴まひろ,刻鳴時雨",
"description": "",
"sampleRate": 44100,
"modelType": "combo",
"f0": true,
"numOfDiffLayers":1,
"numOfNativeLayers":1,
"maxKStep":50
}
]
}

View File

@ -45,6 +45,7 @@ class DiffusionSVC(VoiceChangerModel):
self.settings.tran = self.slotInfo.defaultTune self.settings.tran = self.slotInfo.defaultTune
self.settings.dstId = self.slotInfo.dstId self.settings.dstId = self.slotInfo.dstId
self.settings.kStep = self.slotInfo.defaultKstep self.settings.kStep = self.slotInfo.defaultKstep
self.settings.speedUp = self.slotInfo.defaultSpeedup
print("[Voice Changer] [DiffusionSVC] Initializing... done") print("[Voice Changer] [DiffusionSVC] Initializing... done")

View File

@ -9,6 +9,15 @@ from voice_changer.DiffusionSVC.inferencer.diffusion_svc_model.diffusion.unit2me
from voice_changer.utils.LoadModelParams import LoadModelParams from voice_changer.utils.LoadModelParams import LoadModelParams
from voice_changer.utils.ModelSlotGenerator import ModelSlotGenerator from voice_changer.utils.ModelSlotGenerator import ModelSlotGenerator
def get_divisors(n):
divisors = []
for i in range(1, int(n**0.5)+1):
if n % i == 0:
divisors.append(i)
if i != n // i:
divisors.append(n //i)
return sorted(divisors)
class DiffusionSVCModelSlotGenerator(ModelSlotGenerator): class DiffusionSVCModelSlotGenerator(ModelSlotGenerator):
@classmethod @classmethod
@ -20,7 +29,7 @@ class DiffusionSVCModelSlotGenerator(ModelSlotGenerator):
slotInfo.defaultTune = 0 slotInfo.defaultTune = 0
slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx") slotInfo.isONNX = slotInfo.modelFile.endswith(".onnx")
slotInfo.name = os.path.splitext(os.path.basename(slotInfo.modelFile))[0] slotInfo.name = os.path.splitext(os.path.basename(slotInfo.modelFile))[0]
slotInfo.iconFile = "/assets/icons/noimage.png" # slotInfo.iconFile = "/assets/icons/noimage.png"
slotInfo.embChannels = 768 slotInfo.embChannels = 768
if slotInfo.isONNX: if slotInfo.isONNX:
@ -35,7 +44,9 @@ class DiffusionSVCModelSlotGenerator(ModelSlotGenerator):
slot.kStepMax = diff_args.model.k_step_max slot.kStepMax = diff_args.model.k_step_max
slot.nLayers = diff_args.model.n_layers slot.nLayers = diff_args.model.n_layers
slot.nnLayers = naive_args.model.n_layers slot.nnLayers = naive_args.model.n_layers
diff_args.model.n_spk slot.defaultKstep = slot.kStepMax
divs = get_divisors(slot.defaultKstep)
slot.defaultSpeedup = divs[-2]
slot.speakers = {(x+1): f"user{x+1}" for x in range(diff_args.model.n_spk)} slot.speakers = {(x+1): f"user{x+1}" for x in range(diff_args.model.n_spk)}
return slot return slot

View File

@ -119,7 +119,8 @@ class VoiceChangerManager(ServerDeviceCallbacks):
def loadModel(self, params: LoadModelParams): def loadModel(self, params: LoadModelParams):
if params.isSampleMode: if params.isSampleMode:
# サンプルダウンロード # サンプルダウンロード
downloadSample(self.params.sample_mode, params.sampleId, self.params.model_dir, params.slot, {"useIndex": params.params["rvcIndexDownload"]}) print("[Voice Changer] sample download....", params)
downloadSample(self.params.sample_mode, params.sampleId, self.params.model_dir, params.slot, params.params)
self.modelSlotManager.getAllSlotInfo(reload=True) self.modelSlotManager.getAllSlotInfo(reload=True)
info = {"status": "OK"} info = {"status": "OK"}
return info return info