uploading status

This commit is contained in:
wataru 2023-01-08 20:28:57 +09:00
parent 8082783644
commit 276f086823
11 changed files with 164 additions and 2899 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -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(() => {

View File

@ -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) => {

View File

@ -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);
} }

View File

@ -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)

View File

@ -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()
}) })
}) })

View File

@ -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) {

View File

@ -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)

View File

@ -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)

View File

@ -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)