mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-14 13:52:11 +00:00
seed vc countdown page (#721)
* seed vc countdown page and sections as reusable component * redirects update
This commit is contained in:
1 parent
61295cba43
commit
5b683334b8
18 files changed
+546
-22
No files matched your search
@@ -60,6 +60,7 @@
|
||||
/product-usage* /website/index.html 200
|
||||
/profile* /website/index.html 200
|
||||
/search* /website/index.html 200
|
||||
/seed-vc* /website/index.html 200
|
||||
/set-username* /website/index.html 200
|
||||
/signup* /website/index.html 200
|
||||
/stream* /website/index.html 200
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"local-storage": "^2.0.0",
|
||||
"moment": "^2.29.4",
|
||||
"react-easy-crop": "^5.0.7",
|
||||
"react-helmet-async": "^2.0.5",
|
||||
"react-webcam": "^7.2.0",
|
||||
"universal-cookie": "^6.1.1",
|
||||
"yarn": "^1.22.19"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,71 @@
|
||||
@import "scss/colours.scss";
|
||||
|
||||
.countdown-container {
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
width: 300px;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
padding: 20px 0px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 20px;
|
||||
color: rgba($white, 0.6);
|
||||
margin-bottom: 32px;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.countdown-icon {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
font-size: 36px;
|
||||
background-color: $secondary;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 3px solid rgba($white, 0.2);
|
||||
}
|
||||
|
||||
.countdown-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
background-color: $secondary;
|
||||
border-radius: 8px;
|
||||
padding: 24px 10px;
|
||||
border: 3px solid $primary;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
|
||||
.countdown-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.countdown-value {
|
||||
font-size: 46px;
|
||||
font-weight: bold;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.countdown-label {
|
||||
font-size: 16px;
|
||||
color: rgba($white, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import { faArrowRight, IconDefinition } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button, Container, Panel } from "components/common";
|
||||
import { AppStateContext } from "components/providers/AppStateProvider";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import "./Countdown.scss";
|
||||
|
||||
interface TimeLeft {
|
||||
days?: number;
|
||||
hours?: number;
|
||||
minutes?: number;
|
||||
seconds?: number;
|
||||
}
|
||||
|
||||
interface CountdownProps {
|
||||
endDate: Date;
|
||||
title: string;
|
||||
description: string;
|
||||
icon?: IconDefinition;
|
||||
}
|
||||
|
||||
export default function Countdown({
|
||||
endDate,
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
}: CountdownProps): JSX.Element {
|
||||
const [timeLeft, setTimeLeft] = useState<TimeLeft>(calculateTimeLeft());
|
||||
const [localEndTime, setLocalEndTime] = useState<string>("");
|
||||
const { sessionWrapper } = useContext(AppStateContext);
|
||||
|
||||
useEffect(() => {
|
||||
updateLocalEndTime();
|
||||
|
||||
const timer = setInterval(() => {
|
||||
setTimeLeft(calculateTimeLeft());
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
});
|
||||
|
||||
function calculateTimeLeft(): TimeLeft {
|
||||
const difference = +endDate - +new Date();
|
||||
let timeLeft: TimeLeft = {};
|
||||
|
||||
if (difference > 0) {
|
||||
timeLeft = {
|
||||
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
|
||||
hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
|
||||
minutes: Math.floor((difference / 1000 / 60) % 60),
|
||||
seconds: Math.floor((difference / 1000) % 60),
|
||||
};
|
||||
}
|
||||
|
||||
return timeLeft;
|
||||
}
|
||||
|
||||
function updateLocalEndTime() {
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
timeZoneName: "short",
|
||||
};
|
||||
setLocalEndTime(endDate.toLocaleDateString("en-US", options));
|
||||
}
|
||||
|
||||
return (
|
||||
<Container
|
||||
type="panel"
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
style={{ height: "calc(100vh - 65px)", maxWidth: "768px" }}
|
||||
>
|
||||
<Panel padding={true}>
|
||||
<div className="countdown-container">
|
||||
{icon && (
|
||||
<div className="countdown-icon mb-3">
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</div>
|
||||
)}
|
||||
<h1 className="fw-bold mb-1">{title}</h1>
|
||||
<p className="description">{description}</p>
|
||||
<div className="countdown-wrapper">
|
||||
{Object.entries(timeLeft).map(([interval, value]) => (
|
||||
<div key={interval} className="countdown-item">
|
||||
<span className="countdown-value">{value}</span>
|
||||
<span className="countdown-label">{interval}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="local-time mt-3 text-white opacity-50">
|
||||
<small>Countdown ends local time: {localEndTime}</small>
|
||||
</div>
|
||||
|
||||
{!sessionWrapper.isLoggedIn() && (
|
||||
<Button
|
||||
label="Sign up before launch"
|
||||
className="mt-4"
|
||||
icon={faArrowRight}
|
||||
iconFlip={true}
|
||||
to="/signup"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Panel>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./Countdown";
|
||||
@@ -0,0 +1,42 @@
|
||||
@import "scss/colours.scss";
|
||||
|
||||
.faq-section {
|
||||
background-color: rgba($secondary, 0.8);
|
||||
border-radius: 12px;
|
||||
padding-bottom: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
border: 3px solid rgba($secondary, 0.8);
|
||||
|
||||
.faq-item {
|
||||
h3 {
|
||||
color: lighten($primary, 5%);
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
color: rgba($white, 0.8);
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.faq-section {
|
||||
padding: 20px;
|
||||
padding-top: 2.5rem;
|
||||
border-radius: 0px;
|
||||
|
||||
.faq-item {
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import React from "react";
|
||||
import { Container, Panel } from "components/common";
|
||||
import "./FAQSection.scss";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
|
||||
interface FAQItem {
|
||||
question: string;
|
||||
answer: string;
|
||||
}
|
||||
|
||||
interface FAQSectionProps {
|
||||
title?: string;
|
||||
faqItems: FAQItem[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const FAQSection: React.FC<FAQSectionProps> = ({
|
||||
title = "Frequently Asked Questions",
|
||||
faqItems,
|
||||
className,
|
||||
}) => {
|
||||
const structuredData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
mainEntity: faqItems.map(item => ({
|
||||
"@type": "Question",
|
||||
name: item.question,
|
||||
acceptedAnswer: {
|
||||
"@type": "Answer",
|
||||
text: item.answer,
|
||||
},
|
||||
})),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<script type="application/ld+json">
|
||||
{JSON.stringify(structuredData)}
|
||||
</script>
|
||||
</Helmet>
|
||||
<Container type="panel" className={className}>
|
||||
<Panel padding={true} className="p-4 faq-section">
|
||||
<h2 className="fw-bold mb-5">{title}</h2>
|
||||
<section aria-label="FAQ Section">
|
||||
{faqItems.map((item, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<div className="faq-item">
|
||||
<h3>{item.question}</h3>
|
||||
<p>{item.answer}</p>
|
||||
</div>
|
||||
{index < faqItems.length - 1 && <hr className="my-5" />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</section>
|
||||
</Panel>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FAQSection;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./FAQSection";
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
@import "scss/colours.scss";
|
||||
|
||||
.how-to-use-section {
|
||||
background-color: rgba($secondary, 0.8);
|
||||
border-radius: 12px;
|
||||
padding-bottom: 2rem;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 3rem;
|
||||
border: 3px solid rgba($white, 0.2);
|
||||
|
||||
.how-to-use-icon {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
padding: 14px;
|
||||
background-color: lighten($secondary, 10%);
|
||||
color: $white;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
border: 3px solid lighten($secondary, 20%);
|
||||
|
||||
@media (max-width: 768px) {
|
||||
margin-bottom: 16px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.how-to-use-item {
|
||||
margin-bottom: 30px;
|
||||
|
||||
h3 {
|
||||
color: lighten($primary, 6%);
|
||||
font-size: 20px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
color: rgba($white, 0.8);
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.how-to-use-section {
|
||||
padding: 20px;
|
||||
padding-top: 2.5rem;
|
||||
border-radius: 0px;
|
||||
|
||||
.how-to-use-item {
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import React from "react";
|
||||
import { Container } from "components/common";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||
import "./HowToUseSection.scss";
|
||||
|
||||
interface StepItem {
|
||||
icon: IconDefinition;
|
||||
title: string;
|
||||
description: React.ReactNode;
|
||||
}
|
||||
|
||||
interface HowToUseSectionProps {
|
||||
title?: string;
|
||||
steps: StepItem[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const HowToUseSection: React.FC<HowToUseSectionProps> = ({
|
||||
title = "How to Use",
|
||||
steps,
|
||||
className,
|
||||
}) => {
|
||||
return (
|
||||
<Container type="panel" className={className}>
|
||||
<div className="how-to-use-section p-4">
|
||||
<h2 className="fw-bold mb-5">{title}</h2>
|
||||
<div className="row g-5">
|
||||
{steps.map((step, index) => (
|
||||
<div key={index} className="col-md-4 how-to-use-item">
|
||||
<FontAwesomeIcon icon={step.icon} className="how-to-use-icon" />
|
||||
<h3>{step.title}</h3>
|
||||
<p>{step.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default HowToUseSection;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./HowToUseSection";
|
||||
@@ -13,7 +13,7 @@ export default function AITools() {
|
||||
to?: string;
|
||||
externalLink?: string;
|
||||
title: string;
|
||||
text: string;
|
||||
text?: string;
|
||||
imgSrc?: string;
|
||||
imgAlt: string;
|
||||
videoSrc?: string;
|
||||
@@ -107,6 +107,13 @@ export default function AITools() {
|
||||
imgSrc: "/images/landing/select-f5-tts.webp",
|
||||
imgAlt: "Voice Cloning",
|
||||
},
|
||||
{
|
||||
to: "/seed-vc",
|
||||
title: "Seed-VC Voice Conversion",
|
||||
text: "Zero-shot voice conversion",
|
||||
imgSrc: "/images/landing/select-seed-vc.webp",
|
||||
imgAlt: "Zero-shot Voice Conversion",
|
||||
},
|
||||
{
|
||||
to: "/voice-designer",
|
||||
title: t("productVdTitle"),
|
||||
@@ -130,7 +137,8 @@ export default function AITools() {
|
||||
currentPath.includes("/live-portrait") ||
|
||||
currentPath.includes("/dev-lp") ||
|
||||
currentPath.includes("/beta/") ||
|
||||
currentPath.includes("/face-animator")
|
||||
currentPath.includes("/face-animator") ||
|
||||
currentPath.includes("/webcam-acting")
|
||||
) {
|
||||
items.push({
|
||||
externalLink: "https://discord.gg/fakeyou",
|
||||
@@ -178,6 +186,8 @@ export default function AITools() {
|
||||
// );
|
||||
// }
|
||||
|
||||
const discordItem = items.find(item => item.imgAlt === "Discord Link");
|
||||
|
||||
if (currentPath.includes("/tts")) {
|
||||
items = items.filter(item => item.to !== "/tts");
|
||||
}
|
||||
@@ -186,19 +196,6 @@ export default function AITools() {
|
||||
items = items.filter(item => item.to !== "/voice-conversion");
|
||||
}
|
||||
|
||||
if (currentPath.includes("/beta/")) {
|
||||
items = items.filter(
|
||||
item =>
|
||||
item.to !== "/tts" &&
|
||||
item.to !== "/voice-conversion" &&
|
||||
item.to !== "/voice-designer" &&
|
||||
item.to !== "/face-animator" &&
|
||||
item.to !== "/beta/2d-video-compositor" &&
|
||||
item.to !== "/beta/3d-video-compositor" &&
|
||||
item.to !== "/beta/webcam-acting"
|
||||
);
|
||||
}
|
||||
|
||||
if (currentPath.includes("/tts")) {
|
||||
items = [items[0], items[1], items[2], items[3], items[4], items[5]];
|
||||
}
|
||||
@@ -212,15 +209,15 @@ export default function AITools() {
|
||||
}
|
||||
|
||||
if (currentPath.includes("/style-video")) {
|
||||
items = [items[1], items[2], items[8]];
|
||||
items = [items[1], items[2], discordItem].filter(Boolean) as Item[];
|
||||
}
|
||||
|
||||
if (currentPath.includes("/face-animator")) {
|
||||
items = [items[0], items[1], items[8]];
|
||||
items = [items[0], items[1], discordItem].filter(Boolean) as Item[];
|
||||
}
|
||||
|
||||
if (currentPath.includes("/webcam-acting")) {
|
||||
items = [items[0], items[1], items[8]];
|
||||
items = [items[0], items[1], discordItem].filter(Boolean) as Item[];
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -229,7 +226,7 @@ export default function AITools() {
|
||||
currentPath.includes("/live-portrait") ||
|
||||
currentPath.includes("/dev-lp")
|
||||
) {
|
||||
items = [items[0], items[2], items[8]];
|
||||
items = [items[0], items[2], discordItem].filter(Boolean) as Item[];
|
||||
}
|
||||
|
||||
return <AIToolsRow {...{ items }} />;
|
||||
|
||||
@@ -107,13 +107,17 @@ export function AIToolsItem({
|
||||
<h4 className="fw-bold text-white d-inline-flex align-items-center mb-0">
|
||||
<span>{title}</span>
|
||||
</h4>
|
||||
<h6 className="fw-normal opacity-75 text-white">{text}</h6>
|
||||
{text && (
|
||||
<h6 className="fw-normal opacity-75 text-white">{text}</h6>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!badgeContent && (
|
||||
<>
|
||||
<h3 className="fw-bold text-white mb-1">{title}</h3>
|
||||
<h6 className="fw-normal opacity-75 text-white">{text}</h6>
|
||||
{text && (
|
||||
<h6 className="fw-normal opacity-75 text-white">{text}</h6>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom";
|
||||
// import * as serviceWorker from "./serviceWorker";
|
||||
// import AppTranslated from "./AppTranslated";
|
||||
import { App } from "./App";
|
||||
import { HelmetProvider } from "react-helmet-async";
|
||||
|
||||
const designSystemClass = "fakeyou-refresh";
|
||||
|
||||
@@ -24,7 +25,9 @@ document.getElementsByTagName("html")[0].classList.add(designSystemClass);
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<HelmetProvider>
|
||||
<App />
|
||||
</HelmetProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
@@ -445,6 +445,10 @@ const routes = [
|
||||
path: "/f5-tts",
|
||||
component: lazy(() => import("./pages/f5_tts/F5TTS")),
|
||||
},
|
||||
{
|
||||
path: "/seed-vc",
|
||||
component: lazy(() => import("./pages/seed_vc/SeedVC")),
|
||||
},
|
||||
{
|
||||
path: "/style-video/:mediaToken?",
|
||||
component: lazy(() => import("./pages/style-video")),
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import React from "react";
|
||||
import { faWaveform } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle";
|
||||
import Countdown from "components/common/Countdown";
|
||||
import FAQSection from "components/common/FAQSection";
|
||||
//
|
||||
|
||||
const endDate = new Date("2024-10-23T12:00:00-04:00");
|
||||
|
||||
export default function SeedVC() {
|
||||
usePrefixedDocumentTitle("Seed-VC Zero-shot Voice Conversion");
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
background: `url("/images/bg-svg.svg") no-repeat center center`,
|
||||
backgroundSize: "cover",
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
}}
|
||||
>
|
||||
<Countdown
|
||||
endDate={endDate}
|
||||
title="Seed-VC Zero-shot Voice Conversion"
|
||||
description="New zero-shot voice conversion coming soon..."
|
||||
icon={faWaveform}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* <HowToUseSection title="How to Use F5-TTS" steps={howToUseSteps} /> */}
|
||||
|
||||
<FAQSection faqItems={faqItems} className="mt-5 pt-5" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const faqItems = [
|
||||
{
|
||||
question: "What is Seed-VC Zero-shot Voice Conversion?",
|
||||
answer:
|
||||
"Seed-VC Zero-shot Voice Conversion is an advanced AI-powered tool designed for state-of-the-art voice conversion and singing voice conversion. It uses in-context learning to transform one voice into another without any prior training, making it an ideal choice for projects that require versatile voice modification.",
|
||||
},
|
||||
{
|
||||
question: "How does Seed-VC work?",
|
||||
answer:
|
||||
"Seed-VC leverages cutting-edge AI techniques, including zero-shot learning, to convert voices with just a short audio reference (1–30 seconds). It can adapt to both speaking and singing voices, creating natural-sounding results without the need for extensive data or training.",
|
||||
},
|
||||
{
|
||||
question: "What kind of voice quality can I expect from Seed-VC?",
|
||||
answer:
|
||||
"Seed-VC delivers high-quality, natural-sounding voice conversions, suitable for professional applications like dubbing, voice-overs, and even singing voice transformations. The AI is designed to retain the unique qualities of the target voice while maintaining clear and lifelike output.",
|
||||
},
|
||||
{
|
||||
question: "Can Seed-VC be used for voice-over and dubbing work?",
|
||||
answer:
|
||||
"Definitely! Seed-VC's zero-shot capabilities make it perfect for voice-over and dubbing. Whether you need to create different voices for various characters or adapt a voice to a new language, it can handle the task seamlessly. It also supports singing voice conversion, adding flexibility to musical projects.",
|
||||
},
|
||||
];
|
||||
|
||||
// const howToUseSteps = [
|
||||
// {
|
||||
// icon: faWaveformLines,
|
||||
// title: "Step 1: Upload Your Audio",
|
||||
// description:
|
||||
// "In the panel above, start by adding a reference audio, either record your own voice or upload an audio file. This audio will be used by F5-TTS to clone the voice, enabling the generation of speech that closely resembles the reference voice. For optimal results, ensure the audio is clear and of high quality.",
|
||||
// },
|
||||
// {
|
||||
// icon: faTextSize,
|
||||
// title: "Step 2: Enter Your Text",
|
||||
// description:
|
||||
// "Next, input the text you wish to convert into speech. This text will be synthesized using the voice from your reference audio, allowing you to create personalized audio content. Ensure your text is clear and concise for the best results.",
|
||||
// },
|
||||
// {
|
||||
// icon: faArrowDownToLine,
|
||||
// title: "Step 3: Generate and Save",
|
||||
// description: (
|
||||
// <>
|
||||
// With your audio and text prepared, click 'Generate Speech' to activate
|
||||
// F5-TTS and transform your text into lifelike speech. Once the process is
|
||||
// complete, you can listen to the synthesized audio directly in the output
|
||||
// panel above. If you're happy with the result, click the download button
|
||||
// to save the audio file and use it in your projects!
|
||||
// </>
|
||||
// ),
|
||||
// },
|
||||
// ];
|
||||
@@ -4489,6 +4489,7 @@ __metadata:
|
||||
prettier: ^3.1.0
|
||||
pretty-quick: ^3.1.3
|
||||
react-easy-crop: ^5.0.7
|
||||
react-helmet-async: ^2.0.5
|
||||
react-webcam: ^7.2.0
|
||||
universal-cookie: ^6.1.1
|
||||
yarn: ^1.22.19
|
||||
@@ -12559,6 +12560,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"invariant@npm:^2.2.4":
|
||||
version: 2.2.4
|
||||
resolution: "invariant@npm:2.2.4"
|
||||
dependencies:
|
||||
loose-envify: ^1.0.0
|
||||
checksum: cc3182d793aad82a8d1f0af697b462939cb46066ec48bbf1707c150ad5fad6406137e91a262022c269702e01621f35ef60269f6c0d7fd178487959809acdfb14
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ip@npm:^1.1.0, ip@npm:^1.1.5":
|
||||
version: 1.1.5
|
||||
resolution: "ip@npm:1.1.5"
|
||||
@@ -17925,6 +17935,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-fast-compare@npm:^3.2.2":
|
||||
version: 3.2.2
|
||||
resolution: "react-fast-compare@npm:3.2.2"
|
||||
checksum: 2071415b4f76a3e6b55c84611c4d24dcb12ffc85811a2840b5a3f1ff2d1a99be1020d9437ee7c6e024c9f4cbb84ceb35e48cf84f28fcb00265ad2dfdd3947704
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-fast-marquee@npm:^1.3.5":
|
||||
version: 1.3.5
|
||||
resolution: "react-fast-marquee@npm:1.3.5"
|
||||
@@ -17945,6 +17962,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-helmet-async@npm:^2.0.5":
|
||||
version: 2.0.5
|
||||
resolution: "react-helmet-async@npm:2.0.5"
|
||||
dependencies:
|
||||
invariant: ^2.2.4
|
||||
react-fast-compare: ^3.2.2
|
||||
shallowequal: ^1.1.0
|
||||
peerDependencies:
|
||||
react: ^16.6.0 || ^17.0.0 || ^18.0.0
|
||||
checksum: cc2d13496f6fdee6b5f9472d3f7369db3e70e4fc1a55793708c2bbd90d48b0dedc725fd066f987c7a3d74b03a29bd5e65b9f40fa29bd8239e7cfb526aff4d4b6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-i18next@npm:^11.15.4":
|
||||
version: 11.15.4
|
||||
resolution: "react-i18next@npm:11.15.4"
|
||||
|
||||
Reference in new issue
Block a user