mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 09:48:44 +00:00
enqueue voice designer tts
This commit is contained in:
1 parent
b4ef0f80ee
commit
6bc63a317d
6 files changed
+268
-152
No files matched your search
@@ -6,6 +6,8 @@ export enum FrontendInferenceJobType {
|
||||
FaceAnimation,
|
||||
TextToSpeech,
|
||||
VoiceConversion,
|
||||
VoiceDesignerCreateVoice,
|
||||
VoiceDesignerTts,
|
||||
}
|
||||
|
||||
// NB: Many of these fields are optional despite the response payload containing them
|
||||
@@ -35,11 +37,11 @@ export class InferenceJob {
|
||||
|
||||
constructor(
|
||||
// PK
|
||||
jobToken: string,
|
||||
jobToken: string,
|
||||
// Frontend state
|
||||
frontendJobType: FrontendInferenceJobType,
|
||||
// Status
|
||||
status: string = 'unknown',
|
||||
status: string = "unknown",
|
||||
maybeExtraStatusDescription: string | null = null,
|
||||
attemptCount: number = 0,
|
||||
// Request
|
||||
@@ -85,7 +87,10 @@ export class InferenceJob {
|
||||
}
|
||||
}
|
||||
|
||||
static fromResponse(response: ModelInferenceJobStatus, frontendJobType: FrontendInferenceJobType) : InferenceJob {
|
||||
static fromResponse(
|
||||
response: ModelInferenceJobStatus,
|
||||
frontendJobType: FrontendInferenceJobType
|
||||
): InferenceJob {
|
||||
return new InferenceJob(
|
||||
response.job_token,
|
||||
frontendJobType,
|
||||
|
||||
+147
-115
@@ -3,7 +3,7 @@ import "scss/custom-bootstrap.scss";
|
||||
|
||||
import React from "react";
|
||||
import { ApiConfig } from "@storyteller/components";
|
||||
import Cookies from 'universal-cookie';
|
||||
import Cookies from "universal-cookie";
|
||||
import {
|
||||
DetectLocale,
|
||||
DetectLocaleIsOk,
|
||||
@@ -60,14 +60,17 @@ import { VoiceConversionModelUploadJob } from "@storyteller/components/src/jobs/
|
||||
import { VoiceConversionModelListItem } from "@storyteller/components/src/api/voice_conversion/ListVoiceConversionModels";
|
||||
import HttpBackend from "i18next-http-backend";
|
||||
|
||||
import { InferenceJobs, Session as SessionProvider } from "components/providers";
|
||||
import {
|
||||
InferenceJobs,
|
||||
Session as SessionProvider,
|
||||
} from "components/providers";
|
||||
|
||||
// NB: We're transitioning over to this instance of i18n-next that loads translations over HTTP from Json Files.
|
||||
// The old i18n-next instance (see below) bakes in translations into the compiled javascript blob.
|
||||
// This new instance uses the Locize paid service to manage translation strings on their website. It's automated,
|
||||
// can easily sync to version control, and makes translation easy to maintain across a wide number of languages.
|
||||
export const i18n2 = i18n.createInstance();
|
||||
declare const window: Window & { dataLayer: Record<string, unknown>[]; };
|
||||
declare const window: Window & { dataLayer: Record<string, unknown>[] };
|
||||
|
||||
// OLD i18n-next instance
|
||||
// This instance of i18n-next should not be used for new translations going forward.
|
||||
@@ -196,6 +199,11 @@ function initInferenceJobsByCategoryMap(): Map<
|
||||
inferenceJobsByCategory.set(FrontendInferenceJobType.FaceAnimation, []);
|
||||
inferenceJobsByCategory.set(FrontendInferenceJobType.TextToSpeech, []);
|
||||
inferenceJobsByCategory.set(FrontendInferenceJobType.VoiceConversion, []);
|
||||
inferenceJobsByCategory.set(
|
||||
FrontendInferenceJobType.VoiceDesignerCreateVoice,
|
||||
[]
|
||||
);
|
||||
inferenceJobsByCategory.set(FrontendInferenceJobType.VoiceDesignerTts, []);
|
||||
return inferenceJobsByCategory;
|
||||
}
|
||||
|
||||
@@ -258,7 +266,6 @@ class App extends React.Component<Props, State> {
|
||||
voiceConversionModels: [],
|
||||
maybeSelectedVoiceConversionModel: undefined,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
@@ -302,14 +309,17 @@ class App extends React.Component<Props, State> {
|
||||
// Track only logged-in users (for now)
|
||||
PosthogClient.enablePosthog();
|
||||
PosthogClient.setUsername(username);
|
||||
cookies.set('logged_in_username', username, { path: '/', expires: new Date(Date.now()+3 * 86400000) });
|
||||
cookies.set("logged_in_username", username, {
|
||||
path: "/",
|
||||
expires: new Date(Date.now() + 3 * 86400000),
|
||||
});
|
||||
window.dataLayer.push({
|
||||
'user_id': username,
|
||||
user_id: username,
|
||||
});
|
||||
} else {
|
||||
cookies.remove('logged_in_username', { path: '/' });
|
||||
cookies.remove("logged_in_username", { path: "/" });
|
||||
}
|
||||
|
||||
|
||||
if (!deepEqual(sessionWrapper, this.state.sessionWrapper)) {
|
||||
this.setState({
|
||||
sessionWrapper: sessionWrapper,
|
||||
@@ -321,16 +331,24 @@ class App extends React.Component<Props, State> {
|
||||
const cookies = new Cookies();
|
||||
|
||||
const sessionSubscriptionsWrapper =
|
||||
await SessionSubscriptionsWrapper.lookupActiveSubscriptions();
|
||||
await SessionSubscriptionsWrapper.lookupActiveSubscriptions();
|
||||
|
||||
const plan = sessionSubscriptionsWrapper.getActiveProductSlug();
|
||||
if (plan !== undefined) {
|
||||
cookies.set('logged_in_user_plan', plan, { path: '/', expires: new Date(Date.now()+3 * 86400000) });
|
||||
cookies.set("logged_in_user_plan", plan, {
|
||||
path: "/",
|
||||
expires: new Date(Date.now() + 3 * 86400000),
|
||||
});
|
||||
} else {
|
||||
cookies.remove('logged_in_user_plan', { path: '/' });
|
||||
cookies.remove("logged_in_user_plan", { path: "/" });
|
||||
}
|
||||
|
||||
if (!deepEqual(sessionSubscriptionsWrapper, this.state.sessionSubscriptionsWrapper)) {
|
||||
if (
|
||||
!deepEqual(
|
||||
sessionSubscriptionsWrapper,
|
||||
this.state.sessionSubscriptionsWrapper
|
||||
)
|
||||
) {
|
||||
this.setState({
|
||||
sessionSubscriptionsWrapper: sessionSubscriptionsWrapper,
|
||||
});
|
||||
@@ -812,109 +830,123 @@ class App extends React.Component<Props, State> {
|
||||
*/}
|
||||
|
||||
<div className="migrationComponentWrapper">
|
||||
<InferenceJobs {...{
|
||||
byCategory: this.state.inferenceJobsByCategory
|
||||
}}>
|
||||
<SessionProvider {...{ sessionWrapper: this.state.sessionWrapper }}>
|
||||
<Switch>
|
||||
<Route path="/">
|
||||
<PageContainer
|
||||
sessionWrapper={this.state.sessionWrapper}
|
||||
querySessionAction={this.querySession}
|
||||
sessionSubscriptionsWrapper={
|
||||
this.state.sessionSubscriptionsWrapper
|
||||
}
|
||||
querySessionSubscriptionsAction={
|
||||
this.querySessionSubscriptions
|
||||
}
|
||||
isShowingVocodesNotice={this.state.isShowingVocodesNotice}
|
||||
clearVocodesNotice={this.clearVocodesNotice}
|
||||
isShowingLangaugeNotice={this.state.isShowingLanguageNotice}
|
||||
clearLanguageNotice={this.clearLanguageNotice}
|
||||
displayLanguage={this.state.displayLanguage}
|
||||
primaryLanguageCode={this.state.primaryLanguageCode}
|
||||
isShowingTwitchTtsNotice={
|
||||
this.state.isShowingTwitchTtsNotice
|
||||
}
|
||||
clearTwitchTtsNotice={this.clearTwitchTtsNotice}
|
||||
isShowingPleaseFollowNotice={
|
||||
this.state.isShowingPleaseFollowNotice
|
||||
}
|
||||
clearPleaseFollowNotice={this.clearPleaseFollowNotice}
|
||||
isShowingBootstrapLanguageNotice={
|
||||
this.state.isShowingBootstrapLanguageNotice
|
||||
}
|
||||
clearBootstrapLanguageNotice={
|
||||
this.clearBootstrapLanguageNotice
|
||||
}
|
||||
enqueueInferenceJob={this.enqueueInferenceJob}
|
||||
inferenceJobs={this.state.inferenceJobs}
|
||||
inferenceJobsByCategory={this.state.inferenceJobsByCategory}
|
||||
enqueueTtsJob={this.enqueueTtsJob}
|
||||
ttsInferenceJobs={this.state.ttsInferenceJobs}
|
||||
enqueueW2lJob={this.enqueueW2lJob}
|
||||
w2lInferenceJobs={this.state.w2lInferenceJobs}
|
||||
enqueueTtsModelUploadJob={this.enqueueTtsModelUploadJob}
|
||||
ttsModelUploadJobs={this.state.ttsModelUploadJobs}
|
||||
enqueueW2lTemplateUploadJob={
|
||||
this.enqueueW2lTemplateUploadJob
|
||||
}
|
||||
w2lTemplateUploadJobs={this.state.w2lTemplateUploadJobs}
|
||||
enqueueVocoderUploadJob={this.enqueueVocoderUploadJob}
|
||||
vocoderUploadJobs={this.state.vocoderUploadJobs}
|
||||
enqueueVoiceConversionModelUploadJob={
|
||||
this.enqueueVoiceConversionModelUploadJob
|
||||
}
|
||||
voiceConversionModelUploadJobs={
|
||||
this.state.voiceConversionModelUploadJobs
|
||||
}
|
||||
textBuffer={this.state.textBuffer}
|
||||
setTextBuffer={this.setTextBuffer}
|
||||
clearTextBuffer={this.clearTextBuffer}
|
||||
ttsModels={this.props.allTtsModels}
|
||||
setTtsModels={this.props.setAllTtsModels}
|
||||
allTtsCategories={this.props.allTtsCategories}
|
||||
setAllTtsCategories={this.props.setAllTtsCategories}
|
||||
computedTtsCategoryAssignments={
|
||||
this.props.computedTtsCategoryAssignments
|
||||
}
|
||||
setComputedTtsCategoryAssignments={
|
||||
this.props.setComputedTtsCategoryAssignments
|
||||
}
|
||||
allTtsCategoriesByTokenMap={
|
||||
this.props.allTtsCategoriesByTokenMap
|
||||
}
|
||||
allTtsModelsByTokenMap={this.props.allTtsModelsByTokenMap}
|
||||
ttsModelsByCategoryToken={
|
||||
this.props.ttsModelsByCategoryToken
|
||||
}
|
||||
dropdownCategories={this.props.dropdownCategories}
|
||||
setDropdownCategories={this.props.setDropdownCategories}
|
||||
selectedCategories={this.props.selectedCategories}
|
||||
setSelectedCategories={this.props.setSelectedCategories}
|
||||
maybeSelectedTtsModel={this.props.maybeSelectedTtsModel}
|
||||
setMaybeSelectedTtsModel={
|
||||
this.props.setMaybeSelectedTtsModel
|
||||
}
|
||||
selectedTtsLanguageScope={
|
||||
this.props.selectedTtsLanguageScope
|
||||
}
|
||||
setSelectedTtsLanguageScope={
|
||||
this.props.setSelectedTtsLanguageScope
|
||||
}
|
||||
voiceConversionModels={this.state.voiceConversionModels}
|
||||
setVoiceConversionModels={this.setAllVoiceConversionModels}
|
||||
maybeSelectedVoiceConversionModel={
|
||||
this.state.maybeSelectedVoiceConversionModel
|
||||
}
|
||||
setMaybeSelectedVoiceConversionModel={
|
||||
this.setMaybeSelectedVoiceConversionModel
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</SessionProvider>
|
||||
</InferenceJobs>
|
||||
<InferenceJobs
|
||||
{...{
|
||||
byCategory: this.state.inferenceJobsByCategory,
|
||||
}}
|
||||
>
|
||||
<SessionProvider
|
||||
{...{ sessionWrapper: this.state.sessionWrapper }}
|
||||
>
|
||||
<Switch>
|
||||
<Route path="/">
|
||||
<PageContainer
|
||||
sessionWrapper={this.state.sessionWrapper}
|
||||
querySessionAction={this.querySession}
|
||||
sessionSubscriptionsWrapper={
|
||||
this.state.sessionSubscriptionsWrapper
|
||||
}
|
||||
querySessionSubscriptionsAction={
|
||||
this.querySessionSubscriptions
|
||||
}
|
||||
isShowingVocodesNotice={
|
||||
this.state.isShowingVocodesNotice
|
||||
}
|
||||
clearVocodesNotice={this.clearVocodesNotice}
|
||||
isShowingLangaugeNotice={
|
||||
this.state.isShowingLanguageNotice
|
||||
}
|
||||
clearLanguageNotice={this.clearLanguageNotice}
|
||||
displayLanguage={this.state.displayLanguage}
|
||||
primaryLanguageCode={this.state.primaryLanguageCode}
|
||||
isShowingTwitchTtsNotice={
|
||||
this.state.isShowingTwitchTtsNotice
|
||||
}
|
||||
clearTwitchTtsNotice={this.clearTwitchTtsNotice}
|
||||
isShowingPleaseFollowNotice={
|
||||
this.state.isShowingPleaseFollowNotice
|
||||
}
|
||||
clearPleaseFollowNotice={this.clearPleaseFollowNotice}
|
||||
isShowingBootstrapLanguageNotice={
|
||||
this.state.isShowingBootstrapLanguageNotice
|
||||
}
|
||||
clearBootstrapLanguageNotice={
|
||||
this.clearBootstrapLanguageNotice
|
||||
}
|
||||
enqueueInferenceJob={this.enqueueInferenceJob}
|
||||
inferenceJobs={this.state.inferenceJobs}
|
||||
inferenceJobsByCategory={
|
||||
this.state.inferenceJobsByCategory
|
||||
}
|
||||
enqueueTtsJob={this.enqueueTtsJob}
|
||||
ttsInferenceJobs={this.state.ttsInferenceJobs}
|
||||
enqueueW2lJob={this.enqueueW2lJob}
|
||||
w2lInferenceJobs={this.state.w2lInferenceJobs}
|
||||
enqueueTtsModelUploadJob={this.enqueueTtsModelUploadJob}
|
||||
ttsModelUploadJobs={this.state.ttsModelUploadJobs}
|
||||
enqueueW2lTemplateUploadJob={
|
||||
this.enqueueW2lTemplateUploadJob
|
||||
}
|
||||
w2lTemplateUploadJobs={this.state.w2lTemplateUploadJobs}
|
||||
enqueueVocoderUploadJob={this.enqueueVocoderUploadJob}
|
||||
vocoderUploadJobs={this.state.vocoderUploadJobs}
|
||||
enqueueVoiceConversionModelUploadJob={
|
||||
this.enqueueVoiceConversionModelUploadJob
|
||||
}
|
||||
voiceConversionModelUploadJobs={
|
||||
this.state.voiceConversionModelUploadJobs
|
||||
}
|
||||
textBuffer={this.state.textBuffer}
|
||||
setTextBuffer={this.setTextBuffer}
|
||||
clearTextBuffer={this.clearTextBuffer}
|
||||
ttsModels={this.props.allTtsModels}
|
||||
setTtsModels={this.props.setAllTtsModels}
|
||||
allTtsCategories={this.props.allTtsCategories}
|
||||
setAllTtsCategories={this.props.setAllTtsCategories}
|
||||
computedTtsCategoryAssignments={
|
||||
this.props.computedTtsCategoryAssignments
|
||||
}
|
||||
setComputedTtsCategoryAssignments={
|
||||
this.props.setComputedTtsCategoryAssignments
|
||||
}
|
||||
allTtsCategoriesByTokenMap={
|
||||
this.props.allTtsCategoriesByTokenMap
|
||||
}
|
||||
allTtsModelsByTokenMap={
|
||||
this.props.allTtsModelsByTokenMap
|
||||
}
|
||||
ttsModelsByCategoryToken={
|
||||
this.props.ttsModelsByCategoryToken
|
||||
}
|
||||
dropdownCategories={this.props.dropdownCategories}
|
||||
setDropdownCategories={this.props.setDropdownCategories}
|
||||
selectedCategories={this.props.selectedCategories}
|
||||
setSelectedCategories={this.props.setSelectedCategories}
|
||||
maybeSelectedTtsModel={this.props.maybeSelectedTtsModel}
|
||||
setMaybeSelectedTtsModel={
|
||||
this.props.setMaybeSelectedTtsModel
|
||||
}
|
||||
selectedTtsLanguageScope={
|
||||
this.props.selectedTtsLanguageScope
|
||||
}
|
||||
setSelectedTtsLanguageScope={
|
||||
this.props.setSelectedTtsLanguageScope
|
||||
}
|
||||
voiceConversionModels={this.state.voiceConversionModels}
|
||||
setVoiceConversionModels={
|
||||
this.setAllVoiceConversionModels
|
||||
}
|
||||
maybeSelectedVoiceConversionModel={
|
||||
this.state.maybeSelectedVoiceConversionModel
|
||||
}
|
||||
setMaybeSelectedVoiceConversionModel={
|
||||
this.setMaybeSelectedVoiceConversionModel
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</SessionProvider>
|
||||
</InferenceJobs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -678,6 +678,8 @@ class PageContainer extends React.Component<
|
||||
this.props.sessionSubscriptionsWrapper
|
||||
}
|
||||
inferenceJobs={this.props.inferenceJobs}
|
||||
enqueueInferenceJob={this.props.enqueueInferenceJob}
|
||||
inferenceJobsByCategory={this.props.inferenceJobsByCategory}
|
||||
ttsInferenceJobs={this.props.ttsInferenceJobs}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import React, { useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { faEye, faLanguage, faPencil, faWaveform } from "@fortawesome/pro-solid-svg-icons";
|
||||
import {
|
||||
faEye,
|
||||
faLanguage,
|
||||
faPencil,
|
||||
faWaveform,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle";
|
||||
import Panel from "components/common/Panel";
|
||||
import { Stepper } from "./components/Stepper";
|
||||
@@ -24,8 +29,8 @@ interface RouteParams {
|
||||
function VoiceDesignerFormPage() {
|
||||
const history = useHistory();
|
||||
const { datasets, inputCtrl, voices } = useVoiceRequests();
|
||||
const [language,languageSet] = useState("en");
|
||||
const [visibility,visibilitySet] = useState("");
|
||||
const [language, languageSet] = useState("en");
|
||||
const [visibility, visibilitySet] = useState("");
|
||||
const [title, titleSet] = useState("");
|
||||
|
||||
const audioProps = useFile({}); // contains upload inout state and controls, see docs
|
||||
@@ -36,12 +41,35 @@ function VoiceDesignerFormPage() {
|
||||
{ value: "fr", label: "French" },
|
||||
];
|
||||
|
||||
const visibilityOptions = [{ label: "Public", value: "public" },{ label: "Hidden", value: "hidden" }];
|
||||
const visibilityOptions = [
|
||||
{ label: "Public", value: "public" },
|
||||
{ label: "Hidden", value: "hidden" },
|
||||
];
|
||||
|
||||
const datasetInputs = [
|
||||
{ type: "text", label: "Title", placeholder: "Voice name", value: title, onChange: inputCtrl(titleSet) },
|
||||
{ type: "select", icon: faLanguage, label: "Language", value: language, onChange: inputCtrl(languageSet), options: languages },
|
||||
{ type: "select", icon: faEye, label: "Visibility", value: visibility, onChange: inputCtrl(visibilitySet), options: visibilityOptions }
|
||||
{
|
||||
type: "text",
|
||||
label: "Title",
|
||||
placeholder: "Voice name",
|
||||
value: title,
|
||||
onChange: inputCtrl(titleSet),
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
icon: faLanguage,
|
||||
label: "Language",
|
||||
value: language,
|
||||
onChange: inputCtrl(languageSet),
|
||||
options: languages,
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
icon: faEye,
|
||||
label: "Visibility",
|
||||
value: visibility,
|
||||
onChange: inputCtrl(visibilitySet),
|
||||
options: visibilityOptions,
|
||||
},
|
||||
];
|
||||
|
||||
const { dataset_token } = useParams<RouteParams>();
|
||||
@@ -62,7 +90,9 @@ function VoiceDesignerFormPage() {
|
||||
case 0:
|
||||
return <VoiceDetails {...{ datasetInputs }} />;
|
||||
case 1:
|
||||
return <UploadSamples {...{ audioProps, datasetToken: dataset_token }}/>;
|
||||
return (
|
||||
<UploadSamples {...{ audioProps, datasetToken: dataset_token }} />
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -83,17 +113,17 @@ function VoiceDesignerFormPage() {
|
||||
if (isNewCreation) {
|
||||
// It's a new creation and on the first step
|
||||
|
||||
datasets.create("",{
|
||||
title,
|
||||
creator_set_visibility: visibility,
|
||||
idempotency_token: uuidv4(),
|
||||
}).then((res: any) => {
|
||||
|
||||
if (res && res.success && res.token) {
|
||||
history.push(`/voice-designer/dataset/${ res.token }/upload`);
|
||||
}
|
||||
});
|
||||
|
||||
datasets
|
||||
.create("", {
|
||||
title,
|
||||
creator_set_visibility: visibility,
|
||||
idempotency_token: uuidv4(),
|
||||
})
|
||||
.then((res: any) => {
|
||||
if (res && res.success && res.token) {
|
||||
history.push(`/voice-designer/dataset/${res.token}/upload`);
|
||||
}
|
||||
});
|
||||
} else if (dataset_token) {
|
||||
// It's edit mode and on the first step
|
||||
history.push(`/voice-designer/dataset/${dataset_token}/upload`);
|
||||
@@ -105,14 +135,16 @@ function VoiceDesignerFormPage() {
|
||||
};
|
||||
|
||||
const handleCreateVoice = () => {
|
||||
voices.create("",{
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
voice_dataset_token: dataset_token || "",
|
||||
}).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
history.push("/voice-designer");
|
||||
}
|
||||
});
|
||||
voices
|
||||
.create("", {
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
voice_dataset_token: dataset_token || "",
|
||||
})
|
||||
.then((res: any) => {
|
||||
if (res && res.success) {
|
||||
history.push("/voice-designer");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+48
-6
@@ -20,18 +20,28 @@ import Container from "components/common/Container/Container";
|
||||
import TextArea from "components/common/TextArea";
|
||||
import { Button } from "components/common";
|
||||
import { SessionTtsInferenceResultList } from "v2/view/_common/SessionTtsInferenceResultsList";
|
||||
import { InferenceJob } from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import {
|
||||
FrontendInferenceJobType,
|
||||
InferenceJob,
|
||||
} from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import { TtsInferenceJob } from "@storyteller/components/src/jobs/TtsInferenceJobs";
|
||||
import { faVolumeUp } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { GetVoice } from "@storyteller/components/src/api/voice_designer/voices/GetVoice";
|
||||
import Skeleton from "components/common/Skeleton";
|
||||
import useVoiceRequests from "./useVoiceRequests";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
interface VoiceDesignerUseVoicePageProps {
|
||||
sessionWrapper: SessionWrapper;
|
||||
sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
|
||||
inferenceJobs: Array<InferenceJob>;
|
||||
ttsInferenceJobs: Array<TtsInferenceJob>;
|
||||
enqueueInferenceJob: (
|
||||
jobToken: string,
|
||||
frontendInferenceJobType: FrontendInferenceJobType
|
||||
) => void;
|
||||
inferenceJobsByCategory: Map<FrontendInferenceJobType, Array<InferenceJob>>;
|
||||
}
|
||||
|
||||
export default function VoiceDesignerUseVoicePage(
|
||||
@@ -50,6 +60,8 @@ export default function VoiceDesignerUseVoicePage(
|
||||
voiceToken: "",
|
||||
languageTag: "",
|
||||
});
|
||||
const { inference } = useVoiceRequests();
|
||||
const [isEnqueuing, setIsEnqueuing] = useState(false);
|
||||
|
||||
const getVoiceDetails = useCallback(async (voice_token) => {
|
||||
try {
|
||||
@@ -107,8 +119,28 @@ export default function VoiceDesignerUseVoicePage(
|
||||
// { label: "Front page featured?", value: frontPageFeatured },
|
||||
// ];
|
||||
|
||||
const handleFormSubmit = async (ev: React.FormEvent<HTMLFormElement>) => {
|
||||
ev.preventDefault();
|
||||
const handleEnqueueTts = () => {
|
||||
setIsEnqueuing(true);
|
||||
inference
|
||||
.enqueue("", {
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
text: textBuffer,
|
||||
voice_token: voice_token,
|
||||
})
|
||||
.then((res: any) => {
|
||||
if (res && res.success) {
|
||||
props.enqueueInferenceJob(
|
||||
res.inference_job_token,
|
||||
FrontendInferenceJobType.VoiceDesignerTts
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error enqueuing TTS:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsEnqueuing(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeText = (ev: React.FormEvent<HTMLTextAreaElement>) => {
|
||||
@@ -158,7 +190,7 @@ export default function VoiceDesignerUseVoicePage(
|
||||
<PageHeader title={voiceData.title} subText={subText} />
|
||||
|
||||
<Panel padding={true} mb={true}>
|
||||
<form onSubmit={handleFormSubmit}>
|
||||
<form>
|
||||
<div className="row g-4">
|
||||
<div className="col-12 col-lg-6 d-flex flex-column gap-3">
|
||||
<h4>
|
||||
@@ -172,7 +204,13 @@ export default function VoiceDesignerUseVoicePage(
|
||||
rows={8}
|
||||
/>
|
||||
<div className="d-flex gap-3">
|
||||
<Button icon={faVolumeUp} label="Speak" full={true} />
|
||||
<Button
|
||||
icon={faVolumeUp}
|
||||
label="Speak"
|
||||
full={true}
|
||||
onClick={handleEnqueueTts}
|
||||
isLoading={isEnqueuing}
|
||||
/>
|
||||
<Button
|
||||
icon={faDeleteLeft}
|
||||
label="Clear"
|
||||
@@ -188,7 +226,11 @@ export default function VoiceDesignerUseVoicePage(
|
||||
</h4>
|
||||
<div className="d-flex flex-column gap-3 session-tts-section">
|
||||
<SessionTtsInferenceResultList
|
||||
inferenceJobs={props.inferenceJobs}
|
||||
inferenceJobs={
|
||||
props.inferenceJobsByCategory.get(
|
||||
FrontendInferenceJobType.VoiceDesignerTts
|
||||
)!
|
||||
}
|
||||
ttsInferenceJobs={props.ttsInferenceJobs}
|
||||
sessionSubscriptionsWrapper={
|
||||
props.sessionSubscriptionsWrapper
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
UpdateDataset,
|
||||
UpdateDatasetRequest,
|
||||
} from "@storyteller/components/src/api/voice_designer/voice_datasets/UpdateDataset";
|
||||
import { EnqueueTts } from "@storyteller/components/src/api/voice_designer/inference/EnqueueTts";
|
||||
import { useSession } from "hooks";
|
||||
|
||||
export default function useVoiceRequests() {
|
||||
@@ -84,7 +85,9 @@ export default function useVoiceRequests() {
|
||||
list: datasets,
|
||||
byToken: datasetByToken,
|
||||
},
|
||||
inference: {},
|
||||
inference: {
|
||||
enqueue: EnqueueTts,
|
||||
},
|
||||
voices: {
|
||||
create: CreateVoice,
|
||||
delete: deleteVoice,
|
||||
|
||||
Reference in new issue
Block a user