mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-01-23 13:35:12 +03:00
WIP: model slot edit
This commit is contained in:
parent
4017e6c62c
commit
16598b3034
BIN
client/demo/dist/assets/icons/blank.png
vendored
Normal file
BIN
client/demo/dist/assets/icons/blank.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
client/demo/dist/assets/icons/noimage.png
vendored
Normal file
BIN
client/demo/dist/assets/icons/noimage.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
11
client/demo/dist/index.html
vendored
11
client/demo/dist/index.html
vendored
@ -1 +1,10 @@
|
|||||||
<!doctype html><html style="width:100%;height:100%;overflow:hidden"><head><meta charset="utf-8"/><title>Voice Changer Client Demo</title><script defer="defer" src="index.js"></script></head><body style="width:100%;height:100%;margin:0"><div id="app" style="width:100%;height:100%"></div></body></html>
|
<!DOCTYPE html>
|
||||||
|
<html style="width: 100%; height: 100%; overflow: hidden">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Voice Changer Client Demo</title>
|
||||||
|
<script defer src="index.js"></script></head>
|
||||||
|
<body style="width: 100%; height: 100%; margin: 0px">
|
||||||
|
<div id="app" style="width: 100%; height: 100%"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
1750
client/demo/dist/index.js
vendored
1750
client/demo/dist/index.js
vendored
File diff suppressed because one or more lines are too long
31
client/demo/dist/index.js.LICENSE.txt
vendored
31
client/demo/dist/index.js.LICENSE.txt
vendored
@ -1,31 +0,0 @@
|
|||||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* react-dom.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* react.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license React
|
|
||||||
* scheduler.production.min.js
|
|
||||||
*
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
3514
client/demo/package-lock.json
generated
3514
client/demo/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
BIN
client/demo/public/assets/icons/blank.png
Normal file
BIN
client/demo/public/assets/icons/blank.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
client/demo/public/assets/icons/noimage.png
Normal file
BIN
client/demo/public/assets/icons/noimage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
@ -15,6 +15,7 @@ export const OpenLabCheckbox = "open-lab-checkbox"
|
|||||||
export const OpenLicenseDialogCheckbox = "open-license-dialog-checkbox"
|
export const OpenLicenseDialogCheckbox = "open-license-dialog-checkbox"
|
||||||
export const OpenWaitingDialogCheckbox = "open-waiting-dialog-checkbox"
|
export const OpenWaitingDialogCheckbox = "open-waiting-dialog-checkbox"
|
||||||
export const OpenStartingNoticeDialogCheckbox = "open-starting-notice-dialog-checkbox"
|
export const OpenStartingNoticeDialogCheckbox = "open-starting-notice-dialog-checkbox"
|
||||||
|
export const OpenModelSlotManagerDialogCheckbox = "open-model-slot-manager-dialog-checkbox"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -33,6 +34,7 @@ export type StateControls = {
|
|||||||
showLicenseCheckbox: StateControlCheckbox
|
showLicenseCheckbox: StateControlCheckbox
|
||||||
showWaitingCheckbox: StateControlCheckbox
|
showWaitingCheckbox: StateControlCheckbox
|
||||||
showStartingNoticeCheckbox: StateControlCheckbox
|
showStartingNoticeCheckbox: StateControlCheckbox
|
||||||
|
showModelSlotManagerCheckbox: StateControlCheckbox
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +153,7 @@ export const GuiStateProvider = ({ children }: Props) => {
|
|||||||
const showLicenseCheckbox = useStateControlCheckbox(OpenLicenseDialogCheckbox);
|
const showLicenseCheckbox = useStateControlCheckbox(OpenLicenseDialogCheckbox);
|
||||||
const showWaitingCheckbox = useStateControlCheckbox(OpenWaitingDialogCheckbox);
|
const showWaitingCheckbox = useStateControlCheckbox(OpenWaitingDialogCheckbox);
|
||||||
const showStartingNoticeCheckbox = useStateControlCheckbox(OpenStartingNoticeDialogCheckbox);
|
const showStartingNoticeCheckbox = useStateControlCheckbox(OpenStartingNoticeDialogCheckbox);
|
||||||
|
const showModelSlotManagerCheckbox = useStateControlCheckbox(OpenModelSlotManagerDialogCheckbox);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
openServerControlCheckbox.updateState(true)
|
openServerControlCheckbox.updateState(true)
|
||||||
@ -168,6 +171,7 @@ export const GuiStateProvider = ({ children }: Props) => {
|
|||||||
|
|
||||||
|
|
||||||
showStartingNoticeCheckbox.updateState(false)
|
showStartingNoticeCheckbox.updateState(false)
|
||||||
|
showModelSlotManagerCheckbox.updateState(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -204,7 +208,8 @@ export const GuiStateProvider = ({ children }: Props) => {
|
|||||||
|
|
||||||
showLicenseCheckbox,
|
showLicenseCheckbox,
|
||||||
showWaitingCheckbox,
|
showWaitingCheckbox,
|
||||||
showStartingNoticeCheckbox
|
showStartingNoticeCheckbox,
|
||||||
|
showModelSlotManagerCheckbox
|
||||||
},
|
},
|
||||||
isConverting,
|
isConverting,
|
||||||
setIsConverting,
|
setIsConverting,
|
||||||
|
@ -3,6 +3,7 @@ import { useGuiState } from "./001_GuiStateProvider";
|
|||||||
import { LicenseDialog } from "./901_LicenseDialog";
|
import { LicenseDialog } from "./901_LicenseDialog";
|
||||||
import { WaitingDialog } from "./902_WaitingDialog";
|
import { WaitingDialog } from "./902_WaitingDialog";
|
||||||
import { StartingNoticeDialog } from "./903_StartingNoticeDialog";
|
import { StartingNoticeDialog } from "./903_StartingNoticeDialog";
|
||||||
|
import { ModelSlotManagerDialog } from "./904_ModelSlotManagerDialog";
|
||||||
|
|
||||||
export const Dialogs = () => {
|
export const Dialogs = () => {
|
||||||
const guiState = useGuiState()
|
const guiState = useGuiState()
|
||||||
@ -11,6 +12,7 @@ export const Dialogs = () => {
|
|||||||
{guiState.stateControls.showLicenseCheckbox.trigger}
|
{guiState.stateControls.showLicenseCheckbox.trigger}
|
||||||
{guiState.stateControls.showWaitingCheckbox.trigger}
|
{guiState.stateControls.showWaitingCheckbox.trigger}
|
||||||
{guiState.stateControls.showStartingNoticeCheckbox.trigger}
|
{guiState.stateControls.showStartingNoticeCheckbox.trigger}
|
||||||
|
{guiState.stateControls.showModelSlotManagerCheckbox.trigger}
|
||||||
<div className="dialog-container" id="dialog">
|
<div className="dialog-container" id="dialog">
|
||||||
{guiState.stateControls.showLicenseCheckbox.trigger}
|
{guiState.stateControls.showLicenseCheckbox.trigger}
|
||||||
<LicenseDialog></LicenseDialog>
|
<LicenseDialog></LicenseDialog>
|
||||||
@ -18,6 +20,8 @@ export const Dialogs = () => {
|
|||||||
<WaitingDialog></WaitingDialog>
|
<WaitingDialog></WaitingDialog>
|
||||||
{guiState.stateControls.showStartingNoticeCheckbox.trigger}
|
{guiState.stateControls.showStartingNoticeCheckbox.trigger}
|
||||||
<StartingNoticeDialog></StartingNoticeDialog>
|
<StartingNoticeDialog></StartingNoticeDialog>
|
||||||
|
{guiState.stateControls.showModelSlotManagerCheckbox.trigger}
|
||||||
|
<ModelSlotManagerDialog></ModelSlotManagerDialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
304
client/demo/src/components/demo/904_ModelSlotManagerDialog.tsx
Normal file
304
client/demo/src/components/demo/904_ModelSlotManagerDialog.tsx
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
import React, { useMemo, useState } from "react";
|
||||||
|
import { useGuiState } from "./001_GuiStateProvider";
|
||||||
|
import { getMessage } from "./messages/MessageBuilder";
|
||||||
|
import { isDesktopApp } from "../../const";
|
||||||
|
import { useAppRoot } from "../../001_provider/001_AppRootProvider";
|
||||||
|
import { useAppState } from "../../001_provider/001_AppStateProvider";
|
||||||
|
import { InitialFileUploadSetting, fileSelector } from "@dannadori/voice-changer-client-js";
|
||||||
|
|
||||||
|
|
||||||
|
export type uploadData = {
|
||||||
|
slot: number
|
||||||
|
model: File | null
|
||||||
|
index: File | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const Mode = {
|
||||||
|
"localFile": "localFile",
|
||||||
|
"fromNet": "fromNet"
|
||||||
|
} as const
|
||||||
|
type Mode = typeof Mode[keyof typeof Mode]
|
||||||
|
|
||||||
|
export const ModelSlotManagerDialog = () => {
|
||||||
|
const guiState = useGuiState()
|
||||||
|
const { serverSetting } = useAppState()
|
||||||
|
const [uploadData, setUploadData] = useState<uploadData | null>(null)
|
||||||
|
const [mode, setMode] = useState<Mode>("localFile")
|
||||||
|
const [fromNetTargetIndex, setFromNetTargetIndex] = useState<number>(0)
|
||||||
|
const [lang, setLang] = useState<string>("All")
|
||||||
|
const [sampleId, setSampleId] = useState<string>("")
|
||||||
|
|
||||||
|
const localFileContent = useMemo(() => {
|
||||||
|
if (mode != "localFile") {
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkExtention = (filename: string, acceptExtentions: string[]) => {
|
||||||
|
const ext = filename.split('.').pop();
|
||||||
|
if (!ext) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return acceptExtentions.includes(ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onRVCModelLoadClicked = async (slot: number) => {
|
||||||
|
const file = await fileSelector("")
|
||||||
|
if (checkExtention(file.name, ["pth"]) == false) {
|
||||||
|
alert(`モデルファイルの拡張子は".pth"である必要があります。`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (uploadData?.slot == slot) {
|
||||||
|
setUploadData({ ...uploadData, model: file })
|
||||||
|
} else {
|
||||||
|
const newUploadData = {
|
||||||
|
slot: slot,
|
||||||
|
model: file,
|
||||||
|
index: null
|
||||||
|
}
|
||||||
|
setUploadData(newUploadData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onRVCIndexLoadClicked = async (slot: number) => {
|
||||||
|
const file = await fileSelector("")
|
||||||
|
if (checkExtention(file.name, ["index", "bin"]) == false) {
|
||||||
|
alert(`モデルファイルの拡張子は".pth"である必要があります。`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (uploadData?.slot == slot) {
|
||||||
|
setUploadData({ ...uploadData, index: file })
|
||||||
|
} else {
|
||||||
|
const newUploadData = {
|
||||||
|
slot: slot,
|
||||||
|
model: null,
|
||||||
|
index: file
|
||||||
|
}
|
||||||
|
setUploadData(newUploadData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onUploadClicked = async () => {
|
||||||
|
if (!uploadData) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!uploadData.model) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverSetting.fileUploadSettings[uploadData.slot] = {
|
||||||
|
...InitialFileUploadSetting,
|
||||||
|
rvcModel: { file: uploadData.model },
|
||||||
|
rvcIndex: uploadData.index ? { file: uploadData.index } : null,
|
||||||
|
sampleId: null,
|
||||||
|
isSampleMode: false
|
||||||
|
}
|
||||||
|
serverSetting.setFileUploadSetting(uploadData.slot, {
|
||||||
|
...serverSetting.fileUploadSettings[uploadData.slot]
|
||||||
|
})
|
||||||
|
await serverSetting.loadModel(uploadData.slot)
|
||||||
|
setUploadData(null)
|
||||||
|
}
|
||||||
|
const onClearClicked = () => {
|
||||||
|
setUploadData(null)
|
||||||
|
}
|
||||||
|
const onOpenSampleDownloadDialog = (index: number) => {
|
||||||
|
setMode("fromNet")
|
||||||
|
setFromNetTargetIndex(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const slots = serverSetting.serverSetting.modelSlots.map((x, index) => {
|
||||||
|
let modelFileName = ""
|
||||||
|
if (uploadData?.slot == index) {
|
||||||
|
modelFileName = (uploadData.model?.name || "").replace(/^.*[\\\/]/, '')
|
||||||
|
} else if (x.modelFile && x.modelFile.length > 0) {
|
||||||
|
modelFileName = x.modelFile.replace(/^.*[\\\/]/, '')
|
||||||
|
if (modelFileName.length > 20) {
|
||||||
|
modelFileName = modelFileName.substring(0, 20) + "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let indexFileName = ""
|
||||||
|
if (uploadData?.slot == index) {
|
||||||
|
indexFileName = (uploadData.index?.name || "").replace(/^.*[\\\/]/, '')
|
||||||
|
} else if (x.indexFile && x.indexFile.length > 0) {
|
||||||
|
indexFileName = x.indexFile.replace(/^.*[\\\/]/, '')
|
||||||
|
if (indexFileName.length > 20) {
|
||||||
|
indexFileName = indexFileName.substring(0, 20) + "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const termOfUseUrlLink = x.termsOfUseUrl.length > 0 ? <a href={x.termsOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[terms of use]</a> : <></>
|
||||||
|
|
||||||
|
const fileValueClass = (uploadData?.slot == index) ? "model-slot-detail-row-value-edit" : "model-slot-detail-row-value"
|
||||||
|
|
||||||
|
const iconUrl = x.modelFile && x.modelFile.length > 0 ? (x.iconFile && x.iconFile.length > 0 ? x.iconFile : "/assets/icons/noimage.png") : "/assets/icons/blank.png"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="model-slot">
|
||||||
|
<img src={iconUrl} className="model-slot-icon"></img>
|
||||||
|
<div className="model-slot-detail">
|
||||||
|
<div className="model-slot-detail-row">
|
||||||
|
<div className="model-slot-detail-row-label">[{index}]</div>
|
||||||
|
<div className="model-slot-detail-row-value">{x.name}</div>
|
||||||
|
<div className="">{termOfUseUrlLink}</div>
|
||||||
|
</div>
|
||||||
|
<div className="model-slot-detail-row">
|
||||||
|
<div className="model-slot-detail-row-label">model:</div>
|
||||||
|
<div className={fileValueClass}>{modelFileName}</div>
|
||||||
|
<div className="model-slot-button model-slot-detail-row-button" onClick={() => { onRVCModelLoadClicked(index) }}>select</div>
|
||||||
|
</div>
|
||||||
|
<div className="model-slot-detail-row">
|
||||||
|
<div className="model-slot-detail-row-label">index:</div>
|
||||||
|
<div className={fileValueClass}>{indexFileName}</div>
|
||||||
|
<div className="model-slot-button model-slot-detail-row-button" onClick={() => { onRVCIndexLoadClicked(index) }}>select</div>
|
||||||
|
</div>
|
||||||
|
<div className="model-slot-detail-row">
|
||||||
|
<div className="model-slot-detail-row-label">info: </div>
|
||||||
|
<div className="model-slot-detail-row-value">f0, 40k, 768, onnx, tune, i-rate, p-rate</div>
|
||||||
|
<div className=""></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="model-slot-buttons">
|
||||||
|
<div className="model-slot-button" onClick={() => { onOpenSampleDownloadDialog(index) }}>from net</div>
|
||||||
|
|
||||||
|
{(uploadData?.slot == index) && (uploadData.model != null) ?
|
||||||
|
<div className="model-slot-button" onClick={onUploadClicked}>upload</div> : <div></div>
|
||||||
|
}
|
||||||
|
{(uploadData?.slot == index) && (uploadData.model != null) ?
|
||||||
|
<div className="model-slot-button" onClick={onClearClicked}>clear</div> : <div></div>
|
||||||
|
}
|
||||||
|
{(uploadData?.slot == index) && (uploadData.model != null) ?
|
||||||
|
<div>%</div> : <div></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="model-slot-container">
|
||||||
|
{slots}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
}, [
|
||||||
|
mode,
|
||||||
|
serverSetting.serverSetting.modelSlots,
|
||||||
|
serverSetting.fileUploadSettings,
|
||||||
|
serverSetting.setFileUploadSetting,
|
||||||
|
serverSetting.loadModel,
|
||||||
|
uploadData
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const fromNetContent = useMemo(() => {
|
||||||
|
if (mode != "fromNet") {
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
const langs = serverSetting.serverSetting.sampleModels.reduce((prev, cur) => {
|
||||||
|
if (prev.includes(cur.lang) == false) {
|
||||||
|
prev.push(cur.lang)
|
||||||
|
}
|
||||||
|
return prev
|
||||||
|
}, ["All"] as string[])
|
||||||
|
const langOptions = (
|
||||||
|
langs.map(x => {
|
||||||
|
return <option key={x} value={x}>{x}</option>
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const onDownloadSampleClicked = async (id: string) => {
|
||||||
|
serverSetting.fileUploadSettings[fromNetTargetIndex] = {
|
||||||
|
...InitialFileUploadSetting,
|
||||||
|
rvcModel: null,
|
||||||
|
rvcIndex: null,
|
||||||
|
sampleId: id,
|
||||||
|
isSampleMode: true
|
||||||
|
}
|
||||||
|
await serverSetting.loadModel(fromNetTargetIndex)
|
||||||
|
setMode("localFile")
|
||||||
|
}
|
||||||
|
const options = (
|
||||||
|
serverSetting.serverSetting.sampleModels.filter(x => { return lang == "All" ? true : x.lang == lang }).map((x, index) => {
|
||||||
|
const termOfUseUrlLink = x.termsOfUseUrl.length > 0 ? <a href={x.termsOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[terms of use]</a> : <></>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="model-slot">
|
||||||
|
<img src={x.icon} className="model-slot-icon"></img>
|
||||||
|
<div className="model-slot-detail">
|
||||||
|
<div className="model-slot-detail-row">
|
||||||
|
<div className="model-slot-detail-row-label">name:</div>
|
||||||
|
<div className="model-slot-detail-row-value">{x.name}</div>
|
||||||
|
<div className="">{termOfUseUrlLink}</div>
|
||||||
|
</div>
|
||||||
|
<div className="model-slot-detail-row">
|
||||||
|
<div className="model-slot-detail-row-label">info: </div>
|
||||||
|
<div className="model-slot-detail-row-value">f0, 40k, 768, onnx, tune, i-rate, p-rate</div>
|
||||||
|
<div className=""></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="model-slot-buttons">
|
||||||
|
<div className="model-slot-button" onClick={() => { onDownloadSampleClicked(x.id) }}>download</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>Select Sample for Slot[{fromNetTargetIndex}] <span onClick={() => { setMode("localFile") }}>back</span></div>
|
||||||
|
<div>Lang:
|
||||||
|
<select value={lang} onChange={(e) => { setLang(e.target.value) }}>
|
||||||
|
{langOptions}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="model-slot-container">
|
||||||
|
{options}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}, [
|
||||||
|
mode,
|
||||||
|
fromNetTargetIndex,
|
||||||
|
lang
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
const dialog = useMemo(() => {
|
||||||
|
const closeButtonRow = (
|
||||||
|
<div className="body-row split-3-4-3 left-padding-1">
|
||||||
|
<div className="body-item-text">
|
||||||
|
</div>
|
||||||
|
<div className="body-button-container body-button-container-space-around">
|
||||||
|
<div className="body-button" onClick={() => { guiState.stateControls.showModelSlotManagerCheckbox.updateState(false) }} >close</div>
|
||||||
|
</div>
|
||||||
|
<div className="body-item-text"></div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div className="dialog-frame">
|
||||||
|
<div className="dialog-title">{mode == "localFile" ? "Model Slot Configuration" : "Sample Downloader"}</div>
|
||||||
|
<div className="dialog-fixed-size-content">
|
||||||
|
{localFileContent}
|
||||||
|
{fromNetContent}
|
||||||
|
{closeButtonRow}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
}, [
|
||||||
|
localFileContent,
|
||||||
|
fromNetContent,
|
||||||
|
fromNetTargetIndex,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return dialog;
|
||||||
|
|
||||||
|
};
|
@ -43,7 +43,6 @@ export const ONNXExportRow = (_props: ONNXExportRowProps) => {
|
|||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
guiState.stateControls.showWaitingCheckbox.updateState(false)
|
guiState.stateControls.showWaitingCheckbox.updateState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportOnnx = appState.serverSetting.serverSetting.framework == "PyTorch" ? (
|
const exportOnnx = appState.serverSetting.serverSetting.framework == "PyTorch" ? (
|
||||||
<div className="body-button left-margin-1" onClick={onnxExportButtonAction}>export onnx</div>
|
<div className="body-button left-margin-1" onClick={onnxExportButtonAction}>export onnx</div>
|
||||||
) : <></>
|
) : <></>
|
||||||
|
@ -45,6 +45,9 @@ export const ServerOpertationRow = (props: ServerOpertationRowProps) => {
|
|||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
}
|
}
|
||||||
|
const onModelSlotEditClicked = () => {
|
||||||
|
guiState.stateControls.showModelSlotManagerCheckbox.updateState(true)
|
||||||
|
}
|
||||||
const onReloadClicked = async () => {
|
const onReloadClicked = async () => {
|
||||||
const info = await appState.getInfo()
|
const info = await appState.getInfo()
|
||||||
console.log("info", info)
|
console.log("info", info)
|
||||||
@ -60,6 +63,11 @@ export const ServerOpertationRow = (props: ServerOpertationRowProps) => {
|
|||||||
onDownloadClicked()
|
onDownloadClicked()
|
||||||
}}>download</div> : <></>
|
}}>download</div> : <></>
|
||||||
)
|
)
|
||||||
|
const edit = (
|
||||||
|
props.showDownload ? <div className="body-button left-margin-1" onClick={() => {
|
||||||
|
onModelSlotEditClicked()
|
||||||
|
}}>edit</div> : <></>
|
||||||
|
)
|
||||||
const reload = (
|
const reload = (
|
||||||
props.showReload ? <div className="body-button-container">
|
props.showReload ? <div className="body-button-container">
|
||||||
<div className="body-button" onClick={onReloadClicked}>reload</div>
|
<div className="body-button" onClick={onReloadClicked}>reload</div>
|
||||||
@ -73,6 +81,7 @@ export const ServerOpertationRow = (props: ServerOpertationRowProps) => {
|
|||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
{exportOnnx}
|
{exportOnnx}
|
||||||
{download}
|
{download}
|
||||||
|
{edit}
|
||||||
{reload}
|
{reload}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -695,6 +695,7 @@ body {
|
|||||||
.dialog-frame {
|
.dialog-frame {
|
||||||
color: var(--company-color2);
|
color: var(--company-color2);
|
||||||
width: 40rem;
|
width: 40rem;
|
||||||
|
max-height: 80vh;
|
||||||
border: 2px solid var(--dialog-border-color);
|
border: 2px solid var(--dialog-border-color);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -722,6 +723,95 @@ body {
|
|||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.dialog-fixed-size-content {
|
||||||
|
width: 90%;
|
||||||
|
max-height: 70vh;
|
||||||
|
.model-slot-container {
|
||||||
|
max-height: 60vh;
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: scroll;
|
||||||
|
.model-slot {
|
||||||
|
height: 5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
.model-slot-icon {
|
||||||
|
width: 5rem;
|
||||||
|
height: 5rem;
|
||||||
|
}
|
||||||
|
.model-slot-detail {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
border-bottom: solid 1px #aaa;
|
||||||
|
width: 80%;
|
||||||
|
.model-slot-detail-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
.model-slot-detail-row-label {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
|
.model-slot-detail-row-value {
|
||||||
|
width: 60%;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.model-slot-detail-row-value-edit {
|
||||||
|
width: 60%;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #f00;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.model-slot-detail-row-button {
|
||||||
|
width: 15%;
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.model-slot-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-bottom: solid 1px #a00;
|
||||||
|
width: 20%;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
.model-slot-button {
|
||||||
|
user-select: none;
|
||||||
|
border: solid 1px #999;
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
padding: 1px;
|
||||||
|
&:hover {
|
||||||
|
border: solid 1px #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.model-slot-button-disabled {
|
||||||
|
user-select: none;
|
||||||
|
border: solid 1px #999;
|
||||||
|
border-radius: 2px;
|
||||||
|
vertical-align: middle;
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
.model-slot-button-active {
|
||||||
|
user-select: none;
|
||||||
|
border: solid 1px #333;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: #ada;
|
||||||
|
}
|
||||||
|
.model-slot-button-stanby {
|
||||||
|
user-select: none;
|
||||||
|
border: solid 1px #999;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: #aba;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
border: solid 1px #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dialog-container-show {
|
.dialog-container-show {
|
||||||
|
3318
client/lib/package-lock.json
generated
3318
client/lib/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@dannadori/voice-changer-client-js",
|
"name": "@dannadori/voice-changer-client-js",
|
||||||
"version": "1.0.139",
|
"version": "1.0.140",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@ -47,7 +47,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/readable-stream": "^2.3.15",
|
"@types/readable-stream": "^2.3.15",
|
||||||
"amazon-chime-sdk-js": "^3.14.1",
|
"amazon-chime-sdk-js": "^2.7.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
@ -57,6 +57,49 @@ export class ServerConfigurator {
|
|||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uploadFile2 = async (file: File, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
|
const url = this.serverUrl + "/upload_file"
|
||||||
|
onprogress(0, false)
|
||||||
|
const size = 1024 * 1024;
|
||||||
|
let index = 0; // index値
|
||||||
|
const fileLength = file.size
|
||||||
|
const filename = file.name
|
||||||
|
const fileChunkNum = Math.ceil(fileLength / size)
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const promises: Promise<void>[] = []
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
if (index * size >= fileLength) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const chunk = file.slice(index * size, (index + 1) * size)
|
||||||
|
|
||||||
|
const p = new Promise<void>((resolve) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", new Blob([chunk]));
|
||||||
|
formData.append("filename", `${filename}_${index}`);
|
||||||
|
const request = new Request(url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
fetch(request).then(async (_response) => {
|
||||||
|
// console.log(await response.text())
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
index += 1
|
||||||
|
promises.push(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
if (index * size >= fileLength) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
onprogress(Math.floor(((index) / (fileChunkNum + 1)) * 100), false)
|
||||||
|
}
|
||||||
|
return fileChunkNum
|
||||||
|
}
|
||||||
|
|
||||||
uploadFile = async (buf: ArrayBuffer, filename: string, onprogress: (progress: number, end: boolean) => void) => {
|
uploadFile = async (buf: ArrayBuffer, filename: string, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
const url = this.serverUrl + "/upload_file"
|
const url = this.serverUrl + "/upload_file"
|
||||||
onprogress(0, false)
|
onprogress(0, false)
|
||||||
|
@ -286,6 +286,9 @@ export class VoiceChangerClient {
|
|||||||
uploadFile = (buf: ArrayBuffer, filename: string, onprogress: (progress: number, end: boolean) => void) => {
|
uploadFile = (buf: ArrayBuffer, filename: string, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
return this.configurator.uploadFile(buf, filename, onprogress)
|
return this.configurator.uploadFile(buf, filename, onprogress)
|
||||||
}
|
}
|
||||||
|
uploadFile2 = (file: File, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
|
return this.configurator.uploadFile2(file, onprogress)
|
||||||
|
}
|
||||||
concatUploadedFile = (filename: string, chunkNum: number) => {
|
concatUploadedFile = (filename: string, chunkNum: number) => {
|
||||||
return this.configurator.concatUploadedFile(filename, chunkNum)
|
return this.configurator.concatUploadedFile(filename, chunkNum)
|
||||||
}
|
}
|
||||||
|
@ -217,6 +217,7 @@ type ModelSlot = {
|
|||||||
description: string,
|
description: string,
|
||||||
credit: string,
|
credit: string,
|
||||||
termsOfUseUrl: string,
|
termsOfUseUrl: string,
|
||||||
|
iconFile: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerAudioDevice = {
|
type ServerAudioDevice = {
|
||||||
@ -254,6 +255,7 @@ export type RVCSampleModel = {
|
|||||||
description: string
|
description: string
|
||||||
lang: string
|
lang: string
|
||||||
tag: string
|
tag: string
|
||||||
|
icon: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultServerSetting: ServerInfo = {
|
export const DefaultServerSetting: ServerInfo = {
|
||||||
|
@ -44,7 +44,7 @@ export type FileUploadSetting = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const InitialFileUploadSetting: FileUploadSetting = {
|
export const InitialFileUploadSetting: FileUploadSetting = {
|
||||||
isHalf: true,
|
isHalf: true,
|
||||||
uploaded: false,
|
uploaded: false,
|
||||||
defaultTune: 0,
|
defaultTune: 0,
|
||||||
@ -236,6 +236,16 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const _uploadFile2 = useMemo(() => {
|
||||||
|
return async (file: File, onprogress: (progress: number, end: boolean) => void, dir: string = "") => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
console.log("uploading...", file.name)
|
||||||
|
const num = await props.voiceChangerClient.uploadFile2(file, onprogress)
|
||||||
|
const res = await props.voiceChangerClient.concatUploadedFile(dir + file.name, num)
|
||||||
|
console.log("uploaded", num, res)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
|
||||||
const loadModel = useMemo(() => {
|
const loadModel = useMemo(() => {
|
||||||
return async (slot: number) => {
|
return async (slot: number) => {
|
||||||
@ -307,7 +317,6 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
alert("Sample IDを指定する必要があります。")
|
alert("Sample IDを指定する必要があります。")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -316,9 +325,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
setUploadProgress(0)
|
setUploadProgress(0)
|
||||||
setIsUploading(true)
|
setIsUploading(true)
|
||||||
|
|
||||||
|
// normal models(MMVC13,15, so-vits-svc, RVC)
|
||||||
|
|
||||||
// MMVCv13
|
|
||||||
const normalModels = [
|
const normalModels = [
|
||||||
fileUploadSetting.mmvcv13Config,
|
fileUploadSetting.mmvcv13Config,
|
||||||
fileUploadSetting.mmvcv13Model,
|
fileUploadSetting.mmvcv13Model,
|
||||||
@ -330,13 +337,11 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
fileUploadSetting.soVitsSvc40v2Config,
|
fileUploadSetting.soVitsSvc40v2Config,
|
||||||
fileUploadSetting.soVitsSvc40v2Model,
|
fileUploadSetting.soVitsSvc40v2Model,
|
||||||
fileUploadSetting.soVitsSvc40v2Cluster,
|
fileUploadSetting.soVitsSvc40v2Cluster,
|
||||||
fileUploadSetting.rvcModel,
|
|
||||||
fileUploadSetting.rvcIndex,
|
|
||||||
fileUploadSetting.rvcFeature,
|
|
||||||
|
|
||||||
].filter(x => { return x != null }) as ModelData[]
|
].filter(x => { return x != null }) as ModelData[]
|
||||||
for (let i = 0; i < normalModels.length; i++) {
|
for (let i = 0; i < normalModels.length; i++) {
|
||||||
if (!normalModels[i].data) {
|
if (!normalModels[i].data) {
|
||||||
|
// const fileSize = normalModels[i].file!.size / 1024 / 1024
|
||||||
normalModels[i].data = await normalModels[i].file!.arrayBuffer()
|
normalModels[i].data = await normalModels[i].file!.arrayBuffer()
|
||||||
normalModels[i].filename = await normalModels[i].file!.name
|
normalModels[i].filename = await normalModels[i].file!.name
|
||||||
}
|
}
|
||||||
@ -345,13 +350,39 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
for (let i = 0; i < normalModels.length; i++) {
|
for (let i = 0; i < normalModels.length; i++) {
|
||||||
const progRate = 1 / normalModels.length
|
const progRate = 1 / normalModels.length
|
||||||
const progOffset = 100 * i * progRate
|
const progOffset = 100 * i * progRate
|
||||||
await _uploadFile(normalModels[i], (progress: number, _end: boolean) => {
|
// await _uploadFile(normalModels[i], (progress: number, _end: boolean) => {
|
||||||
|
// setUploadProgress(progress * progRate + progOffset)
|
||||||
|
// })
|
||||||
|
await _uploadFile2(normalModels[i].file!, (progress: number, _end: boolean) => {
|
||||||
setUploadProgress(progress * progRate + progOffset)
|
setUploadProgress(progress * progRate + progOffset)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DDSP-SVC
|
// slotModel ローカルキャッシュ無効(RVC)
|
||||||
|
const slotModels = [
|
||||||
|
fileUploadSetting.rvcModel,
|
||||||
|
fileUploadSetting.rvcIndex,
|
||||||
|
|
||||||
|
].filter(x => { return x != null }) as ModelData[]
|
||||||
|
for (let i = 0; i < slotModels.length; i++) {
|
||||||
|
if (!slotModels[i].data) {
|
||||||
|
slotModels[i].filename = await slotModels[i].file!.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileUploadSetting.isSampleMode == false) {
|
||||||
|
for (let i = 0; i < slotModels.length; i++) {
|
||||||
|
const progRate = 1 / slotModels.length
|
||||||
|
const progOffset = 100 * i * progRate
|
||||||
|
await _uploadFile2(slotModels[i].file!, (progress: number, _end: boolean) => {
|
||||||
|
setUploadProgress(progress * progRate + progOffset)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// DDSP-SVC (ファイル名(config)が被る可能性があるため、アップロードフォルダを分ける必要がある)
|
||||||
const ddspSvcModels = [fileUploadSetting.ddspSvcModel, fileUploadSetting.ddspSvcModelConfig, fileUploadSetting.ddspSvcDiffusion, fileUploadSetting.ddspSvcDiffusionConfig].filter(x => { return x != null }) as ModelData[]
|
const ddspSvcModels = [fileUploadSetting.ddspSvcModel, fileUploadSetting.ddspSvcModelConfig, fileUploadSetting.ddspSvcDiffusion, fileUploadSetting.ddspSvcDiffusionConfig].filter(x => { return x != null }) as ModelData[]
|
||||||
for (let i = 0; i < ddspSvcModels.length; i++) {
|
for (let i = 0; i < ddspSvcModels.length; i++) {
|
||||||
if (!ddspSvcModels[i].data) {
|
if (!ddspSvcModels[i].data) {
|
||||||
|
@ -3,4 +3,5 @@ export * from "./VoiceChangerClient"
|
|||||||
export * from "./util"
|
export * from "./util"
|
||||||
export * from "./hooks/useClient"
|
export * from "./hooks/useClient"
|
||||||
export * from "./hooks/useIndexedDB"
|
export * from "./hooks/useIndexedDB"
|
||||||
export * from "./License"
|
export * from "./License"
|
||||||
|
export * from "./hooks/useServerSetting"
|
@ -13,6 +13,7 @@ class RVCModelSample:
|
|||||||
modelUrl: str = ""
|
modelUrl: str = ""
|
||||||
indexUrl: str = ""
|
indexUrl: str = ""
|
||||||
termsOfUseUrl: str = ""
|
termsOfUseUrl: str = ""
|
||||||
|
icon: str = ""
|
||||||
credit: str = ""
|
credit: str = ""
|
||||||
description: str = ""
|
description: str = ""
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/kikoto_kurage_v2_40k_e100_simple.onnx",
|
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/kikoto_kurage_v2_40k_e100_simple.onnx",
|
||||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/added_IVF5181_Flat_nprobe_1_v2.index.bin",
|
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/added_IVF5181_Flat_nprobe_1_v2.index.bin",
|
||||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/kikoto_kurage/terms_of_use.txt",
|
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/kikoto_kurage/terms_of_use.txt",
|
||||||
|
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_kurage/kikoto_kurage.png",
|
||||||
"credit": "黄琴海月",
|
"credit": "黄琴海月",
|
||||||
"description": "",
|
"description": "",
|
||||||
"sampleRate": 40000,
|
"sampleRate": 40000,
|
||||||
@ -22,6 +23,7 @@
|
|||||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/kikoto_mahiro_v2_40k_simple.onnx",
|
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/kikoto_mahiro_v2_40k_simple.onnx",
|
||||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/added_IVF6881_Flat_nprobe_1_v2.index.bin",
|
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/added_IVF6881_Flat_nprobe_1_v2.index.bin",
|
||||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/kikoto_mahiro/terms_of_use.txt",
|
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/kikoto_mahiro/terms_of_use.txt",
|
||||||
|
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/kikoto_mahiro/kikoto_mahiro.png",
|
||||||
"credit": "黄琴まひろ",
|
"credit": "黄琴まひろ",
|
||||||
"description": "",
|
"description": "",
|
||||||
"sampleRate": 40000,
|
"sampleRate": 40000,
|
||||||
@ -36,6 +38,7 @@
|
|||||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/tokina_shigure_v2_40k_e100_simple.onnx",
|
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/tokina_shigure_v2_40k_e100_simple.onnx",
|
||||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/added_IVF2736_Flat_nprobe_1_v2.index.bin",
|
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/added_IVF2736_Flat_nprobe_1_v2.index.bin",
|
||||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/tokina_shigure/terms_of_use.txt",
|
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/tokina_shigure/terms_of_use.txt",
|
||||||
|
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tokina_shigure/dummy.png",
|
||||||
"credit": "刻鳴時雨",
|
"credit": "刻鳴時雨",
|
||||||
"description": "",
|
"description": "",
|
||||||
"sampleRate": 40000,
|
"sampleRate": 40000,
|
||||||
@ -50,6 +53,7 @@
|
|||||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/amitaro_v2_40k_e100_simple.onnx",
|
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/amitaro_v2_40k_e100_simple.onnx",
|
||||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/added_IVF3139_Flat_nprobe_1_v2.index.bin",
|
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/added_IVF3139_Flat_nprobe_1_v2.index.bin",
|
||||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/amitaro/terms_of_use.txt",
|
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/amitaro/terms_of_use.txt",
|
||||||
|
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/amitaro/amitaro.png",
|
||||||
"credit": "あみたろ",
|
"credit": "あみたろ",
|
||||||
"description": "",
|
"description": "",
|
||||||
"sampleRate": 40000,
|
"sampleRate": 40000,
|
||||||
@ -63,7 +67,8 @@
|
|||||||
"name": "つくよみちゃん(onnx)",
|
"name": "つくよみちゃん(onnx)",
|
||||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/tsukuyomi_v2_40k_e100_simple.onnx",
|
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/tsukuyomi_v2_40k_e100_simple.onnx",
|
||||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/added_IVF7852_Flat_nprobe_1_v2.index.bin",
|
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/added_IVF7852_Flat_nprobe_1_v2.index.bin",
|
||||||
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/blob/main/rvc_v2_alpha/tsukuyomi-chan/terms_of_use.txt",
|
"termsOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc_v2_alpha/tsukuyomi-chan/terms_of_use.txt",
|
||||||
|
"icon": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc_v2_alpha/tsukuyomi-chan/tsukuyomi-chan.png",
|
||||||
"credit": "つくよみちゃん",
|
"credit": "つくよみちゃん",
|
||||||
"description": "",
|
"description": "",
|
||||||
"sampleRate": 40000,
|
"sampleRate": 40000,
|
||||||
|
@ -25,3 +25,4 @@ class ModelSlot:
|
|||||||
credit: str = ""
|
credit: str = ""
|
||||||
termsOfUseUrl: str = ""
|
termsOfUseUrl: str = ""
|
||||||
sampleId: str = ""
|
sampleId: str = ""
|
||||||
|
iconFile: str = ""
|
||||||
|
@ -76,6 +76,20 @@ def downloadInitialSampleModels(
|
|||||||
)
|
)
|
||||||
slotInfo.indexFile = indexPath
|
slotInfo.indexFile = indexPath
|
||||||
line_num += 1
|
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.sampleId = sample.id
|
||||||
slotInfo.credit = sample.credit
|
slotInfo.credit = sample.credit
|
||||||
|
Loading…
Reference in New Issue
Block a user