WIP: integrate vcs to new gui 2

This commit is contained in:
wataru 2023-06-21 03:32:18 +09:00
parent b9c1ee4346
commit c7e72e52db
7 changed files with 166 additions and 33 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useGuiState } from "./001_GuiStateProvider"; import { useGuiState } from "./001_GuiStateProvider";
import { useAppState } from "../../001_provider/001_AppStateProvider"; import { useAppState } from "../../001_provider/001_AppStateProvider";
import { RVCModelSlot, fileSelector } from "@dannadori/voice-changer-client-js"; import { DDSPSVCModelSlot, MMVCv13ModelSlot, MMVCv15ModelSlot, RVCModelSlot, SoVitsSvc40ModelSlot, fileSelector } 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";
import { checkExtention, trimfileName } from "../../utils/utils"; import { checkExtention, trimfileName } from "../../utils/utils";
@ -23,6 +23,9 @@ export const MainScreen = (props: MainScreenProps) => {
messageBuilderState.setMessage(__filename, "rename", { "ja": "リネーム", "en": "rename" }) messageBuilderState.setMessage(__filename, "rename", { "ja": "リネーム", "en": "rename" })
messageBuilderState.setMessage(__filename, "download", { "ja": "ダウンロード", "en": "download" }) messageBuilderState.setMessage(__filename, "download", { "ja": "ダウンロード", "en": "download" })
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, "sample", { "ja": "サンプル", "en": "DL sample" })
messageBuilderState.setMessage(__filename, "upload", { "ja": "アップロード", "en": "upload" })
messageBuilderState.setMessage(__filename, "close", { "ja": "閉じる", "en": "close" })
}, []) }, [])
@ -85,7 +88,9 @@ export const MainScreen = (props: MainScreenProps) => {
<div className="body-item-text"> <div className="body-item-text">
</div> </div>
<div className="body-button-container body-button-container-space-around"> <div className="body-button-container body-button-container-space-around">
<div className="body-button" onClick={() => { props.close() }} >close</div> <div className="body-button" onClick={() => { props.close() }} >
{messageBuilderState.getMessage(__filename, "close")}
</div>
</div> </div>
<div className="body-item-text"></div> <div className="body-item-text"></div>
</div> </div>
@ -167,6 +172,37 @@ export const MainScreen = (props: MainScreenProps) => {
fileRows.push(generateFileRow("model", slotInfo.modelFile)) fileRows.push(generateFileRow("model", slotInfo.modelFile))
fileRows.push(generateFileRow("index", slotInfo.indexFile)) fileRows.push(generateFileRow("index", slotInfo.indexFile))
infoRow = generateInfoRow(`${slotInfo.f0 ? "f0" : "nof0"}, ${slotInfo.samplingRate}, ${slotInfo.embChannels}, ${slotInfo.modelType}, ${slotInfo.defaultTune}, ${slotInfo.defaultIndexRatio}, ${slotInfo.defaultProtect}`) 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(``)
} 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}`))
} 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}`))
} 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}`))
} else { } else {
iconArea = generateIconArea(index, "/assets/icons/blank.png", false) iconArea = generateIconArea(index, "/assets/icons/blank.png", false)
nameRow = generateNameRow(index, "", "") nameRow = generateNameRow(index, "", "")
@ -181,8 +217,8 @@ export const MainScreen = (props: MainScreenProps) => {
{infoRow} {infoRow}
</div> </div>
<div className="model-slot-buttons"> <div className="model-slot-buttons">
<div className="model-slot-button" onClick={() => { props.openFileUploader(index) }} >upload</div> <div className="model-slot-button" onClick={() => { props.openFileUploader(index) }} >{messageBuilderState.getMessage(__filename, "upload")}</div>
<div className="model-slot-button" onClick={() => { props.openSampleDownloader(index) }} >DL sample</div> <div className="model-slot-button" onClick={() => { props.openSampleDownloader(index) }} >{messageBuilderState.getMessage(__filename, "sample")}</div>
</div> </div>
</div > </div >
) )

View File

@ -17,7 +17,11 @@ export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => {
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, "lang", { "ja": "言語", "en": "Lang" })
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" })
}, []) }, [])
@ -82,7 +86,9 @@ export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => {
</div> </div>
</div> </div>
<div className="model-slot-buttons"> <div className="model-slot-buttons">
<div className="model-slot-button" onClick={() => { onDownloadSampleClicked(x.id) }}>download</div> <div className="model-slot-button" onClick={() => { onDownloadSampleClicked(x.id) }}>
{messageBuilderState.getMessage(__filename, "download")}
</div>
</div> </div>
</div> </div>
) )
@ -93,10 +99,13 @@ export const SampleDownloaderScreen = (props: SampleDownloaderScreenProps) => {
<div className="dialog-frame"> <div className="dialog-frame">
<div className="dialog-title">Sample Downloader</div> <div className="dialog-title">Sample Downloader</div>
<div className="dialog-fixed-size-content"> <div className="dialog-fixed-size-content">
<div className="model-slot-header">Select Sample for Slot[{props.targetIndex}] <span onClick={() => { <div className="model-slot-header">
props.backToSlotManager() {messageBuilderState.getMessage(__filename, "header_message")} Slot[{props.targetIndex}]
}} className="model-slot-header-button">&lt;&lt;back</span></div> <span onClick={() => { props.backToSlotManager() }} className="model-slot-header-button">
<div>Lang: &lt;&lt;{messageBuilderState.getMessage(__filename, "back")}
</span>
</div>
<div>{messageBuilderState.getMessage(__filename, "lang")}:
<select value={lang} onChange={(e) => { setLang(e.target.value) }}> <select value={lang} onChange={(e) => { setLang(e.target.value) }}>
{langOptions} {langOptions}
</select> </select>

View File

@ -19,8 +19,11 @@ export const FileUploaderScreen = (props: FileUploaderScreenProps) => {
const messageBuilderState = useMessageBuilder() const messageBuilderState = useMessageBuilder()
useMemo(() => { useMemo(() => {
messageBuilderState.setMessage(__filename, "header_message", { "ja": "ファイルをアップロードしてください. 対象:", "en": "Upload Files for " })
messageBuilderState.setMessage(__filename, "back", { "ja": "戻る", "en": "back" })
messageBuilderState.setMessage(__filename, "select", { "ja": "ファイル選択", "en": "select file" }) messageBuilderState.setMessage(__filename, "select", { "ja": "ファイル選択", "en": "select file" })
messageBuilderState.setMessage(__filename, "upload", { "ja": "アップロード", "en": "upload" }) messageBuilderState.setMessage(__filename, "upload", { "ja": "アップロード", "en": "upload" })
messageBuilderState.setMessage(__filename, "uploading", { "ja": "アップロード中", "en": "uploading" })
messageBuilderState.setMessage(__filename, "alert-model-ext", { messageBuilderState.setMessage(__filename, "alert-model-ext", {
"ja": "ファイルの拡張子は次のモノである必要があります。", "ja": "ファイルの拡張子は次のモノである必要があります。",
"en": "extension of file should be the following." "en": "extension of file should be the following."
@ -132,13 +135,20 @@ export const FileUploaderScreen = (props: FileUploaderScreenProps) => {
} }
const fileRows = generateFileRowsByVCType(voiceChangerType) const fileRows = generateFileRowsByVCType(voiceChangerType)
// appState.serverSetting.uploadProgress == 0 ? `loading model...(wait about 20sec)` : `processing.... ${appState.serverSetting.uploadProgress.toFixed(1)}%` : ""
const buttonLabel = serverSetting.uploadProgress == 0 ?
messageBuilderState.getMessage(__filename, "upload") :
messageBuilderState.getMessage(__filename, "uploading") + `(${serverSetting.uploadProgress.toFixed(1)}%)`
return ( return (
<div className="dialog-frame"> <div className="dialog-frame">
<div className="dialog-title">File Uploader</div> <div className="dialog-title">File Uploader</div>
<div className="dialog-fixed-size-content"> <div className="dialog-fixed-size-content">
<div className="file-uploader-header">Upload Files for Slot[{props.targetIndex}] <span onClick={() => { <div className="file-uploader-header">
props.backToSlotManager() {messageBuilderState.getMessage(__filename, "header_message")} Slot[{props.targetIndex}]
}} className="file-uploader-header-button">&lt;&lt;back</span></div> <span onClick={() => {
props.backToSlotManager()
}} className="file-uploader-header-button">&lt;&lt;{messageBuilderState.getMessage(__filename, "back")}</span></div>
<div className="file-uploader-voice-changer-select" >VoiceChangerType: <div className="file-uploader-voice-changer-select" >VoiceChangerType:
<select value={voiceChangerType} onChange={(e) => { <select value={voiceChangerType} onChange={(e) => {
setVoiceChangerType(e.target.value as VoiceChangerType) setVoiceChangerType(e.target.value as VoiceChangerType)
@ -155,6 +165,9 @@ export const FileUploaderScreen = (props: FileUploaderScreenProps) => {
if (!uploadSetting) { if (!uploadSetting) {
return return
} }
if (serverSetting.uploadProgress != 0) {
return
}
if (checkModelSetting(uploadSetting)) { if (checkModelSetting(uploadSetting)) {
serverSetting.uploadModel(uploadSetting) serverSetting.uploadModel(uploadSetting)
} else { } else {
@ -162,7 +175,7 @@ export const FileUploaderScreen = (props: FileUploaderScreenProps) => {
alert(errorMessage) alert(errorMessage)
} }
}}> }}>
{messageBuilderState.getMessage(__filename, "upload")} {buttonLabel}
</div> </div>
</div> </div>
</div> </div>
@ -174,7 +187,8 @@ export const FileUploaderScreen = (props: FileUploaderScreenProps) => {
props.targetIndex, props.targetIndex,
voiceChangerType, voiceChangerType,
uploadSetting, uploadSetting,
serverSetting.uploadModel serverSetting.uploadModel,
serverSetting.uploadProgress
]) ])

View File

@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useGuiState } from "./001_GuiStateProvider"; import { useGuiState } from "./001_GuiStateProvider";
import { useAppState } from "../../001_provider/001_AppStateProvider"; import { useAppState } from "../../001_provider/001_AppStateProvider";
import { MergeElement, RVCModelType } from "@dannadori/voice-changer-client-js"; import { MergeElement, RVCModelSlot, RVCModelType } from "@dannadori/voice-changer-client-js";
export const MergeLabDialog = () => { export const MergeLabDialog = () => {
@ -23,13 +23,17 @@ export const MergeLabDialog = () => {
const filterItems = useMemo(() => { const filterItems = useMemo(() => {
return serverSetting.serverSetting.modelSlots.reduce((prev, cur) => { return serverSetting.serverSetting.modelSlots.reduce((prev, cur) => {
const key = `${cur.modelType},${cur.samplingRate},${cur.embChannels}` if (cur.voiceChangerType != "RVC") {
const val = { type: cur.modelType, samplingRate: cur.samplingRate, embChannels: cur.embChannels } return prev
}
const curRVC = cur as RVCModelSlot
const key = `${curRVC.modelType},${cur.samplingRate},${curRVC.embChannels}`
const val = { type: curRVC.modelType, samplingRate: cur.samplingRate, embChannels: curRVC.embChannels }
const existKeys = Object.keys(prev) const existKeys = Object.keys(prev)
if (!cur.modelFile || cur.modelFile.length == 0) { if (!cur.modelFile || cur.modelFile.length == 0) {
return prev return prev
} }
if (cur.modelType == "onnxRVC" || cur.modelType == "onnxRVCNono") { if (curRVC.modelType == "onnxRVC" || curRVC.modelType == "onnxRVCNono") {
return prev return prev
} }
if (!existKeys.includes(key)) { if (!existKeys.includes(key)) {
@ -42,11 +46,15 @@ export const MergeLabDialog = () => {
const models = useMemo(() => { const models = useMemo(() => {
return serverSetting.serverSetting.modelSlots.filter(x => { return serverSetting.serverSetting.modelSlots.filter(x => {
if (x.voiceChangerType != "RVC") {
return
}
const xRVC = x as RVCModelSlot
const filterVals = filterItems[currentFilter] const filterVals = filterItems[currentFilter]
if (!filterVals) { if (!filterVals) {
return false return false
} }
if (x.modelType == filterVals.type && x.samplingRate == filterVals.samplingRate && x.embChannels == filterVals.embChannels) { if (xRVC.modelType == filterVals.type && xRVC.samplingRate == filterVals.samplingRate && xRVC.embChannels == filterVals.embChannels) {
return true return true
} else { } else {
return false return false

View File

@ -735,6 +735,7 @@ body {
.model-slot-header, .model-slot-header,
.file-uploader-header { .file-uploader-header {
font-weight: 700; font-weight: 700;
margin: 5px 5px 5px 5px;
.model-slot-header-button, .model-slot-header-button,
.file-uploader-header-button { .file-uploader-header-button {
font-weight: 400; font-weight: 400;
@ -745,7 +746,8 @@ body {
cursor: pointer; cursor: pointer;
vertical-align: middle; vertical-align: middle;
text-align: center; text-align: center;
padding: 1px; padding: 1px 5px 1px 5px;
margin-left: 1rem;
&:hover { &:hover {
border: solid 1px #000; border: solid 1px #000;
} }
@ -755,6 +757,7 @@ body {
max-height: 60vh; max-height: 60vh;
width: 100%; width: 100%;
overflow-y: scroll; overflow-y: scroll;
.model-slot { .model-slot {
height: 5rem; height: 5rem;
display: flex; display: flex;
@ -774,28 +777,43 @@ body {
font-size: 0.8rem; font-size: 0.8rem;
border-bottom: solid 1px #aaa; border-bottom: solid 1px #aaa;
width: 80%; width: 80%;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-track {
background-color: #eee;
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #f7cfec80;
border-radius: 3px;
}
.model-slot-detail-row { .model-slot-detail-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
.model-slot-detail-row-label { .model-slot-detail-row-label {
width: 15%; width: 20%;
white-space: nowrap;
} }
.model-slot-detail-row-value { .model-slot-detail-row-value {
width: 60%; width: 55%;
white-space: nowrap; white-space: nowrap;
} }
.model-slot-detail-row-value-download { .model-slot-detail-row-value-download {
width: 60%; width: 55%;
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
} }
.model-slot-detail-row-value-pointable { .model-slot-detail-row-value-pointable {
width: 60%; width: 55%;
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
} }
.model-slot-detail-row-value-edit { .model-slot-detail-row-value-edit {
width: 60%; width: 55%;
font-weight: 700; font-weight: 700;
color: #f00; color: #f00;
white-space: nowrap; white-space: nowrap;
@ -889,16 +907,17 @@ body {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-top: 1rem; margin-top: 1rem;
margin-bottom: 0.5rem;
justify-content: center; justify-content: center;
.file-uploader-file-select-upload-button { .file-uploader-file-select-upload-button {
width: 8rem; /* width: 12rem; */
user-select: none; user-select: none;
border: solid 1px #999; border: solid 1px #999;
border-radius: 2px; border-radius: 2px;
cursor: pointer; cursor: pointer;
vertical-align: middle; vertical-align: middle;
text-align: center; text-align: center;
padding: 1px; padding: 1px 10px 1px 10px;
&:hover { &:hover {
border: solid 1px #000; border: solid 1px #000;
} }

View File

@ -233,7 +233,54 @@ export type RVCModelSlot = ModelSlot & {
deprecated: boolean deprecated: boolean
} }
export type ModelSlotUnion = RVCModelSlot export type MMVCv13ModelSlot = ModelSlot & {
modelFile: string
configFile: string,
srcId: number
dstId: number
samplingRate: number
}
export type MMVCv15ModelSlot = ModelSlot & {
modelFile: string
configFile: string,
srcId: number
dstId: number
f0Factor: number
samplingRate: number
}
export type SoVitsSvc40ModelSlot = ModelSlot & {
modelFile: string
configFile: string,
clusterFile: string,
dstId: number
samplingRate: number
defaultTune: number
defaultClusterInferRatio: number
noiseScale: number
}
export type DDSPSVCModelSlot = ModelSlot & {
modelFile: string
configFile: string,
diffModelFile: string
diffConfigFile: string
dstId: number
samplingRate: number
defaultTune: number
enhancer: boolean
diffusion: boolean
acc: number
kstep: number
}
export type ModelSlotUnion = RVCModelSlot | MMVCv13ModelSlot | MMVCv15ModelSlot | SoVitsSvc40ModelSlot | DDSPSVCModelSlot
type ServerAudioDevice = { type ServerAudioDevice = {
kind: "audioinput" | "audiooutput", kind: "audioinput" | "audiooutput",