mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-01-23 13:35:12 +03:00
WIP: keep uploaded models
This commit is contained in:
parent
ffd2894d5e
commit
44593719f5
@ -71,6 +71,10 @@
|
||||
"fileKind": "rvcIndex"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sampleModelSelect",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "defaultTuneRow2",
|
||||
"options": {}
|
||||
|
11
client/demo/dist/index.html
vendored
11
client/demo/dist/index.html
vendored
@ -1,10 +1 @@
|
||||
<!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>
|
||||
<!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>
|
1684
client/demo/dist/index.js
vendored
1684
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
Normal file
31
client/demo/dist/index.js.LICENSE.txt
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*! 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.
|
||||
*/
|
28
client/demo/package-lock.json
generated
28
client/demo/package-lock.json
generated
@ -9,7 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@dannadori/voice-changer-client-js": "^1.0.126",
|
||||
"@dannadori/voice-changer-client-js": "^1.0.127",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
||||
@ -24,7 +24,7 @@
|
||||
"@babel/preset-env": "^7.21.5",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@types/node": "^20.1.4",
|
||||
"@types/node": "^20.1.5",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
"autoprefixer": "^10.4.14",
|
||||
@ -3170,9 +3170,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@dannadori/voice-changer-client-js": {
|
||||
"version": "1.0.126",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.126.tgz",
|
||||
"integrity": "sha512-vIXXu0rPlbd220r30SsAVduFlK2jCM2985pHQ/biVeVM7l+qXEIY+Qbr5H1Usx5jHnVCnpjULbRQKhByPeoHTA==",
|
||||
"version": "1.0.127",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.127.tgz",
|
||||
"integrity": "sha512-EkzqkUy8/QO3VwZAR6MZh8zgwG7Oqx4uwzmnujfqlywjqdiYggDzp5n7innJJaJE/z+cUp32dsX7l7l9s2PiGw==",
|
||||
"dependencies": {
|
||||
"@types/readable-stream": "^2.3.15",
|
||||
"amazon-chime-sdk-js": "^3.14.0",
|
||||
@ -3833,9 +3833,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
|
||||
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q=="
|
||||
"version": "20.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz",
|
||||
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg=="
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
@ -13995,9 +13995,9 @@
|
||||
}
|
||||
},
|
||||
"@dannadori/voice-changer-client-js": {
|
||||
"version": "1.0.126",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.126.tgz",
|
||||
"integrity": "sha512-vIXXu0rPlbd220r30SsAVduFlK2jCM2985pHQ/biVeVM7l+qXEIY+Qbr5H1Usx5jHnVCnpjULbRQKhByPeoHTA==",
|
||||
"version": "1.0.127",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.127.tgz",
|
||||
"integrity": "sha512-EkzqkUy8/QO3VwZAR6MZh8zgwG7Oqx4uwzmnujfqlywjqdiYggDzp5n7innJJaJE/z+cUp32dsX7l7l9s2PiGw==",
|
||||
"requires": {
|
||||
"@types/readable-stream": "^2.3.15",
|
||||
"amazon-chime-sdk-js": "^3.14.0",
|
||||
@ -14542,9 +14542,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
|
||||
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q=="
|
||||
"version": "20.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz",
|
||||
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg=="
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
|
@ -24,7 +24,7 @@
|
||||
"@babel/preset-env": "^7.21.5",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@types/node": "^20.1.4",
|
||||
"@types/node": "^20.1.5",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
"autoprefixer": "^10.4.14",
|
||||
@ -52,7 +52,7 @@
|
||||
"webpack-dev-server": "^4.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dannadori/voice-changer-client-js": "^1.0.126",
|
||||
"@dannadori/voice-changer-client-js": "^1.0.127",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
||||
|
@ -71,6 +71,10 @@
|
||||
"fileKind": "rvcIndex"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sampleModelSelect",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "defaultTuneRow2",
|
||||
"options": {}
|
||||
|
@ -22,6 +22,21 @@ export type AppGuiDemoSetting = {
|
||||
}
|
||||
}
|
||||
|
||||
// export type AppGuiDemoSetting2 = {
|
||||
// type: "demo",
|
||||
// id: ClientType,
|
||||
// front: GuiSectionSetting[],
|
||||
// dialogs: {
|
||||
// "license": { title: string, auther: string, contact: string, url: string, license: string }[]
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// export type GuiSectionSetting = {
|
||||
// "title": string,
|
||||
// "components": GuiComponentSetting[]
|
||||
// }
|
||||
|
||||
export type GuiComponentSetting = {
|
||||
"name": string,
|
||||
"options": any
|
||||
|
@ -58,6 +58,7 @@ type GuiStateAndMethod = {
|
||||
|
||||
modelSlotNum: number
|
||||
setModelSlotNum: (val: number) => void
|
||||
|
||||
}
|
||||
|
||||
const GuiStateContext = React.createContext<GuiStateAndMethod | null>(null);
|
||||
@ -85,7 +86,6 @@ export const GuiStateProvider = ({ children }: Props) => {
|
||||
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>(false)//最初のmuteが有効になるように。undefined <-- ??? falseしておけばよさそう。undefinedだとwarningがでる。
|
||||
const [audioOutputForAnalyzer, setAudioOutputForAnalyzer] = useState<string>("default")
|
||||
|
||||
|
||||
const reloadDeviceInfo = async () => {
|
||||
try {
|
||||
const ms = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
|
||||
@ -208,7 +208,8 @@ export const GuiStateProvider = ({ children }: Props) => {
|
||||
setAudioOutputForAnalyzer,
|
||||
|
||||
modelSlotNum,
|
||||
setModelSlotNum
|
||||
setModelSlotNum,
|
||||
|
||||
};
|
||||
return <GuiStateContext.Provider value={providerValue}>{children}</GuiStateContext.Provider>;
|
||||
};
|
||||
|
@ -54,6 +54,7 @@ import { DiffEnablerRow, DiffEnablerRowProps } from "./components/611_DiffEnable
|
||||
import { DiffSettingRow, DiffSettingRowProps } from "./components/612_DiffSettingRow"
|
||||
import { DiffMethodRow, DiffMethodRowProps } from "./components/613_DiffMethodRow"
|
||||
import { ServerOpertationRow, ServerOpertationRowProps } from "./components/207_ServerOpertationRow"
|
||||
import { SampleModelSelectRow, SampleModelSelectRowProps } from "./components/301-j_SampleModelSelectRow"
|
||||
|
||||
export const catalog: { [key: string]: (props: any) => JSX.Element } = {}
|
||||
|
||||
@ -92,6 +93,8 @@ const initialize = () => {
|
||||
addToCatalog("correspondenceSelectRow2", (props: CorrespondenceSelectRow2Props) => { return <CorrespondenceSelectRow2 {...props} /> })
|
||||
addToCatalog("modelSlotRow2", (props: ModelSlotRow2Props) => { return <ModelSlotRow2 {...props} /> })
|
||||
addToCatalog("defaultTuneRow2", (props: DefaultTuneRow2Props) => { return <DefaultTuneRow2 {...props} /> })
|
||||
addToCatalog("sampleModelSelect", (props: SampleModelSelectRowProps) => { return <SampleModelSelectRow {...props} /> })
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -10,7 +10,6 @@ import { SpeakerSetting } from "./600_SpeakerSetting";
|
||||
import { ConverterSetting } from "./700_ConverterSetting";
|
||||
import { AdvancedSetting } from "./800_AdvancedSetting";
|
||||
import { Lab } from "./a00_Lab";
|
||||
import { useAppRoot } from "../../001_provider/001_AppRootProvider";
|
||||
|
||||
export const Demo = () => {
|
||||
|
||||
|
@ -37,7 +37,7 @@ export const ModelSwitchRow = (_props: ModelSwitchRowProps) => {
|
||||
const tuning = `tune:${x.defaultTrans}`
|
||||
const useIndex = x.indexFile != null && x.featureFile != null ? `index:true` : `index:false`
|
||||
const subMetadata = `(${tuning},${useIndex})`
|
||||
const displayName = `${metadata} ${filename} ${subMetadata}`
|
||||
const displayName = `${metadata} ${x.name || filename} ${subMetadata}`
|
||||
|
||||
|
||||
return (
|
||||
|
@ -38,8 +38,14 @@ export const CommonFileSelectRow = (props: CommonFileSelectRowProps) => {
|
||||
const guiState = useGuiState()
|
||||
|
||||
const commonFileSelectRow = useMemo(() => {
|
||||
|
||||
const slot = guiState.modelSlotNum
|
||||
if (!appState.serverSetting.fileUploadSettings[slot]) {
|
||||
return <></>
|
||||
}
|
||||
if (appState.serverSetting.fileUploadSettings[slot].isSampleMode == true) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
|
||||
const getTargetModelData = () => {
|
||||
const targetSlot = appState.serverSetting.fileUploadSettings[slot]
|
||||
@ -66,12 +72,14 @@ export const CommonFileSelectRow = (props: CommonFileSelectRowProps) => {
|
||||
return
|
||||
}
|
||||
appState.serverSetting.fileUploadSettings[slot][props.fileKind]! = { file: file }
|
||||
appState.serverSetting.fileUploadSettings[slot].sampleId = null
|
||||
appState.serverSetting.setFileUploadSetting(slot, {
|
||||
...appState.serverSetting.fileUploadSettings[slot]
|
||||
})
|
||||
}
|
||||
const onFileClearClicked = () => {
|
||||
appState.serverSetting.fileUploadSettings[slot][props.fileKind] = null
|
||||
appState.serverSetting.fileUploadSettings[slot].sampleId = null
|
||||
appState.serverSetting.setFileUploadSetting(slot, {
|
||||
...appState.serverSetting.fileUploadSettings[slot],
|
||||
})
|
||||
|
@ -11,15 +11,20 @@ export const ModelUploadButtonRow2 = (_props: ModelUploadButtonRow2Props) => {
|
||||
const guiState = useGuiState()
|
||||
const modelUploadButtonRow = useMemo(() => {
|
||||
const slot = guiState.modelSlotNum
|
||||
if (!appState.serverSetting.fileUploadSettings[slot]) {
|
||||
return <></>
|
||||
}
|
||||
const onModelUploadClicked = async () => {
|
||||
appState.serverSetting.loadModel(slot)
|
||||
}
|
||||
|
||||
const buttonText = appState.serverSetting.fileUploadSettings[slot].isSampleMode ? "select" : "upload"
|
||||
|
||||
const uploadButtonClassName = appState.serverSetting.isUploading ? "body-button-disabled" : "body-button"
|
||||
const uploadButtonAction = appState.serverSetting.isUploading ? () => { } : onModelUploadClicked
|
||||
const uploadButtonLabel = appState.serverSetting.isUploading ? "wait..." : "upload"
|
||||
const uploadButtonLabel = appState.serverSetting.isUploading ? "wait..." : buttonText
|
||||
const uploadingStatus = appState.serverSetting.isUploading ?
|
||||
appState.serverSetting.uploadProgress == 0 ? `loading model...(wait about 20sec)` : `uploading.... ${appState.serverSetting.uploadProgress.toFixed(1)}%` : ""
|
||||
appState.serverSetting.uploadProgress == 0 ? `loading model...(wait about 20sec)` : `processing.... ${appState.serverSetting.uploadProgress.toFixed(1)}%` : ""
|
||||
|
||||
|
||||
const uploadedText = appState.serverSetting.fileUploadSettings[slot] == undefined ? "" : appState.serverSetting.fileUploadSettings[slot].uploaded ? "" : "not uploaded"
|
||||
|
@ -1,29 +1,57 @@
|
||||
import { MAX_MODEL_SLOT_NUM } from "@dannadori/voice-changer-client-js"
|
||||
import React, { useMemo } from "react"
|
||||
import { useGuiState } from "../001_GuiStateProvider"
|
||||
import { useAppState } from "../../../001_provider/001_AppStateProvider"
|
||||
|
||||
export type ModelSlotRow2Props = {}
|
||||
export const ModelSlotRow2 = (_prop: ModelSlotRow2Props) => {
|
||||
const guiState = useGuiState()
|
||||
const appState = useAppState()
|
||||
|
||||
|
||||
|
||||
const modelSlotRow = useMemo(() => {
|
||||
const slot = guiState.modelSlotNum
|
||||
if (!appState.serverSetting.fileUploadSettings[slot]) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
const onModelSlotChanged = (val: number) => {
|
||||
guiState.setModelSlotNum(val)
|
||||
}
|
||||
const onModeChanged = (val: boolean) => {
|
||||
appState.serverSetting.fileUploadSettings[slot].isSampleMode = val
|
||||
appState.serverSetting.setFileUploadSetting(slot, {
|
||||
...appState.serverSetting.fileUploadSettings[slot],
|
||||
})
|
||||
}
|
||||
|
||||
const isSampleMode = appState.serverSetting.fileUploadSettings[slot].isSampleMode
|
||||
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
|
||||
<div className="body-item-title left-padding-2">Model Slot</div>
|
||||
|
||||
<div className="body-input-container">
|
||||
<select value={slot} onChange={(e) => { onModelSlotChanged(Number(e.target.value)) }}>
|
||||
{Array(MAX_MODEL_SLOT_NUM).fill(0).map((_x, index) => {
|
||||
return <option key={index} value={index} >{index}</option>
|
||||
})}
|
||||
|
||||
</select>
|
||||
<div className="left-padding-1">
|
||||
<input className="left-padding-1" type="radio" id="from-file" name="sample-mode" checked={isSampleMode == false} onChange={() => { onModeChanged(false) }} />
|
||||
<label className="left-padding-05" htmlFor="from-file">file</label>
|
||||
</div>
|
||||
<div className="left-padding-1">
|
||||
<input className="left-padding-1" type="radio" id="from-net" name="sample-mode" checked={isSampleMode == true} onChange={() => { onModeChanged(true) }} />
|
||||
<label className="left-padding-05" htmlFor="from-net">from net</label>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
)
|
||||
}, [guiState.modelSlotNum])
|
||||
}, [guiState.modelSlotNum, appState.serverSetting.fileUploadSettings])
|
||||
|
||||
return modelSlotRow
|
||||
}
|
@ -17,7 +17,7 @@ export const DefaultTuneRow2 = (_props: DefaultTuneRow2Props) => {
|
||||
const onDefaultTuneChanged = (val: number) => {
|
||||
appState.serverSetting.setFileUploadSetting(slot, {
|
||||
...appState.serverSetting.fileUploadSettings[slot],
|
||||
defaultTune: val
|
||||
defaultTune: val,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
import React, { useMemo } from "react"
|
||||
import { useAppState } from "../../../001_provider/001_AppStateProvider"
|
||||
import { useGuiState } from "../001_GuiStateProvider"
|
||||
|
||||
export type SampleModelSelectRowProps = {}
|
||||
export const SampleModelSelectRow = (_props: SampleModelSelectRowProps) => {
|
||||
const appState = useAppState()
|
||||
const guiState = useGuiState()
|
||||
const sampleModelSelectRow = useMemo(() => {
|
||||
const slot = guiState.modelSlotNum
|
||||
const fileUploadSetting = appState.serverSetting.fileUploadSettings[slot]
|
||||
if (!fileUploadSetting) {
|
||||
return <></>
|
||||
}
|
||||
if (fileUploadSetting.isSampleMode == false) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
const options = (
|
||||
appState.serverSetting.serverSetting.sampleModels.map(x => {
|
||||
return <option key={x.id} value={x.id}>{x.name}</option>
|
||||
})
|
||||
)
|
||||
|
||||
const selectedSample = appState.serverSetting.serverSetting.sampleModels.find(x => { return x.id == fileUploadSetting.sampleId })
|
||||
const creditText = selectedSample ? `credit:${selectedSample.credit}` : ""
|
||||
const termOfUseLink = selectedSample ? <a href={selectedSample.termOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[term of use]</a> : <></>
|
||||
|
||||
const onModelSelected = (val: string) => {
|
||||
appState.serverSetting.setFileUploadSetting(slot, {
|
||||
...appState.serverSetting.fileUploadSettings[slot], sampleId: val
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-2 ">Select Model</div>
|
||||
<div>
|
||||
<select value={fileUploadSetting.sampleId || ""} onChange={(e) => { onModelSelected(e.target.value) }}>
|
||||
<option disabled value={""}> -- select model -- </option>
|
||||
{options}
|
||||
</select>
|
||||
</div>
|
||||
<div className="body-item-text">
|
||||
{creditText}{termOfUseLink}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
}, [appState.serverSetting.fileUploadSettings, guiState.modelSlotNum])
|
||||
|
||||
return sampleModelSelectRow
|
||||
}
|
@ -494,6 +494,9 @@ body {
|
||||
.underline {
|
||||
border-bottom: 3px solid #333;
|
||||
}
|
||||
.left-padding-05 {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
.left-padding-1 {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
18
client/lib/package-lock.json
generated
18
client/lib/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.126",
|
||||
"version": "1.0.127",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.126",
|
||||
"version": "1.0.127",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/readable-stream": "^2.3.15",
|
||||
@ -19,7 +19,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/audioworklet": "^0.0.46",
|
||||
"@types/node": "^20.1.4",
|
||||
"@types/node": "^20.1.5",
|
||||
"@types/react": "18.2.6",
|
||||
"@types/react-dom": "18.2.4",
|
||||
"eslint": "^8.40.0",
|
||||
@ -1878,9 +1878,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
|
||||
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q=="
|
||||
"version": "20.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz",
|
||||
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg=="
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
@ -9870,9 +9870,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
|
||||
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q=="
|
||||
"version": "20.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz",
|
||||
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg=="
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.126",
|
||||
"version": "1.0.127",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"directories": {
|
||||
@ -27,7 +27,7 @@
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/audioworklet": "^0.0.46",
|
||||
"@types/node": "^20.1.4",
|
||||
"@types/node": "^20.1.5",
|
||||
"@types/react": "18.2.6",
|
||||
"@types/react-dom": "18.2.4",
|
||||
"eslint": "^8.40.0",
|
||||
|
@ -192,6 +192,12 @@ type ModelSlot = {
|
||||
f0: boolean,
|
||||
samplingRate: number
|
||||
deprecated: boolean
|
||||
|
||||
|
||||
name: string,
|
||||
description: string,
|
||||
credit: string,
|
||||
termsOfUseUrl: string,
|
||||
}
|
||||
|
||||
type ServerAudioDevice = {
|
||||
@ -210,6 +216,7 @@ export type ServerInfo = VoiceChangerServerSetting & {
|
||||
modelSlots: ModelSlot[]
|
||||
serverAudioInputDevices: ServerAudioDevice[]
|
||||
serverAudioOutputDevices: ServerAudioDevice[]
|
||||
sampleModels: RVCSampleModel[]
|
||||
|
||||
}
|
||||
|
||||
@ -217,6 +224,17 @@ export type ServerInfoSoVitsSVC = ServerInfo & {
|
||||
speakers: { [key: string]: number }
|
||||
}
|
||||
|
||||
export type RVCSampleModel = {
|
||||
id: string
|
||||
name: string
|
||||
modelUrl: string
|
||||
indexUrl: string
|
||||
featureUrl: string
|
||||
termOfUseUrl: string
|
||||
credit: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export const DefaultServerSetting: ServerInfo = {
|
||||
// VC Common
|
||||
inputSampleRate: 48000,
|
||||
@ -260,6 +278,7 @@ export const DefaultServerSetting: ServerInfo = {
|
||||
modelSamplingRate: 48000,
|
||||
silenceFront: 1,
|
||||
modelSlotIndex: 0,
|
||||
sampleModels: [],
|
||||
|
||||
useEnhancer: 0,
|
||||
useDiff: 1,
|
||||
|
@ -31,6 +31,9 @@ export type FileUploadSetting = {
|
||||
rvcFeature: ModelData | null
|
||||
rvcIndex: ModelData | null
|
||||
|
||||
isSampleMode: boolean
|
||||
sampleId: string | null
|
||||
|
||||
ddspSvcModel: ModelData | null
|
||||
ddspSvcModelConfig: ModelData | null
|
||||
ddspSvcDiffusion: ModelData | null
|
||||
@ -59,6 +62,9 @@ const InitialFileUploadSetting: FileUploadSetting = {
|
||||
rvcFeature: null,
|
||||
rvcIndex: null,
|
||||
|
||||
isSampleMode: false,
|
||||
sampleId: null,
|
||||
|
||||
ddspSvcModel: null,
|
||||
ddspSvcModelConfig: null,
|
||||
ddspSvcDiffusion: null,
|
||||
@ -226,73 +232,84 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
||||
|
||||
const loadModel = useMemo(() => {
|
||||
return async (slot: number) => {
|
||||
if (props.clientType == "MMVCv13") {
|
||||
if (!fileUploadSettings[slot].mmvcv13Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
const fileUploadSetting = fileUploadSettings[slot]
|
||||
|
||||
if (fileUploadSetting.isSampleMode == false) {
|
||||
if (props.clientType == "MMVCv13") {
|
||||
if (!fileUploadSetting.mmvcv13Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.mmvcv13Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "MMVCv15") {
|
||||
if (!fileUploadSetting.mmvcv15Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.mmvcv15Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "so-vits-svc-40") {
|
||||
if (!fileUploadSetting.soVitsSvc40Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.soVitsSvc40Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "so-vits-svc-40v2") {
|
||||
if (!fileUploadSetting.soVitsSvc40v2Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.soVitsSvc40v2Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "RVC") {
|
||||
if (!fileUploadSetting.rvcModel) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "DDSP-SVC") {
|
||||
if (!fileUploadSetting.ddspSvcModel) {
|
||||
alert("DDSPモデルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.ddspSvcModelConfig) {
|
||||
alert("DDSP Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.ddspSvcDiffusion) {
|
||||
alert("Diffusionモデルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSetting.ddspSvcDiffusionConfig) {
|
||||
alert("Diffusion Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else {//Sampleモード
|
||||
if (!fileUploadSetting.sampleId) {
|
||||
alert("Sample IDを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].mmvcv13Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "MMVCv15") {
|
||||
if (!fileUploadSettings[slot].mmvcv15Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].mmvcv15Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "so-vits-svc-40") {
|
||||
if (!fileUploadSettings[slot].soVitsSvc40Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].soVitsSvc40Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "so-vits-svc-40v2") {
|
||||
if (!fileUploadSettings[slot].soVitsSvc40v2Config) {
|
||||
alert("Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].soVitsSvc40v2Model) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "RVC") {
|
||||
if (!fileUploadSettings[slot].rvcModel) {
|
||||
alert("モデルファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else if (props.clientType == "DDSP-SVC") {
|
||||
if (!fileUploadSettings[slot].ddspSvcModel) {
|
||||
alert("DDSPモデルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].ddspSvcModelConfig) {
|
||||
alert("DDSP Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].ddspSvcDiffusion) {
|
||||
alert("Diffusionモデルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
if (!fileUploadSettings[slot].ddspSvcDiffusionConfig) {
|
||||
alert("Diffusion Configファイルを指定する必要があります。")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!props.voiceChangerClient) return
|
||||
|
||||
setUploadProgress(0)
|
||||
setIsUploading(true)
|
||||
|
||||
const fileUploadSetting = fileUploadSettings[slot]
|
||||
|
||||
|
||||
// MMVCv13
|
||||
const normalModels = [
|
||||
@ -317,12 +334,14 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
||||
normalModels[i].filename = await normalModels[i].file!.name
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < normalModels.length; i++) {
|
||||
const progRate = 1 / normalModels.length
|
||||
const progOffset = 100 * i * progRate
|
||||
await _uploadFile(normalModels[i], (progress: number, _end: boolean) => {
|
||||
setUploadProgress(progress * progRate + progOffset)
|
||||
})
|
||||
if (fileUploadSetting.isSampleMode == false) {
|
||||
for (let i = 0; i < normalModels.length; i++) {
|
||||
const progRate = 1 / normalModels.length
|
||||
const progOffset = 100 * i * progRate
|
||||
await _uploadFile(normalModels[i], (progress: number, _end: boolean) => {
|
||||
setUploadProgress(progress * progRate + progOffset)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DDSP-SVC
|
||||
@ -333,19 +352,22 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
||||
ddspSvcModels[i].filename = await ddspSvcModels[i].file!.name
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < ddspSvcModels.length; i++) {
|
||||
const progRate = 1 / ddspSvcModels.length
|
||||
const progOffset = 100 * i * progRate
|
||||
const dir = i == 0 || i == 1 ? "ddsp_mod/" : "ddsp_diff/"
|
||||
await _uploadFile(ddspSvcModels[i], (progress: number, _end: boolean) => {
|
||||
setUploadProgress(progress * progRate + progOffset)
|
||||
}, dir)
|
||||
if (fileUploadSetting.isSampleMode == false) {
|
||||
for (let i = 0; i < ddspSvcModels.length; i++) {
|
||||
const progRate = 1 / ddspSvcModels.length
|
||||
const progOffset = 100 * i * progRate
|
||||
const dir = i == 0 || i == 1 ? "ddsp_mod/" : "ddsp_diff/"
|
||||
await _uploadFile(ddspSvcModels[i], (progress: number, _end: boolean) => {
|
||||
setUploadProgress(progress * progRate + progOffset)
|
||||
}, dir)
|
||||
}
|
||||
}
|
||||
|
||||
// const configFileName = fileUploadSetting.configFile?.filename || "-"
|
||||
const params = JSON.stringify({
|
||||
trans: fileUploadSetting.defaultTune || 0,
|
||||
files: {
|
||||
sampleId: fileUploadSetting.isSampleMode ? fileUploadSetting.sampleId || "" : "",
|
||||
files: fileUploadSetting.isSampleMode ? {} : {
|
||||
mmvcv13Config: fileUploadSetting.mmvcv13Config?.filename || "",
|
||||
mmvcv13Model: fileUploadSetting.mmvcv13Model?.filename || "",
|
||||
mmvcv15Config: fileUploadSetting.mmvcv15Config?.filename || "",
|
||||
@ -360,32 +382,35 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
||||
rvcIndex: fileUploadSetting.rvcIndex?.filename || "",
|
||||
rvcFeature: fileUploadSetting.rvcFeature?.filename || "",
|
||||
|
||||
|
||||
ddspSvcModel: fileUploadSetting.ddspSvcModel?.filename ? "ddsp_mod/" + fileUploadSetting.ddspSvcModel?.filename : "",
|
||||
ddspSvcModelConfig: fileUploadSetting.ddspSvcModelConfig?.filename ? "ddsp_mod/" + fileUploadSetting.ddspSvcModelConfig?.filename : "",
|
||||
ddspSvcDiffusion: fileUploadSetting.ddspSvcDiffusion?.filename ? "ddsp_diff/" + fileUploadSetting.ddspSvcDiffusion?.filename : "",
|
||||
ddspSvcDiffusionConfig: fileUploadSetting.ddspSvcDiffusionConfig?.filename ? "ddsp_diff/" + fileUploadSetting.ddspSvcDiffusionConfig.filename : "",
|
||||
}
|
||||
})
|
||||
|
||||
if (fileUploadSetting.isHalf == undefined) {
|
||||
fileUploadSetting.isHalf = false
|
||||
}
|
||||
|
||||
console.log("PARAMS:", params)
|
||||
|
||||
const loadPromise = props.voiceChangerClient.loadModel(
|
||||
slot,
|
||||
fileUploadSetting.isHalf,
|
||||
params,
|
||||
)
|
||||
|
||||
|
||||
// サーバでロード中にキャッシュにセーブ
|
||||
storeToCache(slot, fileUploadSetting)
|
||||
|
||||
await loadPromise
|
||||
|
||||
fileUploadSetting.uploaded = true
|
||||
fileUploadSettings[slot] = fileUploadSetting
|
||||
setFileUploadSettings([...fileUploadSettings])
|
||||
|
||||
|
||||
setUploadProgress(0)
|
||||
setIsUploading(false)
|
||||
reloadServerInfo()
|
||||
@ -420,6 +445,9 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
||||
ddspSvcModelConfig: fileUploadSetting.ddspSvcModelConfig ? { data: fileUploadSetting.ddspSvcModelConfig.data, filename: fileUploadSetting.ddspSvcModelConfig.filename } : null,
|
||||
ddspSvcDiffusion: fileUploadSetting.ddspSvcDiffusion ? { data: fileUploadSetting.ddspSvcDiffusion.data, filename: fileUploadSetting.ddspSvcDiffusion.filename } : null,
|
||||
ddspSvcDiffusionConfig: fileUploadSetting.ddspSvcDiffusionConfig ? { data: fileUploadSetting.ddspSvcDiffusionConfig.data, filename: fileUploadSetting.ddspSvcDiffusionConfig.filename } : null,
|
||||
|
||||
isSampleMode: fileUploadSetting.isSampleMode,
|
||||
sampleId: fileUploadSetting.sampleId,
|
||||
}
|
||||
setItem(`${INDEXEDDB_KEY_MODEL_DATA}_${slot}`, saveData)
|
||||
} catch (e) {
|
||||
|
@ -17,7 +17,12 @@ from mods.ssl import create_self_signed_cert
|
||||
from voice_changer.VoiceChangerManager import VoiceChangerManager
|
||||
from sio.MMVC_SocketIOApp import MMVC_SocketIOApp
|
||||
from restapi.MMVC_Rest import MMVC_Rest
|
||||
from const import NATIVE_CLIENT_FILE_MAC, NATIVE_CLIENT_FILE_WIN, SSL_KEY_DIR
|
||||
from const import (
|
||||
NATIVE_CLIENT_FILE_MAC,
|
||||
NATIVE_CLIENT_FILE_WIN,
|
||||
SAMPLES_JSON,
|
||||
SSL_KEY_DIR,
|
||||
)
|
||||
import subprocess
|
||||
import multiprocessing as mp
|
||||
from misc.log_control import setup_loggers
|
||||
@ -41,6 +46,8 @@ def setupArgParser():
|
||||
default=True,
|
||||
help="generate self-signed certificate",
|
||||
)
|
||||
|
||||
parser.add_argument("--samples", type=str, help="path to samples")
|
||||
parser.add_argument("--model_dir", type=str, help="path to model files")
|
||||
|
||||
parser.add_argument(
|
||||
@ -214,6 +221,7 @@ if __name__ == "MMVCServerSIO":
|
||||
mp.freeze_support()
|
||||
voiceChangerParams = VoiceChangerParams(
|
||||
model_dir=args.model_dir,
|
||||
samples=args.samples,
|
||||
content_vec_500=args.content_vec_500,
|
||||
content_vec_500_onnx=args.content_vec_500_onnx,
|
||||
content_vec_500_onnx_on=args.content_vec_500_onnx_on,
|
||||
@ -223,6 +231,11 @@ if __name__ == "MMVCServerSIO":
|
||||
nsf_hifigan=args.nsf_hifigan,
|
||||
)
|
||||
|
||||
try:
|
||||
download({"url": SAMPLES_JSON, "saveTo": args.samples, "position": 0})
|
||||
except Exception as e:
|
||||
print("[Voice Changer] loading sample failed", e)
|
||||
|
||||
if (
|
||||
os.path.exists(voiceChangerParams.hubert_base) is False
|
||||
or os.path.exists(voiceChangerParams.hubert_base_jp) is False
|
||||
@ -244,6 +257,7 @@ if __name__ == "__main__":
|
||||
printMessage("Voice Changerを起動しています。", level=2)
|
||||
|
||||
downloadWeight()
|
||||
os.makedirs(args.model_dir, exist_ok=True)
|
||||
|
||||
PORT = args.p
|
||||
|
||||
|
36
server/ModelSample.py
Normal file
36
server/ModelSample.py
Normal file
@ -0,0 +1,36 @@
|
||||
from dataclasses import dataclass
|
||||
import json
|
||||
|
||||
from const import ModelType
|
||||
|
||||
|
||||
@dataclass
|
||||
class RVCModelSample:
|
||||
id: str = ""
|
||||
name: str = ""
|
||||
modelUrl: str = ""
|
||||
indexUrl: str = ""
|
||||
featureUrl: str = ""
|
||||
termOfUseUrl: str = ""
|
||||
credit: str = ""
|
||||
description: str = ""
|
||||
|
||||
|
||||
def getModelSamples(jsonPath: str, modelType: ModelType):
|
||||
try:
|
||||
with open(jsonPath, "r", encoding="utf-8") as f:
|
||||
jsonDict = json.load(f)
|
||||
|
||||
modelList = jsonDict[modelType]
|
||||
if modelType == "RVC":
|
||||
samples: list[RVCModelSample] = []
|
||||
for s in modelList:
|
||||
modelSample = RVCModelSample(**s)
|
||||
samples.append(modelSample)
|
||||
return samples
|
||||
|
||||
else:
|
||||
raise RuntimeError(f"Unknown model type {modelType}")
|
||||
except Exception as e:
|
||||
print("[Voice Changer] loading sample info error:", e)
|
||||
return None
|
@ -95,3 +95,6 @@ class EnumFrameworkTypes(Enum):
|
||||
class ServerAudioDeviceTypes(Enum):
|
||||
audioinput = "audioinput"
|
||||
audiooutput = "audiooutput"
|
||||
|
||||
|
||||
SAMPLES_JSON = "https://huggingface.co/wok000/vcclient_model/raw/main/samples.json"
|
||||
|
@ -78,7 +78,7 @@ class MMVC_Rest_Fileuploader:
|
||||
params: str = Form(...),
|
||||
):
|
||||
paramDict = json.loads(params)
|
||||
print("paramDict", paramDict)
|
||||
# print("paramDict", paramDict)
|
||||
|
||||
# Change Filepath
|
||||
newFilesDict = {}
|
||||
|
44
server/samples.json
Normal file
44
server/samples.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"RVC": [
|
||||
{
|
||||
"id": "KikotoKurage_Song",
|
||||
"name": "黄琴海月(Song)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_kurage_song/KikotoKurage_Song.pth",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_kurage_song/added_IVF2252_Flat_nprobe_10.index.bin",
|
||||
"featureUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_kurage_song/total_fea.npy",
|
||||
"termOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/kikoto_kurage_song/term_of_use.txt",
|
||||
"credit": "黄琴海月",
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"id": "KikotoKurage_Talk",
|
||||
"name": "黄琴海月(Talk)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_kurage_talk/KikotoKurage_Talk.pth",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_kurage_talk/added_IVF1022_Flat_nprobe_7.index.bin",
|
||||
"featureUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_kurage_talk/total_fea.npy",
|
||||
"termOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/kikoto_kurage_talk/term_of_use.txt",
|
||||
"credit": "黄琴海月",
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"id": "KikotoMahiro_Song",
|
||||
"name": "黄琴まひろ(Song)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_mahiro_song/KikotoMahiro_Song.pth",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_mahiro_song/added_IVF3621_Flat_nprobe_11.index.bin",
|
||||
"featureUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_mahiro_song/total_fea.npy",
|
||||
"termOfUseUrl": "https://huggingface.co/wok000/vcclient_model/blob/main/rvc/kikoto_mahiro_song/term_of_use.txt",
|
||||
"credit": "黄琴まひろ",
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"id": "KikotoMahiro_Talk",
|
||||
"name": "黄琴まひろ(Talk)",
|
||||
"modelUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_mahiro_talk/KikotoMahiro_Talk.pth",
|
||||
"indexUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_mahiro_talk/added_IVF1591_Flat_nprobe_9.index.bin",
|
||||
"featureUrl": "https://huggingface.co/wok000/vcclient_model/resolve/main/rvc/kikoto_mahiro_talk/total_fea.npy",
|
||||
"termOfUseUrl": "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/kikoto_mahiro_talk/term_of_use.txt",
|
||||
"credit": "黄琴まひろ",
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
}
|
@ -20,9 +20,9 @@ def list_audio_device():
|
||||
outputDeviceList = [d for d in audioDeviceList if d["max_output_channels"] > 0]
|
||||
hostapis = sd.query_hostapis()
|
||||
|
||||
print("input:", inputAudioDeviceList)
|
||||
print("output:", outputDeviceList)
|
||||
print("hostapis", hostapis)
|
||||
# print("input:", inputAudioDeviceList)
|
||||
# print("output:", outputDeviceList)
|
||||
# print("hostapis", hostapis)
|
||||
|
||||
serverAudioInputDevices = []
|
||||
serverAudioOutputDevices = []
|
||||
|
@ -18,3 +18,8 @@ class ModelSlot:
|
||||
embChannels: int = 256
|
||||
deprecated: bool = False
|
||||
embedder: EnumEmbedderTypes = EnumEmbedderTypes.hubert
|
||||
|
||||
name: str = ""
|
||||
description: str = ""
|
||||
credit: str = ""
|
||||
termsOfUseUrl: str = ""
|
||||
|
@ -32,6 +32,12 @@ def generateModelSlot(slotDir: str):
|
||||
modelSlot.indexFile = None
|
||||
|
||||
modelSlot.defaultTrans = params["trans"] if "trans" in params else 0
|
||||
modelSlot.name = params["name"] if "name" in params else None
|
||||
modelSlot.description = params["description"] if "description" in params else None
|
||||
modelSlot.credit = params["credit"] if "credit" in params else None
|
||||
modelSlot.termsOfUseUrl = (
|
||||
params["termsOfUseUrl"] if "termsOfUseUrl" in params else None
|
||||
)
|
||||
|
||||
modelSlot.isONNX = modelSlot.modelFile.endswith(".onnx")
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import sys
|
||||
import os
|
||||
import resampy
|
||||
@ -5,6 +6,8 @@ from dataclasses import asdict
|
||||
from typing import cast
|
||||
import numpy as np
|
||||
import torch
|
||||
from MMVCServerSIO import download
|
||||
from ModelSample import RVCModelSample, getModelSamples
|
||||
|
||||
|
||||
# avoiding parse arg error in RVC
|
||||
@ -35,7 +38,7 @@ from voice_changer.RVC.deviceManager.DeviceManager import DeviceManager
|
||||
from voice_changer.RVC.pipeline.Pipeline import Pipeline
|
||||
|
||||
from Exceptions import NoModeLoadedException
|
||||
from const import UPLOAD_DIR
|
||||
from const import TMP_DIR, UPLOAD_DIR
|
||||
import shutil
|
||||
import json
|
||||
|
||||
@ -73,11 +76,86 @@ class RVC:
|
||||
self.loadSlots()
|
||||
print("RVC initialization: ", params)
|
||||
|
||||
sampleModels = getModelSamples(params.samples, "RVC")
|
||||
if sampleModels is not None:
|
||||
self.settings.sampleModels = sampleModels
|
||||
|
||||
# 起動時にスロットにモデルがある場合はロードしておく
|
||||
if len(self.settings.modelSlots) > 0:
|
||||
for i, slot in enumerate(self.settings.modelSlots):
|
||||
if len(slot.modelFile) > 0:
|
||||
self.prepareModel(i)
|
||||
self.settings.modelSlotIndex = i
|
||||
self.switchModel()
|
||||
self.initialLoad = False
|
||||
break
|
||||
|
||||
def getSampleInfo(self, id: str):
|
||||
sampleInfos = list(filter(lambda x: x.id == id, self.settings.sampleModels))
|
||||
if len(sampleInfos) > 0:
|
||||
return sampleInfos[0]
|
||||
else:
|
||||
None
|
||||
|
||||
def downloadModelFiles(self, sampleInfo: RVCModelSample):
|
||||
downloadParams = []
|
||||
|
||||
modelPath = os.path.join(TMP_DIR, os.path.basename(sampleInfo.modelUrl))
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": sampleInfo.modelUrl,
|
||||
"saveTo": modelPath,
|
||||
"position": 0,
|
||||
}
|
||||
)
|
||||
|
||||
indexPath = None
|
||||
if hasattr(sampleInfo, "indexUrl") and sampleInfo.indexUrl != "":
|
||||
indexPath = os.path.join(TMP_DIR, os.path.basename(sampleInfo.indexUrl))
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": sampleInfo.indexUrl,
|
||||
"saveTo": indexPath,
|
||||
"position": 1,
|
||||
}
|
||||
)
|
||||
|
||||
featurePath = None
|
||||
if hasattr(sampleInfo, "featureUrl") or sampleInfo.featureUrl != "":
|
||||
featurePath = os.path.join(TMP_DIR, os.path.basename(sampleInfo.featureUrl))
|
||||
downloadParams.append(
|
||||
{
|
||||
"url": sampleInfo.featureUrl,
|
||||
"saveTo": featurePath,
|
||||
"position": 2,
|
||||
}
|
||||
)
|
||||
with ThreadPoolExecutor() as pool:
|
||||
pool.map(download, downloadParams)
|
||||
return modelPath, indexPath, featurePath
|
||||
|
||||
def loadModel(self, props: LoadModelParams):
|
||||
target_slot_idx = props.slot
|
||||
params = props.params
|
||||
|
||||
# modelName = os.path.splitext(os.path.basename(params["files"]["rvcModel"]))[0]
|
||||
print("loadModel", params)
|
||||
if len(params["sampleId"]) > 0:
|
||||
sampleInfo = self.getSampleInfo(params["sampleId"])
|
||||
if sampleInfo is None:
|
||||
print("[Voice Changer] sampleInfo is None")
|
||||
return
|
||||
modelPath, indexPath, featurePath = self.downloadModelFiles(sampleInfo)
|
||||
params["files"]["rvcModel"] = modelPath
|
||||
if indexPath is not None:
|
||||
params["files"]["rvcIndex"] = indexPath
|
||||
if featurePath is not None:
|
||||
params["files"]["rvcFeature"] = featurePath
|
||||
params["credit"] = sampleInfo.credit
|
||||
params["description"] = sampleInfo.description
|
||||
params["name"] = sampleInfo.name
|
||||
params["sampleId"] = sampleInfo.id
|
||||
params["termOfUseUrl"] = sampleInfo.termOfUseUrl
|
||||
|
||||
slotDir = os.path.join(
|
||||
self.params.model_dir, RVC_MODEL_DIRNAME, str(target_slot_idx)
|
||||
)
|
||||
@ -95,6 +173,16 @@ class RVC:
|
||||
shutil.move(f, dst)
|
||||
json.dump(params, open(os.path.join(slotDir, "params.json"), "w"))
|
||||
self.loadSlots()
|
||||
|
||||
# 初回のみロード(起動時にスロットにモデルがあった場合はinitialLoadはFalseになっている)
|
||||
if self.initialLoad:
|
||||
self.prepareModel(target_slot_idx)
|
||||
self.settings.modelSlotIndex = target_slot_idx
|
||||
self.switchModel()
|
||||
self.initialLoad = False
|
||||
elif target_slot_idx == self.currentSlot:
|
||||
self.prepareModel(target_slot_idx)
|
||||
|
||||
return self.get_info()
|
||||
|
||||
def loadSlots(self):
|
||||
@ -110,24 +198,6 @@ class RVC:
|
||||
modelSlot = generateModelSlot(slotDir)
|
||||
self.settings.modelSlots.append(modelSlot)
|
||||
|
||||
# modelSlot = generateModelSlot(params)
|
||||
# self.settings.modelSlots[target_slot_idx] = modelSlot
|
||||
# print(
|
||||
# f"[Voice Changer] RVC new model is uploaded,{target_slot_idx}",
|
||||
# asdict(modelSlot),
|
||||
# )
|
||||
|
||||
# # 初回のみロード
|
||||
# if self.initialLoad:
|
||||
# self.prepareModel(target_slot_idx)
|
||||
# self.settings.modelSlotIndex = target_slot_idx
|
||||
# self.switchModel()
|
||||
# self.initialLoad = False
|
||||
# elif target_slot_idx == self.currentSlot:
|
||||
# self.prepareModel(target_slot_idx)
|
||||
|
||||
# return self.get_info()
|
||||
|
||||
def update_settings(self, key: str, val: int | float | str):
|
||||
if key in self.settings.intData:
|
||||
# 設定前処理
|
||||
|
@ -1,4 +1,5 @@
|
||||
from dataclasses import dataclass, field
|
||||
from ModelSample import RVCModelSample
|
||||
|
||||
from voice_changer.RVC.ModelSlot import ModelSlot
|
||||
|
||||
@ -25,6 +26,8 @@ class RVCSettings:
|
||||
ModelSlot(), # 6(merged)
|
||||
]
|
||||
)
|
||||
sampleModels: list[RVCModelSample] = field(default_factory=lambda: [])
|
||||
|
||||
indexRatio: float = 0
|
||||
rvcQuality: int = 0
|
||||
silenceFront: int = 1 # 0:off, 1:on
|
||||
|
@ -4,6 +4,7 @@ from dataclasses import dataclass
|
||||
@dataclass
|
||||
class VoiceChangerParams:
|
||||
model_dir: str
|
||||
samples: str
|
||||
content_vec_500: str
|
||||
content_vec_500_onnx: str
|
||||
content_vec_500_onnx_on: bool
|
||||
|
Loading…
Reference in New Issue
Block a user