WIP: sample model

This commit is contained in:
wataru 2023-05-18 02:51:40 +09:00
parent b10afc14b5
commit e9c844b882
18 changed files with 294 additions and 1861 deletions

View File

@ -1,10 +1 @@
<!DOCTYPE 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>
<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>

File diff suppressed because one or more lines are too long

31
client/demo/dist/index.js.LICENSE.txt vendored Normal file
View 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.
*/

View File

@ -9,7 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.127", "@dannadori/voice-changer-client-js": "^1.0.128",
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0", "@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0", "@fortawesome/free-regular-svg-icons": "^6.4.0",
@ -24,7 +24,7 @@
"@babel/preset-env": "^7.21.5", "@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6", "@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.5", "@babel/preset-typescript": "^7.21.5",
"@types/node": "^20.1.5", "@types/node": "^20.1.7",
"@types/react": "^18.2.6", "@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.4",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
@ -47,7 +47,7 @@
"ts-loader": "^9.4.2", "ts-loader": "^9.4.2",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"webpack": "^5.82.1", "webpack": "^5.83.0",
"webpack-cli": "^5.1.1", "webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0" "webpack-dev-server": "^4.15.0"
} }
@ -3170,9 +3170,9 @@
} }
}, },
"node_modules/@dannadori/voice-changer-client-js": { "node_modules/@dannadori/voice-changer-client-js": {
"version": "1.0.127", "version": "1.0.128",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.127.tgz", "resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.128.tgz",
"integrity": "sha512-EkzqkUy8/QO3VwZAR6MZh8zgwG7Oqx4uwzmnujfqlywjqdiYggDzp5n7innJJaJE/z+cUp32dsX7l7l9s2PiGw==", "integrity": "sha512-UTzJla1uIyARbfFSMXxr0nAQx8KDDakSx1VlZ3wZQTeo150hT3Fi/pZEoYtzIPe2zLu+R7EWVl9B0ZIjgjlQgA==",
"dependencies": { "dependencies": {
"@types/readable-stream": "^2.3.15", "@types/readable-stream": "^2.3.15",
"amazon-chime-sdk-js": "^3.14.0", "amazon-chime-sdk-js": "^3.14.0",
@ -3833,9 +3833,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.1.5", "version": "20.1.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.7.tgz",
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg==" "integrity": "sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg=="
}, },
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
@ -10895,9 +10895,9 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.82.1", "version": "5.83.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.0.tgz",
"integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "integrity": "sha512-mdWk7amgh7hMCXzU+uTDGpIJEbkqat2RLgSDW53E1OOSE6U0gmBcWadJ6y0FdQQbGbW0lV2LT9t2iOEZc+FU7w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
@ -13995,9 +13995,9 @@
} }
}, },
"@dannadori/voice-changer-client-js": { "@dannadori/voice-changer-client-js": {
"version": "1.0.127", "version": "1.0.128",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.127.tgz", "resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.128.tgz",
"integrity": "sha512-EkzqkUy8/QO3VwZAR6MZh8zgwG7Oqx4uwzmnujfqlywjqdiYggDzp5n7innJJaJE/z+cUp32dsX7l7l9s2PiGw==", "integrity": "sha512-UTzJla1uIyARbfFSMXxr0nAQx8KDDakSx1VlZ3wZQTeo150hT3Fi/pZEoYtzIPe2zLu+R7EWVl9B0ZIjgjlQgA==",
"requires": { "requires": {
"@types/readable-stream": "^2.3.15", "@types/readable-stream": "^2.3.15",
"amazon-chime-sdk-js": "^3.14.0", "amazon-chime-sdk-js": "^3.14.0",
@ -14542,9 +14542,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "20.1.5", "version": "20.1.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.7.tgz",
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg==" "integrity": "sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg=="
}, },
"@types/prop-types": { "@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
@ -19763,9 +19763,9 @@
} }
}, },
"webpack": { "webpack": {
"version": "5.82.1", "version": "5.83.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.0.tgz",
"integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "integrity": "sha512-mdWk7amgh7hMCXzU+uTDGpIJEbkqat2RLgSDW53E1OOSE6U0gmBcWadJ6y0FdQQbGbW0lV2LT9t2iOEZc+FU7w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",

View File

@ -24,7 +24,7 @@
"@babel/preset-env": "^7.21.5", "@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6", "@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.5", "@babel/preset-typescript": "^7.21.5",
"@types/node": "^20.1.5", "@types/node": "^20.1.7",
"@types/react": "^18.2.6", "@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.4",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
@ -47,12 +47,12 @@
"ts-loader": "^9.4.2", "ts-loader": "^9.4.2",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"webpack": "^5.82.1", "webpack": "^5.83.0",
"webpack-cli": "^5.1.1", "webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0" "webpack-dev-server": "^4.15.0"
}, },
"dependencies": { "dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.127", "@dannadori/voice-changer-client-js": "^1.0.128",
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0", "@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0", "@fortawesome/free-regular-svg-icons": "^6.4.0",

View File

@ -10,7 +10,6 @@ export const ModelSwitchRow = (_props: ModelSwitchRowProps) => {
const modelSwitchRow = useMemo(() => { const modelSwitchRow = useMemo(() => {
const slot = appState.serverSetting.serverSetting.modelSlotIndex const slot = appState.serverSetting.serverSetting.modelSlotIndex
const onSwitchModelClicked = async (slot: number) => { const onSwitchModelClicked = async (slot: number) => {
// Quick hack for same slot is selected. 下桁が実際のSlotID // Quick hack for same slot is selected. 下桁が実際のSlotID
const dummyModelSlotIndex = (Math.floor(Date.now() / 1000)) * 1000 + slot const dummyModelSlotIndex = (Math.floor(Date.now() / 1000)) * 1000 + slot
@ -48,7 +47,6 @@ export const ModelSwitchRow = (_props: ModelSwitchRowProps) => {
const selectedTermOfUseUrl = appState.serverSetting.serverSetting.modelSlots[slot]?.termsOfUseUrl || null const selectedTermOfUseUrl = appState.serverSetting.serverSetting.modelSlots[slot]?.termsOfUseUrl || null
const selectedTermOfUseUrlLink = selectedTermOfUseUrl ? <a href={selectedTermOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[terms of use]</a> : <></> const selectedTermOfUseUrlLink = selectedTermOfUseUrl ? <a href={selectedTermOfUseUrl} target="_blank" rel="noopener noreferrer" className="body-item-text-small">[terms of use]</a> : <></>
console.log("selectedTermOfUseUrl", selectedTermOfUseUrl)
return ( return (
<> <>

View File

@ -12,11 +12,9 @@ export const MergeLabRow = (_props: MergeLabRowProps) => {
const appState = useAppState() const appState = useAppState()
const [defaultTune, setDefaultTune] = useState<number>(0) const [defaultTune, setDefaultTune] = useState<number>(0)
console.log("mergeElements", mergeElements)
// スロットが変更されたときの初期化処理 // スロットが変更されたときの初期化処理
const newSlotChangeKey = useMemo(() => { const newSlotChangeKey = useMemo(() => {
console.log("appState.serverSetting.serverSetting.modelSlots", appState.serverSetting.serverSetting.modelSlots)
return appState.serverSetting.serverSetting.modelSlots.reduce((prev, cur) => { return appState.serverSetting.serverSetting.modelSlots.reduce((prev, cur) => {
return prev + "_" + cur.modelFile return prev + "_" + cur.modelFile
}, "") }, "")

View File

@ -1,12 +1,12 @@
{ {
"name": "@dannadori/voice-changer-client-js", "name": "@dannadori/voice-changer-client-js",
"version": "1.0.127", "version": "1.0.128",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@dannadori/voice-changer-client-js", "name": "@dannadori/voice-changer-client-js",
"version": "1.0.127", "version": "1.0.128",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/readable-stream": "^2.3.15", "@types/readable-stream": "^2.3.15",
@ -19,7 +19,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/audioworklet": "^0.0.46", "@types/audioworklet": "^0.0.46",
"@types/node": "^20.1.5", "@types/node": "^20.1.7",
"@types/react": "18.2.6", "@types/react": "18.2.6",
"@types/react-dom": "18.2.4", "@types/react-dom": "18.2.4",
"eslint": "^8.40.0", "eslint": "^8.40.0",
@ -33,7 +33,7 @@
"rimraf": "^5.0.0", "rimraf": "^5.0.0",
"ts-loader": "^9.4.2", "ts-loader": "^9.4.2",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"webpack": "^5.82.1", "webpack": "^5.83.0",
"webpack-cli": "^5.1.1", "webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0" "webpack-dev-server": "^4.15.0"
} }
@ -1878,9 +1878,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.1.5", "version": "20.1.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.7.tgz",
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg==" "integrity": "sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg=="
}, },
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
@ -7596,9 +7596,9 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.82.1", "version": "5.83.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.0.tgz",
"integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "integrity": "sha512-mdWk7amgh7hMCXzU+uTDGpIJEbkqat2RLgSDW53E1OOSE6U0gmBcWadJ6y0FdQQbGbW0lV2LT9t2iOEZc+FU7w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
@ -9870,9 +9870,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "20.1.5", "version": "20.1.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.7.tgz",
"integrity": "sha512-IvGD1CD/nego63ySR7vrAKEX3AJTcmrAN2kn+/sDNLi1Ff5kBzDeEdqWDplK+0HAEoLYej137Sk0cUU8OLOlMg==" "integrity": "sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg=="
}, },
"@types/prop-types": { "@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
@ -14116,9 +14116,9 @@
} }
}, },
"webpack": { "webpack": {
"version": "5.82.1", "version": "5.83.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.0.tgz",
"integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "integrity": "sha512-mdWk7amgh7hMCXzU+uTDGpIJEbkqat2RLgSDW53E1OOSE6U0gmBcWadJ6y0FdQQbGbW0lV2LT9t2iOEZc+FU7w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",

View File

@ -1,6 +1,6 @@
{ {
"name": "@dannadori/voice-changer-client-js", "name": "@dannadori/voice-changer-client-js",
"version": "1.0.127", "version": "1.0.128",
"description": "", "description": "",
"main": "dist/index.js", "main": "dist/index.js",
"directories": { "directories": {
@ -27,7 +27,7 @@
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/audioworklet": "^0.0.46", "@types/audioworklet": "^0.0.46",
"@types/node": "^20.1.5", "@types/node": "^20.1.7",
"@types/react": "18.2.6", "@types/react": "18.2.6",
"@types/react-dom": "18.2.4", "@types/react-dom": "18.2.4",
"eslint": "^8.40.0", "eslint": "^8.40.0",
@ -41,7 +41,7 @@
"rimraf": "^5.0.0", "rimraf": "^5.0.0",
"ts-loader": "^9.4.2", "ts-loader": "^9.4.2",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"webpack": "^5.82.1", "webpack": "^5.83.0",
"webpack-cli": "^5.1.1", "webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0" "webpack-dev-server": "^4.15.0"
}, },

View File

@ -493,7 +493,7 @@ export type OnnxExporterInfo = {
} }
export const MAX_MODEL_SLOT_NUM = 3 export const MAX_MODEL_SLOT_NUM = 4
// Merge // Merge
export type MergeElement = { export type MergeElement = {

View File

@ -170,7 +170,7 @@ export const useClient = (props: UseClientProps): ClientState => {
await clientSetting.reloadClientSetting() // 実質的な処理の意味はない await clientSetting.reloadClientSetting() // 実質的な処理の意味はない
await serverSetting.reloadServerInfo() await serverSetting.reloadServerInfo()
} }
}, [clientSetting, serverSetting]) }, [clientSetting.reloadClientSetting, serverSetting.reloadServerInfo])
const clearSetting = async () => { const clearSetting = async () => {

View File

@ -463,7 +463,6 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
const reloadServerInfo = useMemo(() => { const reloadServerInfo = useMemo(() => {
return async () => { return async () => {
console.log("reload server info")
if (!props.voiceChangerClient) return if (!props.voiceChangerClient) return
const res = await props.voiceChangerClient.getServerSettings() const res = await props.voiceChangerClient.getServerSettings()

56
server/Downloader.py Executable file
View File

@ -0,0 +1,56 @@
import requests # type: ignore
import os
from tqdm import tqdm
def download(params):
url = params["url"]
saveTo = params["saveTo"]
position = params["position"]
dirname = os.path.dirname(saveTo)
if dirname != "":
os.makedirs(dirname, exist_ok=True)
try:
req = requests.get(url, stream=True, allow_redirects=True)
content_length = req.headers.get("content-length")
progress_bar = tqdm(
total=int(content_length) if content_length is not None else None,
leave=False,
unit="B",
unit_scale=True,
unit_divisor=1024,
position=position,
)
# with tqdm
with open(saveTo, "wb") as f:
for chunk in req.iter_content(chunk_size=1024):
if chunk:
progress_bar.update(len(chunk))
f.write(chunk)
except Exception as e:
print(e)
def download_no_tqdm(params):
url = params["url"]
saveTo = params["saveTo"]
dirname = os.path.dirname(saveTo)
if dirname != "":
os.makedirs(dirname, exist_ok=True)
try:
req = requests.get(url, stream=True, allow_redirects=True)
with open(saveTo, "wb") as f:
countToDot = 0
for chunk in req.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
countToDot += 1
if countToDot % 1024 == 0:
print(".", end="", flush=True)
print("+", end="", flush=True)
except Exception as e:
print(e)

View File

@ -7,9 +7,12 @@ import socket
import platform import platform
import os import os
import argparse import argparse
import requests # type: ignore from Downloader import download, download_no_tqdm
from voice_changer.RVC.SampleDownloader import (
checkRvcModelExist,
downloadInitialSampleModels,
)
from tqdm import tqdm
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
import uvicorn import uvicorn
@ -100,59 +103,6 @@ def printMessage(message, level=0):
print(f"\033[47m {message}\033[0m") print(f"\033[47m {message}\033[0m")
def download(params):
url = params["url"]
saveTo = params["saveTo"]
position = params["position"]
dirname = os.path.dirname(saveTo)
if dirname != "":
os.makedirs(dirname, exist_ok=True)
try:
req = requests.get(url, stream=True, allow_redirects=True)
content_length = req.headers.get("content-length")
progress_bar = tqdm(
total=int(content_length) if content_length is not None else None,
leave=False,
unit="B",
unit_scale=True,
unit_divisor=1024,
position=position,
)
# with tqdm
with open(saveTo, "wb") as f:
for chunk in req.iter_content(chunk_size=1024):
if chunk:
progress_bar.update(len(chunk))
f.write(chunk)
except Exception as e:
print(e)
def download_no_tqdm(params):
url = params["url"]
saveTo = params["saveTo"]
dirname = os.path.dirname(saveTo)
if dirname != "":
os.makedirs(dirname, exist_ok=True)
try:
req = requests.get(url, stream=True, allow_redirects=True)
with open(saveTo, "wb") as f:
countToDot = 0
for chunk in req.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
countToDot += 1
if countToDot % 1024 == 0:
print(".", end="", flush=True)
print("+", end="", flush=True)
except Exception as e:
print(e)
def downloadWeight(): def downloadWeight():
# content_vec_500 = (args.content_vec_500,) # content_vec_500 = (args.content_vec_500,)
# content_vec_500_onnx = (args.content_vec_500_onnx,) # content_vec_500_onnx = (args.content_vec_500_onnx,)
@ -253,11 +203,6 @@ if __name__ == "MMVCServerSIO":
nsf_hifigan=args.nsf_hifigan, nsf_hifigan=args.nsf_hifigan,
) )
try:
download_no_tqdm({"url": SAMPLES_JSON, "saveTo": args.samples, "position": 0})
except Exception as e:
print("[Voice Changer] loading sample failed", e)
if ( if (
os.path.exists(voiceChangerParams.hubert_base) is False os.path.exists(voiceChangerParams.hubert_base) is False
or os.path.exists(voiceChangerParams.hubert_base_jp) is False or os.path.exists(voiceChangerParams.hubert_base_jp) is False
@ -278,9 +223,18 @@ if __name__ == "__main__":
printMessage("Voice Changerを起動しています。", level=2) printMessage("Voice Changerを起動しています。", level=2)
# ダウンロード
downloadWeight() downloadWeight()
os.makedirs(args.model_dir, exist_ok=True) os.makedirs(args.model_dir, exist_ok=True)
try:
download_no_tqdm({"url": SAMPLES_JSON, "saveTo": args.samples, "position": 0})
except Exception as e:
print("[Voice Changer] loading sample failed", e)
if checkRvcModelExist(args.model_dir) is False:
downloadInitialSampleModels(args.samples, args.model_dir)
PORT = args.p PORT = args.p
if os.getenv("EX_PORT"): if os.getenv("EX_PORT"):

View File

@ -98,3 +98,5 @@ class ServerAudioDeviceTypes(Enum):
SAMPLES_JSON = "https://huggingface.co/wok000/vcclient_model/raw/main/samples.json" SAMPLES_JSON = "https://huggingface.co/wok000/vcclient_model/raw/main/samples.json"
RVC_MODEL_DIRNAME = "rvc"
RVC_MAX_SLOT_NUM = 5

2
server/initialize.sh Normal file
View File

@ -0,0 +1,2 @@
rm -r models
rm -r pretrain

View File

@ -1,4 +1,3 @@
from concurrent.futures import ThreadPoolExecutor
import sys import sys
import os import os
import resampy import resampy
@ -6,8 +5,8 @@ from dataclasses import asdict
from typing import cast from typing import cast
import numpy as np import numpy as np
import torch import torch
from MMVCServerSIO import download_no_tqdm from ModelSample import getModelSamples
from ModelSample import RVCModelSample, getModelSamples from voice_changer.RVC.SampleDownloader import downloadModelFiles
# avoiding parse arg error in RVC # avoiding parse arg error in RVC
@ -38,7 +37,7 @@ from voice_changer.RVC.deviceManager.DeviceManager import DeviceManager
from voice_changer.RVC.pipeline.Pipeline import Pipeline from voice_changer.RVC.pipeline.Pipeline import Pipeline
from Exceptions import NoModeLoadedException from Exceptions import NoModeLoadedException
from const import TMP_DIR, UPLOAD_DIR from const import RVC_MAX_SLOT_NUM, RVC_MODEL_DIRNAME, UPLOAD_DIR
import shutil import shutil
import json import json
@ -49,9 +48,6 @@ providers = [
"CPUExecutionProvider", "CPUExecutionProvider",
] ]
RVC_MODEL_DIRNAME = "rvc"
RVC_MAX_SLOT_NUM = 6
class RVC: class RVC:
initialLoad: bool = True initialLoad: bool = True
@ -97,46 +93,6 @@ class RVC:
else: else:
None 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,
}
)
print("[Voice Changer] Downloading model files...", end="")
with ThreadPoolExecutor() as pool:
pool.map(download_no_tqdm, downloadParams)
print("")
return modelPath, indexPath, featurePath
def moveToModelDir(self, file: str, dstDir: str): def moveToModelDir(self, file: str, dstDir: str):
dst = os.path.join(dstDir, os.path.basename(file)) dst = os.path.join(dstDir, os.path.basename(file))
if os.path.exists(dst): if os.path.exists(dst):
@ -155,7 +111,7 @@ class RVC:
if sampleInfo is None: if sampleInfo is None:
print("[Voice Changer] sampleInfo is None") print("[Voice Changer] sampleInfo is None")
return return
modelPath, indexPath, featurePath = self.downloadModelFiles(sampleInfo) modelPath, indexPath, featurePath = downloadModelFiles(sampleInfo)
params["files"]["rvcModel"] = modelPath params["files"]["rvcModel"] = modelPath
if indexPath is not None: if indexPath is not None:
params["files"]["rvcIndex"] = indexPath params["files"]["rvcIndex"] = indexPath

View File

@ -0,0 +1,137 @@
from concurrent.futures import ThreadPoolExecutor
import os
from const import RVC_MODEL_DIRNAME, TMP_DIR
from Downloader import download, download_no_tqdm
from ModelSample import RVCModelSample, getModelSamples
from typing import Any
import json
def checkRvcModelExist(model_dir: str):
rvcModelDir = os.path.join(model_dir, RVC_MODEL_DIRNAME)
if not os.path.exists(rvcModelDir):
return False
return True
def downloadInitialSampleModels(sampleJson: str, model_dir: str):
sampleModelIds = [
"KikotoMahiro_Song",
"TokinaShigure",
"Amitaro_n",
"Tsukuyomi-chan",
]
sampleModels = getModelSamples(sampleJson, "RVC")
if sampleModels is None:
return
downloadParams = []
slot_count = 0
line_num = 0
for sample in sampleModels:
if sample.id in sampleModelIds:
sampleParams: Any = {"files": {}}
slotDir = os.path.join(model_dir, RVC_MODEL_DIRNAME, str(slot_count))
os.makedirs(slotDir, exist_ok=True)
modelFilePath = os.path.join(
slotDir,
os.path.basename(sample.modelUrl),
)
downloadParams.append(
{
"url": sample.modelUrl,
"saveTo": modelFilePath,
"position": line_num,
}
)
sampleParams["files"]["rvcModel"] = modelFilePath
line_num += 1
if hasattr(sample, "indexUrl") and sample.indexUrl != "":
indexPath = os.path.join(
slotDir,
os.path.basename(sample.indexUrl),
)
downloadParams.append(
{
"url": sample.indexUrl,
"saveTo": indexPath,
"position": line_num,
}
)
sampleParams["files"]["rvcIndex"] = modelFilePath
line_num += 1
featurePath = None
if hasattr(sample, "featureUrl") or sample.featureUrl != "":
featurePath = os.path.join(
slotDir,
os.path.basename(sample.featureUrl),
)
downloadParams.append(
{
"url": sample.featureUrl,
"saveTo": featurePath,
"position": line_num,
}
)
sampleParams["files"]["rvcFeatur"] = modelFilePath
line_num += 1
sampleParams["sampleId"] = sample.id
sampleParams["defaultTune"] = 0
sampleParams["defaultIndexRatio"] = 1
sampleParams["credit"] = sample.credit
sampleParams["description"] = sample.description
sampleParams["name"] = sample.name
sampleParams["sampleId"] = sample.id
sampleParams["termsOfUseUrl"] = sample.termsOfUseUrl
jsonFilePath = os.path.join(slotDir, "params.json")
json.dump(sampleParams, open(jsonFilePath, "w"))
slot_count += 1
print("[Voice Changer] Downloading model files...")
with ThreadPoolExecutor() as pool:
pool.map(download, downloadParams)
def downloadModelFiles(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,
}
)
print("[Voice Changer] Downloading model files...", end="")
with ThreadPoolExecutor() as pool:
pool.map(download_no_tqdm, downloadParams)
print("")
return modelPath, indexPath, featurePath