mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-02-03 00:33:57 +03:00
WIP:WebEdition GUI Improve
This commit is contained in:
parent
ab837561d9
commit
82de23bb1a
@ -1,5 +1,5 @@
|
|||||||
import { ClientState, WebModelSlot } from "@dannadori/voice-changer-client-js";
|
import { ClientState, WebModelSlot } from "@dannadori/voice-changer-client-js";
|
||||||
import { VoiceChangerJSClientConfig, VoiceChangerJSClient, ProgressUpdateType, ProgreeeUpdateCallbcckInfo, VoiceChangerType, InputLengthKey } from "@dannadori/voice-changer-js";
|
import { VoiceChangerJSClientConfig, VoiceChangerJSClient, ProgressUpdateType, ProgreeeUpdateCallbcckInfo, VoiceChangerType, InputLengthKey, ResponseTimeInfo } from "@dannadori/voice-changer-js";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
|
||||||
export type UseWebInfoProps = {
|
export type UseWebInfoProps = {
|
||||||
@ -33,6 +33,7 @@ export type WebInfoState = {
|
|||||||
progressWarmup: number;
|
progressWarmup: number;
|
||||||
webModelslot: WebModelSlot;
|
webModelslot: WebModelSlot;
|
||||||
upkey: number;
|
upkey: number;
|
||||||
|
responseTimeInfo: ResponseTimeInfo;
|
||||||
};
|
};
|
||||||
export type WebInfoStateAndMethod = WebInfoState & {
|
export type WebInfoStateAndMethod = WebInfoState & {
|
||||||
loadVoiceChanagerModel: () => Promise<void>;
|
loadVoiceChanagerModel: () => Promise<void>;
|
||||||
@ -160,7 +161,7 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
|||||||
name: "あみたろ",
|
name: "あみたろ",
|
||||||
termOfUse: "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/amitaro_contentvec_256/term_of_use.txt",
|
termOfUse: "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/amitaro_contentvec_256/term_of_use.txt",
|
||||||
sampleRate: sampleRate,
|
sampleRate: sampleRate,
|
||||||
useF0: false,
|
useF0: useF0,
|
||||||
inputLength: inputLength,
|
inputLength: inputLength,
|
||||||
progressCallback,
|
progressCallback,
|
||||||
};
|
};
|
||||||
@ -173,6 +174,11 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
|||||||
const [progressLoadVCModel, setProgressLoadVCModel] = useState<number>(0);
|
const [progressLoadVCModel, setProgressLoadVCModel] = useState<number>(0);
|
||||||
const [progressWarmup, setProgressWarmup] = useState<number>(0);
|
const [progressWarmup, setProgressWarmup] = useState<number>(0);
|
||||||
const [upkey, setUpkey] = useState<number>(0);
|
const [upkey, setUpkey] = useState<number>(0);
|
||||||
|
const [responseTimeInfo, setResponseTimeInfo] = useState<ResponseTimeInfo>({
|
||||||
|
responseTime: 0,
|
||||||
|
realDuration: 0,
|
||||||
|
rtf: 0,
|
||||||
|
});
|
||||||
const voiceChangerJSClient = useRef<VoiceChangerJSClient>();
|
const voiceChangerJSClient = useRef<VoiceChangerJSClient>();
|
||||||
|
|
||||||
const webModelslot: WebModelSlot = useMemo(() => {
|
const webModelslot: WebModelSlot = useMemo(() => {
|
||||||
@ -223,6 +229,7 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
|||||||
// check time
|
// check time
|
||||||
const responseTimeInfo = await voiceChangerJSClient.current.checkResponseTime();
|
const responseTimeInfo = await voiceChangerJSClient.current.checkResponseTime();
|
||||||
console.log("responseTimeInfo", responseTimeInfo);
|
console.log("responseTimeInfo", responseTimeInfo);
|
||||||
|
setResponseTimeInfo(responseTimeInfo);
|
||||||
|
|
||||||
props.clientState?.setInternalAudioProcessCallback({
|
props.clientState?.setInternalAudioProcessCallback({
|
||||||
processAudio: async (data: Uint8Array) => {
|
processAudio: async (data: Uint8Array) => {
|
||||||
@ -231,6 +238,7 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
|||||||
const audio = new Uint8Array(res[0].buffer);
|
const audio = new Uint8Array(res[0].buffer);
|
||||||
if (res[1]) {
|
if (res[1]) {
|
||||||
console.log("RESPONSE!", res[1]);
|
console.log("RESPONSE!", res[1]);
|
||||||
|
setResponseTimeInfo(res[1]);
|
||||||
}
|
}
|
||||||
return audio;
|
return audio;
|
||||||
},
|
},
|
||||||
@ -263,6 +271,7 @@ export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
|||||||
progressWarmup,
|
progressWarmup,
|
||||||
webModelslot,
|
webModelslot,
|
||||||
upkey,
|
upkey,
|
||||||
|
responseTimeInfo,
|
||||||
loadVoiceChanagerModel,
|
loadVoiceChanagerModel,
|
||||||
setUpkey,
|
setUpkey,
|
||||||
setVoiceChangerConfig,
|
setVoiceChangerConfig,
|
||||||
|
@ -48,13 +48,20 @@ export const Portrait = (_props: PortraitProps) => {
|
|||||||
const vol = document.getElementById("status-vol") as HTMLSpanElement;
|
const vol = document.getElementById("status-vol") as HTMLSpanElement;
|
||||||
const buf = document.getElementById("status-buf") as HTMLSpanElement;
|
const buf = document.getElementById("status-buf") as HTMLSpanElement;
|
||||||
const res = document.getElementById("status-res") as HTMLSpanElement;
|
const res = document.getElementById("status-res") as HTMLSpanElement;
|
||||||
|
const rtf = document.getElementById("status-rtf") as HTMLSpanElement;
|
||||||
if (!vol || !buf || !res) {
|
if (!vol || !buf || !res) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vol.innerText = volume.toFixed(4);
|
vol.innerText = volume.toFixed(4);
|
||||||
buf.innerText = bufferingTime.toString();
|
if (webEdition) {
|
||||||
res.innerText = performance.responseTime.toString();
|
buf.innerText = webInfoState.responseTimeInfo.realDuration.toString() ?? "0";
|
||||||
}, [volume, bufferingTime, performance]);
|
res.innerText = webInfoState.responseTimeInfo.responseTime.toString() ?? "0";
|
||||||
|
rtf.innerText = webInfoState.responseTimeInfo.rtf.toString() ?? "0";
|
||||||
|
} else {
|
||||||
|
buf.innerText = bufferingTime.toString();
|
||||||
|
res.innerText = performance.responseTime.toString();
|
||||||
|
}
|
||||||
|
}, [volume, bufferingTime, performance, webInfoState.responseTimeInfo]);
|
||||||
|
|
||||||
const setSelectedClass = () => {
|
const setSelectedClass = () => {
|
||||||
const iframe = document.querySelector(".beatrice-speaker-graph-container");
|
const iframe = document.querySelector(".beatrice-speaker-graph-container");
|
||||||
@ -194,6 +201,9 @@ export const Portrait = (_props: PortraitProps) => {
|
|||||||
<p>
|
<p>
|
||||||
res: <span id="status-res">0</span> ms
|
res: <span id="status-res">0</span> ms
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
rtf: <span id="status-rtf">0</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="portrait-area-terms-of-use">{selectedTermOfUseUrlLink}</div>
|
<div className="portrait-area-terms-of-use">{selectedTermOfUseUrlLink}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useAppState } from "../../../001_provider/001_AppStateProvider";
|
import { useAppState } from "../../../001_provider/001_AppStateProvider";
|
||||||
import { useAppRoot } from "../../../001_provider/001_AppRootProvider";
|
import { useAppRoot } from "../../../001_provider/001_AppRootProvider";
|
||||||
|
import { useGuiState } from "../001_GuiStateProvider";
|
||||||
|
|
||||||
export type WebEditionSettingAreaProps = {};
|
export type WebEditionSettingAreaProps = {};
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
const { serverSetting, webInfoState } = useAppState();
|
const { serverSetting, webInfoState } = useAppState();
|
||||||
const { appGuiSettingState } = useAppRoot();
|
const { appGuiSettingState } = useAppRoot();
|
||||||
const webEdition = appGuiSettingState.edition.indexOf("web") >= 0;
|
const webEdition = appGuiSettingState.edition.indexOf("web") >= 0;
|
||||||
|
const guiState = useGuiState();
|
||||||
|
|
||||||
const selected = useMemo(() => {
|
const selected = useMemo(() => {
|
||||||
if (webEdition) {
|
if (webEdition) {
|
||||||
@ -21,6 +23,8 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const readyForConfig = guiState.isConverting == false && webInfoState.webModelLoadingState == "ready";
|
||||||
|
|
||||||
const versionV1ClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.config.voiceChangerType == "rvcv1" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
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 versionV2ClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.config.voiceChangerType == "rvcv2" ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||||
const verison = (
|
const verison = (
|
||||||
@ -31,17 +35,18 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
<span className="character-area-slider-control-kind"></span>
|
<span className="character-area-slider-control-kind"></span>
|
||||||
<span className="character-area-control-buttons">
|
<span className="character-area-control-buttons">
|
||||||
<span
|
<span
|
||||||
className={versionV1ClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : versionV1ClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.config.voiceChangerType == "rvcv1" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig("rvcv1", webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
webInfoState.setVoiceChangerConfig("rvcv1", webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
v1
|
v1
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={versionV2ClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : versionV2ClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log("v2 clicked!");
|
if (webInfoState.voiceChangerConfig.config.voiceChangerType == "rvcv2" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig("rvcv2", webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
webInfoState.setVoiceChangerConfig("rvcv2", webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -63,16 +68,18 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
<span className="character-area-slider-control-kind"></span>
|
<span className="character-area-slider-control-kind"></span>
|
||||||
<span className="character-area-control-buttons">
|
<span className="character-area-control-buttons">
|
||||||
<span
|
<span
|
||||||
className={sr32KClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : sr32KClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.sampleRate == "32k" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, "32k", webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, "32k", webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
32k
|
32k
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={sr40KClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : sr40KClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.sampleRate == "40k" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, "40k", webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, "40k", webInfoState.voiceChangerConfig.useF0, webInfoState.voiceChangerConfig.inputLength);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -84,6 +91,7 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log("webInfoState.voiceChangerConfig.useF0 ", webInfoState.voiceChangerConfig.useF0);
|
||||||
const pitchEnableClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.useF0 == true ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
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 pitchDisableClassName = "character-area-control-button" + (webInfoState.voiceChangerConfig.useF0 == false ? " character-area-control-button-active" : " character-area-control-button-stanby");
|
||||||
const pitch = (
|
const pitch = (
|
||||||
@ -94,16 +102,18 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
<span className="character-area-slider-control-kind"></span>
|
<span className="character-area-slider-control-kind"></span>
|
||||||
<span className="character-area-control-buttons">
|
<span className="character-area-control-buttons">
|
||||||
<span
|
<span
|
||||||
className={pitchEnableClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : pitchEnableClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.useF0 == true || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, true, webInfoState.voiceChangerConfig.inputLength);
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, true, webInfoState.voiceChangerConfig.inputLength);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Enable
|
Enable
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={pitchDisableClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : pitchDisableClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.useF0 == false || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, false, webInfoState.voiceChangerConfig.inputLength);
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, false, webInfoState.voiceChangerConfig.inputLength);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -126,24 +136,27 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
<span className="character-area-slider-control-kind"></span>
|
<span className="character-area-slider-control-kind"></span>
|
||||||
<span className="character-area-control-buttons">
|
<span className="character-area-control-buttons">
|
||||||
<span
|
<span
|
||||||
className={latencyHighClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : latencyHighClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.inputLength == "24000" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "24000");
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "24000");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
High
|
High
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={latencyMidClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : latencyMidClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.inputLength == "12000" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "12000");
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "12000");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Mid
|
Mid
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={latencyLowClassName}
|
className={!readyForConfig ? "character-area-control-button-disable" : latencyLowClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (webInfoState.voiceChangerConfig.inputLength == "8000" || !readyForConfig) return;
|
||||||
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "8000");
|
webInfoState.setVoiceChangerConfig(webInfoState.voiceChangerConfig.config.voiceChangerType, webInfoState.voiceChangerConfig.sampleRate, webInfoState.voiceChangerConfig.useF0, "8000");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -162,7 +175,19 @@ export const WebEditionSettingArea = (_props: WebEditionSettingAreaProps) => {
|
|||||||
{latency}
|
{latency}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, [serverSetting.serverSetting, serverSetting.updateServerSettings, selected, webInfoState.upkey, webInfoState.voiceChangerConfig.config.voiceChangerType]);
|
}, [
|
||||||
|
serverSetting.serverSetting,
|
||||||
|
serverSetting.updateServerSettings,
|
||||||
|
selected,
|
||||||
|
webInfoState.upkey,
|
||||||
|
webInfoState.voiceChangerConfig.config.voiceChangerType,
|
||||||
|
webInfoState.voiceChangerConfig.sampleRate,
|
||||||
|
webInfoState.voiceChangerConfig.useF0,
|
||||||
|
webInfoState.voiceChangerConfig.inputLength,
|
||||||
|
webInfoState.webModelLoadingState,
|
||||||
|
guiState.isConverting,
|
||||||
|
webInfoState.webModelLoadingState,
|
||||||
|
]);
|
||||||
|
|
||||||
return settingArea;
|
return settingArea;
|
||||||
};
|
};
|
||||||
|
@ -1364,6 +1364,15 @@ body {
|
|||||||
border: solid 1px #000;
|
border: solid 1px #000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.character-area-control-button-disable {
|
||||||
|
width: 5rem;
|
||||||
|
border: solid 1px #333;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: #d3d7d3;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
.character-area-control-passthru-button-stanby {
|
.character-area-control-passthru-button-stanby {
|
||||||
width: 5rem;
|
width: 5rem;
|
||||||
border: solid 1px #999;
|
border: solid 1px #999;
|
||||||
|
Loading…
Reference in New Issue
Block a user