import { BufferSize, createDummyMediaStream, Protocol, VoiceChangerMode, VoiceChangerRequestParamas, VoiceChnagerClient, uploadLargeFile, concatUploadedFile, OnnxExecutionProvider, setOnnxExecutionProvider } from "@dannadori/voice-changer-client-js" import { useEffect, useMemo, useRef, useState } from "react" export type UseClientProps = { audioContext: AudioContext | null audioOutputElementId: string } export type ClientState = { clientInitialized: boolean bufferingTime: number; responseTime: number; volume: number; start: (mmvcServerUrl: string, protocol: Protocol) => Promise; stop: () => Promise; changeInput: (audioInput: MediaStream | string, bufferSize: BufferSize, vfForceDisable: boolean) => Promise changeInputChunkNum: (inputChunkNum: number) => void changeVoiceChangeMode: (voiceChangerMode: VoiceChangerMode) => void changeRequestParams: (params: VoiceChangerRequestParamas) => void uploadFile: (baseUrl: string, file: File, onprogress: (progress: number, end: boolean) => void) => Promise changeOnnxExcecutionProvider: (baseUrl: string, provider: OnnxExecutionProvider) => Promise } export const useClient = (props: UseClientProps): ClientState => { const voiceChangerClientRef = useRef(null) const [clientInitialized, setClientInitialized] = useState(false) const [bufferingTime, setBufferingTime] = useState(0) const [responseTime, setResponseTime] = useState(0) const [volume, setVolume] = useState(0) useEffect(() => { const initialized = async () => { if (!props.audioContext) { return } const voiceChangerClient = new VoiceChnagerClient(props.audioContext, true, { notifySendBufferingTime: (val: number) => { setBufferingTime(val) }, notifyResponseTime: (val: number) => { setResponseTime(val) }, notifyException: (mes: string) => { if (mes.length > 0) { console.log(`error:${mes}`) } } }, { notifyVolume: (vol: number) => { setVolume(vol) } }) await voiceChangerClient.isInitialized() voiceChangerClientRef.current = voiceChangerClient console.log("client initialized!!") setClientInitialized(true) const audio = document.getElementById(props.audioOutputElementId) as HTMLAudioElement audio.srcObject = voiceChangerClientRef.current.stream audio.play() } initialized() }, [props.audioContext]) const start = useMemo(() => { return async (mmvcServerUrl: string, protocol: Protocol) => { if (!voiceChangerClientRef.current) { console.log("client is not initialized") return } voiceChangerClientRef.current.setServerUrl(mmvcServerUrl, protocol, true) voiceChangerClientRef.current.start() } }, []) const stop = useMemo(() => { return async () => { if (!voiceChangerClientRef.current) { // console.log("client is not initialized") return } voiceChangerClientRef.current.stop() } }, []) const changeInput = useMemo(() => { return async (audioInput: MediaStream | string, bufferSize: BufferSize, vfForceDisable: boolean) => { if (!voiceChangerClientRef.current || !props.audioContext) { console.log("not initialized", voiceChangerClientRef.current, props.audioContext) return } if (!audioInput || audioInput == "none") { console.log("setup! 1") const ms = createDummyMediaStream(props.audioContext) await voiceChangerClientRef.current.setup(ms, bufferSize, vfForceDisable) } else { console.log("setup! 2") await voiceChangerClientRef.current.setup(audioInput, bufferSize, vfForceDisable) } } }, [props.audioContext]) const changeInputChunkNum = useMemo(() => { return (inputChunkNum: number) => { if (!voiceChangerClientRef.current) { // console.log("client is not initialized") return } voiceChangerClientRef.current.setInputChunkNum(inputChunkNum) } }, []) const changeVoiceChangeMode = useMemo(() => { return (voiceChangerMode: VoiceChangerMode) => { if (!voiceChangerClientRef.current) { // console.log("client is not initialized") return } voiceChangerClientRef.current.setVoiceChangerMode(voiceChangerMode) } }, []) const changeRequestParams = useMemo(() => { return (params: VoiceChangerRequestParamas) => { if (!voiceChangerClientRef.current) { // console.log("client is not initialized") return } voiceChangerClientRef.current.setRequestParams(params) } }, []) const uploadFile = useMemo(() => { return async (baseUrl: string, file: File, onprogress: (progress: number, end: boolean) => void) => { const num = await uploadLargeFile(baseUrl, file, onprogress) const res = await concatUploadedFile(baseUrl, file, num) console.log("upload", num, res) } }, []) const changeOnnxExcecutionProvider = useMemo(() => { return async (baseUrl: string, provider: OnnxExecutionProvider) => { setOnnxExecutionProvider(baseUrl, provider) } }, []) return { clientInitialized, bufferingTime, responseTime, volume, start, stop, uploadFile, changeInput, changeInputChunkNum, changeVoiceChangeMode, changeRequestParams, changeOnnxExcecutionProvider, } }