mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-01-23 13:35:12 +03:00
WIP:WEB version control
This commit is contained in:
parent
14c73a71d2
commit
ab837561d9
@ -17,11 +17,13 @@ export type WebModelLoadingState = (typeof WebModelLoadingState)[keyof typeof We
|
||||
export type VoiceChangerConfig = {
|
||||
config: VoiceChangerJSClientConfig;
|
||||
modelUrl: string;
|
||||
progressCallback?: ((data: any) => void) | null;
|
||||
portrait: string;
|
||||
name: string;
|
||||
termOfUse: string;
|
||||
f0: boolean;
|
||||
sampleRate: ModelSampleRateStr;
|
||||
useF0: boolean;
|
||||
inputLength: InputLengthKey;
|
||||
progressCallback?: ((data: any) => void) | null;
|
||||
};
|
||||
export type WebInfoState = {
|
||||
voiceChangerConfig: VoiceChangerConfig;
|
||||
@ -35,6 +37,7 @@ export type WebInfoState = {
|
||||
export type WebInfoStateAndMethod = WebInfoState & {
|
||||
loadVoiceChanagerModel: () => Promise<void>;
|
||||
setUpkey: (upkey: number) => void;
|
||||
setVoiceChangerConfig: (voiceChangerType: VoiceChangerType, sampleRate: ModelSampleRateStr, useF0: boolean, inputLength: InputLengthKey) => void;
|
||||
};
|
||||
|
||||
const ModelSampleRateStr = {
|
||||
@ -120,72 +123,51 @@ const f0ModelUrl: { [modelType in VoiceChangerType]: { [inputLength in InputLeng
|
||||
},
|
||||
};
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_24000.bin
|
||||
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_8000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_12000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_16000.bin
|
||||
// https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_24000.bin
|
||||
|
||||
export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
||||
const voiceChangerType: VoiceChangerType = "rvcv1";
|
||||
const inputLength: InputLengthKey = "24000";
|
||||
const useF0 = false;
|
||||
const sampleRate: ModelSampleRateStr = "40k";
|
||||
let modelUrl;
|
||||
if (useF0) {
|
||||
modelUrl = f0ModelUrl[voiceChangerType][inputLength][sampleRate];
|
||||
} else {
|
||||
modelUrl = noF0ModelUrl[voiceChangerType][inputLength][sampleRate];
|
||||
}
|
||||
const [voiceChangerConfig, setVoiceChangerConfig] = useState<VoiceChangerConfig>({
|
||||
config: {
|
||||
voiceChangerType: voiceChangerType,
|
||||
const initVoiceChangerType: VoiceChangerType = "rvcv1";
|
||||
const initInputLength: InputLengthKey = "24000";
|
||||
const initUseF0 = false;
|
||||
const initSampleRate: ModelSampleRateStr = "40k";
|
||||
|
||||
const progressCallback = (data: ProgreeeUpdateCallbcckInfo) => {
|
||||
if (data.progressUpdateType === ProgressUpdateType.loadPreprocessModel) {
|
||||
setProgressLoadPreprocess(data.progress);
|
||||
} else if (data.progressUpdateType === ProgressUpdateType.loadVCModel) {
|
||||
setProgressLoadVCModel(data.progress);
|
||||
} else if (data.progressUpdateType === ProgressUpdateType.checkResponseTime) {
|
||||
setProgressWarmup(data.progress);
|
||||
}
|
||||
};
|
||||
|
||||
const generateVoiceChangerConfig = (voiceChangerType: VoiceChangerType, sampleRate: ModelSampleRateStr, useF0: boolean, inputLength: InputLengthKey) => {
|
||||
let modelUrl;
|
||||
if (useF0) {
|
||||
modelUrl = f0ModelUrl[voiceChangerType][inputLength][sampleRate];
|
||||
} else {
|
||||
modelUrl = noF0ModelUrl[voiceChangerType][inputLength][sampleRate];
|
||||
}
|
||||
|
||||
const config: VoiceChangerConfig = {
|
||||
config: {
|
||||
voiceChangerType: voiceChangerType,
|
||||
inputLength: inputLength,
|
||||
baseUrl: window.location.origin,
|
||||
inputSamplingRate: 48000,
|
||||
outputSamplingRate: 48000,
|
||||
},
|
||||
modelUrl: modelUrl,
|
||||
portrait: `${window.location.origin}/models/amitaro.png`,
|
||||
name: "あみたろ",
|
||||
termOfUse: "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/amitaro_contentvec_256/term_of_use.txt",
|
||||
sampleRate: sampleRate,
|
||||
useF0: false,
|
||||
inputLength: inputLength,
|
||||
baseUrl: window.location.origin,
|
||||
inputSamplingRate: 48000,
|
||||
outputSamplingRate: 48000,
|
||||
},
|
||||
modelUrl: modelUrl,
|
||||
progressCallback: null,
|
||||
portrait: `${window.location.origin}/models/amitaro.png`,
|
||||
name: "あみたろ",
|
||||
termOfUse: "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/amitaro_contentvec_256/term_of_use.txt",
|
||||
f0: false,
|
||||
});
|
||||
progressCallback,
|
||||
};
|
||||
return config;
|
||||
};
|
||||
|
||||
const [voiceChangerConfig, _setVoiceChangerConfig] = useState<VoiceChangerConfig>(generateVoiceChangerConfig(initVoiceChangerType, initSampleRate, initUseF0, initInputLength));
|
||||
const [webModelLoadingState, setWebModelLoadingState] = useState<WebModelLoadingState>(WebModelLoadingState.none);
|
||||
const [progressLoadPreprocess, setProgressLoadPreprocess] = useState<number>(0);
|
||||
const [progressLoadVCModel, setProgressLoadVCModel] = useState<number>(0);
|
||||
@ -205,24 +187,19 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
||||
speakers: {},
|
||||
defaultTune: 0,
|
||||
modelType: "pyTorchRVCNono",
|
||||
f0: voiceChangerConfig.f0,
|
||||
f0: voiceChangerConfig.useF0,
|
||||
samplingRate: 0,
|
||||
modelFile: "",
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const progressCallback = (data: ProgreeeUpdateCallbcckInfo) => {
|
||||
if (data.progressUpdateType === ProgressUpdateType.loadPreprocessModel) {
|
||||
setProgressLoadPreprocess(data.progress);
|
||||
} else if (data.progressUpdateType === ProgressUpdateType.loadVCModel) {
|
||||
setProgressLoadVCModel(data.progress);
|
||||
} else if (data.progressUpdateType === ProgressUpdateType.checkResponseTime) {
|
||||
setProgressWarmup(data.progress);
|
||||
}
|
||||
};
|
||||
setVoiceChangerConfig({ ...voiceChangerConfig, progressCallback });
|
||||
}, []);
|
||||
const setVoiceChangerConfig = (voiceChangerType: VoiceChangerType, sampleRate: ModelSampleRateStr, useF0: boolean, inputLength: InputLengthKey) => {
|
||||
const config = generateVoiceChangerConfig(voiceChangerType, sampleRate, useF0, inputLength);
|
||||
_setVoiceChangerConfig(config);
|
||||
};
|
||||
// useEffect(() => {
|
||||
// setVoiceChangerConfig({ ...voiceChangerConfig, progressCallback });
|
||||
// }, []);
|
||||
|
||||
const loadVoiceChanagerModel = async () => {
|
||||
if (!props.clientState) {
|
||||
@ -232,9 +209,11 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
||||
console.warn("[useWebInfo] clientState is not initialized yet");
|
||||
return;
|
||||
}
|
||||
console.log("loadVoiceChanagerModel1", voiceChangerConfig);
|
||||
setWebModelLoadingState("loading");
|
||||
voiceChangerJSClient.current = new VoiceChangerJSClient();
|
||||
await voiceChangerJSClient.current.initialize(voiceChangerConfig.config, voiceChangerConfig.modelUrl, voiceChangerConfig.progressCallback);
|
||||
console.log("loadVoiceChanagerModel2");
|
||||
|
||||
// worm up
|
||||
setWebModelLoadingState("warmup");
|
||||
@ -266,6 +245,16 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
||||
voiceChangerJSClient.current.setUpkey(upkey);
|
||||
}, [upkey]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("change voice ", voiceChangerConfig);
|
||||
|
||||
setProgressLoadPreprocess(0);
|
||||
setProgressLoadVCModel(0);
|
||||
setProgressWarmup(0);
|
||||
|
||||
loadVoiceChanagerModel();
|
||||
}, [voiceChangerConfig, props.clientState?.initialized]);
|
||||
|
||||
return {
|
||||
voiceChangerConfig,
|
||||
webModelLoadingState,
|
||||
@ -276,5 +265,6 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
||||
upkey,
|
||||
loadVoiceChanagerModel,
|
||||
setUpkey,
|
||||
setVoiceChangerConfig,
|
||||
};
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ export const AppStateProvider = ({ children }: Props) => {
|
||||
useEffect(() => {
|
||||
if (appRoot.appGuiSettingState.edition.indexOf("web") >= 0 && clientState.clientState.initialized) {
|
||||
clientState.clientState.setWorkletNodeSetting({ ...clientState.clientState.setting.workletNodeSetting, protocol: "internal" });
|
||||
webInfoState.loadVoiceChanagerModel();
|
||||
// webInfoState.loadVoiceChanagerModel(); // hook内でuseEffectでinvoke
|
||||
}
|
||||
}, [clientState.clientState.initialized]);
|
||||
|
||||
|
@ -0,0 +1,168 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { useAppState } from "../../../001_provider/001_AppStateProvider";
|
||||
import { useAppRoot } from "../../../001_provider/001_AppRootProvider";
|
||||
|
||||
export type WebEditionSettingAreaProps = {};
|
||||
|
||||
export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
||||
const { serverSetting, webInfoState } = useAppState();
|
||||
const { appGuiSettingState } = useAppRoot();
|
||||
const webEdition = appGuiSettingState.edition.indexOf("web") >= 0;
|
||||
|
||||
const selected = useMemo(() => {
|
||||
if (webEdition) {
|
||||
return webInfoState.webModelslot;
|
||||
}
|
||||
return null;
|
||||
}, [webEdition]);
|
||||
|
||||
const settingArea = useMemo(() => {
|
||||
if (!selected) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const versionV1ClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.config.voiceChangerType == "rvcv1" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const versionV2ClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.config.voiceChangerType == "rvcv2" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const verison = (
|
||||
<div className="character-area-control">
|
||||
<div className="character-area-control-title">Version</div>
|
||||
<div className="character-area-control-field">
|
||||
<div className="character-area-slider-control">
|
||||
<span className="character-area-slider-control-kind"></span>
|
||||
<span className="character-area-control-buttons">
|
||||
<span
|
||||
className={versionV1ClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig("rvcv1", webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||
}}
|
||||
>
|
||||
v1
|
||||
</span>
|
||||
<span
|
||||
className={versionV2ClassName}
|
||||
onClick={() => {
|
||||
console.log("v2 clicked!");
|
||||
webInfoState.setVoiceChangerConfig("rvcv2", webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||
}}
|
||||
>
|
||||
v2
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const sr32KClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.sampleRate == "32k" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const sr40KClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.sampleRate == "40k" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const sampleRate = (
|
||||
<div className="character-area-control">
|
||||
<div className="character-area-control-title">SR</div>
|
||||
<div className="character-area-control-field">
|
||||
<div className="character-area-slider-control">
|
||||
<span className="character-area-slider-control-kind"></span>
|
||||
<span className="character-area-control-buttons">
|
||||
<span
|
||||
className={sr32KClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, "32k", webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||
}}
|
||||
>
|
||||
32k
|
||||
</span>
|
||||
<span
|
||||
className={sr40KClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, "40k", webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||
}}
|
||||
>
|
||||
40k
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const pitchEnableClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.useF0 == true ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const pitchDisableClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.useF0 == false ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const pitch = (
|
||||
<div className="character-area-control">
|
||||
<div className="character-area-control-title">Pitch</div>
|
||||
<div className="character-area-control-field">
|
||||
<div className="character-area-slider-control">
|
||||
<span className="character-area-slider-control-kind"></span>
|
||||
<span className="character-area-control-buttons">
|
||||
<span
|
||||
className={pitchEnableClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, true, webInfoState.voiceChangerConfig.inputLength);
|
||||
}}
|
||||
>
|
||||
Enable
|
||||
</span>
|
||||
<span
|
||||
className={pitchDisableClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, false, webInfoState.voiceChangerConfig.inputLength);
|
||||
}}
|
||||
>
|
||||
Disable
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const latencyHighClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.inputLength == "24000" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const latencyMidClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.inputLength == "12000" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const latencyLowClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.inputLength == "8000" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||
const latency = (
|
||||
<div className="character-area-control">
|
||||
<div className="character-area-control-title">Latency</div>
|
||||
<div className="character-area-control-field">
|
||||
<div className="character-area-slider-control">
|
||||
<span className="character-area-slider-control-kind"></span>
|
||||
<span className="character-area-control-buttons">
|
||||
<span
|
||||
className={latencyHighClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "24000");
|
||||
}}
|
||||
>
|
||||
High
|
||||
</span>
|
||||
<span
|
||||
className={latencyMidClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "12000");
|
||||
}}
|
||||
>
|
||||
Mid
|
||||
</span>
|
||||
<span
|
||||
className={latencyLowClassName}
|
||||
onClick={() => {
|
||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "8000");
|
||||
}}
|
||||
>
|
||||
Low
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{verison}
|
||||
{sampleRate}
|
||||
{pitch}
|
||||
{latency}
|
||||
</>
|
||||
);
|
||||
}, [serverSetting.serverSetting, serverSetting.updateServerSettings, selected, webInfoState.upkey, webInfoState.voiceChangerConfig.config.voiceChangerType]);
|
||||
|
||||
return settingArea;
|
||||
};
|
@ -12,6 +12,7 @@ import { DDSPSVC30SettingArea } from "./101-6_ddsp-svc30SettingArea";
|
||||
import { DiffusionSVCSettingArea } from "./101-7_diffusion-svcSettingArea";
|
||||
import { Portrait } from "./101-0_Portrait";
|
||||
import { useAppRoot } from "../../../001_provider/001_AppRootProvider";
|
||||
import { WebEditionSettingArea } from "./101-8_web-editionSettingArea";
|
||||
|
||||
export type CharacterAreaProps = {};
|
||||
|
||||
@ -226,6 +227,9 @@ export const CharacterArea = (_props: CharacterAreaProps) => {
|
||||
if (!selected) {
|
||||
return <></>;
|
||||
}
|
||||
if (webEdition) {
|
||||
return <></>;
|
||||
}
|
||||
const onUpdateDefaultClicked = async () => {
|
||||
await serverSetting.updateModelDefault();
|
||||
};
|
||||
@ -286,6 +290,7 @@ export const CharacterArea = (_props: CharacterAreaProps) => {
|
||||
<SoVitsSVC40SettingArea />
|
||||
<DDSPSVC30SettingArea />
|
||||
<DiffusionSVCSettingArea />
|
||||
<WebEditionSettingArea />
|
||||
{modelSlotControl}
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user