refactoring hooks
This commit is contained in:
parent
43fd0316ff
commit
ea3bcdcb18
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>
|
||||||
|
641
client/demo/dist/index.js
vendored
641
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.
|
|
||||||
*/
|
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { AUDIO_ELEMENT_FOR_PLAY_RESULT } from "./const";
|
import { AUDIO_ELEMENT_FOR_PLAY_RESULT } from "./const";
|
||||||
import { useServerSetting } from "./101_server_setting";
|
import { useServerSettingArea } from "./101_server_setting";
|
||||||
import { useDeviceSetting } from "./102_device_setting";
|
import { useDeviceSetting } from "./102_device_setting";
|
||||||
import { useConvertSetting } from "./104_convert_setting";
|
import { useConvertSetting } from "./104_convert_setting";
|
||||||
import { useAdvancedSetting } from "./105_advanced_setting";
|
import { useAdvancedSetting } from "./105_advanced_setting";
|
||||||
@ -17,7 +17,7 @@ export const useMicrophoneOptions = () => {
|
|||||||
audioOutputElementId: AUDIO_ELEMENT_FOR_PLAY_RESULT
|
audioOutputElementId: AUDIO_ELEMENT_FOR_PLAY_RESULT
|
||||||
})
|
})
|
||||||
|
|
||||||
const serverSetting = useServerSetting({ clientState })
|
const serverSetting = useServerSettingArea({ clientState })
|
||||||
const deviceSetting = useDeviceSetting(audioContext, { clientState })
|
const deviceSetting = useDeviceSetting(audioContext, { clientState })
|
||||||
const speakerSetting = useSpeakerSetting({ clientState })
|
const speakerSetting = useSpeakerSetting({ clientState })
|
||||||
const convertSetting = useConvertSetting({ clientState })
|
const convertSetting = useConvertSetting({ clientState })
|
||||||
|
@ -11,27 +11,24 @@ export type ServerSettingState = {
|
|||||||
serverSetting: JSX.Element;
|
serverSetting: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useServerSetting = (props: UseServerSettingProps): ServerSettingState => {
|
export const useServerSettingArea = (props: UseServerSettingProps): ServerSettingState => {
|
||||||
const mmvcServerUrlRow = useMemo(() => {
|
const mmvcServerUrlRow = useMemo(() => {
|
||||||
const onSetServerClicked = async () => {
|
const onSetServerClicked = async () => {
|
||||||
const input = document.getElementById("mmvc-server-url") as HTMLInputElement
|
const input = document.getElementById("mmvc-server-url") as HTMLInputElement
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setServerUrl(input.value)
|
||||||
...props.clientState.settingState,
|
|
||||||
mmvcServerUrl: input.value
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-1">MMVC Server</div>
|
<div className="body-item-title left-padding-1">MMVC Server</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="text" defaultValue={props.clientState.settingState.mmvcServerUrl} id="mmvc-server-url" className="body-item-input" />
|
<input type="text" defaultValue={props.clientState.clientSetting.setting.mmvcServerUrl} id="mmvc-server-url" className="body-item-input" />
|
||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
<div className="body-button" onClick={onSetServerClicked}>set</div>
|
<div className="body-button" onClick={onSetServerClicked}>set</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.mmvcServerUrl, props.clientState.clientSetting.setServerUrl])
|
||||||
|
|
||||||
const uploadeModelRow = useMemo(() => {
|
const uploadeModelRow = useMemo(() => {
|
||||||
const onPyTorchFileLoadClicked = async () => {
|
const onPyTorchFileLoadClicked = async () => {
|
||||||
@ -40,14 +37,14 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
alert("モデルファイルの拡張子はpthである必要があります。")
|
alert("モデルファイルの拡張子はpthである必要があります。")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFileUploadSetting({
|
||||||
...props.clientState.settingState,
|
...props.clientState.serverSetting.fileUploadSetting,
|
||||||
pyTorchModel: file
|
pyTorchModel: file
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onPyTorchFileClearClicked = () => {
|
const onPyTorchFileClearClicked = () => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFileUploadSetting({
|
||||||
...props.clientState.settingState,
|
...props.clientState.serverSetting.fileUploadSetting,
|
||||||
pyTorchModel: null
|
pyTorchModel: null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -57,14 +54,14 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
alert("モデルファイルの拡張子はjsonである必要があります。")
|
alert("モデルファイルの拡張子はjsonである必要があります。")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFileUploadSetting({
|
||||||
...props.clientState.settingState,
|
...props.clientState.serverSetting.fileUploadSetting,
|
||||||
configFile: file
|
configFile: file
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onConfigFileClearClicked = () => {
|
const onConfigFileClearClicked = () => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFileUploadSetting({
|
||||||
...props.clientState.settingState,
|
...props.clientState.serverSetting.fileUploadSetting,
|
||||||
configFile: null
|
configFile: null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -74,19 +71,19 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
alert("モデルファイルの拡張子はonnxである必要があります。")
|
alert("モデルファイルの拡張子はonnxである必要があります。")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFileUploadSetting({
|
||||||
...props.clientState.settingState,
|
...props.clientState.serverSetting.fileUploadSetting,
|
||||||
onnxModel: file
|
onnxModel: file
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onOnnxFileClearClicked = () => {
|
const onOnnxFileClearClicked = () => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFileUploadSetting({
|
||||||
...props.clientState.settingState,
|
...props.clientState.serverSetting.fileUploadSetting,
|
||||||
onnxModel: null
|
onnxModel: null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onModelUploadClicked = async () => {
|
const onModelUploadClicked = async () => {
|
||||||
props.clientState.loadModel()
|
props.clientState.serverSetting.loadModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -100,30 +97,30 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
|
||||||
<div className="body-item-title left-padding-2">PyTorch(.pth)</div>
|
|
||||||
<div className="body-item-text">
|
|
||||||
<div>{props.clientState.settingState.pyTorchModel?.name}</div>
|
|
||||||
</div>
|
|
||||||
<div className="body-button-container">
|
|
||||||
<div className="body-button" onClick={onPyTorchFileLoadClicked}>select</div>
|
|
||||||
<div className="body-button left-margin-1" onClick={onPyTorchFileClearClicked}>clear</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-2">Config(.json)</div>
|
<div className="body-item-title left-padding-2">Config(.json)</div>
|
||||||
<div className="body-item-text">
|
<div className="body-item-text">
|
||||||
<div>{props.clientState.settingState.configFile?.name}</div>
|
<div>{props.clientState.serverSetting.fileUploadSetting.configFile?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
<div className="body-button" onClick={onConfigFileLoadClicked}>select</div>
|
<div className="body-button" onClick={onConfigFileLoadClicked}>select</div>
|
||||||
<div className="body-button left-margin-1" onClick={onConfigFileClearClicked}>clear</div>
|
<div className="body-button left-margin-1" onClick={onConfigFileClearClicked}>clear</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
|
<div className="body-item-title left-padding-2">PyTorch(.pth)</div>
|
||||||
|
<div className="body-item-text">
|
||||||
|
<div>{props.clientState.serverSetting.fileUploadSetting.pyTorchModel?.name}</div>
|
||||||
|
</div>
|
||||||
|
<div className="body-button-container">
|
||||||
|
<div className="body-button" onClick={onPyTorchFileLoadClicked}>select</div>
|
||||||
|
<div className="body-button left-margin-1" onClick={onPyTorchFileClearClicked}>clear</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-2">Onnx(.onnx)</div>
|
<div className="body-item-title left-padding-2">Onnx(.onnx)</div>
|
||||||
<div className="body-item-text">
|
<div className="body-item-text">
|
||||||
<div>{props.clientState.settingState.onnxModel?.name}</div>
|
<div>{props.clientState.serverSetting.fileUploadSetting.onnxModel?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
<div className="body-button" onClick={onOnnxFileLoadClicked}>select</div>
|
<div className="body-button" onClick={onOnnxFileLoadClicked}>select</div>
|
||||||
@ -133,7 +130,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-2"></div>
|
<div className="body-item-title left-padding-2"></div>
|
||||||
<div className="body-item-text">
|
<div className="body-item-text">
|
||||||
{props.clientState.isUploading ? `uploading.... ${props.clientState.uploadProgress}%` : ""}
|
{props.clientState.serverSetting.isUploading ? `uploading.... ${props.clientState.serverSetting.uploadProgress}%` : ""}
|
||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
<div className="body-button" onClick={onModelUploadClicked}>upload</div>
|
<div className="body-button" onClick={onModelUploadClicked}>upload</div>
|
||||||
@ -142,23 +139,20 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}, [
|
}, [
|
||||||
props.clientState.settingState,
|
props.clientState.serverSetting.fileUploadSetting,
|
||||||
props.clientState.loadModel,
|
props.clientState.serverSetting.loadModel,
|
||||||
props.clientState.isUploading,
|
props.clientState.serverSetting.isUploading,
|
||||||
props.clientState.uploadProgress])
|
props.clientState.serverSetting.uploadProgress])
|
||||||
|
|
||||||
const protocolRow = useMemo(() => {
|
const protocolRow = useMemo(() => {
|
||||||
const onProtocolChanged = async (val: Protocol) => {
|
const onProtocolChanged = async (val: Protocol) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setProtocol(val)
|
||||||
...props.clientState.settingState,
|
|
||||||
protocol: val
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<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">Protocol</div>
|
<div className="body-item-title left-padding-1">Protocol</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.protocol} onChange={(e) => {
|
<select className="body-select" value={props.clientState.clientSetting.setting.protocol} onChange={(e) => {
|
||||||
onProtocolChanged(e.target.value as
|
onProtocolChanged(e.target.value as
|
||||||
Protocol)
|
Protocol)
|
||||||
}}>
|
}}>
|
||||||
@ -171,20 +165,17 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.protocol, props.clientState.clientSetting.setProtocol])
|
||||||
|
|
||||||
const frameworkRow = useMemo(() => {
|
const frameworkRow = useMemo(() => {
|
||||||
const onFrameworkChanged = async (val: Framework) => {
|
const onFrameworkChanged = async (val: Framework) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setFramework(val)
|
||||||
...props.clientState.settingState,
|
|
||||||
framework: val
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<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">Framework</div>
|
<div className="body-item-title left-padding-1">Framework</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.framework} onChange={(e) => {
|
<select className="body-select" value={props.clientState.serverSetting.setting.framework} onChange={(e) => {
|
||||||
onFrameworkChanged(e.target.value as
|
onFrameworkChanged(e.target.value as
|
||||||
Framework)
|
Framework)
|
||||||
}}>
|
}}>
|
||||||
@ -197,23 +188,20 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.framework, props.clientState.serverSetting.setFramework])
|
||||||
|
|
||||||
const onnxExecutionProviderRow = useMemo(() => {
|
const onnxExecutionProviderRow = useMemo(() => {
|
||||||
if (props.clientState.settingState.framework != "ONNX") {
|
if (props.clientState.serverSetting.setting.framework != "ONNX") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const onOnnxExecutionProviderChanged = async (val: OnnxExecutionProvider) => {
|
const onOnnxExecutionProviderChanged = async (val: OnnxExecutionProvider) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setOnnxExecutionProvider(val)
|
||||||
...props.clientState.settingState,
|
|
||||||
onnxExecutionProvider: val
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="body-row split-3-7 left-padding-1">
|
<div className="body-row split-3-7 left-padding-1">
|
||||||
<div className="body-item-title left-padding-2">OnnxExecutionProvider</div>
|
<div className="body-item-title left-padding-2">OnnxExecutionProvider</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.onnxExecutionProvider} onChange={(e) => {
|
<select className="body-select" value={props.clientState.serverSetting.setting.onnxExecutionProvider} onChange={(e) => {
|
||||||
onOnnxExecutionProviderChanged(e.target.value as
|
onOnnxExecutionProviderChanged(e.target.value as
|
||||||
OnnxExecutionProvider)
|
OnnxExecutionProvider)
|
||||||
}}>
|
}}>
|
||||||
@ -226,7 +214,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.onnxExecutionProvider, props.clientState.serverSetting.setOnnxExecutionProvider])
|
||||||
|
|
||||||
const serverSetting = useMemo(() => {
|
const serverSetting = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
|
@ -68,7 +68,9 @@ 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">AudioInput</div>
|
<div className="body-item-title left-padding-1">AudioInput</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={audioInputForGUI} onChange={(e) => { setAudioInputForGUI(e.target.value) }}>
|
<select className="body-select" value={audioInputForGUI} onChange={(e) => {
|
||||||
|
setAudioInputForGUI(e.target.value)
|
||||||
|
}}>
|
||||||
{
|
{
|
||||||
inputAudioDeviceInfo.map(x => {
|
inputAudioDeviceInfo.map(x => {
|
||||||
return <option key={x.deviceId} value={x.deviceId}>{x.label}</option>
|
return <option key={x.deviceId} value={x.deviceId}>{x.label}</option>
|
||||||
@ -85,21 +87,16 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
if (!audioContext) {
|
if (!audioContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioInputForGUI == "none") {
|
if (audioInputForGUI == "none") {
|
||||||
const ms = createDummyMediaStream(audioContext)
|
const ms = createDummyMediaStream(audioContext)
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setAudioInput(ms)
|
||||||
...props.clientState.settingState,
|
|
||||||
audioInput: ms
|
|
||||||
})
|
|
||||||
} else if (audioInputForGUI == "file") {
|
} else if (audioInputForGUI == "file") {
|
||||||
// file selector (audioMediaInputRow)
|
// file selector (audioMediaInputRow)
|
||||||
} else {
|
} else {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setAudioInput(audioInputForGUI)
|
||||||
...props.clientState.settingState,
|
|
||||||
audioInput: audioInputForGUI
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}, [audioContext, audioInputForGUI])
|
}, [audioContext, audioInputForGUI, props.clientState.clientSetting.setAudioInput])
|
||||||
|
|
||||||
const audioMediaInputRow = useMemo(() => {
|
const audioMediaInputRow = useMemo(() => {
|
||||||
if (audioInputForGUI != "file") {
|
if (audioInputForGUI != "file") {
|
||||||
@ -116,10 +113,7 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
const src = audioContext!.createMediaElementSource(audio);
|
const src = audioContext!.createMediaElementSource(audio);
|
||||||
const dst = audioContext!.createMediaStreamDestination()
|
const dst = audioContext!.createMediaStreamDestination()
|
||||||
src.connect(dst)
|
src.connect(dst)
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setAudioInput(dst.stream)
|
||||||
...props.clientState.settingState,
|
|
||||||
audioInput: dst.stream
|
|
||||||
})
|
|
||||||
// original stream to play.
|
// original stream to play.
|
||||||
const audio_org = document.getElementById(AUDIO_ELEMENT_FOR_TEST_ORIGINAL) as HTMLAudioElement
|
const audio_org = document.getElementById(AUDIO_ELEMENT_FOR_TEST_ORIGINAL) as HTMLAudioElement
|
||||||
audio_org.src = url
|
audio_org.src = url
|
||||||
@ -148,7 +142,7 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [audioInputForGUI])
|
}, [audioInputForGUI, props.clientState.clientSetting.setAudioInput])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -186,12 +180,8 @@ 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">Sample Rate</div>
|
<div className="body-item-title left-padding-1">Sample Rate</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.sampleRate} onChange={(e) => {
|
<select className="body-select" value={props.clientState.clientSetting.setting.sampleRate} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setSampleRate(Number(e.target.value) as SampleRate)
|
||||||
...props.clientState.settingState,
|
|
||||||
sampleRate: Number(e.target.value) as SampleRate
|
|
||||||
})
|
|
||||||
|
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
Object.values(SampleRate).map(x => {
|
Object.values(SampleRate).map(x => {
|
||||||
@ -202,9 +192,7 @@ export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDe
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.sampleRate, props.clientState.clientSetting.setSampleRate])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const deviceSetting = useMemo(() => {
|
const deviceSetting = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo } from "react"
|
import React, { useMemo, useState } from "react"
|
||||||
import { ClientState } from "./hooks/useClient"
|
import { ClientState } from "./hooks/useClient"
|
||||||
|
|
||||||
export type UseSpeakerSettingProps = {
|
export type UseSpeakerSettingProps = {
|
||||||
@ -6,20 +6,19 @@ export type UseSpeakerSettingProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
||||||
|
const [editSpeakerTargetId, setEditSpeakerTargetId] = useState<number>(0)
|
||||||
|
const [editSpeakerTargetName, setEditSpeakerTargetName] = useState<string>("")
|
||||||
|
|
||||||
const srcIdRow = useMemo(() => {
|
const srcIdRow = 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">
|
||||||
<div className="body-item-title left-padding-1">Source Speaker Id</div>
|
<div className="body-item-title left-padding-1">Source Speaker Id</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.srcId} onChange={(e) => {
|
<select className="body-select" value={props.clientState.serverSetting.setting.srcId} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setSrcId(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
srcId: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
props.clientState.settingState.speakers.map(x => {
|
props.clientState.clientSetting.setting.speakers.map(x => {
|
||||||
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
|
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -27,21 +26,18 @@ export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.speakers, props.clientState.serverSetting.setting.srcId, props.clientState.serverSetting.setSrcId])
|
||||||
|
|
||||||
const dstIdRow = useMemo(() => {
|
const dstIdRow = 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">
|
||||||
<div className="body-item-title left-padding-1">Destination Speaker Id</div>
|
<div className="body-item-title left-padding-1">Destination Speaker Id</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.dstId} onChange={(e) => {
|
<select className="body-select" value={props.clientState.serverSetting.setting.dstId} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setDstId(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
dstId: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
props.clientState.settingState.speakers.map(x => {
|
props.clientState.clientSetting.setting.speakers.map(x => {
|
||||||
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
|
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -49,38 +45,29 @@ export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.speakers, props.clientState.serverSetting.setting.dstId, props.clientState.serverSetting.setDstId])
|
||||||
|
|
||||||
const editSpeakerIdMappingRow = useMemo(() => {
|
const editSpeakerIdMappingRow = useMemo(() => {
|
||||||
const onSetSpeakerMappingClicked = async () => {
|
const onSetSpeakerMappingClicked = async () => {
|
||||||
const targetId = props.clientState.settingState.editSpeakerTargetId
|
const targetId = editSpeakerTargetId
|
||||||
const targetName = props.clientState.settingState.editSpeakerTargetName
|
const targetName = editSpeakerTargetName
|
||||||
const targetSpeaker = props.clientState.settingState.speakers.find(x => { return x.id == targetId })
|
const targetSpeaker = props.clientState.clientSetting.setting.speakers.find(x => { return x.id == targetId })
|
||||||
if (targetSpeaker) {
|
if (targetSpeaker) {
|
||||||
if (targetName.length == 0) { // Delete
|
if (targetName.length == 0) { // Delete
|
||||||
const newSpeakers = props.clientState.settingState.speakers.filter(x => { return x.id != targetId })
|
const newSpeakers = props.clientState.clientSetting.setting.speakers.filter(x => { return x.id != targetId })
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setSpeakers(newSpeakers)
|
||||||
...props.clientState.settingState,
|
|
||||||
speakers: newSpeakers
|
|
||||||
})
|
|
||||||
} else { // Update
|
} else { // Update
|
||||||
targetSpeaker.name = targetName
|
targetSpeaker.name = targetName
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setSpeakers([...props.clientState.clientSetting.setting.speakers])
|
||||||
...props.clientState.settingState,
|
|
||||||
speakers: props.clientState.settingState.speakers
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (targetName.length == 0) { // Noop
|
if (targetName.length == 0) { // Noop
|
||||||
} else {// add
|
} else {// add
|
||||||
props.clientState.settingState.speakers.push({
|
props.clientState.clientSetting.setting.speakers.push({
|
||||||
id: targetId,
|
id: targetId,
|
||||||
name: targetName
|
name: targetName
|
||||||
})
|
})
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setSpeakers([...props.clientState.clientSetting.setting.speakers])
|
||||||
...props.clientState.settingState,
|
|
||||||
speakers: props.clientState.settingState.speakers
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,21 +75,15 @@ export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
|||||||
<div className="body-row split-3-1-2-4 left-padding-1 guided">
|
<div className="body-row split-3-1-2-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-1">Edit Speaker Mapping</div>
|
<div className="body-item-title left-padding-1">Edit Speaker Mapping</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={1} max={256} step={1} value={props.clientState.settingState.editSpeakerTargetId} onChange={(e) => {
|
<input type="number" min={1} max={256} step={1} value={editSpeakerTargetId} onChange={(e) => {
|
||||||
const id = Number(e.target.value)
|
const id = Number(e.target.value)
|
||||||
props.clientState.setSettingState({
|
setEditSpeakerTargetId(id)
|
||||||
...props.clientState.settingState,
|
setEditSpeakerTargetName(props.clientState.clientSetting.setting.speakers.find(x => { return x.id == id })?.name || "")
|
||||||
editSpeakerTargetId: id,
|
|
||||||
editSpeakerTargetName: props.clientState.settingState.speakers.find(x => { return x.id == id })?.name || ""
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="text" value={props.clientState.settingState.editSpeakerTargetName} onChange={(e) => {
|
<input type="text" value={editSpeakerTargetName} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
setEditSpeakerTargetName(e.target.value)
|
||||||
...props.clientState.settingState,
|
|
||||||
editSpeakerTargetName: e.target.value
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
@ -110,7 +91,7 @@ export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.speakers, editSpeakerTargetId, editSpeakerTargetName])
|
||||||
|
|
||||||
|
|
||||||
const speakerSetting = useMemo(() => {
|
const speakerSetting = useMemo(() => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { DefaultVoiceChangerRequestParamas, DefaultVoiceChangerOptions, BufferSize } from "@dannadori/voice-changer-client-js"
|
import { BufferSize } from "@dannadori/voice-changer-client-js"
|
||||||
import React, { useMemo, useState } from "react"
|
import React, { useMemo, useState } from "react"
|
||||||
import { ClientState } from "./hooks/useClient"
|
import { ClientState } from "./hooks/useClient"
|
||||||
|
|
||||||
@ -18,11 +18,8 @@ export const useConvertSetting = (props: UseConvertSettingProps): ConvertSetting
|
|||||||
<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">Buffer Size</div>
|
<div className="body-item-title left-padding-1">Buffer Size</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.bufferSize} onChange={(e) => {
|
<select className="body-select" value={props.clientState.clientSetting.setting.bufferSize} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setBufferSize(Number(e.target.value) as BufferSize)
|
||||||
...props.clientState.settingState,
|
|
||||||
bufferSize: Number(e.target.value) as BufferSize
|
|
||||||
})
|
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
Object.values(BufferSize).map(x => {
|
Object.values(BufferSize).map(x => {
|
||||||
@ -33,23 +30,20 @@ export const useConvertSetting = (props: UseConvertSettingProps): ConvertSetting
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.bufferSize, props.clientState.clientSetting.setBufferSize])
|
||||||
|
|
||||||
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">
|
||||||
<div className="body-item-title left-padding-1">Input Chunk Num(128sample/chunk)</div>
|
<div className="body-item-title left-padding-1">Input Chunk Num(128sample/chunk)</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={1} max={256} step={1} value={props.clientState.settingState.inputChunkNum} onChange={(e) => {
|
<input type="number" min={1} max={256} step={1} value={props.clientState.clientSetting.setting.inputChunkNum} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setInputChunkNum(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
inputChunkNum: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.inputChunkNum, props.clientState.clientSetting.setInputChunkNum])
|
||||||
|
|
||||||
const convertChunkNumRow = useMemo(() => {
|
const convertChunkNumRow = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@ -57,80 +51,65 @@ export const useConvertSetting = (props: UseConvertSettingProps): ConvertSetting
|
|||||||
<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">Convert Chunk Num(128sample/chunk)</div>
|
<div className="body-item-title left-padding-1">Convert Chunk Num(128sample/chunk)</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={1} max={256} step={1} value={props.clientState.settingState.convertChunkNum} onChange={(e) => {
|
<input type="number" min={1} max={256} step={1} value={props.clientState.serverSetting.setting.convertChunkNum} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setConvertChunkNum(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
convertChunkNum: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.convertChunkNum, props.clientState.serverSetting.setConvertChunkNum])
|
||||||
|
|
||||||
const gpuRow = useMemo(() => {
|
const gpuRow = 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">
|
||||||
<div className="body-item-title left-padding-1">GPU</div>
|
<div className="body-item-title left-padding-1">GPU</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={-2} max={5} step={1} value={props.clientState.settingState.gpu} onChange={(e) => {
|
<input type="number" min={-2} max={5} step={1} value={props.clientState.serverSetting.setting.gpu} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setGpu(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
gpu: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.gpu, props.clientState.serverSetting.setGpu])
|
||||||
|
|
||||||
const crossFadeOverlapRateRow = useMemo(() => {
|
const crossFadeOverlapRateRow = 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">
|
||||||
<div className="body-item-title left-padding-1">Cross Fade Overlap Rate</div>
|
<div className="body-item-title left-padding-1">Cross Fade Overlap Rate</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={0.1} max={1} step={0.1} value={props.clientState.settingState.crossFadeOverlapRate} onChange={(e) => {
|
<input type="number" min={0.1} max={1} step={0.1} value={props.clientState.serverSetting.setting.crossFadeOverlapRate} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setCrossFadeOverlapRate(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
crossFadeOverlapRate: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.crossFadeOverlapRate, props.clientState.serverSetting.setCrossFadeOverlapRate])
|
||||||
|
|
||||||
const crossFadeOffsetRateRow = useMemo(() => {
|
const crossFadeOffsetRateRow = 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">
|
||||||
<div className="body-item-title left-padding-1">Cross Fade Offset Rate</div>
|
<div className="body-item-title left-padding-1">Cross Fade Offset Rate</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={0} max={1} step={0.1} value={props.clientState.settingState.crossFadeOffsetRate} onChange={(e) => {
|
<input type="number" min={0} max={1} step={0.1} value={props.clientState.serverSetting.setting.crossFadeOffsetRate} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setCrossFadeOffsetRate(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
crossFadeOffsetRate: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.crossFadeOffsetRate, props.clientState.serverSetting.setCrossFadeOffsetRate])
|
||||||
|
|
||||||
const crossFadeEndRateRow = useMemo(() => {
|
const crossFadeEndRateRow = 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">
|
||||||
<div className="body-item-title left-padding-1">Cross Fade End Rate</div>
|
<div className="body-item-title left-padding-1">Cross Fade End Rate</div>
|
||||||
<div className="body-input-container">
|
<div className="body-input-container">
|
||||||
<input type="number" min={0} max={1} step={0.1} value={props.clientState.settingState.crossFadeEndRate} onChange={(e) => {
|
<input type="number" min={0} max={1} step={0.1} value={props.clientState.serverSetting.setting.crossFadeEndRate} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.serverSetting.setCrossFadeEndRate(Number(e.target.value))
|
||||||
...props.clientState.settingState,
|
|
||||||
crossFadeEndRate: Number(e.target.value)
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.serverSetting.setting.crossFadeEndRate, props.clientState.serverSetting.setCrossFadeEndRate])
|
||||||
|
|
||||||
const convertSetting = useMemo(() => {
|
const convertSetting = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
|
@ -18,29 +18,23 @@ export const useAdvancedSetting = (props: UseAdvancedSettingProps): AdvancedSett
|
|||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-1 ">VF Disabled</div>
|
<div className="body-item-title left-padding-1 ">VF Disabled</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" checked={props.clientState.settingState.vfForceDisabled} onChange={(e) => {
|
<input type="checkbox" checked={props.clientState.clientSetting.setting.forceVfDisable} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setVfForceDisabled(e.target.checked)
|
||||||
...props.clientState.settingState,
|
|
||||||
vfForceDisabled: e.target.checked
|
|
||||||
})
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.forceVfDisable, props.clientState.clientSetting.setVfForceDisabled])
|
||||||
|
|
||||||
const voiceChangeModeRow = useMemo(() => {
|
const voiceChangeModeRow = 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">
|
||||||
<div className="body-item-title left-padding-1 ">Voice Change Mode</div>
|
<div className="body-item-title left-padding-1 ">Voice Change Mode</div>
|
||||||
<div className="body-select-container">
|
<div className="body-select-container">
|
||||||
<select className="body-select" value={props.clientState.settingState.voiceChangerMode} onChange={(e) => {
|
<select className="body-select" value={props.clientState.clientSetting.setting.voiceChangerMode} onChange={(e) => {
|
||||||
props.clientState.setSettingState({
|
props.clientState.clientSetting.setVoiceChangerMode(e.target.value as VoiceChangerMode)
|
||||||
...props.clientState.settingState,
|
|
||||||
voiceChangerMode: e.target.value as VoiceChangerMode
|
|
||||||
})
|
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
Object.values(VoiceChangerMode).map(x => {
|
Object.values(VoiceChangerMode).map(x => {
|
||||||
@ -51,7 +45,7 @@ export const useAdvancedSetting = (props: UseAdvancedSettingProps): AdvancedSett
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [props.clientState.settingState])
|
}, [props.clientState.clientSetting.setting.voiceChangerMode, props.clientState.clientSetting.setVoiceChangerMode])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,11 +11,11 @@ export const useServerControl = (props: UseServerControlProps) => {
|
|||||||
const startButtonRow = useMemo(() => {
|
const startButtonRow = useMemo(() => {
|
||||||
const onStartClicked = async () => {
|
const onStartClicked = async () => {
|
||||||
setIsStarted(true)
|
setIsStarted(true)
|
||||||
await props.clientState.start()
|
await props.clientState.clientSetting.start()
|
||||||
}
|
}
|
||||||
const onStopClicked = async () => {
|
const onStopClicked = async () => {
|
||||||
setIsStarted(false)
|
setIsStarted(false)
|
||||||
await props.clientState.stop()
|
await props.clientState.clientSetting.stop()
|
||||||
}
|
}
|
||||||
const startClassName = isStarted ? "body-button-active" : "body-button-stanby"
|
const startClassName = isStarted ? "body-button-active" : "body-button-stanby"
|
||||||
const stopClassName = isStarted ? "body-button-stanby" : "body-button-active"
|
const stopClassName = isStarted ? "body-button-stanby" : "body-button-active"
|
||||||
@ -32,7 +32,7 @@ export const useServerControl = (props: UseServerControlProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
)
|
)
|
||||||
}, [isStarted, props.clientState.start, props.clientState.stop])
|
}, [isStarted, props.clientState.clientSetting.start, props.clientState.clientSetting.stop])
|
||||||
|
|
||||||
const performanceRow = useMemo(() => {
|
const performanceRow = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@ -60,9 +60,9 @@ export const useServerControl = (props: UseServerControlProps) => {
|
|||||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||||
<div className="body-item-title left-padding-1">Model Info:</div>
|
<div className="body-item-title left-padding-1">Model Info:</div>
|
||||||
<div className="body-item-text">
|
<div className="body-item-text">
|
||||||
<span className="body-item-text-item">{props.clientState.serverInfo?.configFile || ""}</span>
|
<span className="body-item-text-item">{props.clientState.serverSetting.serverInfo?.configFile || ""}</span>
|
||||||
<span className="body-item-text-item">{props.clientState.serverInfo?.pyTorchModelFile || ""}</span>
|
<span className="body-item-text-item">{props.clientState.serverSetting.serverInfo?.pyTorchModelFile || ""}</span>
|
||||||
<span className="body-item-text-item">{props.clientState.serverInfo?.onnxModelFile || ""}</span>
|
<span className="body-item-text-item">{props.clientState.serverSetting.serverInfo?.onnxModelFile || ""}</span>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -72,7 +72,7 @@ export const useServerControl = (props: UseServerControlProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}, [props.clientState.getInfo, props.clientState.serverInfo])
|
}, [props.clientState.getInfo, props.clientState.serverSetting.serverInfo])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
export const CHROME_EXTENSION = false
|
export const CHROME_EXTENSION = false
|
||||||
|
|
||||||
|
|
||||||
export const AUDIO_ELEMENT_FOR_PLAY_RESULT = "audio-result"
|
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"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { ServerInfo, BufferSize, createDummyMediaStream, DefaultVoiceChangerOptions, DefaultVoiceChangerRequestParamas, Framework, OnnxExecutionProvider, Protocol, SampleRate, ServerSettingKey, Speaker, VoiceChangerMode, VoiceChangerClient } from "@dannadori/voice-changer-client-js"
|
import { VoiceChangerClient } from "@dannadori/voice-changer-client-js"
|
||||||
import { useEffect, useMemo, useRef, useState } from "react"
|
import { useEffect, useMemo, useRef, useState } from "react"
|
||||||
|
import { ClientSettingState, useClientSetting } from "./useClientSetting"
|
||||||
|
import { ServerSettingState, useServerSetting } from "./useServerSetting"
|
||||||
import { useWorkletSetting, WorkletSettingState } from "./useWorkletSetting"
|
import { useWorkletSetting, WorkletSettingState } from "./useWorkletSetting"
|
||||||
|
|
||||||
export type UseClientProps = {
|
export type UseClientProps = {
|
||||||
@ -7,123 +9,46 @@ export type UseClientProps = {
|
|||||||
audioOutputElementId: string
|
audioOutputElementId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SettingState = {
|
|
||||||
// server setting
|
|
||||||
mmvcServerUrl: string
|
|
||||||
pyTorchModel: File | null
|
|
||||||
configFile: File | null
|
|
||||||
onnxModel: File | null
|
|
||||||
protocol: Protocol
|
|
||||||
framework: Framework
|
|
||||||
onnxExecutionProvider: OnnxExecutionProvider
|
|
||||||
|
|
||||||
// device setting
|
|
||||||
audioInput: string | MediaStream | null;
|
|
||||||
sampleRate: SampleRate;
|
|
||||||
|
|
||||||
// speaker setting
|
|
||||||
speakers: Speaker[]
|
|
||||||
editSpeakerTargetId: number
|
|
||||||
editSpeakerTargetName: string
|
|
||||||
srcId: number
|
|
||||||
dstId: number
|
|
||||||
|
|
||||||
// convert setting
|
|
||||||
bufferSize: BufferSize
|
|
||||||
inputChunkNum: number
|
|
||||||
convertChunkNum: number
|
|
||||||
gpu: number
|
|
||||||
crossFadeOffsetRate: number
|
|
||||||
crossFadeEndRate: number
|
|
||||||
crossFadeOverlapRate: number
|
|
||||||
|
|
||||||
// advanced setting
|
|
||||||
vfForceDisabled: boolean
|
|
||||||
voiceChangerMode: VoiceChangerMode
|
|
||||||
}
|
|
||||||
|
|
||||||
const InitialSettingState: SettingState = {
|
|
||||||
mmvcServerUrl: DefaultVoiceChangerOptions.mmvcServerUrl,
|
|
||||||
pyTorchModel: null,
|
|
||||||
configFile: null,
|
|
||||||
onnxModel: null,
|
|
||||||
protocol: DefaultVoiceChangerOptions.protocol,
|
|
||||||
framework: DefaultVoiceChangerOptions.framework,
|
|
||||||
onnxExecutionProvider: DefaultVoiceChangerOptions.onnxExecutionProvider,
|
|
||||||
|
|
||||||
audioInput: "none",
|
|
||||||
sampleRate: DefaultVoiceChangerOptions.sampleRate,
|
|
||||||
|
|
||||||
speakers: DefaultVoiceChangerOptions.speakers,
|
|
||||||
editSpeakerTargetId: 0,
|
|
||||||
editSpeakerTargetName: "",
|
|
||||||
srcId: DefaultVoiceChangerRequestParamas.srcId,
|
|
||||||
dstId: DefaultVoiceChangerRequestParamas.dstId,
|
|
||||||
|
|
||||||
bufferSize: DefaultVoiceChangerOptions.bufferSize,
|
|
||||||
inputChunkNum: DefaultVoiceChangerOptions.inputChunkNum,
|
|
||||||
convertChunkNum: DefaultVoiceChangerRequestParamas.convertChunkNum,
|
|
||||||
gpu: DefaultVoiceChangerRequestParamas.gpu,
|
|
||||||
crossFadeOffsetRate: DefaultVoiceChangerRequestParamas.crossFadeOffsetRate,
|
|
||||||
crossFadeEndRate: DefaultVoiceChangerRequestParamas.crossFadeEndRate,
|
|
||||||
crossFadeOverlapRate: DefaultVoiceChangerRequestParamas.crossFadeOverlapRate,
|
|
||||||
|
|
||||||
vfForceDisabled: DefaultVoiceChangerOptions.forceVfDisable,
|
|
||||||
voiceChangerMode: DefaultVoiceChangerOptions.voiceChangerMode
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ClientState = {
|
export type ClientState = {
|
||||||
clientInitialized: boolean
|
workletSetting: WorkletSettingState
|
||||||
|
clientSetting: ClientSettingState
|
||||||
|
serverSetting: ServerSettingState
|
||||||
|
|
||||||
bufferingTime: number;
|
bufferingTime: number;
|
||||||
responseTime: number;
|
responseTime: number;
|
||||||
volume: number;
|
volume: number;
|
||||||
uploadProgress: number;
|
|
||||||
isUploading: boolean
|
|
||||||
|
|
||||||
// Setting
|
|
||||||
settingState: SettingState
|
|
||||||
serverInfo: ServerInfo | undefined
|
|
||||||
setSettingState: (setting: SettingState) => void
|
|
||||||
|
|
||||||
// Client Control
|
|
||||||
loadModel: () => Promise<void>
|
|
||||||
start: () => Promise<void>;
|
|
||||||
stop: () => Promise<void>;
|
|
||||||
getInfo: () => Promise<void>
|
getInfo: () => Promise<void>
|
||||||
|
|
||||||
|
|
||||||
workletSetting: WorkletSettingState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useClient = (props: UseClientProps): ClientState => {
|
export const useClient = (props: UseClientProps): ClientState => {
|
||||||
|
|
||||||
// (1) クライアント初期化
|
// (1-1) クライアント
|
||||||
const voiceChangerClientRef = useRef<VoiceChangerClient | null>(null)
|
const voiceChangerClientRef = useRef<VoiceChangerClient | null>(null)
|
||||||
const [voiceChangerClient, setVoiceChangerClient] = useState<VoiceChangerClient | null>(voiceChangerClientRef.current)
|
const [voiceChangerClient, setVoiceChangerClient] = useState<VoiceChangerClient | null>(voiceChangerClientRef.current)
|
||||||
const workletSetting = useWorkletSetting({ voiceChangerClient })
|
//// クライアント初期化待ち用フラグ
|
||||||
const [clientInitialized, setClientInitialized] = useState<boolean>(false)
|
|
||||||
const initializedResolveRef = useRef<(value: void | PromiseLike<void>) => void>()
|
const initializedResolveRef = useRef<(value: void | PromiseLike<void>) => void>()
|
||||||
const initializedPromise = useMemo(() => {
|
const initializedPromise = useMemo(() => {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
initializedResolveRef.current = resolve
|
initializedResolveRef.current = resolve
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
// (1-2) 各種設定
|
||||||
|
const clientSetting = useClientSetting({ voiceChangerClient, audioContext: props.audioContext })
|
||||||
|
const workletSetting = useWorkletSetting({ voiceChangerClient })
|
||||||
|
const serverSetting = useServerSetting({ voiceChangerClient })
|
||||||
|
|
||||||
|
// (1-3) ステータス
|
||||||
const [bufferingTime, setBufferingTime] = useState<number>(0)
|
const [bufferingTime, setBufferingTime] = useState<number>(0)
|
||||||
const [responseTime, setResponseTime] = useState<number>(0)
|
const [responseTime, setResponseTime] = useState<number>(0)
|
||||||
const [volume, setVolume] = useState<number>(0)
|
const [volume, setVolume] = useState<number>(0)
|
||||||
|
|
||||||
|
|
||||||
// Colab対応
|
// (2-1) 初期化処理
|
||||||
useEffect(() => {
|
|
||||||
const params = new URLSearchParams(location.search);
|
|
||||||
const colab = params.get("colab")
|
|
||||||
if (colab == "true") {
|
|
||||||
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initialized = async () => {
|
const initialized = async () => {
|
||||||
if (!props.audioContext) {
|
if (!props.audioContext) {
|
||||||
@ -151,7 +76,6 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
voiceChangerClientRef.current = voiceChangerClient
|
voiceChangerClientRef.current = voiceChangerClient
|
||||||
setVoiceChangerClient(voiceChangerClientRef.current)
|
setVoiceChangerClient(voiceChangerClientRef.current)
|
||||||
console.log("[useClient] client initialized")
|
console.log("[useClient] client initialized")
|
||||||
setClientInitialized(true)
|
|
||||||
|
|
||||||
const audio = document.getElementById(props.audioOutputElementId) as HTMLAudioElement
|
const audio = document.getElementById(props.audioOutputElementId) as HTMLAudioElement
|
||||||
audio.srcObject = voiceChangerClientRef.current.stream
|
audio.srcObject = voiceChangerClientRef.current.stream
|
||||||
@ -162,282 +86,26 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
}, [props.audioContext])
|
}, [props.audioContext])
|
||||||
|
|
||||||
|
|
||||||
|
// (2-2) 情報リロード
|
||||||
// (2) 設定
|
|
||||||
const [settingState, setSettingState] = useState<SettingState>(InitialSettingState)
|
|
||||||
const [displaySettingState, setDisplaySettingState] = useState<SettingState>(InitialSettingState)
|
|
||||||
const [serverInfo, setServerInfo] = useState<ServerInfo>()
|
|
||||||
const [uploadProgress, setUploadProgress] = useState<number>(0)
|
|
||||||
const [isUploading, setIsUploading] = useState<boolean>(false)
|
|
||||||
|
|
||||||
// (2-1) server setting
|
|
||||||
// (a) サーバURL設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
voiceChangerClientRef.current!.setServerUrl(settingState.mmvcServerUrl, true)
|
|
||||||
voiceChangerClientRef.current!.stop()
|
|
||||||
getInfo()
|
|
||||||
|
|
||||||
})()
|
|
||||||
}, [settingState.mmvcServerUrl])
|
|
||||||
// (b) プロトコル設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
voiceChangerClientRef.current!.setProtocol(settingState.protocol)
|
|
||||||
})()
|
|
||||||
}, [settingState.protocol])
|
|
||||||
// (c) フレームワーク設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.framework, "" + settingState.framework)
|
|
||||||
setServerInfo(info)
|
|
||||||
|
|
||||||
})()
|
|
||||||
}, [settingState.framework])
|
|
||||||
// (d) OnnxExecutionProvider設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.onnxExecutionProvider, settingState.onnxExecutionProvider)
|
|
||||||
setServerInfo(info)
|
|
||||||
|
|
||||||
})()
|
|
||||||
}, [settingState.onnxExecutionProvider])
|
|
||||||
|
|
||||||
// (e) モデルアップロード
|
|
||||||
const uploadFile = useMemo(() => {
|
|
||||||
return async (file: File, onprogress: (progress: number, end: boolean) => void) => {
|
|
||||||
await initializedPromise
|
|
||||||
const num = await voiceChangerClientRef.current!.uploadFile(file, onprogress)
|
|
||||||
const res = await voiceChangerClientRef.current!.concatUploadedFile(file, num)
|
|
||||||
console.log("uploaded", num, res)
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
const loadModel = useMemo(() => {
|
|
||||||
return async () => {
|
|
||||||
if (!settingState.pyTorchModel && !settingState.onnxModel) {
|
|
||||||
alert("PyTorchモデルとONNXモデルのどちらか一つ以上指定する必要があります。")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!settingState.configFile) {
|
|
||||||
alert("Configファイルを指定する必要があります。")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await initializedPromise
|
|
||||||
setUploadProgress(0)
|
|
||||||
setIsUploading(true)
|
|
||||||
const models = [settingState.pyTorchModel, settingState.onnxModel].filter(x => { return x != null }) as File[]
|
|
||||||
for (let i = 0; i < models.length; i++) {
|
|
||||||
const progRate = 1 / models.length
|
|
||||||
const progOffset = 100 * i * progRate
|
|
||||||
await uploadFile(models[i], (progress: number, end: boolean) => {
|
|
||||||
// console.log(progress * progRate + progOffset, end, progRate,)
|
|
||||||
setUploadProgress(progress * progRate + progOffset)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
await uploadFile(settingState.configFile, (progress: number, end: boolean) => {
|
|
||||||
console.log(progress, end)
|
|
||||||
})
|
|
||||||
|
|
||||||
const serverInfo = await voiceChangerClientRef.current!.loadModel(settingState.configFile, settingState.pyTorchModel, settingState.onnxModel)
|
|
||||||
console.log(serverInfo)
|
|
||||||
setUploadProgress(0)
|
|
||||||
setIsUploading(false)
|
|
||||||
}
|
|
||||||
}, [settingState.pyTorchModel, settingState.onnxModel, settingState.configFile])
|
|
||||||
|
|
||||||
// (2-2) device setting
|
|
||||||
// (a) インプット設定。audio nodes の設定の都合上、バッファサイズの変更も併せて反映させる。
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
if (!settingState.audioInput || settingState.audioInput == "none") {
|
|
||||||
console.log("[useClient] setup!(1)", settingState.audioInput)
|
|
||||||
const ms = createDummyMediaStream(props.audioContext!)
|
|
||||||
await voiceChangerClientRef.current!.setup(ms, settingState.bufferSize, settingState.vfForceDisabled)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.log("[useClient] setup!(2)", settingState.audioInput)
|
|
||||||
await voiceChangerClientRef.current!.setup(settingState.audioInput, settingState.bufferSize, settingState.vfForceDisabled)
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
}, [settingState.audioInput, settingState.bufferSize, settingState.vfForceDisabled])
|
|
||||||
|
|
||||||
|
|
||||||
// (2-3) speaker setting
|
|
||||||
// (a) srcId設定。
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.srcId, "" + settingState.srcId)
|
|
||||||
setServerInfo(info)
|
|
||||||
|
|
||||||
})()
|
|
||||||
}, [settingState.srcId])
|
|
||||||
|
|
||||||
// (b) dstId設定。
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.dstId, "" + settingState.dstId)
|
|
||||||
setServerInfo(info)
|
|
||||||
|
|
||||||
})()
|
|
||||||
}, [settingState.dstId])
|
|
||||||
|
|
||||||
|
|
||||||
// (2-4) convert setting
|
|
||||||
// (a) input chunk num設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
voiceChangerClientRef.current!.setInputChunkNum(settingState.inputChunkNum)
|
|
||||||
})()
|
|
||||||
}, [settingState.inputChunkNum])
|
|
||||||
|
|
||||||
// (b) convert chunk num設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.convertChunkNum, "" + settingState.convertChunkNum)
|
|
||||||
setServerInfo(info)
|
|
||||||
})()
|
|
||||||
}, [settingState.convertChunkNum])
|
|
||||||
|
|
||||||
// (c) gpu設定
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.gpu, "" + settingState.gpu)
|
|
||||||
setServerInfo(info)
|
|
||||||
})()
|
|
||||||
}, [settingState.gpu])
|
|
||||||
|
|
||||||
// (d) crossfade設定1
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.crossFadeOffsetRate, "" + settingState.crossFadeOffsetRate)
|
|
||||||
setServerInfo(info)
|
|
||||||
})()
|
|
||||||
}, [settingState.crossFadeOffsetRate])
|
|
||||||
|
|
||||||
// (e) crossfade設定2
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.crossFadeEndRate, "" + settingState.crossFadeEndRate)
|
|
||||||
setServerInfo(info)
|
|
||||||
})()
|
|
||||||
}, [settingState.crossFadeEndRate])
|
|
||||||
|
|
||||||
// (f) crossfade設定3
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
const info = await voiceChangerClientRef.current!.updateServerSettings(ServerSettingKey.crossFadeOverlapRate, "" + settingState.crossFadeOverlapRate)
|
|
||||||
setServerInfo(info)
|
|
||||||
})()
|
|
||||||
}, [settingState.crossFadeOverlapRate])
|
|
||||||
|
|
||||||
|
|
||||||
// (2-5) advanced setting
|
|
||||||
//// VFDisableはinput設定で合わせて設定。
|
|
||||||
// (a) voice changer mode
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
await initializedPromise
|
|
||||||
voiceChangerClientRef.current!.setVoiceChangerMode(settingState.voiceChangerMode)
|
|
||||||
voiceChangerClientRef.current!.stop()
|
|
||||||
})()
|
|
||||||
}, [settingState.voiceChangerMode])
|
|
||||||
|
|
||||||
// (2-6) server control
|
|
||||||
// (1) start
|
|
||||||
const start = useMemo(() => {
|
|
||||||
return async () => {
|
|
||||||
await initializedPromise
|
|
||||||
voiceChangerClientRef.current!.setServerUrl(settingState.mmvcServerUrl, true)
|
|
||||||
voiceChangerClientRef.current!.start()
|
|
||||||
}
|
|
||||||
}, [settingState.mmvcServerUrl])
|
|
||||||
// (2) stop
|
|
||||||
const stop = useMemo(() => {
|
|
||||||
return async () => {
|
|
||||||
await initializedPromise
|
|
||||||
voiceChangerClientRef.current!.stop()
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// (3) get info
|
|
||||||
const getInfo = useMemo(() => {
|
const getInfo = useMemo(() => {
|
||||||
return async () => {
|
return async () => {
|
||||||
await initializedPromise
|
await initializedPromise
|
||||||
const serverSettings = await voiceChangerClientRef.current!.getServerSettings()
|
await clientSetting.reloadClientSetting()
|
||||||
const clientSettings = await voiceChangerClientRef.current!.getClientSettings()
|
await serverSetting.reloadServerInfo()
|
||||||
setServerInfo(serverSettings)
|
|
||||||
console.log(serverSettings, clientSettings)
|
|
||||||
}
|
}
|
||||||
}, [])
|
}, [clientSetting, serverSetting])
|
||||||
|
|
||||||
// (x)
|
|
||||||
useEffect(() => {
|
|
||||||
if (serverInfo && serverInfo.status == "OK") {
|
|
||||||
setDisplaySettingState({
|
|
||||||
...settingState,
|
|
||||||
convertChunkNum: serverInfo.convertChunkNum,
|
|
||||||
crossFadeOffsetRate: serverInfo.crossFadeOffsetRate,
|
|
||||||
crossFadeEndRate: serverInfo.crossFadeEndRate,
|
|
||||||
gpu: serverInfo.gpu,
|
|
||||||
srcId: serverInfo.srcId,
|
|
||||||
dstId: serverInfo.dstId,
|
|
||||||
framework: serverInfo.framework,
|
|
||||||
onnxExecutionProvider: !!serverInfo.providers && serverInfo.providers.length > 0 ? serverInfo.providers[0] as OnnxExecutionProvider : "CPUExecutionProvider"
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
setDisplaySettingState({
|
|
||||||
...settingState,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [settingState, serverInfo])
|
|
||||||
|
|
||||||
|
|
||||||
// Colab対応
|
|
||||||
useEffect(() => {
|
|
||||||
const params = new URLSearchParams(location.search);
|
|
||||||
const colab = params.get("colab")
|
|
||||||
if (colab == "true") {
|
|
||||||
setSettingState({
|
|
||||||
...settingState,
|
|
||||||
protocol: "rest",
|
|
||||||
inputChunkNum: 64
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
clientInitialized,
|
|
||||||
bufferingTime,
|
bufferingTime,
|
||||||
responseTime,
|
responseTime,
|
||||||
volume,
|
volume,
|
||||||
uploadProgress,
|
|
||||||
isUploading,
|
|
||||||
|
|
||||||
settingState: displaySettingState,
|
|
||||||
serverInfo,
|
|
||||||
setSettingState,
|
|
||||||
loadModel,
|
|
||||||
start,
|
|
||||||
stop,
|
|
||||||
getInfo,
|
getInfo,
|
||||||
|
|
||||||
workletSetting
|
clientSetting,
|
||||||
|
workletSetting,
|
||||||
|
serverSetting,
|
||||||
}
|
}
|
||||||
}
|
}
|
184
client/demo/src/hooks/useClientSetting.ts
Normal file
184
client/demo/src/hooks/useClientSetting.ts
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import { BufferSize, createDummyMediaStream, DefaultVoiceChangerClientSetting, Protocol, SampleRate, Speaker, VoiceChangerClient, VoiceChangerClientSetting, VoiceChangerMode } from "@dannadori/voice-changer-client-js"
|
||||||
|
import { useState, useMemo, useRef, useEffect } from "react"
|
||||||
|
|
||||||
|
export type UseClientSettingProps = {
|
||||||
|
voiceChangerClient: VoiceChangerClient | null
|
||||||
|
audioContext: AudioContext | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ClientSettingState = {
|
||||||
|
setting: VoiceChangerClientSetting;
|
||||||
|
setServerUrl: (url: string) => void;
|
||||||
|
setProtocol: (proto: Protocol) => void;
|
||||||
|
setAudioInput: (audioInput: string | MediaStream | null) => Promise<void>
|
||||||
|
setBufferSize: (bufferSize: BufferSize) => Promise<void>
|
||||||
|
setVfForceDisabled: (vfForceDisabled: boolean) => Promise<void>
|
||||||
|
setInputChunkNum: (num: number) => void;
|
||||||
|
setVoiceChangerMode: (mode: VoiceChangerMode) => void
|
||||||
|
setSampleRate: (num: SampleRate) => void
|
||||||
|
setSpeakers: (speakers: Speaker[]) => void
|
||||||
|
|
||||||
|
start: () => Promise<void>
|
||||||
|
stop: () => Promise<void>
|
||||||
|
reloadClientSetting: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useClientSetting = (props: UseClientSettingProps): ClientSettingState => {
|
||||||
|
const settingRef = useRef<VoiceChangerClientSetting>(DefaultVoiceChangerClientSetting)
|
||||||
|
const [setting, _setSetting] = useState<VoiceChangerClientSetting>(settingRef.current)
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// 設定
|
||||||
|
/////////////
|
||||||
|
const setServerUrl = useMemo(() => {
|
||||||
|
return (url: string) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.setServerUrl(url)
|
||||||
|
settingRef.current.mmvcServerUrl = url
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setProtocol = useMemo(() => {
|
||||||
|
return (proto: Protocol) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.setProtocol(proto)
|
||||||
|
settingRef.current.protocol = proto
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const _setInput = async () => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
|
||||||
|
if (!settingRef.current.audioInput || settingRef.current.audioInput == "none") {
|
||||||
|
console.log("[useClient] setup!(1)", settingRef.current.audioInput)
|
||||||
|
const ms = createDummyMediaStream(props.audioContext!)
|
||||||
|
await props.voiceChangerClient.setup(ms, settingRef.current.bufferSize, settingRef.current.forceVfDisable)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log("[useClient] setup!(2)", settingRef.current.audioInput)
|
||||||
|
await props.voiceChangerClient.setup(settingRef.current.audioInput, settingRef.current.bufferSize, settingRef.current.forceVfDisable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setAudioInput = useMemo(() => {
|
||||||
|
return async (audioInput: string | MediaStream | null) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
settingRef.current.audioInput = audioInput
|
||||||
|
await _setInput()
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setBufferSize = useMemo(() => {
|
||||||
|
return async (bufferSize: BufferSize) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
settingRef.current.bufferSize = bufferSize
|
||||||
|
await _setInput()
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setVfForceDisabled = useMemo(() => {
|
||||||
|
return async (vfForceDisabled: boolean) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
settingRef.current.forceVfDisable = vfForceDisabled
|
||||||
|
await _setInput()
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setInputChunkNum = useMemo(() => {
|
||||||
|
return (num: number) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.setInputChunkNum(num)
|
||||||
|
settingRef.current.inputChunkNum = num
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setVoiceChangerMode = useMemo(() => {
|
||||||
|
return (mode: VoiceChangerMode) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.setVoiceChangerMode(mode)
|
||||||
|
settingRef.current.voiceChangerMode = mode
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setSampleRate = useMemo(() => {
|
||||||
|
return (num: SampleRate) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
//props.voiceChangerClient.setSampleRate(num) // Not Implemented
|
||||||
|
settingRef.current.sampleRate = num
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setSpeakers = useMemo(() => {
|
||||||
|
return (speakers: Speaker[]) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
settingRef.current.speakers = speakers
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// 操作
|
||||||
|
/////////////
|
||||||
|
// (1) start
|
||||||
|
const start = useMemo(() => {
|
||||||
|
return async () => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.setServerUrl(setting.mmvcServerUrl, true)
|
||||||
|
props.voiceChangerClient.start()
|
||||||
|
}
|
||||||
|
}, [setting.mmvcServerUrl, props.voiceChangerClient])
|
||||||
|
// (2) stop
|
||||||
|
const stop = useMemo(() => {
|
||||||
|
return async () => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
props.voiceChangerClient.stop()
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
const reloadClientSetting = useMemo(() => {
|
||||||
|
return async () => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
await props.voiceChangerClient.getClientSettings()
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// Colab対応
|
||||||
|
/////////////
|
||||||
|
useEffect(() => {
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const colab = params.get("colab")
|
||||||
|
if (colab == "true") {
|
||||||
|
settingRef.current.protocol = "rest"
|
||||||
|
settingRef.current.inputChunkNum = 64
|
||||||
|
_setSetting({ ...settingRef.current })
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
setting,
|
||||||
|
setServerUrl,
|
||||||
|
setProtocol,
|
||||||
|
setAudioInput,
|
||||||
|
setBufferSize,
|
||||||
|
setVfForceDisabled,
|
||||||
|
setInputChunkNum,
|
||||||
|
setVoiceChangerMode,
|
||||||
|
setSampleRate,
|
||||||
|
setSpeakers,
|
||||||
|
|
||||||
|
start,
|
||||||
|
stop,
|
||||||
|
reloadClientSetting
|
||||||
|
}
|
||||||
|
}
|
217
client/demo/src/hooks/useServerSetting.ts
Normal file
217
client/demo/src/hooks/useServerSetting.ts
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
import { DefaultVoiceChangerServerSetting, Framework, OnnxExecutionProvider, ServerInfo, ServerSettingKey, VoiceChangerClient, VoiceChangerServerSetting, } from "@dannadori/voice-changer-client-js"
|
||||||
|
import { useState, useMemo, useRef, } from "react"
|
||||||
|
|
||||||
|
|
||||||
|
export type FileUploadSetting = {
|
||||||
|
pyTorchModel: File | null
|
||||||
|
configFile: File | null
|
||||||
|
onnxModel: File | null
|
||||||
|
}
|
||||||
|
const InitialFileUploadSetting: FileUploadSetting = {
|
||||||
|
pyTorchModel: null,
|
||||||
|
configFile: null,
|
||||||
|
onnxModel: null,
|
||||||
|
}
|
||||||
|
export type UseServerSettingProps = {
|
||||||
|
voiceChangerClient: VoiceChangerClient | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ServerSettingState = {
|
||||||
|
setting: VoiceChangerServerSetting;
|
||||||
|
serverInfo: ServerInfo | undefined;
|
||||||
|
fileUploadSetting: FileUploadSetting
|
||||||
|
setFramework: (framework: Framework) => Promise<boolean>;
|
||||||
|
setOnnxExecutionProvider: (provider: OnnxExecutionProvider) => Promise<boolean>;
|
||||||
|
setSrcId: (num: number) => Promise<boolean>;
|
||||||
|
setDstId: (num: number) => Promise<boolean>;
|
||||||
|
setConvertChunkNum: (num: number) => Promise<boolean>;
|
||||||
|
setGpu: (num: number) => Promise<boolean>;
|
||||||
|
setCrossFadeOffsetRate: (num: number) => Promise<boolean>;
|
||||||
|
setCrossFadeEndRate: (num: number) => Promise<boolean>;
|
||||||
|
setCrossFadeOverlapRate: (num: number) => Promise<boolean>;
|
||||||
|
reloadServerInfo: () => Promise<void>;
|
||||||
|
setFileUploadSetting: (val: FileUploadSetting) => void
|
||||||
|
loadModel: () => Promise<void>
|
||||||
|
uploadProgress: number
|
||||||
|
isUploading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useServerSetting = (props: UseServerSettingProps): ServerSettingState => {
|
||||||
|
const settingRef = useRef<VoiceChangerServerSetting>(DefaultVoiceChangerServerSetting)
|
||||||
|
const [setting, _setSetting] = useState<VoiceChangerServerSetting>(settingRef.current)
|
||||||
|
const [serverInfo, _setServerInfo] = useState<ServerInfo>()
|
||||||
|
const [fileUploadSetting, setFileUploadSetting] = useState<FileUploadSetting>(InitialFileUploadSetting)
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// 設定
|
||||||
|
/////////////
|
||||||
|
//// サーバに設定後、反映された情報と照合して値が一致していることを確認。一致していない場合はalert
|
||||||
|
const _set_and_store = async (key: ServerSettingKey, newVal: string) => {
|
||||||
|
if (!props.voiceChangerClient) return false
|
||||||
|
|
||||||
|
const res = await props.voiceChangerClient.updateServerSettings(key, "" + newVal)
|
||||||
|
|
||||||
|
_setServerInfo(res)
|
||||||
|
if (newVal == res[key]) {
|
||||||
|
_setSetting({
|
||||||
|
...settingRef.current,
|
||||||
|
convertChunkNum: res.convertChunkNum,
|
||||||
|
srcId: res.srcId,
|
||||||
|
dstId: res.dstId,
|
||||||
|
gpu: res.gpu,
|
||||||
|
crossFadeOffsetRate: res.crossFadeOffsetRate,
|
||||||
|
crossFadeEndRate: res.crossFadeEndRate,
|
||||||
|
crossFadeOverlapRate: res.crossFadeOverlapRate,
|
||||||
|
framework: res.framework,
|
||||||
|
onnxExecutionProvider: (!!res.onnxExecutionProvider && res.onnxExecutionProvider.length > 0) ? res.onnxExecutionProvider[0] as OnnxExecutionProvider : DefaultVoiceChangerServerSetting.onnxExecutionProvider
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
alert(`[ServerSetting] setting failed. [key:${key}, new:${newVal}, res:${res[key]}]`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFramework = useMemo(() => {
|
||||||
|
return async (framework: Framework) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.framework, "" + framework)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setOnnxExecutionProvider = useMemo(() => {
|
||||||
|
return async (provider: OnnxExecutionProvider) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.onnxExecutionProvider, "" + provider)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setSrcId = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.srcId, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setDstId = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.dstId, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setConvertChunkNum = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.convertChunkNum, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setGpu = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.gpu, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
const setCrossFadeOffsetRate = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.crossFadeOffsetRate, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
const setCrossFadeEndRate = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.crossFadeEndRate, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
const setCrossFadeOverlapRate = useMemo(() => {
|
||||||
|
return async (num: number) => {
|
||||||
|
return await _set_and_store(ServerSettingKey.crossFadeOverlapRate, "" + num)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// 操作
|
||||||
|
/////////////
|
||||||
|
const [uploadProgress, setUploadProgress] = useState<number>(0)
|
||||||
|
const [isUploading, setIsUploading] = useState<boolean>(false)
|
||||||
|
|
||||||
|
// (e) モデルアップロード
|
||||||
|
const _uploadFile = useMemo(() => {
|
||||||
|
return async (file: File, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
const num = await props.voiceChangerClient.uploadFile(file, onprogress)
|
||||||
|
const res = await props.voiceChangerClient.concatUploadedFile(file, num)
|
||||||
|
console.log("uploaded", num, res)
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
const loadModel = useMemo(() => {
|
||||||
|
return async () => {
|
||||||
|
if (!fileUploadSetting.pyTorchModel && !fileUploadSetting.onnxModel) {
|
||||||
|
alert("PyTorchモデルとONNXモデルのどちらか一つ以上指定する必要があります。")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!fileUploadSetting.configFile) {
|
||||||
|
alert("Configファイルを指定する必要があります。")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
setUploadProgress(0)
|
||||||
|
setIsUploading(true)
|
||||||
|
const models = [fileUploadSetting.pyTorchModel, fileUploadSetting.onnxModel].filter(x => { return x != null }) as File[]
|
||||||
|
for (let i = 0; i < models.length; i++) {
|
||||||
|
const progRate = 1 / models.length
|
||||||
|
const progOffset = 100 * i * progRate
|
||||||
|
await _uploadFile(models[i], (progress: number, end: boolean) => {
|
||||||
|
// console.log(progress * progRate + progOffset, end, progRate,)
|
||||||
|
setUploadProgress(progress * progRate + progOffset)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await _uploadFile(fileUploadSetting.configFile, (progress: number, end: boolean) => {
|
||||||
|
console.log(progress, end)
|
||||||
|
})
|
||||||
|
|
||||||
|
const serverInfo = await props.voiceChangerClient.loadModel(fileUploadSetting.configFile, fileUploadSetting.pyTorchModel, fileUploadSetting.onnxModel)
|
||||||
|
console.log(serverInfo)
|
||||||
|
setUploadProgress(0)
|
||||||
|
setIsUploading(false)
|
||||||
|
}
|
||||||
|
}, [fileUploadSetting, props.voiceChangerClient])
|
||||||
|
|
||||||
|
const reloadServerInfo = useMemo(() => {
|
||||||
|
return async () => {
|
||||||
|
if (!props.voiceChangerClient) return
|
||||||
|
const res = await props.voiceChangerClient.getServerSettings()
|
||||||
|
_setServerInfo(res)
|
||||||
|
_setSetting({
|
||||||
|
...settingRef.current,
|
||||||
|
convertChunkNum: res.convertChunkNum,
|
||||||
|
srcId: res.srcId,
|
||||||
|
dstId: res.dstId,
|
||||||
|
gpu: res.gpu,
|
||||||
|
crossFadeOffsetRate: res.crossFadeOffsetRate,
|
||||||
|
crossFadeEndRate: res.crossFadeEndRate,
|
||||||
|
crossFadeOverlapRate: res.crossFadeOverlapRate,
|
||||||
|
framework: res.framework,
|
||||||
|
onnxExecutionProvider: (!!res.onnxExecutionProvider && res.onnxExecutionProvider.length > 0) ? res.onnxExecutionProvider[0] as OnnxExecutionProvider : DefaultVoiceChangerServerSetting.onnxExecutionProvider
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}, [props.voiceChangerClient])
|
||||||
|
|
||||||
|
return {
|
||||||
|
setting,
|
||||||
|
serverInfo,
|
||||||
|
fileUploadSetting,
|
||||||
|
setFramework,
|
||||||
|
setOnnxExecutionProvider,
|
||||||
|
setSrcId,
|
||||||
|
setDstId,
|
||||||
|
setConvertChunkNum,
|
||||||
|
setGpu,
|
||||||
|
setCrossFadeOffsetRate,
|
||||||
|
setCrossFadeEndRate,
|
||||||
|
setCrossFadeOverlapRate,
|
||||||
|
reloadServerInfo,
|
||||||
|
setFileUploadSetting,
|
||||||
|
loadModel,
|
||||||
|
uploadProgress,
|
||||||
|
isUploading,
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ import { VoiceChangerWorkletNode, VolumeListener } from "./VoiceChangerWorkletNo
|
|||||||
import workerjs from "raw-loader!../worklet/dist/index.js";
|
import workerjs from "raw-loader!../worklet/dist/index.js";
|
||||||
import { VoiceFocusDeviceTransformer, VoiceFocusTransformDevice } from "amazon-chime-sdk-js";
|
import { VoiceFocusDeviceTransformer, VoiceFocusTransformDevice } from "amazon-chime-sdk-js";
|
||||||
import { createDummyMediaStream, validateUrl } from "./util";
|
import { createDummyMediaStream, validateUrl } from "./util";
|
||||||
import { BufferSize, DefaultVoiceChangerOptions, Protocol, ServerSettingKey, VoiceChangerMode, VOICE_CHANGER_CLIENT_EXCEPTION, WorkletSetting } from "./const";
|
import { BufferSize, DefaultVoiceChangerClientSetting, Protocol, ServerSettingKey, VoiceChangerMode, VOICE_CHANGER_CLIENT_EXCEPTION, WorkletSetting } from "./const";
|
||||||
import MicrophoneStream from "microphone-stream";
|
import MicrophoneStream from "microphone-stream";
|
||||||
import { AudioStreamer, Callbacks, AudioStreamerListeners } from "./AudioStreamer";
|
import { AudioStreamer, Callbacks, AudioStreamerListeners } from "./AudioStreamer";
|
||||||
import { ServerConfigurator } from "./ServerConfigurator";
|
import { ServerConfigurator } from "./ServerConfigurator";
|
||||||
@ -85,8 +85,8 @@ export class VoiceChangerClient {
|
|||||||
this.vcNode.connect(this.currentMediaStreamAudioDestinationNode) // vc node -> output node
|
this.vcNode.connect(this.currentMediaStreamAudioDestinationNode) // vc node -> output node
|
||||||
// (vc nodeにはaudio streamerのcallbackでデータが投げ込まれる)
|
// (vc nodeにはaudio streamerのcallbackでデータが投げ込まれる)
|
||||||
this.audioStreamer = new AudioStreamer(this.callbacks, audioStreamerListeners, { objectMode: true, })
|
this.audioStreamer = new AudioStreamer(this.callbacks, audioStreamerListeners, { objectMode: true, })
|
||||||
this.audioStreamer.setInputChunkNum(DefaultVoiceChangerOptions.inputChunkNum)
|
this.audioStreamer.setInputChunkNum(DefaultVoiceChangerClientSetting.inputChunkNum)
|
||||||
this.audioStreamer.setVoiceChangerMode(DefaultVoiceChangerOptions.voiceChangerMode)
|
this.audioStreamer.setVoiceChangerMode(DefaultVoiceChangerClientSetting.voiceChangerMode)
|
||||||
|
|
||||||
if (this.vfEnable) {
|
if (this.vfEnable) {
|
||||||
this.vf = await VoiceFocusDeviceTransformer.create({ variant: 'c20' })
|
this.vf = await VoiceFocusDeviceTransformer.create({ variant: 'c20' })
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// 187.5chunk -> 1sec
|
// 187.5chunk -> 1sec
|
||||||
|
|
||||||
// types
|
// types
|
||||||
export type VoiceChangerRequestParamas = {
|
export type VoiceChangerServerSetting = {
|
||||||
convertChunkNum: number, // VITSに入力する変換サイズ。(入力データの2倍以上の大きさで指定。それより小さいものが指定された場合は、サーバ側で自動的に入力の2倍のサイズが設定される。)
|
convertChunkNum: number, // VITSに入力する変換サイズ。(入力データの2倍以上の大きさで指定。それより小さいものが指定された場合は、サーバ側で自動的に入力の2倍のサイズが設定される。)
|
||||||
srcId: number,
|
srcId: number,
|
||||||
dstId: number,
|
dstId: number,
|
||||||
@ -16,9 +16,11 @@ export type VoiceChangerRequestParamas = {
|
|||||||
crossFadeEndRate: number,
|
crossFadeEndRate: number,
|
||||||
crossFadeOverlapRate: number,
|
crossFadeOverlapRate: number,
|
||||||
|
|
||||||
|
framework: Framework
|
||||||
|
onnxExecutionProvider: OnnxExecutionProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VoiceChangerOptions = {
|
export type VoiceChangerClientSetting = {
|
||||||
audioInput: string | MediaStream | null,
|
audioInput: string | MediaStream | null,
|
||||||
mmvcServerUrl: string,
|
mmvcServerUrl: string,
|
||||||
protocol: Protocol,
|
protocol: Protocol,
|
||||||
@ -28,8 +30,6 @@ export type VoiceChangerOptions = {
|
|||||||
speakers: Speaker[],
|
speakers: Speaker[],
|
||||||
forceVfDisable: boolean,
|
forceVfDisable: boolean,
|
||||||
voiceChangerMode: VoiceChangerMode,
|
voiceChangerMode: VoiceChangerMode,
|
||||||
onnxExecutionProvider: OnnxExecutionProvider,
|
|
||||||
framework: Framework
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WorkletSetting = {
|
export type WorkletSetting = {
|
||||||
@ -52,11 +52,12 @@ export type ServerInfo = {
|
|||||||
convertChunkNum: number,
|
convertChunkNum: number,
|
||||||
crossFadeOffsetRate: number,
|
crossFadeOffsetRate: number,
|
||||||
crossFadeEndRate: number,
|
crossFadeEndRate: number,
|
||||||
|
crossFadeOverlapRate: number,
|
||||||
gpu: number,
|
gpu: number,
|
||||||
srcId: number,
|
srcId: number,
|
||||||
dstId: number,
|
dstId: number,
|
||||||
framework: Framework,
|
framework: Framework,
|
||||||
providers: string[]
|
onnxExecutionProvider: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ export const ServerSettingKey = {
|
|||||||
export type ServerSettingKey = typeof ServerSettingKey[keyof typeof ServerSettingKey]
|
export type ServerSettingKey = typeof ServerSettingKey[keyof typeof ServerSettingKey]
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
export const DefaultVoiceChangerRequestParamas: VoiceChangerRequestParamas = {
|
export const DefaultVoiceChangerServerSetting: VoiceChangerServerSetting = {
|
||||||
convertChunkNum: 32, //(★1)
|
convertChunkNum: 32, //(★1)
|
||||||
srcId: 107,
|
srcId: 107,
|
||||||
dstId: 100,
|
dstId: 100,
|
||||||
@ -128,10 +129,13 @@ export const DefaultVoiceChangerRequestParamas: VoiceChangerRequestParamas = {
|
|||||||
crossFadeLowerValue: 0.1,
|
crossFadeLowerValue: 0.1,
|
||||||
crossFadeOffsetRate: 0.1,
|
crossFadeOffsetRate: 0.1,
|
||||||
crossFadeEndRate: 0.9,
|
crossFadeEndRate: 0.9,
|
||||||
crossFadeOverlapRate: 0.5
|
crossFadeOverlapRate: 0.5,
|
||||||
|
framework: "PyTorch",
|
||||||
|
onnxExecutionProvider: "CPUExecutionProvider"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultVoiceChangerOptions: VoiceChangerOptions = {
|
export const DefaultVoiceChangerClientSetting: VoiceChangerClientSetting = {
|
||||||
audioInput: null,
|
audioInput: null,
|
||||||
mmvcServerUrl: "",
|
mmvcServerUrl: "",
|
||||||
protocol: "sio",
|
protocol: "sio",
|
||||||
@ -162,8 +166,6 @@ export const DefaultVoiceChangerOptions: VoiceChangerOptions = {
|
|||||||
],
|
],
|
||||||
forceVfDisable: false,
|
forceVfDisable: false,
|
||||||
voiceChangerMode: "realtime",
|
voiceChangerMode: "realtime",
|
||||||
framework: "PyTorch",
|
|
||||||
onnxExecutionProvider: "CPUExecutionProvider"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultWorkletSetting: WorkletSetting = {
|
export const DefaultWorkletSetting: WorkletSetting = {
|
||||||
|
@ -95,7 +95,7 @@ class VoiceChanger():
|
|||||||
def get_info(self):
|
def get_info(self):
|
||||||
data = asdict(self.settings)
|
data = asdict(self.settings)
|
||||||
|
|
||||||
data["providers"] = self.onnx_session.get_providers() if self.onnx_session != None else []
|
data["onnxExecutionProvider"] = self.onnx_session.get_providers() if self.onnx_session != None else []
|
||||||
files = ["configFile", "pyTorchModelFile", "onnxModelFile"]
|
files = ["configFile", "pyTorchModelFile", "onnxModelFile"]
|
||||||
for f in files:
|
for f in files:
|
||||||
if data[f]!=None and os.path.exists(data[f]):
|
if data[f]!=None and os.path.exists(data[f]):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user