mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-03-15 04:13:57 +03:00
uploading status
This commit is contained in:
parent
8082783644
commit
276f086823
2
client/demo/dist/index.js
vendored
2
client/demo/dist/index.js
vendored
File diff suppressed because one or more lines are too long
2744
client/demo/dist/index.js.LICENSE.txt
vendored
2744
client/demo/dist/index.js.LICENSE.txt
vendored
File diff suppressed because it is too large
Load Diff
@ -14,13 +14,19 @@ import { ServerSettingKey } from "@dannadori/voice-changer-client-js";
|
|||||||
|
|
||||||
export const useMicrophoneOptions = () => {
|
export const useMicrophoneOptions = () => {
|
||||||
const [audioContext, setAudioContext] = useState<AudioContext | null>(null)
|
const [audioContext, setAudioContext] = useState<AudioContext | null>(null)
|
||||||
|
const [loadModelFunc, setLoadModelFunc] = useState<() => Promise<void>>()
|
||||||
|
const [uploadProgress, setUploadProgress] = useState<number>(0)
|
||||||
|
const [isUploading, setIsUploading] = useState<boolean>(false)
|
||||||
const clientState = useClient({
|
const clientState = useClient({
|
||||||
audioContext: audioContext,
|
audioContext: audioContext,
|
||||||
audioOutputElementId: AUDIO_ELEMENT_FOR_PLAY_RESULT
|
audioOutputElementId: AUDIO_ELEMENT_FOR_PLAY_RESULT
|
||||||
})
|
})
|
||||||
|
|
||||||
const serverSetting = useServerSetting({
|
const serverSetting = useServerSetting({
|
||||||
clientState
|
clientState,
|
||||||
|
loadModelFunc,
|
||||||
|
uploadProgress: uploadProgress,
|
||||||
|
isUploading: isUploading
|
||||||
})
|
})
|
||||||
const deviceSetting = useDeviceSetting(audioContext)
|
const deviceSetting = useDeviceSetting(audioContext)
|
||||||
const speakerSetting = useSpeakerSetting()
|
const speakerSetting = useSpeakerSetting()
|
||||||
@ -34,7 +40,8 @@ export const useMicrophoneOptions = () => {
|
|||||||
getInfo: clientState.getInfo,
|
getInfo: clientState.getInfo,
|
||||||
volume: clientState.volume,
|
volume: clientState.volume,
|
||||||
bufferingTime: clientState.bufferingTime,
|
bufferingTime: clientState.bufferingTime,
|
||||||
responseTime: clientState.responseTime
|
responseTime: clientState.responseTime,
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -51,70 +58,94 @@ export const useMicrophoneOptions = () => {
|
|||||||
// 101 ServerSetting
|
// 101 ServerSetting
|
||||||
//// サーバ変更
|
//// サーバ変更
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.setServerUrl(serverSetting.mmvcServerUrl)
|
clientState.setServerUrl(serverSetting.mmvcServerUrl)
|
||||||
}, [clientState.clientInitialized, serverSetting.mmvcServerUrl])
|
}, [serverSetting.mmvcServerUrl])
|
||||||
//// プロトコル変更
|
//// プロトコル変更
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.setProtocol(serverSetting.protocol)
|
clientState.setProtocol(serverSetting.protocol)
|
||||||
}, [clientState.clientInitialized, serverSetting.protocol])
|
}, [serverSetting.protocol])
|
||||||
//// フレームワーク変更
|
//// フレームワーク変更
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.framework, serverSetting.framework)
|
clientState.updateSettings(ServerSettingKey.framework, serverSetting.framework)
|
||||||
}, [clientState.clientInitialized, serverSetting.framework])
|
}, [serverSetting.framework])
|
||||||
//// OnnxExecutionProvider変更
|
//// OnnxExecutionProvider変更
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.onnxExecutionProvider, serverSetting.onnxExecutionProvider)
|
clientState.updateSettings(ServerSettingKey.onnxExecutionProvider, serverSetting.onnxExecutionProvider)
|
||||||
}, [clientState.clientInitialized, serverSetting.onnxExecutionProvider])
|
}, [serverSetting.onnxExecutionProvider])
|
||||||
|
|
||||||
// 102 DeviceSetting
|
// 102 DeviceSetting
|
||||||
//// 入力情報の設定
|
//// 入力情報の設定
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.changeInput(deviceSetting.audioInput, convertSetting.bufferSize, advancedSetting.vfForceDisabled)
|
clientState.changeInput(deviceSetting.audioInput, convertSetting.bufferSize, advancedSetting.vfForceDisabled)
|
||||||
}, [clientState.clientInitialized, deviceSetting.audioInput, convertSetting.bufferSize, advancedSetting.vfForceDisabled])
|
}, [deviceSetting.audioInput, convertSetting.bufferSize, advancedSetting.vfForceDisabled])
|
||||||
|
|
||||||
// 103 SpeakerSetting
|
// 103 SpeakerSetting
|
||||||
// 音声変換元、変換先の設定
|
// 音声変換元、変換先の設定
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.srcId, speakerSetting.srcId)
|
clientState.updateSettings(ServerSettingKey.srcId, speakerSetting.srcId)
|
||||||
}, [clientState.clientInitialized, speakerSetting.srcId])
|
}, [speakerSetting.srcId])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.dstId, speakerSetting.dstId)
|
clientState.updateSettings(ServerSettingKey.dstId, speakerSetting.dstId)
|
||||||
}, [clientState.clientInitialized, speakerSetting.dstId])
|
}, [speakerSetting.dstId])
|
||||||
|
|
||||||
// 104 ConvertSetting
|
// 104 ConvertSetting
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.setInputChunkNum(convertSetting.inputChunkNum)
|
clientState.setInputChunkNum(convertSetting.inputChunkNum)
|
||||||
}, [clientState.clientInitialized, convertSetting.inputChunkNum])
|
}, [convertSetting.inputChunkNum])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.convertChunkNum, convertSetting.convertChunkNum)
|
clientState.updateSettings(ServerSettingKey.convertChunkNum, convertSetting.convertChunkNum)
|
||||||
}, [clientState.clientInitialized, convertSetting.convertChunkNum])
|
}, [convertSetting.convertChunkNum])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.gpu, convertSetting.gpu)
|
clientState.updateSettings(ServerSettingKey.gpu, convertSetting.gpu)
|
||||||
}, [clientState.clientInitialized, convertSetting.gpu])
|
}, [convertSetting.gpu])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.crossFadeOffsetRate, convertSetting.crossFadeOffsetRate)
|
clientState.updateSettings(ServerSettingKey.crossFadeOffsetRate, convertSetting.crossFadeOffsetRate)
|
||||||
}, [clientState.clientInitialized, convertSetting.crossFadeOffsetRate])
|
}, [convertSetting.crossFadeOffsetRate])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.updateSettings(ServerSettingKey.crossFadeEndRate, convertSetting.crossFadeEndRate)
|
clientState.updateSettings(ServerSettingKey.crossFadeEndRate, convertSetting.crossFadeEndRate)
|
||||||
}, [clientState.clientInitialized, convertSetting.crossFadeEndRate])
|
}, [convertSetting.crossFadeEndRate])
|
||||||
|
|
||||||
// 105 AdvancedSetting
|
// 105 AdvancedSetting
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clientState.clientInitialized) return
|
|
||||||
clientState.setVoiceChangerMode(advancedSetting.voiceChangerMode)
|
clientState.setVoiceChangerMode(advancedSetting.voiceChangerMode)
|
||||||
}, [clientState.clientInitialized, advancedSetting.voiceChangerMode])
|
}, [advancedSetting.voiceChangerMode])
|
||||||
|
|
||||||
|
|
||||||
|
// Model Load
|
||||||
|
useEffect(() => {
|
||||||
|
const loadModel = () => {
|
||||||
|
return async () => {
|
||||||
|
if (!serverSetting.pyTorchModel && !serverSetting.onnxModel) {
|
||||||
|
alert("PyTorchモデルとONNXモデルのどちらか一つ以上指定する必要があります。")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!serverSetting.configFile) {
|
||||||
|
alert("Configファイルを指定する必要があります。")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setUploadProgress(0)
|
||||||
|
setIsUploading(true)
|
||||||
|
const models = [serverSetting.pyTorchModel, serverSetting.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 clientState.uploadFile(models[i], (progress: number, end: boolean) => {
|
||||||
|
// console.log(progress * progRate + progOffset, end, progRate,)
|
||||||
|
setUploadProgress(progress * progRate + progOffset)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await clientState.uploadFile(serverSetting.configFile, (progress: number, end: boolean) => {
|
||||||
|
console.log(progress, end)
|
||||||
|
})
|
||||||
|
|
||||||
|
await clientState.loadModel(serverSetting.configFile, serverSetting.pyTorchModel, serverSetting.onnxModel)
|
||||||
|
setUploadProgress(0)
|
||||||
|
setIsUploading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setLoadModelFunc(loadModel)
|
||||||
|
}, [serverSetting.configFile, serverSetting.pyTorchModel, serverSetting.onnxModel])
|
||||||
|
|
||||||
|
|
||||||
const voiceChangerSetting = useMemo(() => {
|
const voiceChangerSetting = useMemo(() => {
|
||||||
|
@ -5,6 +5,9 @@ import { ClientState } from "./hooks/useClient"
|
|||||||
|
|
||||||
export type UseServerSettingProps = {
|
export type UseServerSettingProps = {
|
||||||
clientState: ClientState
|
clientState: ClientState
|
||||||
|
loadModelFunc: (() => Promise<void>) | undefined
|
||||||
|
uploadProgress: number,
|
||||||
|
isUploading: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ServerSettingState = {
|
export type ServerSettingState = {
|
||||||
@ -16,6 +19,7 @@ export type ServerSettingState = {
|
|||||||
framework: string;
|
framework: string;
|
||||||
onnxExecutionProvider: OnnxExecutionProvider;
|
onnxExecutionProvider: OnnxExecutionProvider;
|
||||||
protocol: Protocol;
|
protocol: Protocol;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useServerSetting = (props: UseServerSettingProps): ServerSettingState => {
|
export const useServerSetting = (props: UseServerSettingProps): ServerSettingState => {
|
||||||
@ -54,6 +58,9 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
}
|
}
|
||||||
setPyTorchModel(file)
|
setPyTorchModel(file)
|
||||||
}
|
}
|
||||||
|
const onPyTorchFileClearClicked = () => {
|
||||||
|
setPyTorchModel(null)
|
||||||
|
}
|
||||||
const onConfigFileLoadClicked = async () => {
|
const onConfigFileLoadClicked = async () => {
|
||||||
const file = await fileSelector("")
|
const file = await fileSelector("")
|
||||||
if (file.name.endsWith(".json") == false) {
|
if (file.name.endsWith(".json") == false) {
|
||||||
@ -62,6 +69,9 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
}
|
}
|
||||||
setConfigFile(file)
|
setConfigFile(file)
|
||||||
}
|
}
|
||||||
|
const onConfigFileClearClicked = () => {
|
||||||
|
setConfigFile(null)
|
||||||
|
}
|
||||||
const onOnnxFileLoadClicked = async () => {
|
const onOnnxFileLoadClicked = async () => {
|
||||||
const file = await fileSelector("")
|
const file = await fileSelector("")
|
||||||
if (file.name.endsWith(".onnx") == false) {
|
if (file.name.endsWith(".onnx") == false) {
|
||||||
@ -70,31 +80,14 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
}
|
}
|
||||||
setOnnxModel(file)
|
setOnnxModel(file)
|
||||||
}
|
}
|
||||||
|
const onOnnxFileClearClicked = () => {
|
||||||
|
setOnnxModel(null)
|
||||||
|
}
|
||||||
const onModelUploadClicked = async () => {
|
const onModelUploadClicked = async () => {
|
||||||
if (!pyTorchModel && !onnxModel) {
|
if (!props.loadModelFunc) {
|
||||||
alert("PyTorchモデルとONNXモデルのどちらか一つ以上指定する必要があります。")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!configFile) {
|
props.loadModelFunc()
|
||||||
alert("Configファイルを指定する必要があります。")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (pyTorchModel) {
|
|
||||||
await props.clientState.uploadFile(pyTorchModel, (progress: number, end: boolean) => {
|
|
||||||
console.log(progress, end)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (onnxModel) {
|
|
||||||
await props.clientState.uploadFile(onnxModel, (progress: number, end: boolean) => {
|
|
||||||
console.log(progress, end)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
await props.clientState.uploadFile(configFile, (progress: number, end: boolean) => {
|
|
||||||
console.log(progress, end)
|
|
||||||
})
|
|
||||||
|
|
||||||
await props.clientState.loadModel(configFile, pyTorchModel, onnxModel)
|
|
||||||
console.log("loaded")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -115,6 +108,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</div>
|
</div>
|
||||||
<div className="body-button-container">
|
<div className="body-button-container">
|
||||||
<div className="body-button" onClick={onPyTorchFileLoadClicked}>select</div>
|
<div className="body-button" onClick={onPyTorchFileLoadClicked}>select</div>
|
||||||
|
<div className="body-button left-margin-1" onClick={onPyTorchFileClearClicked}>clear</div>
|
||||||
</div>
|
</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">
|
||||||
@ -124,6 +118,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</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>
|
</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">
|
||||||
@ -133,11 +128,13 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</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>
|
||||||
|
<div className="body-button left-margin-1" onClick={onOnnxFileClearClicked}>clear</div>
|
||||||
</div>
|
</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"></div>
|
<div className="body-item-title left-padding-2"></div>
|
||||||
<div className="body-item-text">
|
<div className="body-item-text">
|
||||||
|
{props.isUploading ? `uploading.... ${props.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>
|
||||||
@ -145,7 +142,7 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}, [pyTorchModel, configFile, onnxModel, mmvcServerUrl])
|
}, [pyTorchModel, configFile, onnxModel, props.loadModelFunc, props.isUploading, props.uploadProgress])
|
||||||
|
|
||||||
const protocolRow = useMemo(() => {
|
const protocolRow = useMemo(() => {
|
||||||
const onProtocolChanged = async (val: Protocol) => {
|
const onProtocolChanged = async (val: Protocol) => {
|
||||||
|
@ -194,6 +194,12 @@ body {
|
|||||||
.left-padding-2 {
|
.left-padding-2 {
|
||||||
padding-left: 2rem;
|
padding-left: 2rem;
|
||||||
}
|
}
|
||||||
|
.left-margin-1 {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
.left-margin-2 {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
.highlight {
|
.highlight {
|
||||||
background-color: rgba(200, 200, 255, 0.3);
|
background-color: rgba(200, 200, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,13 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
const [responseTime, setResponseTime] = useState<number>(0)
|
const [responseTime, setResponseTime] = useState<number>(0)
|
||||||
const [volume, setVolume] = useState<number>(0)
|
const [volume, setVolume] = useState<number>(0)
|
||||||
|
|
||||||
|
const initializedResolveRef = useRef<(value: void | PromiseLike<void>) => void>()
|
||||||
|
const initializedPromise = useMemo(() => {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
initializedResolveRef.current = resolve
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initialized = async () => {
|
const initialized = async () => {
|
||||||
if (!props.audioContext) {
|
if (!props.audioContext) {
|
||||||
@ -63,6 +70,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
setVolume(vol)
|
setVolume(vol)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await voiceChangerClient.isInitialized()
|
await voiceChangerClient.isInitialized()
|
||||||
voiceChangerClientRef.current = voiceChangerClient
|
voiceChangerClientRef.current = voiceChangerClient
|
||||||
console.log("[useClient] client initialized")
|
console.log("[useClient] client initialized")
|
||||||
@ -71,6 +79,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
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
|
||||||
audio.play()
|
audio.play()
|
||||||
|
initializedResolveRef.current!()
|
||||||
}
|
}
|
||||||
initialized()
|
initialized()
|
||||||
}, [props.audioContext])
|
}, [props.audioContext])
|
||||||
@ -78,10 +87,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
// Client Setting
|
// Client Setting
|
||||||
const setServerUrl = useMemo(() => {
|
const setServerUrl = useMemo(() => {
|
||||||
return async (mmvcServerUrl: string) => {
|
return async (mmvcServerUrl: string) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
console.log("client is not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
voiceChangerClientRef.current.setServerUrl(mmvcServerUrl, true)
|
voiceChangerClientRef.current.setServerUrl(mmvcServerUrl, true)
|
||||||
voiceChangerClientRef.current.stop()
|
voiceChangerClientRef.current.stop()
|
||||||
}
|
}
|
||||||
@ -89,30 +95,21 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
|
|
||||||
const setProtocol = useMemo(() => {
|
const setProtocol = useMemo(() => {
|
||||||
return async (protocol: Protocol) => {
|
return async (protocol: Protocol) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
console.log("client is not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
voiceChangerClientRef.current.setProtocol(protocol)
|
voiceChangerClientRef.current.setProtocol(protocol)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const setInputChunkNum = useMemo(() => {
|
const setInputChunkNum = useMemo(() => {
|
||||||
return async (num: number) => {
|
return async (num: number) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
console.log("client is not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
voiceChangerClientRef.current.setInputChunkNum(num)
|
voiceChangerClientRef.current.setInputChunkNum(num)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const setVoiceChangerMode = useMemo(() => {
|
const setVoiceChangerMode = useMemo(() => {
|
||||||
return async (val: VoiceChangerMode) => {
|
return async (val: VoiceChangerMode) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
console.log("client is not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
voiceChangerClientRef.current.setVoiceChangerMode(val)
|
voiceChangerClientRef.current.setVoiceChangerMode(val)
|
||||||
voiceChangerClientRef.current.stop()
|
voiceChangerClientRef.current.stop()
|
||||||
}
|
}
|
||||||
@ -122,20 +119,14 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
// Client Control
|
// Client Control
|
||||||
const start = useMemo(() => {
|
const start = useMemo(() => {
|
||||||
return async (mmvcServerUrl: string) => {
|
return async (mmvcServerUrl: string) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
console.log("client is not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
voiceChangerClientRef.current.setServerUrl(mmvcServerUrl, true)
|
voiceChangerClientRef.current.setServerUrl(mmvcServerUrl, true)
|
||||||
voiceChangerClientRef.current.start()
|
voiceChangerClientRef.current.start()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
const stop = useMemo(() => {
|
const stop = useMemo(() => {
|
||||||
return async () => {
|
return async () => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
// console.log("client is not initialized")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
voiceChangerClientRef.current.stop()
|
voiceChangerClientRef.current.stop()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
@ -144,10 +135,8 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
// Device Setting
|
// Device Setting
|
||||||
const changeInput = useMemo(() => {
|
const changeInput = useMemo(() => {
|
||||||
return async (audioInput: MediaStream | string, bufferSize: BufferSize, vfForceDisable: boolean) => {
|
return async (audioInput: MediaStream | string, bufferSize: BufferSize, vfForceDisable: boolean) => {
|
||||||
if (!voiceChangerClientRef.current || !props.audioContext) {
|
await initializedPromise
|
||||||
console.log("[useClient] not initialized", voiceChangerClientRef.current, props.audioContext)
|
if (!props.audioContext) return
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!audioInput || audioInput == "none") {
|
if (!audioInput || audioInput == "none") {
|
||||||
console.log("[useClient] setup!(1)", audioInput)
|
console.log("[useClient] setup!(1)", audioInput)
|
||||||
const ms = createDummyMediaStream(props.audioContext)
|
const ms = createDummyMediaStream(props.audioContext)
|
||||||
@ -165,9 +154,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
// Server Setting
|
// Server Setting
|
||||||
const uploadFile = useMemo(() => {
|
const uploadFile = useMemo(() => {
|
||||||
return async (file: File, onprogress: (progress: number, end: boolean) => void) => {
|
return async (file: File, onprogress: (progress: number, end: boolean) => void) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
throw "[useClient] Client Not Initialized."
|
|
||||||
}
|
|
||||||
const num = await voiceChangerClientRef.current.uploadFile(file, onprogress)
|
const num = await voiceChangerClientRef.current.uploadFile(file, onprogress)
|
||||||
const res = await voiceChangerClientRef.current.concatUploadedFile(file, num)
|
const res = await voiceChangerClientRef.current.concatUploadedFile(file, num)
|
||||||
console.log("upload", num, res)
|
console.log("upload", num, res)
|
||||||
@ -176,9 +163,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
|
|
||||||
const loadModel = useMemo(() => {
|
const loadModel = useMemo(() => {
|
||||||
return async (configFile: File, pyTorchModelFile: File | null, onnxModelFile: File | null) => {
|
return async (configFile: File, pyTorchModelFile: File | null, onnxModelFile: File | null) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
throw "[useClient] Client Not Initialized."
|
|
||||||
}
|
|
||||||
await voiceChangerClientRef.current.loadModel(configFile, pyTorchModelFile, onnxModelFile)
|
await voiceChangerClientRef.current.loadModel(configFile, pyTorchModelFile, onnxModelFile)
|
||||||
console.log("load model")
|
console.log("load model")
|
||||||
}
|
}
|
||||||
@ -186,9 +171,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
|
|
||||||
const updateSettings = useMemo(() => {
|
const updateSettings = useMemo(() => {
|
||||||
return async (key: ServerSettingKey, val: string | number) => {
|
return async (key: ServerSettingKey, val: string | number) => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
throw "[useClient] Client Not Initialized."
|
|
||||||
}
|
|
||||||
return await voiceChangerClientRef.current.updateServerSettings(key, "" + val)
|
return await voiceChangerClientRef.current.updateServerSettings(key, "" + val)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
@ -196,9 +179,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
|||||||
// Information
|
// Information
|
||||||
const getInfo = useMemo(() => {
|
const getInfo = useMemo(() => {
|
||||||
return async () => {
|
return async () => {
|
||||||
if (!voiceChangerClientRef.current) {
|
await initializedPromise
|
||||||
throw "[useClient] Client Not Initialized."
|
|
||||||
}
|
|
||||||
const serverSettings = await voiceChangerClientRef.current.getServerSettings()
|
const serverSettings = await voiceChangerClientRef.current.getServerSettings()
|
||||||
const clientSettings = await voiceChangerClientRef.current.getClientSettings()
|
const clientSettings = await voiceChangerClientRef.current.getClientSettings()
|
||||||
console.log(serverSettings, clientSettings)
|
console.log(serverSettings, clientSettings)
|
||||||
|
@ -59,7 +59,7 @@ export class ServerConfigurator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const chunkNum = fileChunks.length
|
const chunkNum = fileChunks.length
|
||||||
console.log("FILE_CHUNKS:", chunkNum, fileChunks)
|
// console.log("FILE_CHUNKS:", chunkNum, fileChunks)
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -77,8 +77,8 @@ export class ServerConfigurator {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
});
|
});
|
||||||
fetch(request).then(async (response) => {
|
fetch(request).then(async (_response) => {
|
||||||
console.log(await response.text())
|
// console.log(await response.text())
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -122,9 +122,7 @@ export class VoiceChnagerClient {
|
|||||||
|
|
||||||
// create mic stream
|
// create mic stream
|
||||||
if (this.micStream) {
|
if (this.micStream) {
|
||||||
console.log("DESTROY!!!!!!!!!!!!!!!!!!!")
|
|
||||||
this.micStream.unpipe()
|
this.micStream.unpipe()
|
||||||
// this.micStream.stop()
|
|
||||||
this.micStream.destroy()
|
this.micStream.destroy()
|
||||||
this.micStream = null
|
this.micStream = null
|
||||||
}
|
}
|
||||||
@ -176,9 +174,8 @@ export class VoiceChnagerClient {
|
|||||||
setServerUrl = (serverUrl: string, openTab: boolean = false) => {
|
setServerUrl = (serverUrl: string, openTab: boolean = false) => {
|
||||||
const url = validateUrl(serverUrl)
|
const url = validateUrl(serverUrl)
|
||||||
const pageUrl = `${location.protocol}//${location.host}`
|
const pageUrl = `${location.protocol}//${location.host}`
|
||||||
console.log("SERVER CHECK", url, pageUrl)
|
|
||||||
|
|
||||||
if (url != pageUrl && location.protocol == "https:" && this.sslCertified.includes(url) == false) {
|
if (url != pageUrl && url.length != 0 && location.protocol == "https:" && this.sslCertified.includes(url) == false) {
|
||||||
if (openTab) {
|
if (openTab) {
|
||||||
const value = window.confirm("MMVC Server is different from this page's origin. Open tab to open ssl connection. OK? (You can close the opened tab after ssl connection succeed.)");
|
const value = window.confirm("MMVC Server is different from this page's origin. Open tab to open ssl connection. OK? (You can close the opened tab after ssl connection succeed.)");
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -9,7 +9,7 @@ import logging
|
|||||||
# logger = logging.getLogger("uvicorn.error")
|
# logger = logging.getLogger("uvicorn.error")
|
||||||
# logger.addFilter(UvicornSuppressFilter())
|
# logger.addFilter(UvicornSuppressFilter())
|
||||||
# # logger.propagate = False
|
# # logger.propagate = False
|
||||||
# logger = logging.getLogger("multipart.multipart")
|
logger = logging.getLogger("multipart.multipart")
|
||||||
# logger.propagate = False
|
logger.propagate = False
|
||||||
|
|
||||||
logging.getLogger('asyncio').setLevel(logging.WARNING)
|
logging.getLogger('asyncio').setLevel(logging.WARNING)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import base64, struct
|
import base64, struct
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import traceback
|
||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
@ -10,14 +11,7 @@ from pydantic import BaseModel
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
class VoiceModel(BaseModel):
|
class VoiceModel(BaseModel):
|
||||||
gpu: int
|
|
||||||
srcId: int
|
|
||||||
dstId: int
|
|
||||||
timestamp: int
|
timestamp: int
|
||||||
convertChunkNum: int
|
|
||||||
crossFadeLowerValue: float
|
|
||||||
crossFadeOffsetRate:float
|
|
||||||
crossFadeEndRate:float
|
|
||||||
buffer: str
|
buffer: str
|
||||||
|
|
||||||
class MMVC_Rest_VoiceChanger:
|
class MMVC_Rest_VoiceChanger:
|
||||||
@ -30,14 +24,7 @@ class MMVC_Rest_VoiceChanger:
|
|||||||
|
|
||||||
def test(self, voice: VoiceModel):
|
def test(self, voice: VoiceModel):
|
||||||
try:
|
try:
|
||||||
gpu = voice.gpu
|
|
||||||
srcId = voice.srcId
|
|
||||||
dstId = voice.dstId
|
|
||||||
timestamp = voice.timestamp
|
timestamp = voice.timestamp
|
||||||
convertChunkNum = voice.convertChunkNum
|
|
||||||
crossFadeLowerValue = voice.crossFadeLowerValue
|
|
||||||
crossFadeOffsetRate = voice.crossFadeOffsetRate
|
|
||||||
crossFadeEndRate = voice.crossFadeEndRate
|
|
||||||
buffer = voice.buffer
|
buffer = voice.buffer
|
||||||
wav = base64.b64decode(buffer)
|
wav = base64.b64decode(buffer)
|
||||||
|
|
||||||
@ -51,17 +38,12 @@ class MMVC_Rest_VoiceChanger:
|
|||||||
# unpackedData.astype(np.int16))
|
# unpackedData.astype(np.int16))
|
||||||
|
|
||||||
self.tlock.acquire()
|
self.tlock.acquire()
|
||||||
changedVoice = self.voiceChangerManager.changeVoice(
|
changedVoice = self.voiceChangerManager.changeVoice( unpackedData)
|
||||||
gpu, srcId, dstId, timestamp, convertChunkNum, crossFadeLowerValue, crossFadeOffsetRate, crossFadeEndRate, unpackedData)
|
|
||||||
self.tlock.release()
|
self.tlock.release()
|
||||||
|
|
||||||
changedVoiceBase64 = base64.b64encode(changedVoice).decode('utf-8')
|
changedVoiceBase64 = base64.b64encode(changedVoice).decode('utf-8')
|
||||||
data = {
|
data = {
|
||||||
"gpu": gpu,
|
|
||||||
"srcId": srcId,
|
|
||||||
"dstId": dstId,
|
|
||||||
"timestamp": timestamp,
|
"timestamp": timestamp,
|
||||||
"convertChunkNum": voice.convertChunkNum,
|
|
||||||
"changedVoiceBase64": changedVoiceBase64
|
"changedVoiceBase64": changedVoiceBase64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +53,7 @@ class MMVC_Rest_VoiceChanger:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("REQUEST PROCESSING!!!! EXCEPTION!!!", e)
|
print("REQUEST PROCESSING!!!! EXCEPTION!!!", e)
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
self.tlock.release()
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,19 +86,25 @@ class VoiceChanger():
|
|||||||
self.onnx_session = None
|
self.onnx_session = None
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
|
if hasattr(self, "net_g"):
|
||||||
del self.net_g
|
del self.net_g
|
||||||
|
if hasattr(self, "onnx_session"):
|
||||||
del self.onnx_session
|
del self.onnx_session
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
data = asdict(self.settings)
|
data = asdict(self.settings)
|
||||||
data["providers"] = self.onnx_session.get_providers() if hasattr(self, "onnx_session") else ""
|
data["providers"] = self.onnx_session.get_providers() if self.onnx_session != None else ""
|
||||||
files = ["config_file", "pyTorch_model_file", "onnx_model_file"]
|
files = ["config_file", "pyTorch_model_file", "onnx_model_file"]
|
||||||
for f in files:
|
for f in files:
|
||||||
|
if os.path.exists(f):
|
||||||
data[f] = os.path.basename(data[f])
|
data[f] = os.path.basename(data[f])
|
||||||
|
else:
|
||||||
|
data[f] = ""
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def update_setteings(self, key:str, val:any):
|
def update_setteings(self, key:str, val:any):
|
||||||
if key == "onnxExecutionProvider":
|
if key == "onnxExecutionProvider" and self.onnx_session != None:
|
||||||
if val == "CUDAExecutionProvider":
|
if val == "CUDAExecutionProvider":
|
||||||
provider_options=[{'device_id': self.settings.gpu}]
|
provider_options=[{'device_id': self.settings.gpu}]
|
||||||
self.onnx_session.set_providers(providers=[val], provider_options=provider_options)
|
self.onnx_session.set_providers(providers=[val], provider_options=provider_options)
|
||||||
@ -107,7 +113,7 @@ class VoiceChanger():
|
|||||||
return self.get_info()
|
return self.get_info()
|
||||||
elif key in self.settings.intData:
|
elif key in self.settings.intData:
|
||||||
setattr(self.settings, key, int(val))
|
setattr(self.settings, key, int(val))
|
||||||
if key == "gpu" and val >= 0 and val < self.gpu_num and hasattr(self, "onnx_session"):
|
if key == "gpu" and val >= 0 and val < self.gpu_num and self.onnx_session != None:
|
||||||
providers = self.onnx_session.get_providers()
|
providers = self.onnx_session.get_providers()
|
||||||
print("Providers::::", providers)
|
print("Providers::::", providers)
|
||||||
if "CUDAExecutionProvider" in providers:
|
if "CUDAExecutionProvider" in providers:
|
||||||
@ -176,7 +182,10 @@ class VoiceChanger():
|
|||||||
|
|
||||||
|
|
||||||
def _onnx_inference(self, data, inputSize):
|
def _onnx_inference(self, data, inputSize):
|
||||||
if hasattr(self, 'onnx_session'):
|
if hasattr(self, "onnx_session") == False or self.onnx_session == None:
|
||||||
|
print("[Voice Changer] No ONNX session.")
|
||||||
|
return np.zeros(1).astype(np.int16)
|
||||||
|
|
||||||
x, x_lengths, spec, spec_lengths, y, y_lengths, sid_src = [x for x in data]
|
x, x_lengths, spec, spec_lengths, y, y_lengths, sid_src = [x for x in data]
|
||||||
sid_tgt1 = torch.LongTensor([self.settings.dstId])
|
sid_tgt1 = torch.LongTensor([self.settings.dstId])
|
||||||
# if spec.size()[2] >= 8:
|
# if spec.size()[2] >= 8:
|
||||||
@ -201,10 +210,12 @@ class VoiceChanger():
|
|||||||
result = cur
|
result = cur
|
||||||
self.np_prev_audio1 = audio1
|
self.np_prev_audio1 = audio1
|
||||||
return result
|
return result
|
||||||
else:
|
|
||||||
raise ValueError(ERROR_NO_ONNX_SESSION, "No ONNX Session.")
|
|
||||||
|
|
||||||
def _pyTorch_inference(self, data, inputSize):
|
def _pyTorch_inference(self, data, inputSize):
|
||||||
|
if hasattr(self, "net_g") == False or self.net_g ==None:
|
||||||
|
print("[Voice Changer] No pyTorch session.")
|
||||||
|
return np.zeros(1).astype(np.int16)
|
||||||
|
|
||||||
if self.settings.gpu < 0 or self.gpu_num == 0:
|
if self.settings.gpu < 0 or self.gpu_num == 0:
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
x, x_lengths, spec, spec_lengths, y, y_lengths, sid_src = [x.cpu() for x in data]
|
x, x_lengths, spec, spec_lengths, y, y_lengths, sid_src = [x.cpu() for x in data]
|
||||||
@ -281,8 +292,11 @@ class VoiceChanger():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("VC PROCESSING!!!! EXCEPTION!!!", e)
|
print("VC PROCESSING!!!! EXCEPTION!!!", e)
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
if hasattr(self, "np_prev_audio1"):
|
||||||
del self.np_prev_audio1
|
del self.np_prev_audio1
|
||||||
|
if hasattr(self, "prev_audio1"):
|
||||||
del self.prev_audio1
|
del self.prev_audio1
|
||||||
|
return np.zeros(1).astype(np.int16)
|
||||||
|
|
||||||
result = result.astype(np.int16)
|
result = result.astype(np.int16)
|
||||||
# print("on_request result size:",result.shape)
|
# print("on_request result size:",result.shape)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user