WIP: diffusion svc model slot info

This commit is contained in:
w-okada 2023-07-17 08:20:41 +09:00
parent 37468e3cc9
commit 022fda0aa6
4 changed files with 215 additions and 192 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,156 +1,169 @@
import React, { useMemo } from "react";
import { useGuiState } from "./001_GuiStateProvider";
import { useAppState } from "../../001_provider/001_AppStateProvider";
import { DDSPSVCModelSlot, MMVCv13ModelSlot, MMVCv15ModelSlot, RVCModelSlot, SoVitsSvc40ModelSlot, fileSelector } from "@dannadori/voice-changer-client-js";
import { DDSPSVCModelSlot, DiffusionSVCModelSlot, MMVCv13ModelSlot, MMVCv15ModelSlot, RVCModelSlot, SoVitsSvc40ModelSlot, fileSelector } from "@dannadori/voice-changer-client-js";
import { useMessageBuilder } from "../../hooks/useMessageBuilder";
import { ModelSlotManagerDialogScreen } from "./904_ModelSlotManagerDialog";
import { checkExtention, trimfileName } from "../../utils/utils";
export type MainScreenProps = {
screen: ModelSlotManagerDialogScreen
close: () => void
openSampleDownloader: (slotIndex: number) => void
openFileUploader: (slotIndex: number) => void
openEditor: (slotIndex: number) => void
}
screen: ModelSlotManagerDialogScreen;
close: () => void;
openSampleDownloader: (slotIndex: number) => void;
openFileUploader: (slotIndex: number) => void;
openEditor: (slotIndex: number) => void;
};
export const MainScreen = (props: MainScreenProps) => {
const { serverSetting } = useAppState()
const guiState = useGuiState()
const messageBuilderState = useMessageBuilder()
const { serverSetting } = useAppState();
const guiState = useGuiState();
const messageBuilderState = useMessageBuilder();
useMemo(() => {
messageBuilderState.setMessage(__filename, "change_icon", { "ja": "アイコン変更", "en": "chage icon" })
messageBuilderState.setMessage(__filename, "rename", { "ja": "リネーム", "en": "rename" })
messageBuilderState.setMessage(__filename, "download", { "ja": "ダウンロード", "en": "download" })
messageBuilderState.setMessage(__filename, "terms_of_use", { "ja": "利用規約", "en": "terms of use" })
messageBuilderState.setMessage(__filename, "sample", { "ja": "サンプル", "en": "DL sample" })
messageBuilderState.setMessage(__filename, "upload", { "ja": "アップロード", "en": "upload" })
messageBuilderState.setMessage(__filename, "edit", { "ja": "編集", "en": "edit" })
messageBuilderState.setMessage(__filename, "close", { "ja": "閉じる", "en": "close" })
}, [])
messageBuilderState.setMessage(__filename, "change_icon", { ja: "アイコン変更", en: "chage icon" });
messageBuilderState.setMessage(__filename, "rename", { ja: "リネーム", en: "rename" });
messageBuilderState.setMessage(__filename, "download", { ja: "ダウンロード", en: "download" });
messageBuilderState.setMessage(__filename, "terms_of_use", { ja: "利用規約", en: "terms of use" });
messageBuilderState.setMessage(__filename, "sample", { ja: "サンプル", en: "DL sample" });
messageBuilderState.setMessage(__filename, "upload", { ja: "アップロード", en: "upload" });
messageBuilderState.setMessage(__filename, "edit", { ja: "編集", en: "edit" });
messageBuilderState.setMessage(__filename, "close", { ja: "閉じる", en: "close" });
}, []);
const screen = useMemo(() => {
if (props.screen != "Main") {
return <></>
return <></>;
}
if (!serverSetting.serverSetting.modelSlots) {
return <></>
return <></>;
}
const iconAction = async (index: number) => {
if (!serverSetting.serverSetting.modelSlots[index].name || serverSetting.serverSetting.modelSlots[index].name.length == 0) {
return
return;
}
const file = await fileSelector("")
const file = await fileSelector("");
if (checkExtention(file.name, ["png", "jpg", "jpeg", "gif"]) == false) {
alert(`サムネイルの拡張子は".png", ".jpg", ".jpeg", ".gif"である必要があります。`)
return
alert(`サムネイルの拡張子は".png", ".jpg", ".jpeg", ".gif"である必要があります。`);
return;
}
await serverSetting.uploadAssets(index, "iconFile", file)
}
await serverSetting.uploadAssets(index, "iconFile", file);
};
const nameValueAction = async (index: number) => {
if (!serverSetting.serverSetting.modelSlots[index].name || serverSetting.serverSetting.modelSlots[index].name.length == 0) {
return
return;
}
// Open Text Input Dialog
const p = new Promise<string>((resolve) => {
guiState.setTextInputResolve({ resolve: resolve })
})
guiState.stateControls.showTextInputCheckbox.updateState(true)
guiState.setTextInputResolve({ resolve: resolve });
});
guiState.stateControls.showTextInputCheckbox.updateState(true);
const text = await p;
// Send to Server
if (text.length > 0) {
console.log("input text:", text)
await serverSetting.updateModelInfo(index, "name", text)
console.log("input text:", text);
await serverSetting.updateModelInfo(index, "name", text);
}
}
};
const fileValueAction = (url: string) => {
if (url.length == 0) {
return
return;
}
const link = document.createElement("a")
link.href = "./" + url
link.download = url.replace(/^.*[\\\/]/, '')
link.click()
link.remove()
}
const link = document.createElement("a");
link.href = "./" + url;
link.download = url.replace(/^.*[\\\/]/, "");
link.click();
link.remove();
};
const closeButtonRow = (
<div className="body-row split-3-4-3 left-padding-1">
<div className="body-item-text">
</div>
<div className="body-item-text"></div>
<div className="body-button-container body-button-container-space-around">
<div className="body-button" onClick={() => { props.close() }} >
<div
className="body-button"
onClick={() => {
props.close();
}}
>
{messageBuilderState.getMessage(__filename, "close")}
</div>
</div>
<div className="body-item-text"></div>
</div>
)
);
const slotRow = serverSetting.serverSetting.modelSlots.map((x, index) => {
// モデルのアイコン
const generateIconArea = (slotIndex: number, iconUrl: string, tooltip: boolean) => {
const realIconUrl = iconUrl.length > 0 ? iconUrl : "/assets/icons/noimage.png"
const iconDivClass = tooltip ? "tooltip" : ""
const iconClass = tooltip ? "model-slot-icon-pointable" : "model-slot-icon"
const realIconUrl = iconUrl.length > 0 ? iconUrl : "/assets/icons/noimage.png";
const iconDivClass = tooltip ? "tooltip" : "";
const iconClass = tooltip ? "model-slot-icon-pointable" : "model-slot-icon";
return (
<div className={iconDivClass}>
<img src={realIconUrl} className={iconClass} onClick={() => { iconAction(slotIndex) }} />
<div className="tooltip-text tooltip-text-thin tooltip-text-lower">
{messageBuilderState.getMessage(__filename, "change_icon")}
</div>
<img
src={realIconUrl}
className={iconClass}
onClick={() => {
iconAction(slotIndex);
}}
/>
<div className="tooltip-text tooltip-text-thin tooltip-text-lower">{messageBuilderState.getMessage(__filename, "change_icon")}</div>
</div>
)
}
);
};
// モデルの名前
const generateNameRow = (slotIndex: number, name: string, termsOfUseUrl: string) => {
const nameValueClass = name.length > 0 ? "model-slot-detail-row-value-pointable tooltip" : "model-slot-detail-row-value"
const displayName = name.length > 0 ? name : "blank"
const termOfUseUrlLink = termsOfUseUrl.length > 0 ? <a href={termsOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[{messageBuilderState.getMessage(__filename, "terms_of_use")}]</a> : <></>
const nameValueClass = name.length > 0 ? "model-slot-detail-row-value-pointable tooltip" : "model-slot-detail-row-value";
const displayName = name.length > 0 ? name : "blank";
const termOfUseUrlLink =
termsOfUseUrl.length > 0 ? (
<a href={termsOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">
[{messageBuilderState.getMessage(__filename, "terms_of_use")}]
</a>
) : (
<></>
);
return (
<div className="model-slot-detail-row">
<div className="model-slot-detail-row-label">[{slotIndex}]</div>
<div className={nameValueClass} onClick={() => { nameValueAction(slotIndex) }}>
<div
className={nameValueClass}
onClick={() => {
nameValueAction(slotIndex);
}}
>
{displayName}
<div className="tooltip-text tooltip-text-thin">
{messageBuilderState.getMessage(__filename, "rename")}
</div>
<div className="tooltip-text tooltip-text-thin">{messageBuilderState.getMessage(__filename, "rename")}</div>
</div>
<div className="">{termOfUseUrlLink}</div>
</div>
)
}
);
};
// モデルを構成するファイル
const generateFileRow = (title: string, filePath: string) => {
const fileValueClass = filePath.length > 0 ? "model-slot-detail-row-value-download tooltip" : "model-slot-detail-row-value"
const fileValueClass = filePath.length > 0 ? "model-slot-detail-row-value-download tooltip" : "model-slot-detail-row-value";
return (
<div key={`${title}`} className="model-slot-detail-row">
<div className="model-slot-detail-row-label">{title}:</div>
<div className={fileValueClass} onClick={() => { fileValueAction(filePath) }}>
<div
className={fileValueClass}
onClick={() => {
fileValueAction(filePath);
}}
>
{trimfileName(filePath, 20)}
<div className="tooltip-text tooltip-text-thin">
{messageBuilderState.getMessage(__filename, "download")}
</div>
<div className="tooltip-text tooltip-text-thin">{messageBuilderState.getMessage(__filename, "download")}</div>
</div>
</div>
)
}
);
};
// その他情報欄
const generateInfoRow = (info: string) => {
@ -160,55 +173,60 @@ export const MainScreen = (props: MainScreenProps) => {
<div className="model-slot-detail-row-value">{info}</div>
<div className=""></div>
</div>
)
}
);
};
let iconArea = <></>
let nameRow = <></>
const fileRows = []
let infoRow = <></>
let iconArea = <></>;
let nameRow = <></>;
const fileRows = [];
let infoRow = <></>;
if (x.voiceChangerType == "RVC") {
const slotInfo = x as RVCModelSlot
iconArea = generateIconArea(index, slotInfo.iconFile, true)
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl)
fileRows.push(generateFileRow("model", slotInfo.modelFile))
fileRows.push(generateFileRow("index", slotInfo.indexFile))
infoRow = generateInfoRow(`${slotInfo.f0 ? "f0" : "nof0"}, ${slotInfo.samplingRate}, ${slotInfo.embChannels}, ${slotInfo.modelType}, ${slotInfo.defaultTune}, ${slotInfo.defaultIndexRatio}, ${slotInfo.defaultProtect}`)
const slotInfo = x as RVCModelSlot;
iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
fileRows.push(generateFileRow("model", slotInfo.modelFile));
fileRows.push(generateFileRow("index", slotInfo.indexFile));
infoRow = generateInfoRow(`${slotInfo.f0 ? "f0" : "nof0"}, ${slotInfo.samplingRate}, ${slotInfo.embChannels}, ${slotInfo.modelType}, ${slotInfo.defaultTune}, ${slotInfo.defaultIndexRatio}, ${slotInfo.defaultProtect}`);
} else if (x.voiceChangerType == "MMVCv13") {
const slotInfo = x as MMVCv13ModelSlot
iconArea = generateIconArea(index, slotInfo.iconFile, true)
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl)
fileRows.push(generateFileRow("config", slotInfo.configFile))
fileRows.push(generateFileRow("model", slotInfo.modelFile))
infoRow = generateInfoRow(``)
const slotInfo = x as MMVCv13ModelSlot;
iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
fileRows.push(generateFileRow("config", slotInfo.configFile));
fileRows.push(generateFileRow("model", slotInfo.modelFile));
infoRow = generateInfoRow(``);
} else if (x.voiceChangerType == "MMVCv15") {
const slotInfo = x as MMVCv15ModelSlot
iconArea = generateIconArea(index, slotInfo.iconFile, true)
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl)
fileRows.push(generateFileRow("config", slotInfo.configFile))
fileRows.push(generateFileRow("model", slotInfo.modelFile))
infoRow = generateInfoRow((`f0factor:${slotInfo.f0Factor}`))
const slotInfo = x as MMVCv15ModelSlot;
iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
fileRows.push(generateFileRow("config", slotInfo.configFile));
fileRows.push(generateFileRow("model", slotInfo.modelFile));
infoRow = generateInfoRow(`f0factor:${slotInfo.f0Factor}`);
} else if (x.voiceChangerType == "so-vits-svc-40") {
const slotInfo = x as SoVitsSvc40ModelSlot
iconArea = generateIconArea(index, slotInfo.iconFile, true)
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl)
fileRows.push(generateFileRow("config", slotInfo.configFile))
fileRows.push(generateFileRow("model", slotInfo.modelFile))
fileRows.push(generateFileRow("cluster", slotInfo.clusterFile))
infoRow = generateInfoRow((`tune:${slotInfo.defaultTune},cluster:${slotInfo.defaultClusterInferRatio},noise:${slotInfo.noiseScale}`))
const slotInfo = x as SoVitsSvc40ModelSlot;
iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
fileRows.push(generateFileRow("config", slotInfo.configFile));
fileRows.push(generateFileRow("model", slotInfo.modelFile));
fileRows.push(generateFileRow("cluster", slotInfo.clusterFile));
infoRow = generateInfoRow(`tune:${slotInfo.defaultTune},cluster:${slotInfo.defaultClusterInferRatio},noise:${slotInfo.noiseScale}`);
} else if (x.voiceChangerType == "DDSP-SVC") {
const slotInfo = x as DDSPSVCModelSlot
iconArea = generateIconArea(index, slotInfo.iconFile, true)
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl)
fileRows.push(generateFileRow("config", slotInfo.configFile))
fileRows.push(generateFileRow("model", slotInfo.modelFile))
fileRows.push(generateFileRow("diff conf", slotInfo.diffConfigFile))
fileRows.push(generateFileRow("diff model", slotInfo.diffModelFile))
infoRow = generateInfoRow((`tune:${slotInfo.defaultTune},acc:${slotInfo.acc},ks:${slotInfo.kstep}, diff:${slotInfo.diffusion},enh:${slotInfo.enhancer}`))
const slotInfo = x as DDSPSVCModelSlot;
iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
fileRows.push(generateFileRow("config", slotInfo.configFile));
fileRows.push(generateFileRow("model", slotInfo.modelFile));
fileRows.push(generateFileRow("diff conf", slotInfo.diffConfigFile));
fileRows.push(generateFileRow("diff model", slotInfo.diffModelFile));
infoRow = generateInfoRow(`tune:${slotInfo.defaultTune},acc:${slotInfo.acc},ks:${slotInfo.kstep}, diff:${slotInfo.diffusion},enh:${slotInfo.enhancer}`);
} else if (x.voiceChangerType == "Diffusion-SVC") {
const slotInfo = x as DiffusionSVCModelSlot;
iconArea = generateIconArea(index, slotInfo.iconFile, true);
nameRow = generateNameRow(index, slotInfo.name, slotInfo.termsOfUseUrl);
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},`);
} else {
iconArea = generateIconArea(index, "/assets/icons/blank.png", false)
nameRow = generateNameRow(index, "", "")
iconArea = generateIconArea(index, "/assets/icons/blank.png", false);
nameRow = generateNameRow(index, "", "");
}
return (
<div key={index} className="model-slot">
@ -219,26 +237,45 @@ export const MainScreen = (props: MainScreenProps) => {
{infoRow}
</div>
<div className="model-slot-buttons">
<div className="model-slot-button" onClick={() => { props.openFileUploader(index) }} >{messageBuilderState.getMessage(__filename, "upload")}</div>
<div className="model-slot-button" onClick={() => { props.openSampleDownloader(index) }} >{messageBuilderState.getMessage(__filename, "sample")}</div>
<div className="model-slot-button" onClick={() => { props.openEditor(index) }} >{messageBuilderState.getMessage(__filename, "edit")}</div>
<div
className="model-slot-button"
onClick={() => {
props.openFileUploader(index);
}}
>
{messageBuilderState.getMessage(__filename, "upload")}
</div>
<div
className="model-slot-button"
onClick={() => {
props.openSampleDownloader(index);
}}
>
{messageBuilderState.getMessage(__filename, "sample")}
</div>
<div
className="model-slot-button"
onClick={() => {
props.openEditor(index);
}}
>
{messageBuilderState.getMessage(__filename, "edit")}
</div>
</div>
</div >
)
})
</div>
);
});
return (
<div className="dialog-frame">
<div className="dialog-title">Model Slot Configuration</div>
<div className="dialog-fixed-size-content">
<div className="model-slot-container">
{slotRow}
</div>
<div className="model-slot-container">{slotRow}</div>
{closeButtonRow}
</div>
</div>
)
}, [props.screen, serverSetting.serverSetting])
);
}, [props.screen, serverSetting.serverSetting]);
return screen
}
return screen;
};

View File

@ -6,68 +6,54 @@ import { FileUploaderScreen } from "./904-3_FileUploader";
import { EditorScreen } from "./904-4_Editor";
export type uploadData = {
slot: number
model: File | null
index: File | null
}
slot: number;
model: File | null;
index: File | null;
};
export const ModelSlotSettingMode = {
"localFile": "localFile",
"fromNet": "fromNet"
} as const
export type ModelSlotSettingMode = typeof ModelSlotSettingMode[keyof typeof ModelSlotSettingMode]
localFile: "localFile",
fromNet: "fromNet",
} as const;
export type ModelSlotSettingMode = (typeof ModelSlotSettingMode)[keyof typeof ModelSlotSettingMode];
export const ModelSlotManagerDialogScreen = {
"Main": "Main",
"SampleDownloader": "SampleDownloader",
"FileUploader": "FileUploader",
"Editor": "Editor"
} as const
export type ModelSlotManagerDialogScreen = typeof ModelSlotManagerDialogScreen[keyof typeof ModelSlotManagerDialogScreen]
Main: "Main",
SampleDownloader: "SampleDownloader",
FileUploader: "FileUploader",
Editor: "Editor",
} as const;
export type ModelSlotManagerDialogScreen = (typeof ModelSlotManagerDialogScreen)[keyof typeof ModelSlotManagerDialogScreen];
export const ModelSlotManagerDialog = () => {
const guiState = useGuiState()
const [screen, setScreen] = useState<ModelSlotManagerDialogScreen>("Main")
const [targetIndex, setTargetIndex] = useState<number>(0)
const guiState = useGuiState();
const [screen, setScreen] = useState<ModelSlotManagerDialogScreen>("Main");
const [targetIndex, setTargetIndex] = useState<number>(0);
const dialog = useMemo(() => {
const close = () => { guiState.stateControls.showModelSlotManagerCheckbox.updateState(false) }
const openSampleDownloader = (index: number) => { setTargetIndex(index); setScreen("SampleDownloader") }
const openFileUploader = (index: number) => { setTargetIndex(index); setScreen("FileUploader") }
const openEditor = (index: number) => { setTargetIndex(index); setScreen("Editor") }
const close = () => {
guiState.stateControls.showModelSlotManagerCheckbox.updateState(false);
};
const openSampleDownloader = (index: number) => {
setTargetIndex(index);
setScreen("SampleDownloader");
};
const openFileUploader = (index: number) => {
setTargetIndex(index);
setScreen("FileUploader");
};
const openEditor = (index: number) => {
setTargetIndex(index);
setScreen("Editor");
};
const backToSlotManager = () => { setScreen("Main") }
const mainScreen = (
<MainScreen
screen={screen}
close={close}
openSampleDownloader={openSampleDownloader}
openFileUploader={openFileUploader}
openEditor={openEditor}
/>
)
const sampleDownloaderScreen = (
<SampleDownloaderScreen
screen={screen}
targetIndex={targetIndex}
close={close}
backToSlotManager={backToSlotManager} />
)
const fileUploaderScreen = (
<FileUploaderScreen
screen={screen}
targetIndex={targetIndex}
close={close}
backToSlotManager={backToSlotManager} />
)
const editorScreen = (
<EditorScreen
screen={screen}
targetIndex={targetIndex}
close={close}
backToSlotManager={backToSlotManager} />
)
const backToSlotManager = () => {
setScreen("Main");
};
const mainScreen = <MainScreen screen={screen} close={close} openSampleDownloader={openSampleDownloader} openFileUploader={openFileUploader} openEditor={openEditor} />;
const sampleDownloaderScreen = <SampleDownloaderScreen screen={screen} targetIndex={targetIndex} close={close} backToSlotManager={backToSlotManager} />;
const fileUploaderScreen = <FileUploaderScreen screen={screen} targetIndex={targetIndex} close={close} backToSlotManager={backToSlotManager} />;
const editorScreen = <EditorScreen screen={screen} targetIndex={targetIndex} close={close} backToSlotManager={backToSlotManager} />;
return (
<div className="dialog-frame">
{mainScreen}
@ -75,10 +61,8 @@ export const ModelSlotManagerDialog = () => {
{fileUploaderScreen}
{editorScreen}
</div>
)
}, [screen, targetIndex])
);
}, [screen, targetIndex]);
return dialog;
};

View File

@ -276,6 +276,8 @@ export type DiffusionSVCModelSlot = ModelSlot & {
defaultKstep : number
defaultSpeedup: number
kStepMax: number
nLayers: number
nnLayers: number
speakers: { [key: number]: string }
}