mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-03-15 04:13:57 +03:00
WIP: store stting 1
This commit is contained in:
parent
1ef44ea086
commit
921825b597
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>
|
||||||
|
630
client/demo/dist/index.js
vendored
630
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.
|
|
||||||
*/
|
|
94
client/demo/package-lock.json
generated
94
client/demo/package-lock.json
generated
@ -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.28",
|
"@dannadori/voice-changer-client-js": "^1.0.55",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
@ -46,6 +46,42 @@
|
|||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"../lib": {
|
||||||
|
"name": "@dannadori/voice-changer-client-js",
|
||||||
|
"version": "1.0.34",
|
||||||
|
"extraneous": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/readable-stream": "^2.3.15",
|
||||||
|
"amazon-chime-sdk-js": "^3.10.0",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
|
"microphone-stream": "^6.0.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"readable-stream": "^4.3.0",
|
||||||
|
"socket.io-client": "^4.5.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/audioworklet": "^0.0.36",
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"@types/react": "18.0.27",
|
||||||
|
"@types/react-dom": "18.0.10",
|
||||||
|
"eslint": "^8.32.0",
|
||||||
|
"eslint-config-prettier": "^8.6.0",
|
||||||
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
"eslint-plugin-react": "^7.32.1",
|
||||||
|
"eslint-webpack-plugin": "^3.2.0",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"prettier": "^2.8.3",
|
||||||
|
"raw-loader": "^4.0.2",
|
||||||
|
"rimraf": "^4.1.2",
|
||||||
|
"ts-loader": "^9.4.2",
|
||||||
|
"typescript": "^4.9.4",
|
||||||
|
"webpack": "^5.75.0",
|
||||||
|
"webpack-cli": "^5.0.1",
|
||||||
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||||
@ -3175,12 +3211,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@dannadori/voice-changer-client-js": {
|
"node_modules/@dannadori/voice-changer-client-js": {
|
||||||
"version": "1.0.28",
|
"version": "1.0.55",
|
||||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.28.tgz",
|
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.55.tgz",
|
||||||
"integrity": "sha512-phxRkImC7FYYdH4m5uFqrRsSeAJOHtBb9tFagqvBHKUzLb6VCUAh8urUbeitLdgtGuBg+QjF/lSLIPdx/fOjyg==",
|
"integrity": "sha512-Gwqw7Wgq5XjdDux/UcQ9rSW9UdSpTeZ4Kva+cb/JYMiojkFrlKB0ghC4HaKxhvIsRlrx3MU02aUPbUKjrjQsbg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/readable-stream": "^2.3.15",
|
"@types/readable-stream": "^2.3.15",
|
||||||
"amazon-chime-sdk-js": "^3.10.0",
|
"amazon-chime-sdk-js": "^3.10.0",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
"microphone-stream": "^6.0.1",
|
"microphone-stream": "^6.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
@ -6727,6 +6764,11 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -7313,6 +7355,14 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"dependencies": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lines-and-columns": {
|
"node_modules/lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
@ -7356,6 +7406,14 @@
|
|||||||
"node": ">=6.11.5"
|
"node": ">=6.11.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"dependencies": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
@ -13238,12 +13296,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@dannadori/voice-changer-client-js": {
|
"@dannadori/voice-changer-client-js": {
|
||||||
"version": "1.0.28",
|
"version": "1.0.55",
|
||||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.28.tgz",
|
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.55.tgz",
|
||||||
"integrity": "sha512-phxRkImC7FYYdH4m5uFqrRsSeAJOHtBb9tFagqvBHKUzLb6VCUAh8urUbeitLdgtGuBg+QjF/lSLIPdx/fOjyg==",
|
"integrity": "sha512-Gwqw7Wgq5XjdDux/UcQ9rSW9UdSpTeZ4Kva+cb/JYMiojkFrlKB0ghC4HaKxhvIsRlrx3MU02aUPbUKjrjQsbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/readable-stream": "^2.3.15",
|
"@types/readable-stream": "^2.3.15",
|
||||||
"amazon-chime-sdk-js": "^3.10.0",
|
"amazon-chime-sdk-js": "^3.10.0",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
"microphone-stream": "^6.0.1",
|
"microphone-stream": "^6.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
@ -15951,6 +16010,11 @@
|
|||||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -16355,6 +16419,14 @@
|
|||||||
"type-check": "~0.4.0"
|
"type-check": "~0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"requires": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lines-and-columns": {
|
"lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
@ -16391,6 +16463,14 @@
|
|||||||
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"requires": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"locate-path": {
|
"locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dannadori/voice-changer-client-js": "^1.0.28",
|
"@dannadori/voice-changer-client-js": "^1.0.55",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,10 @@ const root = createRoot(container);
|
|||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|
||||||
const { voiceChangerSetting } = useMicrophoneOptions()
|
const { voiceChangerSetting, clearSetting } = useMicrophoneOptions()
|
||||||
|
|
||||||
const onClearSettingClicked = async () => {
|
const onClearSettingClicked = async () => {
|
||||||
//@ts-ignore
|
clearSetting()
|
||||||
await chrome.storage.local.clear();
|
|
||||||
//@ts-ignore
|
|
||||||
await chrome.storage.sync.clear();
|
|
||||||
|
|
||||||
location.reload()
|
location.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,10 @@ export const useMicrophoneOptions = () => {
|
|||||||
const advancedSetting = useAdvancedSetting({ clientState })
|
const advancedSetting = useAdvancedSetting({ clientState })
|
||||||
const serverControl = useServerControl({ clientState })
|
const serverControl = useServerControl({ clientState })
|
||||||
|
|
||||||
|
const clearSetting = async () => {
|
||||||
|
await clientState.clearSetting()
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const createAudioContext = () => {
|
const createAudioContext = () => {
|
||||||
const ctx = new AudioContext()
|
const ctx = new AudioContext()
|
||||||
@ -59,6 +63,7 @@ export const useMicrophoneOptions = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
voiceChangerSetting,
|
voiceChangerSetting,
|
||||||
|
clearSetting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { fileSelectorAsDataURL, createDummyMediaStream, SampleRate } from "@dannadori/voice-changer-client-js"
|
import { fileSelectorAsDataURL, createDummyMediaStream, SampleRate } from "@dannadori/voice-changer-client-js"
|
||||||
import React, { useEffect, useMemo, useState } from "react"
|
import React, { useEffect, useMemo, useState } from "react"
|
||||||
import { AUDIO_ELEMENT_FOR_PLAY_RESULT, AUDIO_ELEMENT_FOR_TEST_CONVERTED, AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK, AUDIO_ELEMENT_FOR_TEST_ORIGINAL } from "./const"
|
import { AUDIO_ELEMENT_FOR_PLAY_RESULT, AUDIO_ELEMENT_FOR_TEST_CONVERTED, AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK, AUDIO_ELEMENT_FOR_TEST_ORIGINAL, INDEXEDDB_KEY_AUDIO_OUTPUT } from "./const"
|
||||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||||
|
import { useIndexedDB } from "./hooks/useIndexedDB";
|
||||||
|
|
||||||
|
|
||||||
const reloadDevices = async () => {
|
const reloadDevices = async () => {
|
||||||
@ -46,24 +47,28 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
const [audioInputForGUI, setAudioInputForGUI] = useState<string>("none")
|
const [audioInputForGUI, setAudioInputForGUI] = useState<string>("none")
|
||||||
const [audioOutputForGUI, setAudioOutputForGUI] = useState<string>("none")
|
const [audioOutputForGUI, setAudioOutputForGUI] = useState<string>("none")
|
||||||
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>()//最初のmuteが有効になるように。undefined
|
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>()//最初のmuteが有効になるように。undefined
|
||||||
|
const { getItem, setItem } = useIndexedDB()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initialize = async () => {
|
const initialize = async () => {
|
||||||
const audioInfo = await reloadDevices()
|
const audioInfo = await reloadDevices()
|
||||||
setInputAudioDeviceInfo(audioInfo[0])
|
setInputAudioDeviceInfo(audioInfo[0])
|
||||||
setOutputAudioDeviceInfo(audioInfo[1])
|
setOutputAudioDeviceInfo(audioInfo[1])
|
||||||
// if (CHROME_EXTENSION) {
|
|
||||||
// //@ts-ignore
|
|
||||||
// const storedOptions = await chrome.storage.local.get("microphoneOptions")
|
|
||||||
// if (storedOptions) {
|
|
||||||
// setOptions(storedOptions)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
initialize()
|
initialize()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof props.clientState.clientSetting.setting.audioInput == "string") {
|
||||||
|
if (inputAudioDeviceInfo.find(x => {
|
||||||
|
// console.log("COMPARE:", x.deviceId, props.clientState.clientSetting.setting.audioInput)
|
||||||
|
return x.deviceId == props.clientState.clientSetting.setting.audioInput
|
||||||
|
})) {
|
||||||
|
setAudioInputForGUI(props.clientState.clientSetting.setting.audioInput)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [inputAudioDeviceInfo, props.clientState.clientSetting.setting.audioInput])
|
||||||
|
|
||||||
const audioInputRow = useMemo(() => {
|
const audioInputRow = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@ -82,7 +87,7 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [inputAudioDeviceInfo, audioInputForGUI])
|
}, [inputAudioDeviceInfo, audioInputForGUI, props.clientState.clientSetting.setting.audioInput])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -90,10 +95,7 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioInputForGUI == "none") {
|
if (audioInputForGUI == "file") {
|
||||||
const ms = createDummyMediaStream(audioContext)
|
|
||||||
props.clientState.clientSetting.setAudioInput(ms)
|
|
||||||
} else if (audioInputForGUI == "file") {
|
|
||||||
// file selector (audioMediaInputRow)
|
// file selector (audioMediaInputRow)
|
||||||
} else {
|
} else {
|
||||||
props.clientState.clientSetting.setAudioInput(audioInputForGUI)
|
props.clientState.clientSetting.setAudioInput(audioInputForGUI)
|
||||||
@ -161,7 +163,10 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
<div className="body-row split-3-7 left-padding-1 guided">
|
<div className="body-row split-3-7 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-1">AudioOutput</div>
|
<div className="body-item-title left-padding-1">AudioOutput</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={audioOutputForGUI} onChange={(e) => { setAudioOutputForGUI(e.target.value) }}>
|
<select className="body-select" value={audioOutputForGUI} onChange={(e) => {
|
||||||
|
setAudioOutputForGUI(e.target.value)
|
||||||
|
setItem(INDEXEDDB_KEY_AUDIO_OUTPUT, e.target.value)
|
||||||
|
}}>
|
||||||
{
|
{
|
||||||
outputAudioDeviceInfo.map(x => {
|
outputAudioDeviceInfo.map(x => {
|
||||||
return <option key={x.deviceId} value={x.deviceId}>{x.label}</option>
|
return <option key={x.deviceId} value={x.deviceId}>{x.label}</option>
|
||||||
@ -175,16 +180,33 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
}, [outputAudioDeviceInfo, audioOutputForGUI])
|
}, [outputAudioDeviceInfo, audioOutputForGUI])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (audioOutputForGUI == "none") return
|
|
||||||
[AUDIO_ELEMENT_FOR_PLAY_RESULT, AUDIO_ELEMENT_FOR_TEST_ORIGINAL, AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK].forEach(x => {
|
[AUDIO_ELEMENT_FOR_PLAY_RESULT, AUDIO_ELEMENT_FOR_TEST_ORIGINAL, AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK].forEach(x => {
|
||||||
const audio = document.getElementById(x) as HTMLAudioElement
|
const audio = document.getElementById(x) as HTMLAudioElement
|
||||||
if (audio) {
|
if (audio) {
|
||||||
|
if (audioOutputForGUI == "none") {
|
||||||
|
// @ts-ignore
|
||||||
|
audio.setSinkId("")
|
||||||
|
|
||||||
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
audio.setSinkId(audioOutputForGUI)
|
audio.setSinkId(audioOutputForGUI)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}, [audioOutputForGUI])
|
}, [audioOutputForGUI])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadCache = async () => {
|
||||||
|
const key = await getItem(INDEXEDDB_KEY_AUDIO_OUTPUT)
|
||||||
|
if (key) {
|
||||||
|
setAudioOutputForGUI(key as string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadCache()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
[AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK].forEach(x => {
|
[AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK].forEach(x => {
|
||||||
const audio = document.getElementById(x) as HTMLAudioElement
|
const audio = document.getElementById(x) as HTMLAudioElement
|
||||||
|
@ -10,7 +10,6 @@ export type ConvertSettingState = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useConvertSetting = (props: UseConvertSettingProps): ConvertSettingState => {
|
export const useConvertSetting = (props: UseConvertSettingProps): ConvertSettingState => {
|
||||||
|
|
||||||
const inputChunkNumRow = useMemo(() => {
|
const inputChunkNumRow = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
<div className="body-row split-3-7 left-padding-1 guided">
|
<div className="body-row split-3-7 left-padding-1 guided">
|
||||||
|
@ -4,3 +4,6 @@ export const AUDIO_ELEMENT_FOR_PLAY_RESULT = "audio-result"
|
|||||||
export const AUDIO_ELEMENT_FOR_TEST_ORIGINAL = "audio-test-original"
|
export const AUDIO_ELEMENT_FOR_TEST_ORIGINAL = "audio-test-original"
|
||||||
export const AUDIO_ELEMENT_FOR_TEST_CONVERTED = "audio-test-converted"
|
export const AUDIO_ELEMENT_FOR_TEST_CONVERTED = "audio-test-converted"
|
||||||
export const AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK = "audio-test-converted-echoback"
|
export const AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK = "audio-test-converted-echoback"
|
||||||
|
|
||||||
|
|
||||||
|
export const INDEXEDDB_KEY_AUDIO_OUTPUT = "INDEXEDDB_KEY_AUDIO_OUTPUT"
|
50
client/demo/src/hooks/useIndexedDB.ts
Normal file
50
client/demo/src/hooks/useIndexedDB.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { INDEXEDDB_DB_APP_NAME, INDEXEDDB_DB_NAME } from "@dannadori/voice-changer-client-js";
|
||||||
|
import localForage from "localforage";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
export type IndexedDBState = {
|
||||||
|
dummy: string
|
||||||
|
}
|
||||||
|
export type IndexedDBStateAndMethod = IndexedDBState & {
|
||||||
|
setItem: (key: string, value: unknown) => Promise<void>,
|
||||||
|
getItem: (key: string) => Promise<unknown>
|
||||||
|
removeItem: (key: string) => Promise<void>
|
||||||
|
// clearAll: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useIndexedDB = (): IndexedDBStateAndMethod => {
|
||||||
|
localForage.config({
|
||||||
|
driver: localForage.INDEXEDDB,
|
||||||
|
name: INDEXEDDB_DB_APP_NAME,
|
||||||
|
version: 1.0,
|
||||||
|
storeName: INDEXEDDB_DB_NAME,
|
||||||
|
description: 'appStorage'
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const setItem = useMemo(() => {
|
||||||
|
return async (key: string, value: unknown) => {
|
||||||
|
await localForage.setItem(key, value)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
const getItem = useMemo(() => {
|
||||||
|
return async (key: string) => {
|
||||||
|
return await localForage.getItem(key)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const removeItem = useMemo(() => {
|
||||||
|
return async (key: string) => {
|
||||||
|
return await localForage.removeItem(key)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
dummy: "",
|
||||||
|
setItem,
|
||||||
|
getItem,
|
||||||
|
removeItem,
|
||||||
|
}
|
||||||
|
}
|
47
client/lib/package-lock.json
generated
47
client/lib/package-lock.json
generated
@ -1,16 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@dannadori/voice-changer-client-js",
|
"name": "@dannadori/voice-changer-client-js",
|
||||||
"version": "1.0.28",
|
"version": "1.0.55",
|
||||||
"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.28",
|
"version": "1.0.55",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/readable-stream": "^2.3.15",
|
"@types/readable-stream": "^2.3.15",
|
||||||
"amazon-chime-sdk-js": "^3.10.0",
|
"amazon-chime-sdk-js": "^3.10.0",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
"microphone-stream": "^6.0.1",
|
"microphone-stream": "^6.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
@ -4173,6 +4174,11 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -4729,6 +4735,14 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"dependencies": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/load-json-file": {
|
"node_modules/load-json-file": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||||
@ -4767,6 +4781,14 @@
|
|||||||
"node": ">=8.9.0"
|
"node": ">=8.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"dependencies": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
@ -11062,6 +11084,11 @@
|
|||||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -11448,6 +11475,14 @@
|
|||||||
"type-check": "~0.4.0"
|
"type-check": "~0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"requires": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||||
@ -11477,6 +11512,14 @@
|
|||||||
"json5": "^2.1.2"
|
"json5": "^2.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"requires": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"locate-path": {
|
"locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@dannadori/voice-changer-client-js",
|
"name": "@dannadori/voice-changer-client-js",
|
||||||
"version": "1.0.28",
|
"version": "1.0.55",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@ -45,10 +45,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/readable-stream": "^2.3.15",
|
"@types/readable-stream": "^2.3.15",
|
||||||
|
"amazon-chime-sdk-js": "^3.10.0",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
|
"microphone-stream": "^6.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"amazon-chime-sdk-js": "^3.10.0",
|
|
||||||
"microphone-stream": "^6.0.1",
|
|
||||||
"readable-stream": "^4.3.0",
|
"readable-stream": "^4.3.0",
|
||||||
"socket.io-client": "^4.5.4"
|
"socket.io-client": "^4.5.4"
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import { VoiceChangerWorkletProcessorRequest } from "./@types/voice-changer-work
|
|||||||
// input node(mic or MediaStream) -> [vf node] -> microphne stream -> audio streamer ->
|
// input node(mic or MediaStream) -> [vf node] -> microphne stream -> audio streamer ->
|
||||||
// sio/rest server -> audio streamer-> vc node -> output node
|
// sio/rest server -> audio streamer-> vc node -> output node
|
||||||
|
|
||||||
|
import { BlockingQueue } from "./utils/BlockingQueue";
|
||||||
|
|
||||||
export class VoiceChangerClient {
|
export class VoiceChangerClient {
|
||||||
private configurator: ServerConfigurator
|
private configurator: ServerConfigurator
|
||||||
@ -35,6 +35,8 @@ export class VoiceChangerClient {
|
|||||||
|
|
||||||
private sslCertified: string[] = []
|
private sslCertified: string[] = []
|
||||||
|
|
||||||
|
private sem = new BlockingQueue<number>();
|
||||||
|
|
||||||
private callbacks: Callbacks = {
|
private callbacks: Callbacks = {
|
||||||
onVoiceReceived: (voiceChangerMode: VoiceChangerMode, data: ArrayBuffer): void => {
|
onVoiceReceived: (voiceChangerMode: VoiceChangerMode, data: ArrayBuffer): void => {
|
||||||
// console.log(voiceChangerMode, data)
|
// console.log(voiceChangerMode, data)
|
||||||
@ -73,6 +75,7 @@ export class VoiceChangerClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(ctx: AudioContext, vfEnable: boolean, audioStreamerListeners: AudioStreamerListeners, volumeListener: VolumeListener) {
|
constructor(ctx: AudioContext, vfEnable: boolean, audioStreamerListeners: AudioStreamerListeners, volumeListener: VolumeListener) {
|
||||||
|
this.sem.enqueue(0);
|
||||||
this.configurator = new ServerConfigurator()
|
this.configurator = new ServerConfigurator()
|
||||||
this.ctx = ctx
|
this.ctx = ctx
|
||||||
this.vfEnable = vfEnable
|
this.vfEnable = vfEnable
|
||||||
@ -98,6 +101,15 @@ export class VoiceChangerClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lock = async () => {
|
||||||
|
const num = await this.sem.dequeue();
|
||||||
|
return num;
|
||||||
|
};
|
||||||
|
private unlock = (num: number) => {
|
||||||
|
this.sem.enqueue(num + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
isInitialized = async () => {
|
isInitialized = async () => {
|
||||||
if (this.promiseForInitialize) {
|
if (this.promiseForInitialize) {
|
||||||
await this.promiseForInitialize
|
await this.promiseForInitialize
|
||||||
@ -107,6 +119,7 @@ export class VoiceChangerClient {
|
|||||||
|
|
||||||
// forceVfDisable is for the condition that vf is enabled in constructor.
|
// forceVfDisable is for the condition that vf is enabled in constructor.
|
||||||
setup = async (input: string | MediaStream, bufferSize: BufferSize, forceVfDisable: boolean = false) => {
|
setup = async (input: string | MediaStream, bufferSize: BufferSize, forceVfDisable: boolean = false) => {
|
||||||
|
const lockNum = await this.lock()
|
||||||
// condition check
|
// condition check
|
||||||
if (!this.vcNode) {
|
if (!this.vcNode) {
|
||||||
console.warn("vc node is not initialized.")
|
console.warn("vc node is not initialized.")
|
||||||
@ -156,6 +169,7 @@ export class VoiceChangerClient {
|
|||||||
} else {
|
} else {
|
||||||
this.micStream.playRecording()
|
this.micStream.playRecording()
|
||||||
}
|
}
|
||||||
|
await this.unlock(lockNum)
|
||||||
}
|
}
|
||||||
get stream(): MediaStream {
|
get stream(): MediaStream {
|
||||||
return this.currentMediaStreamAudioDestinationNode.stream
|
return this.currentMediaStreamAudioDestinationNode.stream
|
||||||
|
@ -189,3 +189,11 @@ export const VOICE_CHANGER_CLIENT_EXCEPTION = {
|
|||||||
export type VOICE_CHANGER_CLIENT_EXCEPTION = typeof VOICE_CHANGER_CLIENT_EXCEPTION[keyof typeof VOICE_CHANGER_CLIENT_EXCEPTION]
|
export type VOICE_CHANGER_CLIENT_EXCEPTION = typeof VOICE_CHANGER_CLIENT_EXCEPTION[keyof typeof VOICE_CHANGER_CLIENT_EXCEPTION]
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// indexedDB
|
||||||
|
////////////////////////////////////
|
||||||
|
export const INDEXEDDB_DB_APP_NAME = "INDEXEDDB_KEY_VOICE_CHANGER"
|
||||||
|
export const INDEXEDDB_DB_NAME = "INDEXEDDB_KEY_VOICE_CHANGER_DB"
|
||||||
|
export const INDEXEDDB_KEY_CLIENT = "INDEXEDDB_KEY_VOICE_CHANGER_LIB_CLIENT"
|
||||||
|
export const INDEXEDDB_KEY_SERVER = "INDEXEDDB_KEY_VOICE_CHANGER_LIB_SERVER"
|
||||||
|
export const INDEXEDDB_KEY_WORKLET = "INDEXEDDB_KEY_VOICE_CHANGER_LIB_WORKLET"
|
@ -19,6 +19,7 @@ export type ClientState = {
|
|||||||
volume: number;
|
volume: number;
|
||||||
|
|
||||||
getInfo: () => Promise<void>
|
getInfo: () => Promise<void>
|
||||||
|
clearSetting: () => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -105,6 +106,11 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
}, [clientSetting, serverSetting])
|
}, [clientSetting, serverSetting])
|
||||||
|
|
||||||
|
|
||||||
|
const clearSetting = async () => {
|
||||||
|
await clientSetting.clearSetting()
|
||||||
|
await workletSetting.clearSetting()
|
||||||
|
await serverSetting.clearSetting()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bufferingTime,
|
bufferingTime,
|
||||||
@ -116,5 +122,6 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
clientSetting,
|
clientSetting,
|
||||||
workletSetting,
|
workletSetting,
|
||||||
serverSetting,
|
serverSetting,
|
||||||
|
clearSetting,
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,8 @@
|
|||||||
import { useState, useMemo, useRef, useEffect } from "react"
|
import { useState, useMemo, useRef, useEffect } from "react"
|
||||||
import { VoiceChangerClientSetting, Protocol, BufferSize, VoiceChangerMode, SampleRate, Speaker, DefaultVoiceChangerClientSetting } from "../const"
|
import { VoiceChangerClientSetting, Protocol, BufferSize, VoiceChangerMode, SampleRate, Speaker, DefaultVoiceChangerClientSetting, INDEXEDDB_KEY_CLIENT } from "../const"
|
||||||
import { createDummyMediaStream } from "../util"
|
import { createDummyMediaStream } from "../util"
|
||||||
import { VoiceChangerClient } from "../VoiceChangerClient"
|
import { VoiceChangerClient } from "../VoiceChangerClient"
|
||||||
|
import { useIndexedDB } from "./useIndexedDB"
|
||||||
|
|
||||||
export type UseClientSettingProps = {
|
export type UseClientSettingProps = {
|
||||||
voiceChangerClient: VoiceChangerClient | null
|
voiceChangerClient: VoiceChangerClient | null
|
||||||
@ -10,6 +11,7 @@ export type UseClientSettingProps = {
|
|||||||
|
|
||||||
export type ClientSettingState = {
|
export type ClientSettingState = {
|
||||||
setting: VoiceChangerClientSetting;
|
setting: VoiceChangerClientSetting;
|
||||||
|
clearSetting: () => Promise<void>
|
||||||
setServerUrl: (url: string) => void;
|
setServerUrl: (url: string) => void;
|
||||||
setProtocol: (proto: Protocol) => void;
|
setProtocol: (proto: Protocol) => void;
|
||||||
setAudioInput: (audioInput: string | MediaStream | null) => Promise<void>
|
setAudioInput: (audioInput: string | MediaStream | null) => Promise<void>
|
||||||
@ -28,6 +30,57 @@ export type ClientSettingState = {
|
|||||||
export const useClientSetting = (props: UseClientSettingProps): ClientSettingState => {
|
export const useClientSetting = (props: UseClientSettingProps): ClientSettingState => {
|
||||||
const settingRef = useRef<VoiceChangerClientSetting>(DefaultVoiceChangerClientSetting)
|
const settingRef = useRef<VoiceChangerClientSetting>(DefaultVoiceChangerClientSetting)
|
||||||
const [setting, _setSetting] = useState<VoiceChangerClientSetting>(settingRef.current)
|
const [setting, _setSetting] = useState<VoiceChangerClientSetting>(settingRef.current)
|
||||||
|
const { setItem, getItem, removeItem } = useIndexedDB()
|
||||||
|
|
||||||
|
// 初期化 その1 DBから取得
|
||||||
|
useEffect(() => {
|
||||||
|
const loadCache = async () => {
|
||||||
|
const setting = await getItem(INDEXEDDB_KEY_CLIENT)
|
||||||
|
if (!setting) {
|
||||||
|
// デフォルト設定
|
||||||
|
console.log("No Chache",)
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const colab = params.get("colab")
|
||||||
|
if (colab == "true") {
|
||||||
|
settingRef.current.protocol = "rest"
|
||||||
|
settingRef.current.inputChunkNum = 64
|
||||||
|
} else {
|
||||||
|
settingRef.current.protocol = "sio"
|
||||||
|
settingRef.current.inputChunkNum = 32
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
settingRef.current = setting as VoiceChangerClientSetting
|
||||||
|
}
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCache()
|
||||||
|
}, [])
|
||||||
|
// 初期化 その2 クライアントに設定
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.setServerUrl(settingRef.current.mmvcServerUrl)
|
||||||
|
props.voiceChangerClient.setInputChunkNum(settingRef.current.inputChunkNum)
|
||||||
|
props.voiceChangerClient.setProtocol(settingRef.current.protocol)
|
||||||
|
props.voiceChangerClient.setVoiceChangerMode(settingRef.current.voiceChangerMode)
|
||||||
|
|
||||||
|
// Input, bufferSize, VoiceFocus Disableは_setInputで設定
|
||||||
|
_setInput()
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
|
||||||
|
const setSetting = async (setting: VoiceChangerClientSetting) => {
|
||||||
|
const storeData = { ...setting }
|
||||||
|
if (typeof storeData.audioInput != "string") {
|
||||||
|
storeData.audioInput = null
|
||||||
|
}
|
||||||
|
setItem(INDEXEDDB_KEY_CLIENT, storeData)
|
||||||
|
_setSetting(setting)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearSetting = async () => {
|
||||||
|
await removeItem(INDEXEDDB_KEY_CLIENT)
|
||||||
|
}
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
// 設定
|
// 設定
|
||||||
@ -37,7 +90,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
props.voiceChangerClient.setServerUrl(url, true)
|
props.voiceChangerClient.setServerUrl(url, true)
|
||||||
settingRef.current.mmvcServerUrl = url
|
settingRef.current.mmvcServerUrl = url
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -46,20 +99,20 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
props.voiceChangerClient.setProtocol(proto)
|
props.voiceChangerClient.setProtocol(proto)
|
||||||
settingRef.current.protocol = proto
|
settingRef.current.protocol = proto
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
const _setInput = async () => {
|
const _setInput = async () => {
|
||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
|
// console.log("[useClient] setup!(0)", settingRef.current.audioInput)
|
||||||
if (!settingRef.current.audioInput || settingRef.current.audioInput == "none") {
|
if (!settingRef.current.audioInput || settingRef.current.audioInput == "none") {
|
||||||
console.log("[useClient] setup!(1)", settingRef.current.audioInput)
|
// console.log("[useClient] setup!(1)", settingRef.current.audioInput)
|
||||||
const ms = createDummyMediaStream(props.audioContext!)
|
const ms = createDummyMediaStream(props.audioContext!)
|
||||||
await props.voiceChangerClient.setup(ms, settingRef.current.bufferSize, settingRef.current.forceVfDisable)
|
await props.voiceChangerClient.setup(ms, settingRef.current.bufferSize, settingRef.current.forceVfDisable)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log("[useClient] setup!(2)", settingRef.current.audioInput)
|
// console.log("[useClient] setup!(2)", settingRef.current.audioInput)
|
||||||
await props.voiceChangerClient.setup(settingRef.current.audioInput, settingRef.current.bufferSize, settingRef.current.forceVfDisable)
|
await props.voiceChangerClient.setup(settingRef.current.audioInput, settingRef.current.bufferSize, settingRef.current.forceVfDisable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,9 +122,8 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
settingRef.current.audioInput = audioInput
|
settingRef.current.audioInput = audioInput
|
||||||
await _setInput()
|
await _setInput()
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
const setBufferSize = useMemo(() => {
|
const setBufferSize = useMemo(() => {
|
||||||
@ -79,7 +131,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
settingRef.current.bufferSize = bufferSize
|
settingRef.current.bufferSize = bufferSize
|
||||||
await _setInput()
|
await _setInput()
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -88,7 +140,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
settingRef.current.forceVfDisable = vfForceDisabled
|
settingRef.current.forceVfDisable = vfForceDisabled
|
||||||
await _setInput()
|
await _setInput()
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -97,7 +149,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
props.voiceChangerClient.setInputChunkNum(num)
|
props.voiceChangerClient.setInputChunkNum(num)
|
||||||
settingRef.current.inputChunkNum = num
|
settingRef.current.inputChunkNum = num
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -106,7 +158,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
props.voiceChangerClient.setVoiceChangerMode(mode)
|
props.voiceChangerClient.setVoiceChangerMode(mode)
|
||||||
settingRef.current.voiceChangerMode = mode
|
settingRef.current.voiceChangerMode = mode
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -115,7 +167,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
//props.voiceChangerClient.setSampleRate(num) // Not Implemented
|
//props.voiceChangerClient.setSampleRate(num) // Not Implemented
|
||||||
settingRef.current.sampleRate = num
|
settingRef.current.sampleRate = num
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -123,7 +175,7 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
return (speakers: Speaker[]) => {
|
return (speakers: Speaker[]) => {
|
||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
settingRef.current.speakers = speakers
|
settingRef.current.speakers = speakers
|
||||||
_setSetting({ ...settingRef.current })
|
setSetting({ ...settingRef.current })
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
@ -152,27 +204,10 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
|||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
//////////////
|
|
||||||
// デフォルト設定
|
|
||||||
/////////////
|
|
||||||
useEffect(() => {
|
|
||||||
const params = new URLSearchParams(location.search);
|
|
||||||
const colab = params.get("colab")
|
|
||||||
if (colab == "true") {
|
|
||||||
setProtocol("rest")
|
|
||||||
setInputChunkNum(64)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setProtocol("sio")
|
|
||||||
setInputChunkNum(32)
|
|
||||||
|
|
||||||
}
|
|
||||||
}, [props.voiceChangerClient])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setting,
|
setting,
|
||||||
|
clearSetting,
|
||||||
setServerUrl,
|
setServerUrl,
|
||||||
setProtocol,
|
setProtocol,
|
||||||
setAudioInput,
|
setAudioInput,
|
||||||
|
50
client/lib/src/hooks/useIndexedDB.ts
Normal file
50
client/lib/src/hooks/useIndexedDB.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import localForage from "localforage";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { INDEXEDDB_DB_APP_NAME, INDEXEDDB_DB_NAME } from "../const";
|
||||||
|
|
||||||
|
|
||||||
|
export type IndexedDBState = {
|
||||||
|
dummy: string
|
||||||
|
}
|
||||||
|
export type IndexedDBStateAndMethod = IndexedDBState & {
|
||||||
|
setItem: (key: string, value: unknown) => Promise<void>,
|
||||||
|
getItem: (key: string) => Promise<unknown>
|
||||||
|
removeItem: (key: string) => Promise<void>
|
||||||
|
// clearAll: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useIndexedDB = (): IndexedDBStateAndMethod => {
|
||||||
|
localForage.config({
|
||||||
|
driver: localForage.INDEXEDDB,
|
||||||
|
name: INDEXEDDB_DB_APP_NAME,
|
||||||
|
version: 1.0,
|
||||||
|
storeName: INDEXEDDB_DB_NAME,
|
||||||
|
description: 'appStorage'
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const setItem = useMemo(() => {
|
||||||
|
return async (key: string, value: unknown) => {
|
||||||
|
await localForage.setItem(key, value)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
const getItem = useMemo(() => {
|
||||||
|
return async (key: string) => {
|
||||||
|
return await localForage.getItem(key)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const removeItem = useMemo(() => {
|
||||||
|
return async (key: string) => {
|
||||||
|
return await localForage.removeItem(key)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
dummy: "",
|
||||||
|
setItem,
|
||||||
|
getItem,
|
||||||
|
removeItem,
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { useState, useMemo, useRef, useEffect } from "react"
|
import { useState, useMemo, useRef, useEffect } from "react"
|
||||||
import { VoiceChangerServerSetting, ServerInfo, Framework, OnnxExecutionProvider, DefaultVoiceChangerServerSetting, ServerSettingKey } from "../const"
|
import { VoiceChangerServerSetting, ServerInfo, Framework, OnnxExecutionProvider, DefaultVoiceChangerServerSetting, ServerSettingKey, INDEXEDDB_KEY_SERVER } from "../const"
|
||||||
import { VoiceChangerClient } from "../VoiceChangerClient"
|
import { VoiceChangerClient } from "../VoiceChangerClient"
|
||||||
|
import { useIndexedDB } from "./useIndexedDB"
|
||||||
|
|
||||||
|
|
||||||
export type FileUploadSetting = {
|
export type FileUploadSetting = {
|
||||||
@ -19,6 +20,7 @@ export type UseServerSettingProps = {
|
|||||||
|
|
||||||
export type ServerSettingState = {
|
export type ServerSettingState = {
|
||||||
setting: VoiceChangerServerSetting;
|
setting: VoiceChangerServerSetting;
|
||||||
|
clearSetting: () => Promise<void>
|
||||||
serverInfo: ServerInfo | undefined;
|
serverInfo: ServerInfo | undefined;
|
||||||
fileUploadSetting: FileUploadSetting
|
fileUploadSetting: FileUploadSetting
|
||||||
setFramework: (framework: Framework) => Promise<boolean>;
|
setFramework: (framework: Framework) => Promise<boolean>;
|
||||||
@ -43,6 +45,31 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
const [setting, _setSetting] = useState<VoiceChangerServerSetting>(settingRef.current)
|
const [setting, _setSetting] = useState<VoiceChangerServerSetting>(settingRef.current)
|
||||||
const [serverInfo, _setServerInfo] = useState<ServerInfo>()
|
const [serverInfo, _setServerInfo] = useState<ServerInfo>()
|
||||||
const [fileUploadSetting, setFileUploadSetting] = useState<FileUploadSetting>(InitialFileUploadSetting)
|
const [fileUploadSetting, setFileUploadSetting] = useState<FileUploadSetting>(InitialFileUploadSetting)
|
||||||
|
const { setItem, getItem, removeItem } = useIndexedDB()
|
||||||
|
|
||||||
|
|
||||||
|
// 初期化 その1 DBから取得
|
||||||
|
useEffect(() => {
|
||||||
|
const loadCache = async () => {
|
||||||
|
const setting = await getItem(INDEXEDDB_KEY_SERVER)
|
||||||
|
if (!setting) {
|
||||||
|
} else {
|
||||||
|
settingRef.current = setting as VoiceChangerServerSetting
|
||||||
|
}
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCache()
|
||||||
|
}, [])
|
||||||
|
// 初期化 その2 クライアントに設定
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
// props.voiceChangerClient.setServerUrl(settingRef.current.mmvcServerUrl)
|
||||||
|
// props.voiceChangerClient.setInputChunkNum(settingRef.current.inputChunkNum)
|
||||||
|
// props.voiceChangerClient.setProtocol(settingRef.current.protocol)
|
||||||
|
// props.voiceChangerClient.setVoiceChangerMode(settingRef.current.voiceChangerMode)
|
||||||
|
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
// 設定
|
// 設定
|
||||||
@ -55,7 +82,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
|
|
||||||
_setServerInfo(res)
|
_setServerInfo(res)
|
||||||
if (newVal == res[key]) {
|
if (newVal == res[key]) {
|
||||||
_setSetting({
|
const newSetting: VoiceChangerServerSetting = {
|
||||||
...settingRef.current,
|
...settingRef.current,
|
||||||
convertChunkNum: res.convertChunkNum,
|
convertChunkNum: res.convertChunkNum,
|
||||||
minConvertSize: res.minConvertSize,
|
minConvertSize: res.minConvertSize,
|
||||||
@ -67,7 +94,9 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
crossFadeOverlapRate: res.crossFadeOverlapRate,
|
crossFadeOverlapRate: res.crossFadeOverlapRate,
|
||||||
framework: res.framework,
|
framework: res.framework,
|
||||||
onnxExecutionProvider: (!!res.onnxExecutionProvider && res.onnxExecutionProvider.length > 0) ? res.onnxExecutionProvider[0] as OnnxExecutionProvider : DefaultVoiceChangerServerSetting.onnxExecutionProvider
|
onnxExecutionProvider: (!!res.onnxExecutionProvider && res.onnxExecutionProvider.length > 0) ? res.onnxExecutionProvider[0] as OnnxExecutionProvider : DefaultVoiceChangerServerSetting.onnxExecutionProvider
|
||||||
})
|
}
|
||||||
|
_setSetting(newSetting)
|
||||||
|
setItem(INDEXEDDB_KEY_SERVER, newSetting)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
alert(`[ServerSetting] 設定が反映されていません([key:${key}, new:${newVal}, res:${res[key]}])。モデルの切り替えの場合、処理が非同期で行われるため反映されていないように見える場合があります。サーバコントロールのリロードボタンを押すとGUIに反映されるます。`)
|
alert(`[ServerSetting] 設定が反映されていません([key:${key}, new:${newVal}, res:${res[key]}])。モデルの切り替えの場合、処理が非同期で行われるため反映されていないように見える場合があります。サーバコントロールのリロードボタンを押すとGUIに反映されるます。`)
|
||||||
@ -206,22 +235,14 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const clearSetting = async () => {
|
||||||
//////////////
|
await removeItem(INDEXEDDB_KEY_SERVER)
|
||||||
// デフォルト設定
|
|
||||||
/////////////
|
|
||||||
useEffect(() => {
|
|
||||||
const params = new URLSearchParams(location.search);
|
|
||||||
const colab = params.get("colab")
|
|
||||||
if (colab == "true") {
|
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setting,
|
setting,
|
||||||
|
clearSetting,
|
||||||
serverInfo,
|
serverInfo,
|
||||||
fileUploadSetting,
|
fileUploadSetting,
|
||||||
setFramework,
|
setFramework,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useState, useMemo, useEffect } from "react"
|
import { useState, useMemo, useEffect } from "react"
|
||||||
import { WorkletSetting, DefaultWorkletSetting } from "../const";
|
import { WorkletSetting, DefaultWorkletSetting, INDEXEDDB_KEY_WORKLET } from "../const";
|
||||||
import { VoiceChangerClient } from "../VoiceChangerClient";
|
import { VoiceChangerClient } from "../VoiceChangerClient";
|
||||||
|
import { useIndexedDB } from "./useIndexedDB";
|
||||||
|
|
||||||
export type UseWorkletSettingProps = {
|
export type UseWorkletSettingProps = {
|
||||||
voiceChangerClient: VoiceChangerClient | null
|
voiceChangerClient: VoiceChangerClient | null
|
||||||
@ -8,45 +9,64 @@ export type UseWorkletSettingProps = {
|
|||||||
|
|
||||||
export type WorkletSettingState = {
|
export type WorkletSettingState = {
|
||||||
setting: WorkletSetting;
|
setting: WorkletSetting;
|
||||||
|
clearSetting: () => Promise<void>
|
||||||
setSetting: (setting: WorkletSetting) => void;
|
setSetting: (setting: WorkletSetting) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWorkletSetting = (props: UseWorkletSettingProps): WorkletSettingState => {
|
export const useWorkletSetting = (props: UseWorkletSettingProps): WorkletSettingState => {
|
||||||
const [setting, _setSetting] = useState<WorkletSetting>(DefaultWorkletSetting)
|
const [setting, _setSetting] = useState<WorkletSetting>(DefaultWorkletSetting)
|
||||||
|
const { setItem, getItem, removeItem } = useIndexedDB()
|
||||||
|
// 初期化 その1 DBから取得
|
||||||
|
useEffect(() => {
|
||||||
|
const loadCache = async () => {
|
||||||
|
const setting = await getItem(INDEXEDDB_KEY_WORKLET)
|
||||||
|
if (!setting) {
|
||||||
|
// デフォルト設定
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const colab = params.get("colab")
|
||||||
|
if (colab == "true") {
|
||||||
|
_setSetting({
|
||||||
|
numTrancateTreshold: 300,
|
||||||
|
volTrancateThreshold: 0.0005,
|
||||||
|
volTrancateLength: 32,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
_setSetting({
|
||||||
|
numTrancateTreshold: 150,
|
||||||
|
volTrancateThreshold: 0.0005,
|
||||||
|
volTrancateLength: 32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_setSetting({
|
||||||
|
...(setting as WorkletSetting)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadCache()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// 初期化 その2 クライアントに設定
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.configureWorklet(setting)
|
||||||
|
}, [props.voiceChangerClient, setting])
|
||||||
|
|
||||||
const setSetting = useMemo(() => {
|
const setSetting = useMemo(() => {
|
||||||
return (setting: WorkletSetting) => {
|
return (setting: WorkletSetting) => {
|
||||||
if (!props.voiceChangerClient) return
|
if (!props.voiceChangerClient) return
|
||||||
props.voiceChangerClient.configureWorklet(setting)
|
props.voiceChangerClient.configureWorklet(setting)
|
||||||
_setSetting(setting)
|
_setSetting(setting)
|
||||||
|
setItem(INDEXEDDB_KEY_WORKLET, setting)
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const clearSetting = async () => {
|
||||||
//////////////
|
await removeItem(INDEXEDDB_KEY_WORKLET)
|
||||||
// デフォルト設定
|
|
||||||
/////////////
|
|
||||||
useEffect(() => {
|
|
||||||
const params = new URLSearchParams(location.search);
|
|
||||||
const colab = params.get("colab")
|
|
||||||
if (colab == "true") {
|
|
||||||
setSetting({
|
|
||||||
numTrancateTreshold: 300,
|
|
||||||
volTrancateThreshold: 0.0005,
|
|
||||||
volTrancateLength: 32,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
setSetting({
|
|
||||||
numTrancateTreshold: 150,
|
|
||||||
volTrancateThreshold: 0.0005,
|
|
||||||
volTrancateLength: 32,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}, [props.voiceChangerClient])
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setting,
|
setting,
|
||||||
|
clearSetting,
|
||||||
setSetting
|
setSetting
|
||||||
}
|
}
|
||||||
}
|
}
|
41
client/lib/src/utils/BlockingQueue.ts
Normal file
41
client/lib/src/utils/BlockingQueue.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
export class BlockingQueue<T> {
|
||||||
|
private _promises: Promise<T>[];
|
||||||
|
private _resolvers: ((t: T) => void)[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._resolvers = [];
|
||||||
|
this._promises = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private _add() {
|
||||||
|
this._promises.push(
|
||||||
|
new Promise((resolve) => {
|
||||||
|
this._resolvers.push(resolve);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueue(t: T) {
|
||||||
|
if (this._resolvers.length == 0) this._add();
|
||||||
|
const resolve = this._resolvers.shift()!;
|
||||||
|
resolve(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
dequeue() {
|
||||||
|
if (this._promises.length == 0) this._add();
|
||||||
|
const promise = this._promises.shift()!;
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty() {
|
||||||
|
return this._promises.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBlocked() {
|
||||||
|
return this._resolvers.length != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get length() {
|
||||||
|
return this._promises.length - this._resolvers.length;
|
||||||
|
}
|
||||||
|
}
|
@ -37,9 +37,9 @@ class VocieChangerSettings():
|
|||||||
|
|
||||||
class VoiceChanger():
|
class VoiceChanger():
|
||||||
|
|
||||||
def __init__(self, config: str):
|
def __init__(self):
|
||||||
# 初期化
|
# 初期化
|
||||||
self.settings = VocieChangerSettings(configFile=config)
|
self.settings = VocieChangerSettings()
|
||||||
self.unpackedData_length = 0
|
self.unpackedData_length = 0
|
||||||
self.net_g = None
|
self.net_g = None
|
||||||
self.onnx_session = None
|
self.onnx_session = None
|
||||||
@ -47,17 +47,7 @@ class VoiceChanger():
|
|||||||
self.currentCrossFadeEndRate = 0
|
self.currentCrossFadeEndRate = 0
|
||||||
self.currentCrossFadeOverlapRate = 0
|
self.currentCrossFadeOverlapRate = 0
|
||||||
|
|
||||||
# 共通で使用する情報を収集
|
|
||||||
# self.hps = utils.get_hparams_from_file(config)
|
|
||||||
self.hps = get_hparams_from_file(config)
|
|
||||||
self.gpu_num = torch.cuda.device_count()
|
self.gpu_num = torch.cuda.device_count()
|
||||||
|
|
||||||
# text_norm = text_to_sequence("a", self.hps.data.text_cleaners)
|
|
||||||
# print("text_norm1: ",text_norm)
|
|
||||||
# text_norm = commons.intersperse(text_norm, 0)
|
|
||||||
# print("text_norm2: ",text_norm)
|
|
||||||
# self.text_norm = torch.LongTensor(text_norm)
|
|
||||||
|
|
||||||
self.text_norm = torch.LongTensor([0, 6, 0])
|
self.text_norm = torch.LongTensor([0, 6, 0])
|
||||||
self.audio_buffer = torch.zeros(1, 0)
|
self.audio_buffer = torch.zeros(1, 0)
|
||||||
self.prev_audio = np.zeros(1)
|
self.prev_audio = np.zeros(1)
|
||||||
@ -67,6 +57,7 @@ class VoiceChanger():
|
|||||||
|
|
||||||
def loadModel(self, config: str, pyTorch_model_file: str = None, onnx_model_file: str = None):
|
def loadModel(self, config: str, pyTorch_model_file: str = None, onnx_model_file: str = None):
|
||||||
self.settings.configFile = config
|
self.settings.configFile = config
|
||||||
|
self.hps = get_hparams_from_file(config)
|
||||||
if pyTorch_model_file != None:
|
if pyTorch_model_file != None:
|
||||||
self.settings.pyTorchModelFile = pyTorch_model_file
|
self.settings.pyTorchModelFile = pyTorch_model_file
|
||||||
if onnx_model_file:
|
if onnx_model_file:
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from voice_changer.VoiceChanger import VoiceChanger
|
from voice_changer.VoiceChanger import VoiceChanger
|
||||||
|
|
||||||
|
|
||||||
class VoiceChangerManager():
|
class VoiceChangerManager():
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance(cls):
|
def get_instance(cls):
|
||||||
if not hasattr(cls, "_instance"):
|
if not hasattr(cls, "_instance"):
|
||||||
cls._instance = cls()
|
cls._instance = cls()
|
||||||
|
cls._instance.voiceChanger = VoiceChanger()
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def loadModel(self, config, model, onnx_model):
|
def loadModel(self, config, model, onnx_model):
|
||||||
if hasattr(self, 'voiceChanger') == False:
|
|
||||||
self.voiceChanger = VoiceChanger(config)
|
|
||||||
info = self.voiceChanger.loadModel(config, model, onnx_model)
|
info = self.voiceChanger.loadModel(config, model, onnx_model)
|
||||||
info["status"] = "OK"
|
info["status"] = "OK"
|
||||||
return info
|
return info
|
||||||
|
Loading…
x
Reference in New Issue
Block a user