mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-11 20:32:12 +00:00
UI for editing custom vocoders in TTS models
This commit is contained in:
1 parent
322bcd5504
commit
72d6c0c528
3 files changed
+146
-7
No files matched your search
@@ -284,6 +284,14 @@ class ApiConfig {
|
||||
return base_url + query;
|
||||
}
|
||||
|
||||
listVocoderModels(): string {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/vocoder/list`;
|
||||
}
|
||||
|
||||
getVocoderModel(vocoderToken: string): string {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/vocoder/model/${vocoderToken}`;
|
||||
}
|
||||
|
||||
createCategory(): string {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/category/create`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
import { ApiConfig } from "../ApiConfig";
|
||||
|
||||
export interface ListVocoderModelsSuccessResponse {
|
||||
success: boolean,
|
||||
vocoders: Array<VocoderModel>
|
||||
}
|
||||
|
||||
export interface VocoderModel {
|
||||
vocoder_token: string,
|
||||
vocoder_type: string,
|
||||
title: string,
|
||||
is_staff_recommended: boolean,
|
||||
creator_username: string,
|
||||
creator_display_name: string,
|
||||
creator_gravatar_hash: string,
|
||||
created_at: Date,
|
||||
updated_at: Date,
|
||||
moderator_fields: VocoderModelModeratorFields | undefined | null,
|
||||
}
|
||||
|
||||
export interface VocoderModelModeratorFields {
|
||||
is_mod_disabled_from_public_use: boolean,
|
||||
is_mod_disabled_from_author_use: boolean,
|
||||
is_mod_author_editing_locked: boolean,
|
||||
mod_deleted_at: string | undefined | null,
|
||||
user_deleted_at: string | undefined | null,
|
||||
}
|
||||
|
||||
|
||||
export interface ListVocoderModelsErrorResponse {
|
||||
success: boolean,
|
||||
}
|
||||
|
||||
type ListVocoderModelsResponse = ListVocoderModelsSuccessResponse | ListVocoderModelsErrorResponse;
|
||||
|
||||
export function ListVocoderModelsIsOk(response: ListVocoderModelsResponse): response is ListVocoderModelsSuccessResponse {
|
||||
return response?.success === true;
|
||||
}
|
||||
|
||||
export function ListVocoderModelsIsError(response: ListVocoderModelsResponse): response is ListVocoderModelsErrorResponse {
|
||||
return response?.success === false;
|
||||
}
|
||||
|
||||
export async function ListVocoderModels() : Promise<ListVocoderModelsResponse>
|
||||
{
|
||||
const endpoint = new ApiConfig().listVocoderModels();
|
||||
|
||||
return await fetch(endpoint, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (!res) {
|
||||
return { success : false }; // TODO: This loses error semantics and is deprecated
|
||||
}
|
||||
|
||||
if (res && 'success' in res) {
|
||||
return res;
|
||||
} else {
|
||||
return { success : false };
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
return { success : false };
|
||||
});
|
||||
}
|
||||
@@ -13,6 +13,11 @@ import {
|
||||
TtsModel,
|
||||
TtsModelLookupError,
|
||||
} from "@storyteller/components/src/api/tts/GetTtsModel";
|
||||
import {
|
||||
ListVocoderModels,
|
||||
ListVocoderModelsIsOk,
|
||||
VocoderModel,
|
||||
} from "@storyteller/components/src/api/vocoder/ListVocoderModels";
|
||||
import { BackLink } from "../../_common/BackLink";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
@@ -51,20 +56,28 @@ function TtsModelEditPage(props: Props) {
|
||||
const [ttsModel, setTtsModel] = useState<TtsModel | undefined>(undefined);
|
||||
const [notFoundState, setNotFoundState] = useState<boolean>(false);
|
||||
|
||||
// Vocoder lookup
|
||||
const [vocoderModels, setVocoderModels] = useState<VocoderModel[]>([]);
|
||||
|
||||
// Fields
|
||||
const [title, setTitle] = useState("");
|
||||
const [textPipelineType, setTextPipelineType] = useState<string | null>(null);
|
||||
const [descriptionMarkdown, setDescriptionMarkdown] = useState("");
|
||||
const [fullLanguageTag, setFullLanguageTag] = useState(""); // NB: Should be full IETF, eg. ["en", "en-US", "es-419", etc.]
|
||||
const [visibility, setVisibility] = useState(DEFAULT_VISIBILITY);
|
||||
const [defaultPretrainedVocoder, setDefaultPretrainedVocoder] = useState(
|
||||
DEFAULT_PRETRAINED_VOCODER
|
||||
);
|
||||
const [isFrontPageFeatured, setIsFrontPageFeatured] = useState(false);
|
||||
const [isTwitchFeatured, setIsTwitchFeatured] = useState(false);
|
||||
const [suggestedUniqueBotCommand, setSuggestedUniqueBotCommand] =
|
||||
useState("");
|
||||
|
||||
// Vocoder config (modern)
|
||||
const [maybeCustomVocoderToken, setMaybeCustomVocoderToken] = useState<string | null>(null);
|
||||
|
||||
// Vocoder config (legacy)
|
||||
const [defaultPretrainedVocoder, setDefaultPretrainedVocoder] = useState(
|
||||
DEFAULT_PRETRAINED_VOCODER
|
||||
);
|
||||
|
||||
const getModel = useCallback(async (token) => {
|
||||
const model = await GetTtsModel(token);
|
||||
|
||||
@@ -81,14 +94,17 @@ function TtsModelEditPage(props: Props) {
|
||||
setDescriptionMarkdown(model.description_markdown || "");
|
||||
setFullLanguageTag(model.ietf_language_tag || DEFAULT_MODEL_LANGUAGE);
|
||||
setVisibility(model.creator_set_visibility || DEFAULT_VISIBILITY);
|
||||
setDefaultPretrainedVocoder(
|
||||
model.maybe_default_pretrained_vocoder || DEFAULT_PRETRAINED_VOCODER
|
||||
);
|
||||
setIsFrontPageFeatured(model.is_front_page_featured || false);
|
||||
setIsTwitchFeatured(model.is_twitch_featured || false);
|
||||
setSuggestedUniqueBotCommand(
|
||||
model.maybe_suggested_unique_bot_command || ""
|
||||
);
|
||||
if (!!model.maybe_custom_vocoder) {
|
||||
setMaybeCustomVocoderToken(model.maybe_custom_vocoder.vocoder_token);
|
||||
}
|
||||
setDefaultPretrainedVocoder(
|
||||
model.maybe_default_pretrained_vocoder || DEFAULT_PRETRAINED_VOCODER
|
||||
);
|
||||
} else if (GetTtsModelIsErr(model)) {
|
||||
switch (model) {
|
||||
case TtsModelLookupError.NotFound:
|
||||
@@ -98,9 +114,20 @@ function TtsModelEditPage(props: Props) {
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
const listVocoderModels = useCallback(async () => {
|
||||
const models = await ListVocoderModels();
|
||||
|
||||
if (ListVocoderModelsIsOk(models)) {
|
||||
setVocoderModels(models.vocoders);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getModel(token);
|
||||
}, [token, getModel]);
|
||||
listVocoderModels();
|
||||
}, [token, getModel, listVocoderModels]);
|
||||
|
||||
const handleTitleChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
@@ -138,6 +165,13 @@ function TtsModelEditPage(props: Props) {
|
||||
setDefaultPretrainedVocoder((ev.target as HTMLSelectElement).value);
|
||||
};
|
||||
|
||||
const handleCustomVocoderChange = (
|
||||
ev: React.FormEvent<HTMLSelectElement>
|
||||
) => {
|
||||
setMaybeCustomVocoderToken((ev.target as HTMLSelectElement).value);
|
||||
};
|
||||
|
||||
|
||||
const handleIsFrontPageFeaturedChange = (
|
||||
ev: React.FormEvent<HTMLSelectElement>
|
||||
) => {
|
||||
@@ -184,6 +218,7 @@ function TtsModelEditPage(props: Props) {
|
||||
creator_set_visibility: visibility || DEFAULT_VISIBILITY,
|
||||
maybe_default_pretrained_vocoder:
|
||||
defaultPretrainedVocoder || DEFAULT_PRETRAINED_VOCODER,
|
||||
maybe_custom_vocoder_token: maybeCustomVocoderToken,
|
||||
ietf_language_tag: fullLanguageTag || DEFAULT_MODEL_LANGUAGE,
|
||||
text_pipeline_type: textPipelineType,
|
||||
};
|
||||
@@ -312,6 +347,17 @@ function TtsModelEditPage(props: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
let customVocoderOptions = vocoderModels.map((vocoder) => {
|
||||
return (
|
||||
<option
|
||||
key={vocoder.vocoder_token}
|
||||
value={vocoder.vocoder_token}
|
||||
>
|
||||
{vocoder.title} (by {vocoder.creator_display_name})
|
||||
</option>
|
||||
)
|
||||
});
|
||||
|
||||
let usableTextPipelines = isModerator
|
||||
? TEXT_PIPELINE_NAMES_FOR_MODERATORS
|
||||
: TEXT_PIPELINE_NAMES;
|
||||
@@ -437,6 +483,20 @@ function TtsModelEditPage(props: Props) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="sub-title">Custom tuned vocoder</label>
|
||||
<div className="form-group">
|
||||
<select
|
||||
name="custom_vocoder"
|
||||
onChange={handleCustomVocoderChange}
|
||||
value={maybeCustomVocoderToken || ""}
|
||||
className="form-select"
|
||||
>
|
||||
{customVocoderOptions}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Model Visibility {visibilityIcon}
|
||||
|
||||
Reference in new issue
Block a user