voice-changer/client/lib/src/hooks/useClient.ts

140 lines
4.8 KiB
TypeScript
Raw Normal View History

2023-01-07 14:07:39 +03:00
import { useEffect, useMemo, useRef, useState } from "react"
2023-01-12 17:01:45 +03:00
import { VoiceChangerClient } from "../VoiceChangerClient"
2023-01-12 10:38:45 +03:00
import { ClientSettingState, useClientSetting } from "./useClientSetting"
import { ServerSettingState, useServerSetting } from "./useServerSetting"
2023-01-11 22:52:01 +03:00
import { useWorkletSetting, WorkletSettingState } from "./useWorkletSetting"
2023-01-07 14:07:39 +03:00
export type UseClientProps = {
audioContext: AudioContext | null
audioOutputElementId: string
}
export type ClientState = {
2023-02-18 22:56:16 +03:00
// 各種設定I/Fへの参照
2023-01-12 10:38:45 +03:00
workletSetting: WorkletSettingState
clientSetting: ClientSettingState
serverSetting: ServerSettingState
2023-02-18 22:56:16 +03:00
// モニタリングデータ
2023-01-07 14:07:39 +03:00
bufferingTime: number;
responseTime: number;
volume: number;
2023-02-18 22:56:16 +03:00
outputRecordData: Float32Array[] | null; // Serverから帰ってきたデータをレコードしたもの
2023-01-08 10:18:20 +03:00
2023-02-18 22:56:16 +03:00
// 情報取得
2023-01-08 10:18:20 +03:00
getInfo: () => Promise<void>
2023-02-18 22:56:16 +03:00
// 設定クリア
2023-01-29 03:42:45 +03:00
clearSetting: () => Promise<void>
2023-01-07 14:07:39 +03:00
}
2023-01-11 17:12:29 +03:00
2023-01-07 14:07:39 +03:00
export const useClient = (props: UseClientProps): ClientState => {
2023-01-12 10:38:45 +03:00
// (1-1) クライアント
2023-01-11 22:52:01 +03:00
const voiceChangerClientRef = useRef<VoiceChangerClient | null>(null)
const [voiceChangerClient, setVoiceChangerClient] = useState<VoiceChangerClient | null>(voiceChangerClientRef.current)
2023-01-12 10:38:45 +03:00
//// クライアント初期化待ち用フラグ
2023-01-08 14:28:57 +03:00
const initializedResolveRef = useRef<(value: void | PromiseLike<void>) => void>()
const initializedPromise = useMemo(() => {
return new Promise<void>((resolve) => {
initializedResolveRef.current = resolve
})
}, [])
2023-01-12 10:38:45 +03:00
2023-02-18 22:56:16 +03:00
// (1-2) 各種設定I/F
2023-01-12 10:38:45 +03:00
const clientSetting = useClientSetting({ voiceChangerClient, audioContext: props.audioContext })
const workletSetting = useWorkletSetting({ voiceChangerClient })
const serverSetting = useServerSetting({ voiceChangerClient })
2023-02-18 22:56:16 +03:00
// (1-3) モニタリングデータ
2023-01-10 16:49:16 +03:00
const [bufferingTime, setBufferingTime] = useState<number>(0)
const [responseTime, setResponseTime] = useState<number>(0)
const [volume, setVolume] = useState<number>(0)
const [outputRecordData, setOutputRecordData] = useState<Float32Array[] | null>(null)
2023-01-08 14:28:57 +03:00
2023-01-16 02:09:53 +03:00
// (1-4) エラーステータス
const errorCountRef = useRef<number>(0)
2023-01-12 10:38:45 +03:00
// (2-1) 初期化処理
2023-01-07 14:07:39 +03:00
useEffect(() => {
const initialized = async () => {
if (!props.audioContext) {
return
}
2023-01-11 22:52:01 +03:00
const voiceChangerClient = new VoiceChangerClient(props.audioContext, true, {
2023-01-07 14:07:39 +03:00
notifySendBufferingTime: (val: number) => {
setBufferingTime(val)
},
notifyResponseTime: (val: number) => {
setResponseTime(val)
},
notifyException: (mes: string) => {
if (mes.length > 0) {
console.log(`error:${mes}`)
2023-01-16 02:09:53 +03:00
errorCountRef.current += 1
if (errorCountRef.current > 100) {
alert("エラーが頻発しています。対象としているフレームワークのモデルがロードされているか確認してください。")
errorCountRef.current = 0
}
2023-01-07 14:07:39 +03:00
}
}
}, {
notifyVolume: (vol: number) => {
setVolume(vol)
},
notifyOutputRecordData: (data: Float32Array[]) => {
setOutputRecordData(data)
2023-01-07 14:07:39 +03:00
}
})
2023-01-08 14:28:57 +03:00
2023-01-07 14:07:39 +03:00
await voiceChangerClient.isInitialized()
voiceChangerClientRef.current = voiceChangerClient
2023-01-11 22:52:01 +03:00
setVoiceChangerClient(voiceChangerClientRef.current)
2023-01-08 10:18:20 +03:00
console.log("[useClient] client initialized")
2023-01-07 14:07:39 +03:00
const audio = document.getElementById(props.audioOutputElementId) as HTMLAudioElement
audio.srcObject = voiceChangerClientRef.current.stream
audio.play()
2023-01-08 14:28:57 +03:00
initializedResolveRef.current!()
2023-01-07 14:07:39 +03:00
}
initialized()
}, [props.audioContext])
2023-01-08 10:18:20 +03:00
2023-01-12 10:38:45 +03:00
// (2-2) 情報リロード
2023-01-08 10:18:20 +03:00
const getInfo = useMemo(() => {
return async () => {
2023-01-08 14:28:57 +03:00
await initializedPromise
await clientSetting.reloadClientSetting() // 実質的な処理の意味はない
2023-01-12 10:38:45 +03:00
await serverSetting.reloadServerInfo()
2023-01-10 20:19:54 +03:00
}
2023-01-12 10:38:45 +03:00
}, [clientSetting, serverSetting])
2023-01-11 17:12:29 +03:00
2023-01-29 03:42:45 +03:00
const clearSetting = async () => {
await clientSetting.clearSetting()
await workletSetting.clearSetting()
await serverSetting.clearSetting()
}
2023-01-11 22:52:01 +03:00
2023-01-07 14:07:39 +03:00
return {
2023-02-18 22:56:16 +03:00
// 各種設定I/Fへの参照
clientSetting,
workletSetting,
serverSetting,
// モニタリングデータ
2023-01-07 14:07:39 +03:00
bufferingTime,
responseTime,
volume,
outputRecordData,
2023-01-07 14:07:39 +03:00
2023-02-18 22:56:16 +03:00
// 情報取得
2023-01-08 10:18:20 +03:00
getInfo,
2023-01-11 22:52:01 +03:00
2023-02-18 22:56:16 +03:00
// 設定クリア
2023-01-29 03:42:45 +03:00
clearSetting,
2023-01-07 14:07:39 +03:00
}
}