mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 17:08:13 +00:00
Upload Vocoder Flow
This commit is contained in:
1 parent
6e40db5c60
commit
e484ba9b92
13 files changed
+531
-427
No files matched your search
@@ -380,6 +380,14 @@ class ApiConfig {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/voice_clone_requests/check`;
|
||||
}
|
||||
|
||||
enqueueRetrievalJob(): string {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/retrieval/enqueue`;
|
||||
}
|
||||
|
||||
getRetrievalJobStatus(jobToken: string): string {
|
||||
return `${this.getScheme()}://${this.getNewApiHost()}/retrieval/job_status/${jobToken}`;
|
||||
}
|
||||
|
||||
// =============== Storyteller-specific ===============
|
||||
|
||||
listTwitchEventRules(): string {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { ApiConfig } from "../ApiConfig";
|
||||
|
||||
export interface EnqueueRetrievalRequest {
|
||||
idempotency_token: string,
|
||||
title: string,
|
||||
download_url: string,
|
||||
generic_download_type: string,
|
||||
}
|
||||
|
||||
export interface EnqueueRetrievalSuccessResponse {
|
||||
success: boolean,
|
||||
job_token: string,
|
||||
}
|
||||
|
||||
export interface EnqueueRetrievalErrorResponse {
|
||||
success: boolean,
|
||||
}
|
||||
|
||||
type EnqueueRetrievalResponse = EnqueueRetrievalSuccessResponse | EnqueueRetrievalErrorResponse;
|
||||
|
||||
export function EnqueueRetrievalIsOk(response: EnqueueRetrievalResponse): response is EnqueueRetrievalSuccessResponse {
|
||||
return response?.success === true;
|
||||
}
|
||||
|
||||
export function EnqueueRetrievalIsError(response: EnqueueRetrievalResponse): response is EnqueueRetrievalErrorResponse {
|
||||
return response?.success === false;
|
||||
}
|
||||
|
||||
export async function EnqueueRetrieval(request: EnqueueRetrievalRequest) : Promise<EnqueueRetrievalResponse>
|
||||
{
|
||||
const endpoint = new ApiConfig().enqueueRetrievalJob();
|
||||
|
||||
return fetch(endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res && 'success' in res) {
|
||||
return res;
|
||||
} else {
|
||||
return { success : false };
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
return { success : false };
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { ApiConfig } from "../ApiConfig";
|
||||
|
||||
export interface GetRetrievalJobStatusSuccessResponse {
|
||||
success: boolean,
|
||||
state: RetrievalJobStatus,
|
||||
}
|
||||
|
||||
export interface RetrievalJobStatus {
|
||||
// Job primary key
|
||||
job_token: string,
|
||||
|
||||
// Job state machine (enum) and retry count
|
||||
status: string,
|
||||
attempt_count: number,
|
||||
|
||||
// Optional unstructured extra details during the inference process
|
||||
maybe_extra_status_description?: string,
|
||||
|
||||
// Job completion: foreign key to entity
|
||||
maybe_downloaded_entity_type?: string,
|
||||
maybe_downloaded_entity_token?: string,
|
||||
|
||||
created_at: Date,
|
||||
updated_at: Date,
|
||||
}
|
||||
|
||||
export interface GetRetrievalJobStatusErrorResponse {
|
||||
success: boolean,
|
||||
}
|
||||
|
||||
type GetRetrievalJobStatusResponse = GetRetrievalJobStatusSuccessResponse | GetRetrievalJobStatusErrorResponse;
|
||||
|
||||
export function GetRetrievalJobStatusIsOk(response: GetRetrievalJobStatusResponse): response is GetRetrievalJobStatusSuccessResponse {
|
||||
return response?.success === true;
|
||||
}
|
||||
|
||||
export function GetRetrievalJobStatusIsError(response: GetRetrievalJobStatusResponse): response is GetRetrievalJobStatusErrorResponse {
|
||||
return response?.success === false;
|
||||
}
|
||||
|
||||
export async function GetRetrievalJobStatus(jobToken: string) : Promise<GetRetrievalJobStatusResponse>
|
||||
{
|
||||
const endpoint = new ApiConfig().getRetrievalJobStatus(jobToken);
|
||||
|
||||
return fetch(endpoint, {
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res && 'success' in res) {
|
||||
return res;
|
||||
} else {
|
||||
return { success : false };
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
return { success : false };
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { RetrievalJobStatus } from "../api/retrieval/GetRetrievalJobStatus";
|
||||
import { JobState, jobStateFromString } from "./JobStates";
|
||||
|
||||
|
||||
export class VocoderUploadJob {
|
||||
jobToken: string;
|
||||
maybeDownloadedEntityType: string | undefined | null;
|
||||
maybeDownloadedEntityToken: string | undefined | null;
|
||||
jobState: JobState;
|
||||
maybeExtraStatusDescription: string | null;
|
||||
attemptCount: number;
|
||||
|
||||
constructor(
|
||||
jobToken: string,
|
||||
status: string = 'unknown',
|
||||
maybeExtraStatusDescription: string | null = null,
|
||||
attemptCount: number = 0,
|
||||
maybeDownloadedEntityType: string | undefined | null = undefined,
|
||||
maybeDownloadedEntityToken: string | undefined | null = undefined
|
||||
) {
|
||||
this.jobState = jobStateFromString(status);
|
||||
this.maybeExtraStatusDescription = maybeExtraStatusDescription;
|
||||
this.attemptCount = attemptCount;
|
||||
this.jobToken = jobToken;
|
||||
if (!!maybeDownloadedEntityType) {
|
||||
this.maybeDownloadedEntityType = maybeDownloadedEntityType;
|
||||
}
|
||||
if (!!maybeDownloadedEntityToken) {
|
||||
this.maybeDownloadedEntityToken = maybeDownloadedEntityToken;
|
||||
}
|
||||
}
|
||||
|
||||
static fromResponse(response: RetrievalJobStatus) : VocoderUploadJob {
|
||||
return new VocoderUploadJob(
|
||||
response.job_token,
|
||||
response.status,
|
||||
response.maybe_extra_status_description || null,
|
||||
response.attempt_count || 0,
|
||||
response.maybe_downloaded_entity_type,
|
||||
response.maybe_downloaded_entity_token,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export interface VocoderUploadJobStateResponsePayload {
|
||||
success: boolean,
|
||||
state?: VocoderUploadJobState,
|
||||
}
|
||||
|
||||
export interface VocoderUploadJobState {
|
||||
job_token: string,
|
||||
status: string,
|
||||
maybe_extra_status_description: string | null,
|
||||
attempt_count: number | undefined,
|
||||
maybe_downloaded_entity_type: string | undefined | null,
|
||||
maybe_downloaded_entity_token: string | undefined | null,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
}
|
||||
@@ -31,6 +31,8 @@ import { FAKEYOU_MERGED_TRANSLATIONS } from "./_i18n/FakeYouTranslations";
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import { USE_REFRESH } from "./Refresh";
|
||||
import { VocoderUploadJob } from "@storyteller/components/src/jobs/VocoderUploadJobs";
|
||||
import { GetRetrievalJobStatus, GetRetrievalJobStatusIsOk } from "@storyteller/components/src/api/retrieval/GetRetrievalJobStatus";
|
||||
|
||||
i18n
|
||||
.use(initReactI18next) // passes i18n down to react-i18next
|
||||
@@ -108,6 +110,7 @@ interface State {
|
||||
w2lInferenceJobs: Array<W2lInferenceJob>;
|
||||
ttsModelUploadJobs: Array<TtsModelUploadJob>;
|
||||
w2lTemplateUploadJobs: Array<W2lTemplateUploadJob>;
|
||||
vocoderUploadJobs: Array<VocoderUploadJob>;
|
||||
|
||||
// Current text entered
|
||||
textBuffer: string;
|
||||
@@ -163,6 +166,7 @@ class App extends React.Component<Props, State> {
|
||||
w2lInferenceJobs: [],
|
||||
ttsModelUploadJobs: [],
|
||||
w2lTemplateUploadJobs: [],
|
||||
vocoderUploadJobs: [],
|
||||
|
||||
textBuffer: "",
|
||||
};
|
||||
@@ -543,6 +547,42 @@ class App extends React.Component<Props, State> {
|
||||
});
|
||||
};
|
||||
|
||||
enqueueVocoderUploadJob = (jobToken: string) => {
|
||||
const newJob = new VocoderUploadJob(jobToken);
|
||||
let uploadJobs = this.state.vocoderUploadJobs.concat([newJob]);
|
||||
|
||||
this.setState({
|
||||
vocoderUploadJobs: uploadJobs,
|
||||
});
|
||||
};
|
||||
|
||||
checkVocoderUploadJob = async (jobToken: string) => {
|
||||
const lookupResult = await GetRetrievalJobStatus(jobToken);
|
||||
|
||||
if (GetRetrievalJobStatusIsOk(lookupResult)) {
|
||||
let updatedJobs: Array<VocoderUploadJob> = [];
|
||||
|
||||
this.state.vocoderUploadJobs.forEach((existingJob) => {
|
||||
if (
|
||||
existingJob.jobToken !== lookupResult.state!.job_token ||
|
||||
!jobStateCanChange(existingJob.jobState)
|
||||
) {
|
||||
updatedJobs.push(existingJob);
|
||||
return;
|
||||
}
|
||||
|
||||
let updatedJob = VocoderUploadJob.fromResponse(
|
||||
lookupResult.state!
|
||||
);
|
||||
updatedJobs.push(updatedJob);
|
||||
});
|
||||
|
||||
this.setState({
|
||||
vocoderUploadJobs: updatedJobs,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
pollJobs = () => {
|
||||
this.state.ttsInferenceJobs.forEach((job) => {
|
||||
if (jobStateCanChange(job.jobState)) {
|
||||
@@ -564,6 +604,11 @@ class App extends React.Component<Props, State> {
|
||||
this.checkW2lTemplateUploadJob(job.jobToken);
|
||||
}
|
||||
});
|
||||
this.state.vocoderUploadJobs.forEach((job) => {
|
||||
if (jobStateCanChange(job.jobState)) {
|
||||
this.checkVocoderUploadJob(job.jobToken);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
setMigrationMode = (mode: MigrationMode) => {
|
||||
@@ -644,6 +689,8 @@ class App extends React.Component<Props, State> {
|
||||
this.enqueueW2lTemplateUploadJob
|
||||
}
|
||||
w2lTemplateUploadJobs={this.state.w2lTemplateUploadJobs}
|
||||
enqueueVocoderUploadJob={this.enqueueVocoderUploadJob}
|
||||
vocoderUploadJobs={this.state.vocoderUploadJobs}
|
||||
textBuffer={this.state.textBuffer}
|
||||
setTextBuffer={this.setTextBuffer}
|
||||
clearTextBuffer={this.clearTextBuffer}
|
||||
|
||||
@@ -17,13 +17,14 @@ import { TtsInferenceJob, W2lInferenceJob } from '../../App';
|
||||
import { TtsModelDeletePage } from './tts/tts_model_delete/TtsModelDeletePage';
|
||||
import { TtsModelEditPage } from './tts/tts_model_edit/TtsModelEditPage';
|
||||
import { TtsModelUploadJob } from '@storyteller/components/src/jobs/TtsModelUploadJobs';
|
||||
import { VocoderUploadJob } from '@storyteller/components/src/jobs/VocoderUploadJobs';
|
||||
import { TtsModelViewPage } from './tts/tts_model_view/TtsModelViewPage';
|
||||
import { TtsResultDeletePage } from './tts/tts_result_delete/TtsResultDeletePage';
|
||||
import { TtsResultViewPage } from './tts/tts_result_view/TtsResultViewPage';
|
||||
import { ContributeIndexPage } from './contribute/ContributeIndexPage';
|
||||
import { UploadTtsModelFc } from './upload/UploadTtsModelFc';
|
||||
import { UploadW2lPhotoFc } from './upload/UploadW2lPhotoFc';
|
||||
import { UploadW2lVideoFc } from './upload/UploadW2lVideoFc';
|
||||
import { UploadTtsModelPage } from './upload/UploadTtsModelPage';
|
||||
import { UploadW2lPhotoPage } from './upload/UploadW2lPhotoPage';
|
||||
import { UploadW2lVideoPage } from './upload/UploadW2lVideoPage';
|
||||
import { W2lResultViewFc } from './w2l/w2l_result_view/W2lResultViewFc';
|
||||
import { W2lTemplateListFc } from './w2l/w2l_template_list/W2lTemplateListFc';
|
||||
import { W2lTemplateUploadJob } from '@storyteller/components/src/jobs/W2lTemplateUploadJobs';
|
||||
@@ -53,6 +54,7 @@ import ScrollToTop from './_common/ScrollToTop';
|
||||
import { Language } from '@storyteller/components/src/i18n/Language';
|
||||
import { VoiceCloneRequestPage } from './clone_voice_requests/VoiceCloneRequestPage';
|
||||
import { VocodesPage } from './vocodes/VocodesPage';
|
||||
import { UploadVocoderPage } from './upload/UploadVocoderPage';
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
@@ -87,6 +89,9 @@ interface Props {
|
||||
enqueueW2lTemplateUploadJob: (jobToken: string) => void,
|
||||
w2lTemplateUploadJobs: Array<W2lTemplateUploadJob>,
|
||||
|
||||
enqueueVocoderUploadJob: (jobToken: string) => void,
|
||||
vocoderUploadJobs: Array<VocoderUploadJob>,
|
||||
|
||||
textBuffer: string,
|
||||
setTextBuffer: (textBuffer: string) => void,
|
||||
clearTextBuffer: () => void,
|
||||
@@ -293,7 +298,7 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/w2l_photo">
|
||||
<UploadW2lPhotoFc
|
||||
<UploadW2lPhotoPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
w2lTemplateUploadJobs={this.props.w2lTemplateUploadJobs}
|
||||
enqueueW2lTemplateUploadJob={this.props.enqueueW2lTemplateUploadJob}
|
||||
@@ -301,7 +306,7 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/w2l_video">
|
||||
<UploadW2lVideoFc
|
||||
<UploadW2lVideoPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
w2lTemplateUploadJobs={this.props.w2lTemplateUploadJobs}
|
||||
enqueueW2lTemplateUploadJob={this.props.enqueueW2lTemplateUploadJob}
|
||||
@@ -309,13 +314,21 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/tts">
|
||||
<UploadTtsModelFc
|
||||
<UploadTtsModelPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
ttsModelUploadJobs={this.props.ttsModelUploadJobs}
|
||||
enqueueTtsModelUploadJob={this.props.enqueueTtsModelUploadJob}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/vocoder" exact={true}>
|
||||
<UploadVocoderPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
vocoderUploadJobs={this.props.vocoderUploadJobs}
|
||||
enqueueVocoderUploadJob={this.props.enqueueVocoderUploadJob}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/contribute">
|
||||
<ContributeIndexPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { JobState } from "@storyteller/components/src/jobs/JobStates";
|
||||
import { motion } from "framer-motion";
|
||||
import { container, sessionItem, item } from "../../../data/animation";
|
||||
import { VocoderUploadJob } from "@storyteller/components/src/jobs/VocoderUploadJobs";
|
||||
|
||||
interface Props {
|
||||
vocoderUploadJobs: Array<VocoderUploadJob>;
|
||||
}
|
||||
|
||||
function SessionVocoderUploadResultListFc(props: Props) {
|
||||
let results: Array<JSX.Element> = [];
|
||||
|
||||
props.vocoderUploadJobs.forEach((job) => {
|
||||
if (!job.maybeDownloadedEntityToken) {
|
||||
let stateDescription = "Pending...";
|
||||
|
||||
switch (job.jobState) {
|
||||
case JobState.PENDING:
|
||||
case JobState.UNKNOWN:
|
||||
stateDescription =
|
||||
job.maybeExtraStatusDescription == null
|
||||
? "Pending..."
|
||||
: job.maybeExtraStatusDescription;
|
||||
break;
|
||||
case JobState.STARTED:
|
||||
stateDescription =
|
||||
job.maybeExtraStatusDescription == null
|
||||
? "Started..."
|
||||
: job.maybeExtraStatusDescription;
|
||||
break;
|
||||
case JobState.ATTEMPT_FAILED:
|
||||
stateDescription = `Failed ${job.attemptCount} attempt(s). Will retry...`;
|
||||
break;
|
||||
case JobState.COMPLETE_FAILURE:
|
||||
case JobState.DEAD:
|
||||
stateDescription =
|
||||
"Failed Permanently. Please tell us in Discord so we can fix. :(";
|
||||
break;
|
||||
case JobState.COMPLETE_SUCCESS:
|
||||
stateDescription = "Success!"; // Not sure why we're here instead of other branch!
|
||||
break;
|
||||
}
|
||||
|
||||
results.push(
|
||||
<div key={job.jobToken}>
|
||||
<div className="alert alert-primary">{stateDescription}</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
let permalink = `/vocoder/${job.maybeDownloadedEntityToken}`;
|
||||
|
||||
results.push(
|
||||
<div key={job.jobToken}>
|
||||
<motion.div
|
||||
className="panel py-4 p-3 p-lg-4 gap-4"
|
||||
variants={sessionItem}
|
||||
>
|
||||
Complete!
|
||||
<Link to={permalink} className="btn btn-primary ms-4">
|
||||
See & use vocoder model
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let title = <span />;
|
||||
if (results.length !== 0) {
|
||||
title = (
|
||||
<motion.h2 className="text-center text-lg-start fw-bold" variants={item}>
|
||||
Vocoder Upload Status
|
||||
</motion.h2>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.div initial="hidden" animate="visible" variants={container}>
|
||||
<div className="container-panel pt-4 pb-5">
|
||||
<div className="pb-4">{title}</div>
|
||||
<div className="d-flex flex-column gap-4">{results}</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export { SessionVocoderUploadResultListFc };
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
faImage,
|
||||
faTags,
|
||||
faHandsHelping,
|
||||
faChartArea,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { USE_REFRESH } from "../../../Refresh";
|
||||
import { motion } from "framer-motion";
|
||||
import { container, item, panel } from "../../../data/animation";
|
||||
|
||||
@@ -31,96 +31,6 @@ function ContributeIndexPage(props: Props) {
|
||||
? t("pages.contributeIndex.buttonCreateCategory")
|
||||
: t("pages.contributeIndex.buttonSuggestCategory");
|
||||
|
||||
if (!USE_REFRESH) {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<h1 className="title is-1">
|
||||
{" "}
|
||||
{t("pages.contributeIndex.heroTitle")}{" "}
|
||||
</h1>
|
||||
<h1 className="subtitle is-3">
|
||||
<Trans i18nKey="pages.contributeIndex.heroSubtitle">
|
||||
You make FakeYou <strong>better</strong> by contributing
|
||||
</Trans>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div className="content is-medium">
|
||||
<p>{t("pages.contributeIndex.introText")}</p>
|
||||
|
||||
<h3 className="title is-3">
|
||||
{t("pages.contributeIndex.headingUploadModels")}
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<Trans i18nKey="pages.contributeIndex.describeUploadModels">
|
||||
Create new voices and video templates for FakeYou.
|
||||
<DiscordLink
|
||||
text={t("pages.contributeIndex.discordLink1")}
|
||||
iconAfterText={true}
|
||||
/>
|
||||
to learn how.
|
||||
</Trans>
|
||||
</p>
|
||||
|
||||
<Link
|
||||
to="/upload/tts"
|
||||
className="button is-link is-large is-fullwidth "
|
||||
>
|
||||
{t("pages.contributeIndex.buttonUploadVoice")}
|
||||
</Link>
|
||||
|
||||
<br />
|
||||
|
||||
<Link
|
||||
to="/upload/w2l_video"
|
||||
className="button is-link is-large is-fullwidth "
|
||||
>
|
||||
{t("pages.contributeIndex.buttonUploadW2lVideo")}
|
||||
</Link>
|
||||
|
||||
<br />
|
||||
|
||||
<Link
|
||||
to="/upload/w2l_photo"
|
||||
className="button is-link is-large is-fullwidth"
|
||||
>
|
||||
{t("pages.contributeIndex.buttonUploadW2lPhoto")}
|
||||
</Link>
|
||||
|
||||
<h3 className="title is-3">{categoryHeading}</h3>
|
||||
|
||||
<p>{t("pages.contributeIndex.describeSuggest")}</p>
|
||||
|
||||
<Link
|
||||
to={FrontendUrlConfig.createCategoryPage()}
|
||||
className="button is-info is-large is-fullwidth"
|
||||
>
|
||||
{categoryButton}
|
||||
</Link>
|
||||
|
||||
<h3 className="title is-3">
|
||||
{t("pages.contributeIndex.headingMore")}
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<Trans i18nKey="pages.contributeIndex.describeMore">
|
||||
Want to contribute code, design, or data science?
|
||||
<DiscordLink
|
||||
text={t("pages.contributeIndex.discordLink2")}
|
||||
iconAfterText={true}
|
||||
/>
|
||||
!
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.div initial="hidden" animate="visible" variants={container}>
|
||||
<div className="container py-5 px-md-4 px-lg-5 px-xl-3">
|
||||
@@ -161,6 +71,10 @@ function ContributeIndexPage(props: Props) {
|
||||
<FontAwesomeIcon icon={faVolumeHigh} className="me-3" />
|
||||
{t("pages.contributeIndex.buttonUploadVoice")}
|
||||
</Link>
|
||||
<Link to="/upload/vocoder" className="btn btn-primary w-100">
|
||||
<FontAwesomeIcon icon={faChartArea} className="me-3" />
|
||||
Upload Vocoder
|
||||
</Link>
|
||||
<Link to="/upload/w2l_video" className="btn btn-primary w-100">
|
||||
<FontAwesomeIcon icon={faVideo} className="me-3" />
|
||||
{t("pages.contributeIndex.buttonUploadW2lVideo")}
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ interface TtsModelUploadJobResponsePayload {
|
||||
job_token?: string;
|
||||
}
|
||||
|
||||
function UploadTtsModelFc(props: Props) {
|
||||
function UploadTtsModelPage(props: Props) {
|
||||
let history = useHistory();
|
||||
|
||||
const [downloadUrl, setDownloadUrl] = useState("");
|
||||
@@ -232,4 +232,4 @@ function UploadTtsModelFc(props: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
export { UploadTtsModelFc };
|
||||
export { UploadTtsModelPage };
|
||||
@@ -0,0 +1,182 @@
|
||||
import React, { useState } from "react";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
import { DiscordLink } from "@storyteller/components/src/elements/DiscordLink";
|
||||
import { EnqueueRetrieval, EnqueueRetrievalIsOk } from "@storyteller/components/src/api/retrieval/EnqueueRetrieval";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { BackLink } from "../_common/BackLink";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FrontendUrlConfig } from "../../../common/FrontendUrlConfig";
|
||||
import { motion } from "framer-motion";
|
||||
import { container, item, panel } from "../../../data/animation";
|
||||
import { VocoderUploadJob } from "@storyteller/components/src/jobs/VocoderUploadJobs";
|
||||
import { SessionVocoderUploadResultListFc } from "../_common/SessionVocoderUploadResultsListFc";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
enqueueVocoderUploadJob: (jobToken: string) => void;
|
||||
vocoderUploadJobs: Array<VocoderUploadJob>;
|
||||
}
|
||||
|
||||
function UploadVocoderPage(props: Props) {
|
||||
let history = useHistory();
|
||||
|
||||
const [downloadUrl, setDownloadUrl] = useState("");
|
||||
const [title, setTitle] = useState("");
|
||||
const [downloadUrlInvalidReason] = useState("");
|
||||
const [titleInvalidReason] = useState("");
|
||||
|
||||
if (!props.sessionWrapper.isLoggedIn()) {
|
||||
return (
|
||||
<div className="container py-5">
|
||||
<div className="py-5">
|
||||
<h1 className="fw-semibold text-center mb-4">
|
||||
You need to create an account or log in.
|
||||
</h1>
|
||||
<div className="d-flex gap-3 justify-content-center">
|
||||
<Link className="btn btn-secondary" to="/login">
|
||||
Login
|
||||
</Link>
|
||||
<Link className="btn btn-primary" to="/signup">
|
||||
Sign Up
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const handleDownloadUrlChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
const downloadUrlValue = (ev.target as HTMLInputElement).value;
|
||||
setDownloadUrl(downloadUrlValue);
|
||||
return false;
|
||||
};
|
||||
|
||||
const handleTitleChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||
ev.preventDefault();
|
||||
const titleValue = (ev.target as HTMLInputElement).value;
|
||||
setTitle(titleValue);
|
||||
return false;
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (ev: React.FormEvent<HTMLFormElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
let idempotencyToken = uuidv4();
|
||||
|
||||
const request = {
|
||||
idempotency_token: idempotencyToken,
|
||||
title: title,
|
||||
download_url: downloadUrl,
|
||||
generic_download_type: 'hifigan',
|
||||
};
|
||||
|
||||
const response = await EnqueueRetrieval(request);
|
||||
|
||||
if (EnqueueRetrievalIsOk(response)) {
|
||||
props.enqueueVocoderUploadJob(response.job_token);
|
||||
history.push("/");
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div initial="hidden" animate="visible" variants={container}>
|
||||
<div className="container pt-5 pb-4 px-md-4 px-lg-5 px-xl-3">
|
||||
<div className="d-flex flex-column">
|
||||
<motion.h1 className="display-5 fw-bold" variants={item}>
|
||||
Upload Vocoder Model
|
||||
</motion.h1>
|
||||
<motion.h4 variants={item}>Make your voice sound better!</motion.h4>
|
||||
<motion.div className="my-3" variants={item}>
|
||||
<BackLink
|
||||
link={FrontendUrlConfig.contributePage()}
|
||||
text="Back to contribute page"
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
className="container pt-3 d-flex flex-column gap-3 px-md-4 px-lg-5 px-xl-3"
|
||||
variants={item}
|
||||
>
|
||||
<p>
|
||||
If you're new to voice cloning, join our{" "}
|
||||
<span>
|
||||
<DiscordLink />
|
||||
</span>{" "}
|
||||
to get started. We have a friendly community that can help you start
|
||||
creating your own voices of your favorite characters.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once your vocoder is successfully uploaded, you'll be able to
|
||||
add it to your voice models. Others will be able to use it too, and
|
||||
you'll get credited.
|
||||
</p>
|
||||
|
||||
{/* TODO TEMP (2022-03-08) <p>
|
||||
Please do not upload voices that you didn't train yourself or voices of individuals
|
||||
who wish to not be voice cloned. We'll post a list of banned voices soon.
|
||||
</p>*/}
|
||||
</motion.div>
|
||||
|
||||
<motion.form onSubmit={handleFormSubmit} variants={panel}>
|
||||
<div className="container-panel py-5">
|
||||
<div className="panel p-3 py-4 p-lg-4">
|
||||
<div className="d-flex flex-column gap-4">
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Vocoder Title, eg. "High Pitched Voices (trained on Powerpuff Girls, MLP, and various anime characters)"
|
||||
</label>
|
||||
<div className="form-group">
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
placeholder="Title"
|
||||
value={title}
|
||||
onChange={handleTitleChange}
|
||||
/>
|
||||
</div>
|
||||
<p className="help">{titleInvalidReason}</p>
|
||||
</div>
|
||||
|
||||
{/*
|
||||
https://drive.google.com/file/d/{TOKEN}/view?usp=sharing
|
||||
*/}
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Download URL, eg. Google Drive link
|
||||
</label>
|
||||
<div className="form-group">
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
placeholder="Download URL"
|
||||
value={downloadUrl}
|
||||
onChange={handleDownloadUrlChange}
|
||||
/>
|
||||
</div>
|
||||
<p className="help">{downloadUrlInvalidReason}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<motion.div className="container pb-5" variants={item}>
|
||||
<button className="btn btn-primary w-100">Upload</button>
|
||||
</motion.div>
|
||||
</motion.form>
|
||||
|
||||
<SessionVocoderUploadResultListFc
|
||||
vocoderUploadJobs={props.vocoderUploadJobs}
|
||||
/>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export { UploadVocoderPage };
|
||||
+2
-2
@@ -21,7 +21,7 @@ interface Props {
|
||||
w2lTemplateUploadJobs: Array<W2lTemplateUploadJob>;
|
||||
}
|
||||
|
||||
function UploadW2lPhotoFc(props: Props) {
|
||||
function UploadW2lPhotoPage(props: Props) {
|
||||
let history = useHistory();
|
||||
|
||||
const [downloadUrl, setDownloadUrl] = useState("");
|
||||
@@ -174,4 +174,4 @@ function UploadW2lPhotoFc(props: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
export { UploadW2lPhotoFc };
|
||||
export { UploadW2lPhotoPage };
|
||||
+2
-2
@@ -21,7 +21,7 @@ interface Props {
|
||||
w2lTemplateUploadJobs: Array<W2lTemplateUploadJob>;
|
||||
}
|
||||
|
||||
function UploadW2lVideoFc(props: Props) {
|
||||
function UploadW2lVideoPage(props: Props) {
|
||||
let history = useHistory();
|
||||
|
||||
const [downloadUrl, setDownloadUrl] = useState("");
|
||||
@@ -173,4 +173,4 @@ function UploadW2lVideoFc(props: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
export { UploadW2lVideoFc };
|
||||
export { UploadW2lVideoPage };
|
||||
@@ -11746,14 +11746,6 @@ react-scripts@5.0.0:
|
||||
optionalDependencies:
|
||||
fsevents "^2.3.2"
|
||||
|
||||
react-tsparticles@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/react-tsparticles/-/react-tsparticles-2.1.3.tgz#45e570d869c3b26760525d8dcc52ea5cc8095f0c"
|
||||
integrity sha512-1Jc0Z8umkCHzY3qebs7nBLUXfeygEBAdubfWg7PjeYuYmjUHymneUXzXGiPLbqIMN+QQNM69485O3QLWks9lng==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.3"
|
||||
tsparticles-engine "^2.0.6"
|
||||
|
||||
react@^16.13.1:
|
||||
version "16.14.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
|
||||
@@ -13601,322 +13593,6 @@ tslib@^2.1.0, tslib@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||
|
||||
tsparticles-engine@^2.0.6, tsparticles-engine@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-engine/-/tsparticles-engine-2.1.3.tgz#d8922cf7811c40e5e9b87b18f9cc86043af8e900"
|
||||
integrity sha512-BmCo534tF5yRQofUczGSfCFrdeMYO6e7FXHv6AdRxL+j9NNPH3zF4HX6k24tbO4kmTH8tGX/+F9mugEQVo9AEg==
|
||||
|
||||
tsparticles-interaction-external-attract@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-attract/-/tsparticles-interaction-external-attract-2.1.3.tgz#9a6be2683d77f9ed214a0ca4d478c40bed87b2f4"
|
||||
integrity sha512-r9DDDlmzA47j0hrmur/2ITip4Qwki3fM1yNgmro048CPamF5pnrhCZBG8zq8hy6BO8KASe55OU5KCAJ9Zt3T2w==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-bounce@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-bounce/-/tsparticles-interaction-external-bounce-2.1.3.tgz#69ba88c7148a1c5790b570f38ea36ca365341dc8"
|
||||
integrity sha512-ueRHeuQhXMgWGhxFd3REK2/L4QJjhAuQxGZxIM6Tl80EmYNsCXSyQJ3RG/A839eLpGHDg5fLIytcilfu9o3XvA==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-bubble@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-bubble/-/tsparticles-interaction-external-bubble-2.1.3.tgz#27cc5350df4d968e0be8d1215de82cc173074272"
|
||||
integrity sha512-0ov4Glx0xfANPX7Tw09vOGC4MjrMoQkA8dqaRuPl8Q2SPGIMpWUWrBK9LzaZdfgtCixSeI+D/c7sgwEU5NovJg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-connect@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-connect/-/tsparticles-interaction-external-connect-2.1.3.tgz#bab9643e5e2b835defa90f54547091dd93d7efd1"
|
||||
integrity sha512-dHbVmYboa8bCEjkCn6QA81Lam6h+2nEORwL/ALee1gAsgyHU+cHWZ9umrL5dhYVbW3uxIn03zwZEwO+tSbISLw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-grab@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-grab/-/tsparticles-interaction-external-grab-2.1.3.tgz#2c0e788b37c104682d74fd7c01bdb9d362aa18ed"
|
||||
integrity sha512-Q/wbjf24YozYJJ73r2ISEQ5ixjgBXEe2s0fAW+7r+p3D4MGTYUPLmFdapislO9AW9mRLif60k4T2cWzbXxmx+w==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-pause@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-pause/-/tsparticles-interaction-external-pause-2.1.3.tgz#86ad1cc120b79b2ce33845372915da26f1e9a898"
|
||||
integrity sha512-M1OMqN1pkpUcPdXdZoqjSJNfXUZy1qCTu+Yuy6O2trQUL2fMmnqWYUxqvcOLVgGSuacC1PCnoypBXt0BIjKyhw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-push@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-push/-/tsparticles-interaction-external-push-2.1.3.tgz#2d259b65397555ec12667ab5c06901cb0e462957"
|
||||
integrity sha512-tRzQy8DgxPy3iQkDCARKbRy1OFST4f+WOvzzMEyphddbFZq5cllvT4s61sVrzH4gWO+6ryT/e9PQH1Q0sYG9Mw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-remove@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-remove/-/tsparticles-interaction-external-remove-2.1.3.tgz#3e6fd4abbe4e4bca1aed49a228908d265d3e4ac0"
|
||||
integrity sha512-9jWds7NcQmrptg+RcRAKYy/vTtwAMz5DbIu4W1WjJ13NmoGuL0opv58bADEaY3rCEXLDPk2L8YU2792rWkp5Rg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-repulse@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-repulse/-/tsparticles-interaction-external-repulse-2.1.3.tgz#01f10b9a8aeb50af88dd388af5d4ddb02147ea41"
|
||||
integrity sha512-MuZ1yCCxcL9h87oKtqgf+/m8kSFlo3L0J/hMK5dfGFKVhF3TR9kFb/4gCZngtCUUZh5ciWHpvnUwZ9Wk/SakEg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-external-trail@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-external-trail/-/tsparticles-interaction-external-trail-2.1.3.tgz#1ed0e9f17b86bd0c25eb65eacf94f89b22793413"
|
||||
integrity sha512-IhrCgksvwP1JvZ31U/G5Hypp2WQ4ID8foB4IbOVD/mOvemUQW3G8o/cohSDwKXB5jQFclGgQOizMK/k/0wVMAg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-particles-attract@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-particles-attract/-/tsparticles-interaction-particles-attract-2.1.3.tgz#df28dfa4310ae8a81eab50203490b6d21c80c9bb"
|
||||
integrity sha512-AG1HtpquRE5qTR2V3lnQ5fcCjlBa9RzxiiVeOX5dJDhvLrBA2NUPNRkGTMyl6PJZSnFnjMDKFQ/d24/A+ILWxQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-particles-collisions@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-particles-collisions/-/tsparticles-interaction-particles-collisions-2.1.3.tgz#6452c8044eb513102d97e315d6a1d5d4b6056383"
|
||||
integrity sha512-V4x6EzjmkWZBuUfVvCBelBbxYx+eiHYTf18ebLE73atfaSKnMHo9UentU18W47Zw0Z5aur+4/V0hS2uUFmSq1Q==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-interaction-particles-links@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-interaction-particles-links/-/tsparticles-interaction-particles-links-2.1.3.tgz#f3a4573c130659f4da630ab0dc6a61aa05c09334"
|
||||
integrity sha512-/gh3MAwQUfufkXcOggw0UwFJBXgs0hm0cvCNRFLx54qmzGFNjy7efkOFxl3YeqyQanqLiKYZmHdZEkNEYMnWIQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-move-base@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-move-base/-/tsparticles-move-base-2.1.3.tgz#b958970e07725340cd6ddbb213639173eb2b5c25"
|
||||
integrity sha512-aq9k3682zaKxe6R8MwdldoYnizCTntUj7VbJ0kXQ2QV+F/Fk8y50okbYslxbpKASP6yIGE9wXK3m9QqH5VQAXQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-move-parallax@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-move-parallax/-/tsparticles-move-parallax-2.1.3.tgz#25b494e960aecff77f6f7def4f96a3bd345753a3"
|
||||
integrity sha512-Miy/eMYTc+dO4n9wtd6PpONDpAy1Ta0+4tSY6K+QBse+Fp5bjokBSpnwDyAmIbgAcbj5XMlMp8yzCcE7ptlIhg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-particles.js@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-particles.js/-/tsparticles-particles.js-2.1.3.tgz#431ed900210fca8fe40be0b52a06244307eef9f7"
|
||||
integrity sha512-V1NZ3b8rUrRzaFixq9pUDw2OxAIYp6b8/CSmt/3SR7UZnC0q/lSAw9HDQzqhsCNOpFc0PzQa0ogB6sMY3eaEgA==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-plugin-absorbers@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-plugin-absorbers/-/tsparticles-plugin-absorbers-2.1.3.tgz#d8e79389287484bd7d030b6b6e32fb6b279b61be"
|
||||
integrity sha512-MRkP05QVNYwA4rV0nWTKOc+dANJ+dzw+t55qI7Xh9nmUineRJc784fjgZHk+/NDjgcfNb6RN05BSDkLzlANy3g==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-plugin-emitters@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-plugin-emitters/-/tsparticles-plugin-emitters-2.1.3.tgz#dd7769049a59e050e5a35877809103020d7d2ba1"
|
||||
integrity sha512-G5IB+06AQR066Ss9XeszXsPbikEJjmdal/IzIwALaslQUIlGgJQhlPYY3R1aUAgtY7Oit0O6gFDqURs3dj9d8Q==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-plugin-polygon-mask@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-plugin-polygon-mask/-/tsparticles-plugin-polygon-mask-2.1.3.tgz#ca3fbe7c8540ae018acb10549384daff66b1172e"
|
||||
integrity sha512-D8uuPZ+MpO2nBjeoYThePty3G3MGmBNIlQE92anrfUTEEKYjTlczY+nHlORfdNBL9fFwMiMnr/FgJwD0D68BdQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-circle@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-circle/-/tsparticles-shape-circle-2.1.3.tgz#a771e0aa40060104cbc85a0a402eb1bc4aa5e10e"
|
||||
integrity sha512-OA6C67QEB3lL+GWOMOAmINYkHDO9LO929OTtkce6YDtrvm44zND5VhgevVYhriPvkxE5/n85F13cWNo2rO8LRw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-image@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-image/-/tsparticles-shape-image-2.1.3.tgz#418ccb8b9505a65b9b264d040384d7d07c1e5d48"
|
||||
integrity sha512-aV9JFnM4FjVIB0fNSf3agkiXPySdiM1f+9JyUaKSfMxYZPoY7hj6Mva3hQJQ+2GLDQE5fTjj+/IH9qQuSm5eiA==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-line@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-line/-/tsparticles-shape-line-2.1.3.tgz#1761dc2081f9271ef4edc0c8bbeb2e896661a3a5"
|
||||
integrity sha512-22A3VvZvTN5g1iql8hNIU6NLcT72WKBtOPwKEFBTom7Foo7xrOH/xvjbTVN/TDUDKD86dMnsKVn0xF2NHk634A==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-polygon@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-polygon/-/tsparticles-shape-polygon-2.1.3.tgz#a143f5a1eca6d702008ba509936fc22ae26fa07f"
|
||||
integrity sha512-VEMD1K+uvPY7dq8JBYQn6zsuRlDiRyMGnxTy6XKTQhVp3Zs6zwZ/789WnepUc42QAYvKzofg8G/POsevhOWOvA==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-square@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-square/-/tsparticles-shape-square-2.1.3.tgz#f28d9c60a1189ea9ee1982968e6be276220adba7"
|
||||
integrity sha512-/q7aOUM5Kz+SRhpyICAvyBRmZy1Xt9Z545GHy6tqmxNn4RmiWNoqUda1V2DmMBD+rRb5jan7cQb37HQvltdrPQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-star@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-star/-/tsparticles-shape-star-2.1.3.tgz#63860426121391941585e9adc698ee140651d405"
|
||||
integrity sha512-aKsWgK1iGJSBOpWJ9u5JW9X0zAWz9G1jMYSScCbLEVAQ98WV7xSEYsNOSdanedOsXfH2PNssk4KKxb5Cwz8qcg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-shape-text@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-shape-text/-/tsparticles-shape-text-2.1.3.tgz#aee95157b72d732acaefc2d6ed7d732c8a31833d"
|
||||
integrity sha512-bsuHXHECRpl9Ty/70pEv1JHgdEjdq8GI2TrNCN7lyANuIFBka5gvmHqOIdKtuebqJb6OlNQB5E58EOiHvLObfw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-slim@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-slim/-/tsparticles-slim-2.1.3.tgz#6f60191b91ca75ee4257de49b67662277b020a31"
|
||||
integrity sha512-8FYaJt0oEWyKzLevi6dslFah5fIPAuxuqW25aJJxZJT0fu83HtHqgLinieFdoNS13afu+qKp+XlwYrkkczjStg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
tsparticles-interaction-external-attract "^2.1.3"
|
||||
tsparticles-interaction-external-bounce "^2.1.3"
|
||||
tsparticles-interaction-external-bubble "^2.1.3"
|
||||
tsparticles-interaction-external-connect "^2.1.3"
|
||||
tsparticles-interaction-external-grab "^2.1.3"
|
||||
tsparticles-interaction-external-pause "^2.1.3"
|
||||
tsparticles-interaction-external-push "^2.1.3"
|
||||
tsparticles-interaction-external-remove "^2.1.3"
|
||||
tsparticles-interaction-external-repulse "^2.1.3"
|
||||
tsparticles-interaction-particles-attract "^2.1.3"
|
||||
tsparticles-interaction-particles-collisions "^2.1.3"
|
||||
tsparticles-interaction-particles-links "^2.1.3"
|
||||
tsparticles-move-base "^2.1.3"
|
||||
tsparticles-move-parallax "^2.1.3"
|
||||
tsparticles-particles.js "^2.1.3"
|
||||
tsparticles-shape-circle "^2.1.3"
|
||||
tsparticles-shape-image "^2.1.3"
|
||||
tsparticles-shape-line "^2.1.3"
|
||||
tsparticles-shape-polygon "^2.1.3"
|
||||
tsparticles-shape-square "^2.1.3"
|
||||
tsparticles-shape-star "^2.1.3"
|
||||
tsparticles-shape-text "^2.1.3"
|
||||
tsparticles-updater-angle "^2.1.3"
|
||||
tsparticles-updater-color "^2.1.3"
|
||||
tsparticles-updater-life "^2.1.3"
|
||||
tsparticles-updater-opacity "^2.1.3"
|
||||
tsparticles-updater-out-modes "^2.1.3"
|
||||
tsparticles-updater-size "^2.1.3"
|
||||
tsparticles-updater-stroke-color "^2.1.3"
|
||||
|
||||
tsparticles-updater-angle@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-angle/-/tsparticles-updater-angle-2.1.3.tgz#2b34b9279d7e968717e5e86bd9e23d1f53223e76"
|
||||
integrity sha512-9yiCS8iZYexSyLAaTOkge2WM5ZUDZv6B4lWpgoUQANNScnrDkCkPHOb7ZYq4fbHYA+GElppAjamDsg2WBT5bsg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-color@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-color/-/tsparticles-updater-color-2.1.3.tgz#59e2973fd021d6cff0301b32e408083b48279301"
|
||||
integrity sha512-gsCLmwJsPauVyExRMUu0IA9R5HbEKgZ4/wndLLFxpdz/+b8PElL+SMxywEUf4WWWMC8o/1JQxlQmuW0Q+EWwyQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-life@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-life/-/tsparticles-updater-life-2.1.3.tgz#8fc77c1ae0b4a995248a082c8abb5dd92393a6fe"
|
||||
integrity sha512-de9kkz6PFDq8OSrhNdmD24SpUC92Oz15QCiu4Sxbg98ngUun6ejE/3SZku9CX0lXgDK8k9IcH1SrIT4RzM2JKA==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-opacity@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-opacity/-/tsparticles-updater-opacity-2.1.3.tgz#ae8734fa9320322447c81f27a6ece448168b9809"
|
||||
integrity sha512-WQEFM4KyLCE87LWUn8Wxh/Wmwlg/GLXvTJkFYRGjD1AjW85CJO9DM0t3O+xjKq3hR4LaMFRHF4Fki/PhmnUF+Q==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-out-modes@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-out-modes/-/tsparticles-updater-out-modes-2.1.3.tgz#fef5eed3b6cb934fcb9e9b33f635d373d6adbbbf"
|
||||
integrity sha512-u7JtAKyvKCq7gwuN+NlzVJNYwvVBMx3wPCyJNZvaK9umM51lQHJCRsNj57lJ7jSJlaWsEYspw3rPXRvaw/+dVA==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-roll@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-roll/-/tsparticles-updater-roll-2.1.3.tgz#ebd6d0f06d4ec552121277f5a5c90230190e739f"
|
||||
integrity sha512-0T9wEuclcV1nfNlmJH4zDco+7xB/tBFzCYVbZ1qnfwT29J66gz7/9iBYk7iRr91uhxckHXO4VcyJCk+e0vVb1w==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-size@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-size/-/tsparticles-updater-size-2.1.3.tgz#42e2250c178ee192e89bc82385b92d4e7f4fe2eb"
|
||||
integrity sha512-uPpSvi73saaytTSfEtiLdlaJU81uLhDWwMe8UoVEsIggJ5nUQzGU9/WP97iSYR10zr9Xzof1Zweksj4hWvf3mQ==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-stroke-color@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-stroke-color/-/tsparticles-updater-stroke-color-2.1.3.tgz#e53b4cf27fb130b2ae088c1544d2fd7f5871f082"
|
||||
integrity sha512-TSZcbhtt92710fBzF19OqwDu6ZN0LccLHFNgmWPy1EFT5oULe9ZrH6aWqEJ7q4HCdbxZytW+7rv5YRsRL15M0Q==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-tilt@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-tilt/-/tsparticles-updater-tilt-2.1.3.tgz#e653c381568a7bb276f0fca04822727affa7cf58"
|
||||
integrity sha512-avSUIc6QOp/caaWUNodCQhNwLdvuC8fhDn7JiUcq2Z95YwcJTfM1JsvD2J6UeNQL5Jj2+cxjtECCQ1JzK0Sutg==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-twinkle@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-twinkle/-/tsparticles-updater-twinkle-2.1.3.tgz#61d905276e92fe2282c781f172bdef90116a778f"
|
||||
integrity sha512-89WwhJRCIKWNUdK56pq8DuXuDriO/1gfddEImTeFGmA/q1my1W3nGX8LvHIR0/d9kS6tuL6sQIGolXOLwgp5Yw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles-updater-wobble@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles-updater-wobble/-/tsparticles-updater-wobble-2.1.3.tgz#dd2ada0b9efd4a5e481e5a35fe653f01eed9bac0"
|
||||
integrity sha512-UpucA4hBIn/bLYZeJgCb/JPHmSfHIUpjbEenyHm7u1BK+PuiiNDVZ13o9ClIXKDiOK6ebgIMy8afxmPIHGmG1Q==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
|
||||
tsparticles@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tsparticles/-/tsparticles-2.1.3.tgz#c23dce62f69274872f9f1044769227c06f0daf2a"
|
||||
integrity sha512-7fKNV+6B9CcKQbFVFre2Rx2BAkW86/1jXjZGh9B0u+l6EARZSwS2aMOYWP1lJuzvHSmupoG0cGmZfKTr7/AIZw==
|
||||
dependencies:
|
||||
tsparticles-engine "^2.1.3"
|
||||
tsparticles-interaction-external-trail "^2.1.3"
|
||||
tsparticles-plugin-absorbers "^2.1.3"
|
||||
tsparticles-plugin-emitters "^2.1.3"
|
||||
tsparticles-plugin-polygon-mask "^2.1.3"
|
||||
tsparticles-slim "^2.1.3"
|
||||
tsparticles-updater-roll "^2.1.3"
|
||||
tsparticles-updater-tilt "^2.1.3"
|
||||
tsparticles-updater-twinkle "^2.1.3"
|
||||
tsparticles-updater-wobble "^2.1.3"
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
||||
|
||||
Reference in new issue
Block a user