mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-03-13 19:34:02 +03:00
fix some bugs
This commit is contained in:
parent
98db8862b5
commit
35ca5a7618
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
2647
client/demo/dist/index.js.LICENSE.txt
vendored
2647
client/demo/dist/index.js.LICENSE.txt
vendored
File diff suppressed because it is too large
Load Diff
14
client/demo/package-lock.json
generated
14
client/demo/package-lock.json
generated
@ -9,7 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@dannadori/voice-changer-client-js": "^1.0.76",
|
||||
"@dannadori/voice-changer-client-js": "^1.0.78",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.3.0",
|
||||
@ -3187,9 +3187,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@dannadori/voice-changer-client-js": {
|
||||
"version": "1.0.76",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.76.tgz",
|
||||
"integrity": "sha512-NOYlPaarEwhxv7CzegXzbiC5XA8ARDwLnU2pn7JSCH8EAfk4SV+qGohdSg12H1Z3u0ry7RT2kyWPNJuMH0dZ5A==",
|
||||
"version": "1.0.78",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.78.tgz",
|
||||
"integrity": "sha512-1M5X7WKhpBXaiMxNxrXYeGRby52vq1QUkSzbBWq73kBd0ANesbeLxshhYN+fXCdazTbcDbb5ONNaFw797e7kSA==",
|
||||
"dependencies": {
|
||||
"@types/readable-stream": "^2.3.15",
|
||||
"amazon-chime-sdk-js": "^3.11.0",
|
||||
@ -13473,9 +13473,9 @@
|
||||
}
|
||||
},
|
||||
"@dannadori/voice-changer-client-js": {
|
||||
"version": "1.0.76",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.76.tgz",
|
||||
"integrity": "sha512-NOYlPaarEwhxv7CzegXzbiC5XA8ARDwLnU2pn7JSCH8EAfk4SV+qGohdSg12H1Z3u0ry7RT2kyWPNJuMH0dZ5A==",
|
||||
"version": "1.0.78",
|
||||
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.78.tgz",
|
||||
"integrity": "sha512-1M5X7WKhpBXaiMxNxrXYeGRby52vq1QUkSzbBWq73kBd0ANesbeLxshhYN+fXCdazTbcDbb5ONNaFw797e7kSA==",
|
||||
"requires": {
|
||||
"@types/readable-stream": "^2.3.15",
|
||||
"amazon-chime-sdk-js": "^3.11.0",
|
||||
|
@ -51,7 +51,7 @@
|
||||
"webpack-dev-server": "^4.11.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dannadori/voice-changer-client-js": "^1.0.76",
|
||||
"@dannadori/voice-changer-client-js": "^1.0.78",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.3.0",
|
||||
|
@ -1,16 +1,18 @@
|
||||
import * as React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./css/App.css"
|
||||
import { useMemo, } from "react";
|
||||
import { ErrorInfo, useMemo, useState, } from "react";
|
||||
import { useMicrophoneOptions } from "./100_options_microphone";
|
||||
import { AppStateProvider, useAppState } from "./001_provider/001_AppStateProvider";
|
||||
|
||||
|
||||
import localForage from "localforage";
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { fas } from "@fortawesome/free-solid-svg-icons";
|
||||
import { far } from "@fortawesome/free-regular-svg-icons";
|
||||
import { fab } from "@fortawesome/free-brands-svg-icons";
|
||||
import { AppRootProvider } from "./001_provider/001_AppRootProvider";
|
||||
import ErrorBoundary from "./001_provider/900_ErrorBoundary";
|
||||
import { INDEXEDDB_KEY_CLIENT, INDEXEDDB_KEY_MODEL_DATA, INDEXEDDB_KEY_SERVER, INDEXEDDB_KEY_WORKLET, INDEXEDDB_KEY_WORKLETNODE } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
library.add(fas, far, fab);
|
||||
|
||||
@ -21,7 +23,6 @@ const root = createRoot(container);
|
||||
const App = () => {
|
||||
const appState = useAppState()
|
||||
const { voiceChangerSetting } = useMicrophoneOptions()
|
||||
|
||||
const titleRow = useMemo(() => {
|
||||
return (
|
||||
<div className="top-title">
|
||||
@ -87,14 +88,73 @@ const App = () => {
|
||||
}
|
||||
|
||||
const AppStateWrapper = () => {
|
||||
// const appRoot = useAppRoot()
|
||||
// if (!appRoot.audioContextState.audioContext) {
|
||||
// return <>please click window</>
|
||||
// }
|
||||
// エラーバウンダリー設定
|
||||
const [error, setError] = useState<{ error: Error, errorInfo: ErrorInfo }>()
|
||||
|
||||
// localForage.config({
|
||||
// driver: localForage.INDEXEDDB,
|
||||
// name: INDEXEDDB_DB_APP_NAME,
|
||||
// version: 1.0,
|
||||
// storeName: INDEXEDDB_DB_NAME,
|
||||
// description: 'appStorage'
|
||||
// })
|
||||
|
||||
const errorComponent = useMemo(() => {
|
||||
const errorName = error?.error.name || "no error name"
|
||||
const errorMessage = error?.error.message || "no error message"
|
||||
const errorInfos = (error?.errorInfo.componentStack || "no error stack").split("\n")
|
||||
|
||||
const onClearCacheClicked = () => {
|
||||
[
|
||||
INDEXEDDB_KEY_CLIENT,
|
||||
INDEXEDDB_KEY_SERVER,
|
||||
INDEXEDDB_KEY_WORKLETNODE,
|
||||
INDEXEDDB_KEY_MODEL_DATA,
|
||||
INDEXEDDB_KEY_WORKLET
|
||||
].forEach((x) => {
|
||||
localForage.removeItem(x)
|
||||
})
|
||||
location.reload();
|
||||
}
|
||||
return (
|
||||
<div className="error-container">
|
||||
<div className="top-error-message">
|
||||
ちょっと問題が起きたみたいです。
|
||||
</div>
|
||||
<div className="top-error-description">
|
||||
<p>このアプリで管理している情報をクリアすると回復する場合があります。</p>
|
||||
<p>下記のボタンを押して情報をクリアします。</p>
|
||||
<p><button onClick={onClearCacheClicked}>アプリを初期化</button></p>
|
||||
</div>
|
||||
<div className="error-detail">
|
||||
<div className="error-name">
|
||||
{errorName}
|
||||
</div>
|
||||
<div className="error-message">
|
||||
{errorMessage}
|
||||
</div>
|
||||
<div className="error-info-container">
|
||||
{errorInfos.map(x => {
|
||||
return <div className="error-info-line" key={x}>{x}</div>
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [error])
|
||||
|
||||
const updateError = (error: Error, errorInfo: React.ErrorInfo) => {
|
||||
console.log("error compo", error, errorInfo)
|
||||
setError({ error, errorInfo })
|
||||
}
|
||||
|
||||
return (
|
||||
<AppStateProvider>
|
||||
<App></App>
|
||||
</AppStateProvider>
|
||||
<ErrorBoundary fallback={errorComponent} onError={updateError}>
|
||||
<AppStateProvider>
|
||||
<App></App>
|
||||
</AppStateProvider>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
@ -103,3 +163,4 @@ root.render(
|
||||
<AppStateWrapper></AppStateWrapper>
|
||||
</AppRootProvider>
|
||||
);
|
||||
|
||||
|
@ -13,8 +13,8 @@ export const useAudioConfig = (): AudioConfigState => {
|
||||
document.removeEventListener('mousedown', createAudioContext);
|
||||
setAudioContext(ctx)
|
||||
}
|
||||
document.addEventListener('touchstart', createAudioContext);
|
||||
document.addEventListener('mousedown', createAudioContext);
|
||||
document.addEventListener('touchstart', createAudioContext, false);
|
||||
document.addEventListener('mousedown', createAudioContext, false);
|
||||
}, [])
|
||||
|
||||
const ret: AudioConfigState = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useContext } from "react";
|
||||
import React, { useContext, useRef } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { AudioConfigState, useAudioConfig } from "../001_globalHooks/001_useAudioConfig";
|
||||
|
||||
@ -8,6 +8,7 @@ type Props = {
|
||||
|
||||
type AppRootValue = {
|
||||
audioContextState: AudioConfigState
|
||||
|
||||
}
|
||||
|
||||
const AppRootContext = React.createContext<AppRootValue | null>(null);
|
||||
@ -21,9 +22,8 @@ export const useAppRoot = (): AppRootValue => {
|
||||
|
||||
export const AppRootProvider = ({ children }: Props) => {
|
||||
const audioContextState = useAudioConfig()
|
||||
|
||||
const providerValue: AppRootValue = {
|
||||
audioContextState
|
||||
audioContextState,
|
||||
};
|
||||
|
||||
return <AppRootContext.Provider value={providerValue}>{children}</AppRootContext.Provider>;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
import React, { useContext, useEffect } from "react";
|
||||
import React, { useContext, useEffect, useRef } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { useVCClient, VCClientState } from "../001_globalHooks/001_useVCClient";
|
||||
import { FrontendManagerStateAndMethod, useFrontendManager } from "../001_globalHooks/010_useFrontendManager";
|
||||
@ -12,6 +12,7 @@ type Props = {
|
||||
type AppStateValue = ClientState & {
|
||||
audioContext: AudioContext
|
||||
frontendManagerState: FrontendManagerStateAndMethod;
|
||||
initializedRef: React.MutableRefObject<boolean>
|
||||
}
|
||||
|
||||
const AppStateContext = React.createContext<AppStateValue | null>(null);
|
||||
@ -28,10 +29,21 @@ export const AppStateProvider = ({ children }: Props) => {
|
||||
const clientState = useVCClient({ audioContext: appRoot.audioContextState.audioContext })
|
||||
const frontendManagerState = useFrontendManager();
|
||||
|
||||
const initializedRef = useRef<boolean>(false)
|
||||
useEffect(() => {
|
||||
if (clientState.clientState.initialized) {
|
||||
initializedRef.current = true
|
||||
}
|
||||
}, [clientState.clientState.initialized])
|
||||
|
||||
|
||||
const providerValue: AppStateValue = {
|
||||
audioContext: appRoot.audioContextState.audioContext!,
|
||||
...clientState.clientState,
|
||||
frontendManagerState
|
||||
frontendManagerState,
|
||||
initializedRef
|
||||
|
||||
|
||||
};
|
||||
|
||||
return <AppStateContext.Provider value={providerValue}>{children}</AppStateContext.Provider>;
|
||||
|
56
client/demo/src/001_provider/900_ErrorBoundary.tsx
Normal file
56
client/demo/src/001_provider/900_ErrorBoundary.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import React, { createRef, ErrorInfo } from 'react';
|
||||
|
||||
type ErrorBoundaryProps = {
|
||||
children: React.ReactNode;
|
||||
fallback: React.ReactNode;
|
||||
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
||||
}
|
||||
|
||||
type ErrorBoundaryState = {
|
||||
hasError: boolean;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
private eventHandler: () => void
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
this.eventHandler = this.updateError.bind(this);
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(_error: Error) {
|
||||
// console.warn("React Error Boundary Catch", error)
|
||||
return { hasError: true };
|
||||
}
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
// For logging
|
||||
console.warn("React Error Boundary Catch", error, errorInfo)
|
||||
const { onError } = this.props;
|
||||
if (onError) {
|
||||
onError(error, errorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 非同期例外対応
|
||||
updateError() {
|
||||
this.setState({ hasError: true });
|
||||
}
|
||||
componentDidMount() {
|
||||
window.addEventListener('unhandledrejection', this.eventHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('unhandledrejection', this.eventHandler)
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default ErrorBoundary;
|
@ -29,11 +29,17 @@ export const useServerControl = () => {
|
||||
|
||||
const startButtonRow = useMemo(() => {
|
||||
const onStartClicked = async () => {
|
||||
if (!appState.audioContext) {
|
||||
await new Promise<void>((resolve) => {
|
||||
console.log("wait 2000ms")
|
||||
setTimeout(resolve, 1000 * 2)
|
||||
})
|
||||
if (!appState.initializedRef.current) {
|
||||
while (true) {
|
||||
// console.log("wait 500ms")
|
||||
await new Promise<void>((resolve) => {
|
||||
setTimeout(resolve, 500)
|
||||
})
|
||||
// console.log("initiliazed", appState.initializedRef.current)
|
||||
if (appState.initializedRef.current) {
|
||||
break
|
||||
}
|
||||
}
|
||||
setStartWithAudioContextCreate(true)
|
||||
} else {
|
||||
appState.frontendManagerState.setIsConverting(true)
|
||||
|
@ -121,6 +121,9 @@ export const useModelSettingArea = (): ServerSettingState => {
|
||||
const pyTorchFilenameText = appState.serverSetting.fileUploadSetting.pyTorchModel?.filename || appState.serverSetting.fileUploadSetting.pyTorchModel?.file?.name || ""
|
||||
const correspondenceFileText = appState.clientSetting.clientSetting.correspondences ? JSON.stringify(appState.clientSetting.clientSetting.correspondences.map(x => { return x.dirname })) : ""
|
||||
|
||||
const uploadingStatus = appState.serverSetting.isUploading ?
|
||||
appState.serverSetting.uploadProgress == 0 ? `loading model...(wait about 20sec)` : `uploading.... ${appState.serverSetting.uploadProgress}%` : ""
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
@ -190,7 +193,7 @@ export const useModelSettingArea = (): ServerSettingState => {
|
||||
<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-text">
|
||||
{appState.serverSetting.isUploading ? `uploading.... ${appState.serverSetting.uploadProgress}%` : ""}
|
||||
{uploadingStatus}
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className={uploadButtonClassName} onClick={uploadButtonAction}>{uploadButtonLabel}</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Yusei+Magic&display=swap");
|
||||
|
||||
@import "./101_RotatedButton.css";
|
||||
|
||||
@import "./Error.css";
|
||||
:root {
|
||||
--text-color: #333;
|
||||
--company-color1: rgba(64, 119, 187, 1);
|
||||
@ -54,6 +54,12 @@ body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.first-gesture {
|
||||
background: rgba(200, 0, 0, 0.2);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Main + Section Partition*/
|
||||
.main-body {
|
||||
|
30
client/demo/src/css/Error.css
Normal file
30
client/demo/src/css/Error.css
Normal file
@ -0,0 +1,30 @@
|
||||
.error-container {
|
||||
margin: 2rem;
|
||||
.top-error-message {
|
||||
color: #44a;
|
||||
font-size: 2rem;
|
||||
font-weight: 100;
|
||||
}
|
||||
.top-error-description {
|
||||
color: #444;
|
||||
font-size: 1rem;
|
||||
font-weight: 100;
|
||||
}
|
||||
.error-detail {
|
||||
margin-top: 2rem;
|
||||
padding: 1rem;
|
||||
border: 1px solid;
|
||||
.error-name {
|
||||
font-weight: 700;
|
||||
}
|
||||
.error-message {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.error-info-container {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
.error-info-line {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
client/lib/package-lock.json
generated
4
client/lib/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.77",
|
||||
"version": "1.0.78",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.77",
|
||||
"version": "1.0.78",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/readable-stream": "^2.3.15",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.77",
|
||||
"version": "1.0.78",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"directories": {
|
||||
|
@ -11,6 +11,7 @@ export type UseClientProps = {
|
||||
}
|
||||
|
||||
export type ClientState = {
|
||||
initialized: boolean
|
||||
// 各種設定I/Fへの参照
|
||||
workletSetting: WorkletSettingState
|
||||
clientSetting: ClientSettingState
|
||||
@ -43,6 +44,7 @@ const InitialPerformanceData: PerformanceData = {
|
||||
|
||||
export const useClient = (props: UseClientProps): ClientState => {
|
||||
|
||||
const [initialized, setInitialized] = useState<boolean>(false)
|
||||
// (1-1) クライアント
|
||||
const voiceChangerClientRef = useRef<VoiceChangerClient | null>(null)
|
||||
const [voiceChangerClient, setVoiceChangerClient] = useState<VoiceChangerClient | null>(voiceChangerClientRef.current)
|
||||
@ -110,6 +112,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
||||
audio.srcObject = voiceChangerClientRef.current.stream
|
||||
audio.play()
|
||||
initializedResolveRef.current!()
|
||||
setInitialized(true)
|
||||
}
|
||||
initialized()
|
||||
}, [props.audioContext])
|
||||
@ -133,6 +136,7 @@ export const useClient = (props: UseClientProps): ClientState => {
|
||||
}
|
||||
|
||||
return {
|
||||
initialized,
|
||||
// 各種設定I/Fへの参照
|
||||
clientSetting,
|
||||
workletNodeSetting,
|
||||
|
@ -28,6 +28,10 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
|
||||
useEffect(() => {
|
||||
const loadCache = async () => {
|
||||
const setting = await getItem(INDEXEDDB_KEY_CLIENT) as VoiceChangerClientSetting
|
||||
if (!setting) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log("[ClientSetting] Load Setting from db", setting)
|
||||
if (setting.audioInput == "null") {
|
||||
setting.audioInput = null
|
||||
|
Loading…
x
Reference in New Issue
Block a user