mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-12 04:42:16 +00:00
Merge pull request #224 from storytold/bflat-fy-landing-update
Bflat fy landing update
This commit is contained in:
5 files changed
+317
-51
No files matched your search
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 10 KiB |
@@ -1076,6 +1076,55 @@ styles with important tags:
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.upload-component {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
|
||||
.panel {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
height: 100%;
|
||||
border: dashed 2px rgba($white, 0.12) !important;
|
||||
border-radius: 0.5rem;
|
||||
transition: 0.1s all;
|
||||
|
||||
&:hover {
|
||||
background-color: lighten($panel, 6%);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-zone-drag {
|
||||
background-color: $white !important;
|
||||
}
|
||||
|
||||
.filename {
|
||||
display: block;
|
||||
max-width: 230px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.supported-files {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-vc {
|
||||
flex-wrap: nowrap;
|
||||
height: auto;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.video-container {
|
||||
border: 2px solid;
|
||||
border-color: #ffffff20;
|
||||
@@ -1323,7 +1372,7 @@ textarea {
|
||||
}
|
||||
|
||||
.lead {
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faDiscord, faTwitter } from "@fortawesome/free-brands-svg-icons";
|
||||
import { WebUrl } from "../../../../common/WebUrl";
|
||||
import { faMicrophone, faRightLeft } from "@fortawesome/pro-solid-svg-icons";
|
||||
// import { Analytics } from "../../../../../common/Analytics";
|
||||
|
||||
interface Props {
|
||||
@@ -97,7 +98,7 @@ function LandingPage(props: Props) {
|
||||
|
||||
return (
|
||||
<motion.div initial="hidden" animate="visible" variants={container}>
|
||||
<div className="container pb-md-5 pt-lg-5 mb-4 px-md-5 px-lg-5 px-xl-3">
|
||||
<div className="container pb-5 pb-lg-0 pt-lg-2 px-md-5 px-lg-5 px-xl-3">
|
||||
<div className="row flex-md-row-reverse">
|
||||
<div className="col-12 col-lg-5 p-md-0 d-flex justify-content-center">
|
||||
<img
|
||||
@@ -108,10 +109,10 @@ function LandingPage(props: Props) {
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-lg-7 d-flex flex-column justify-content-center flex-reverse px-md-5 px-lg-3">
|
||||
<h1 className="fw-bold display-4 text-center text-lg-start px-md-5 px-lg-0">
|
||||
<h1 className="fw-bold display-5 text-center text-lg-start px-md-5 px-lg-0">
|
||||
Text to Speech, Voice Conversion & AI Tools
|
||||
</h1>
|
||||
<p className="lead opacity-75 pb-4 text-center text-lg-start px-md-5 px-lg-0">
|
||||
<p className="lead opacity-75 pb-4 text-center text-lg-start px-md-5 px-lg-0 pe-lg-5">
|
||||
Generate audio or videos of your favorite characters saying
|
||||
anything you want with FakeYou's deep fake tech.
|
||||
</p>
|
||||
@@ -125,6 +126,175 @@ function LandingPage(props: Props) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="container-panel pb-5 mb-5">
|
||||
<div className="panel p-3 py-4 p-md-4">
|
||||
<div className="d-flex gap-4">
|
||||
<form
|
||||
className="w-100 d-flex flex-column"
|
||||
// onSubmit={handleFormSubmit}
|
||||
>
|
||||
<div className="row gx-5 gy-5">
|
||||
<div className="col-12 d-flex flex-column gap-4">
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Choose Target Voice (xxx to choose from)
|
||||
</label>
|
||||
<div className="input-icon-search pb-4">
|
||||
<span className="form-control-feedback">
|
||||
<FontAwesomeIcon icon={faMicrophone} />
|
||||
</span>
|
||||
|
||||
{/* <VcModelListSearch
|
||||
voiceConversionModels={props.voiceConversionModels}
|
||||
setVoiceConversionModels={props.setVoiceConversionModels}
|
||||
maybeSelectedVoiceConversionModel={
|
||||
props.maybeSelectedVoiceConversionModel
|
||||
}
|
||||
setMaybeSelectedVoiceConversionModel={interceptModelChange}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul className="nav nav-tabs nav-vc" id="myTab" role="tablist">
|
||||
<li className="nav-item w-100" role="presentation">
|
||||
<button
|
||||
className="nav-link active w-100"
|
||||
id="prerecorded-tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#prerecorded"
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls="prerecorded"
|
||||
aria-selected="true"
|
||||
>
|
||||
Pre-recorded
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item w-100" role="presentation">
|
||||
<button
|
||||
className="nav-link w-100"
|
||||
id="recordaudio-tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#recordaudio"
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls="recordaudio"
|
||||
aria-selected="false"
|
||||
>
|
||||
Microphone
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="tab-content" id="myTabContent">
|
||||
<div
|
||||
className="tab-pane fade show active"
|
||||
id="prerecorded"
|
||||
role="tabpanel"
|
||||
aria-labelledby="prerecorded-tab"
|
||||
>
|
||||
<div className="d-flex flex-column gap-4 h-100">
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Upload Input Audio
|
||||
</label>
|
||||
<div className="d-flex flex-column gap-3 upload-component">
|
||||
{/* <UploadComponent
|
||||
setMediaUploadToken={setMediaUploadToken}
|
||||
formIsCleared={formIsCleared}
|
||||
setFormIsCleared={setFormIsCleared}
|
||||
setCanConvert={setCanConvert}
|
||||
changeConvertIdempotencyToken={
|
||||
changeConvertIdempotencyToken
|
||||
}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/*<div>
|
||||
<label className="sub-title">
|
||||
Or pick from your audio collection (5 files)
|
||||
</label>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<div className="input-icon-search">
|
||||
<span className="form-control-feedback">
|
||||
<FontAwesomeIcon icon={faFiles} />
|
||||
</span>
|
||||
|
||||
<Select
|
||||
value="test"
|
||||
classNames={SearchFieldClass}
|
||||
// On mobile, we don't want the onscreen keyboard to take up half the UI.
|
||||
autoFocus={false}
|
||||
isSearchable={false}
|
||||
// NB: The following settings improve upon performance.
|
||||
// See: https://github.com/JedWatson/react-select/issues/3128
|
||||
filterOption={createFilter({
|
||||
ignoreAccents: false,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>*/}
|
||||
|
||||
<div>
|
||||
<label className="sub-title">Convert Audio</label>
|
||||
|
||||
<div className="d-flex gap-3">
|
||||
<button className="btn btn-primary w-100">
|
||||
<FontAwesomeIcon
|
||||
icon={faRightLeft}
|
||||
className="me-2"
|
||||
/>
|
||||
Convert
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="tab-pane fade"
|
||||
id="recordaudio"
|
||||
role="tabpanel"
|
||||
aria-labelledby="recordaudio-tab"
|
||||
>
|
||||
<div className="d-flex flex-column gap-4 h-100">
|
||||
<div>
|
||||
<label className="sub-title">Record Audio</label>
|
||||
<div className="d-flex flex-column gap-3 upload-component">
|
||||
{/* <RecordComponent
|
||||
setMediaUploadToken={setMediaUploadToken}
|
||||
formIsCleared={formIsCleared}
|
||||
setFormIsCleared={setFormIsCleared}
|
||||
setCanConvert={setCanConvert}
|
||||
changeConvertIdempotencyToken={
|
||||
changeConvertIdempotencyToken
|
||||
}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="sub-title">Convert Audio</label>
|
||||
|
||||
<div className="d-flex gap-3">
|
||||
<button className="btn btn-primary w-100">
|
||||
<FontAwesomeIcon
|
||||
icon={faRightLeft}
|
||||
className="me-2"
|
||||
/>
|
||||
Convert
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="container pt-3 pt-md-0 pb-5 px-md-5 px-xl-3">
|
||||
<h2 className="fw-bold mb-4">AI Tools</h2>
|
||||
<div className="row g-4 position-relative">
|
||||
@@ -153,7 +323,7 @@ function LandingPage(props: Props) {
|
||||
<div className="panel panel-select d-flex flex-column align-items-center">
|
||||
<div className="d-flex px-4 pt-4 align-items-center w-100">
|
||||
<div className="flex-grow-1">
|
||||
<h3 className="fw-bold text-white mb-1">Voice Conversion</h3>
|
||||
<h3 className="fw-bold text-white mb-1">Voice to Voice</h3>
|
||||
<h6 className="fw-normal opacity-75 text-white">
|
||||
Speak as someone else
|
||||
</h6>
|
||||
@@ -228,21 +398,24 @@ function LandingPage(props: Props) {
|
||||
<div className="col-12 col-md-6 col-lg-5 d-flex flex-column justify-content-center gap-3">
|
||||
<h2 className="fw-bold">Make your favorite characters talk</h2>
|
||||
<p className="opacity-75">
|
||||
Our AI-powered text to speech service lets you choose your
|
||||
favorite character's voice and input any text to hear them say it.
|
||||
Our AI-powered text-to-speech and voice transformer tools let you
|
||||
convert your text or voice into your favorite character's voice.
|
||||
Perfect for content creators and anyone looking to add personality
|
||||
to their messages.
|
||||
</p>
|
||||
<div className="d-flex mt-3">
|
||||
<div className="d-flex mt-3 gap-3">
|
||||
<Link to="/tts" className="btn btn-primary">
|
||||
Generate text-to-speech
|
||||
Text-to-Speech
|
||||
</Link>
|
||||
<Link to="/tts" className="btn btn-primary">
|
||||
Voice Transformer
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="container section px-md-5 px-xl-3">
|
||||
{/* <div className="container section px-md-5 px-xl-3">
|
||||
<div className="row g-4 g-lg-5">
|
||||
<div className="col-12 col-md-6 col-lg-7">
|
||||
<div className="position-relative">
|
||||
@@ -278,7 +451,7 @@ function LandingPage(props: Props) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div className="d-flex flex-column section align-items-center panel rounded-0 my-5">
|
||||
<div className="d-flex flex-column align-items-center text-center cta-container">
|
||||
|
||||
@@ -14,11 +14,21 @@ import {
|
||||
import UploadComponent from "./components/UploadComponent";
|
||||
import RecordComponent from "./components/RecordComponent";
|
||||
import { usePrefixedDocumentTitle } from "../../../../../common/UsePrefixedDocumentTitle";
|
||||
import { ListVoiceConversionModels, VoiceConversionModelListItem } from "@storyteller/components/src/api/voice_conversion/ListVoiceConversionModels";
|
||||
import {
|
||||
ListVoiceConversionModels,
|
||||
VoiceConversionModelListItem,
|
||||
} from "@storyteller/components/src/api/voice_conversion/ListVoiceConversionModels";
|
||||
import { VcModelListSearch } from "./components/VcModelListSearchComponent";
|
||||
import { EnqueueVoiceConversion, EnqueueVoiceConversionIsSuccess, EnqueueVoiceConversionRequest } from "@storyteller/components/src/api/voice_conversion/EnqueueVoiceConversion";
|
||||
import {
|
||||
EnqueueVoiceConversion,
|
||||
EnqueueVoiceConversionIsSuccess,
|
||||
EnqueueVoiceConversionRequest,
|
||||
} from "@storyteller/components/src/api/voice_conversion/EnqueueVoiceConversion";
|
||||
import { Analytics } from "../../../../../common/Analytics";
|
||||
import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import {
|
||||
FrontendInferenceJobType,
|
||||
InferenceJob,
|
||||
} from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import { SessionVoiceConversionResultsList } from "../../../_common/SessionVoiceConversionResultsList";
|
||||
|
||||
interface Props {
|
||||
@@ -26,12 +36,19 @@ interface Props {
|
||||
sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
|
||||
|
||||
voiceConversionModels: Array<VoiceConversionModelListItem>;
|
||||
setVoiceConversionModels: (ttsVoices: Array<VoiceConversionModelListItem>) => void;
|
||||
setVoiceConversionModels: (
|
||||
ttsVoices: Array<VoiceConversionModelListItem>
|
||||
) => void;
|
||||
|
||||
maybeSelectedVoiceConversionModel?: VoiceConversionModelListItem;
|
||||
setMaybeSelectedVoiceConversionModel: (maybeSelectedVoiceConversionModel: VoiceConversionModelListItem) => void;
|
||||
setMaybeSelectedVoiceConversionModel: (
|
||||
maybeSelectedVoiceConversionModel: VoiceConversionModelListItem
|
||||
) => void;
|
||||
|
||||
enqueueInferenceJob: (jobToken: string, frontendInferenceJobType: FrontendInferenceJobType) => void;
|
||||
enqueueInferenceJob: (
|
||||
jobToken: string,
|
||||
frontendInferenceJobType: FrontendInferenceJobType
|
||||
) => void;
|
||||
inferenceJobs: Array<InferenceJob>;
|
||||
inferenceJobsByCategory: Map<FrontendInferenceJobType, Array<InferenceJob>>;
|
||||
}
|
||||
@@ -41,9 +58,13 @@ function VcModelListPage(props: Props) {
|
||||
|
||||
const [canConvert, setCanConvert] = useState(false);
|
||||
|
||||
const [mediaUploadToken, setMediaUploadToken] = useState<string|undefined>(undefined);
|
||||
const [mediaUploadToken, setMediaUploadToken] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const [convertIdempotencyToken, setConvertIdempotencyToken] = useState(uuidv4());
|
||||
const [convertIdempotencyToken, setConvertIdempotencyToken] = useState(
|
||||
uuidv4()
|
||||
);
|
||||
|
||||
// NB: Something of a UI hack here.
|
||||
// The 3rd party microphone component doesn't let you clear it, so we emulate form clearing
|
||||
@@ -90,32 +111,48 @@ function VcModelListPage(props: Props) {
|
||||
|
||||
const changeConvertIdempotencyToken = () => {
|
||||
setConvertIdempotencyToken(uuidv4());
|
||||
}
|
||||
};
|
||||
|
||||
const interceptModelChange = (maybeSelectedVoiceConversionModel: VoiceConversionModelListItem) => {
|
||||
if (maybeSelectedVoiceConversionModel !== props.maybeSelectedVoiceConversionModel) {
|
||||
const interceptModelChange = (
|
||||
maybeSelectedVoiceConversionModel: VoiceConversionModelListItem
|
||||
) => {
|
||||
if (
|
||||
maybeSelectedVoiceConversionModel !==
|
||||
props.maybeSelectedVoiceConversionModel
|
||||
) {
|
||||
changeConvertIdempotencyToken();
|
||||
}
|
||||
props.setMaybeSelectedVoiceConversionModel(maybeSelectedVoiceConversionModel);
|
||||
}
|
||||
props.setMaybeSelectedVoiceConversionModel(
|
||||
maybeSelectedVoiceConversionModel
|
||||
);
|
||||
};
|
||||
|
||||
const handleVoiceConversion = async () => {
|
||||
if (props.maybeSelectedVoiceConversionModel === undefined || mediaUploadToken === undefined) {
|
||||
if (
|
||||
props.maybeSelectedVoiceConversionModel === undefined ||
|
||||
mediaUploadToken === undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let request : EnqueueVoiceConversionRequest = {
|
||||
let request: EnqueueVoiceConversionRequest = {
|
||||
uuid_idempotency_token: convertIdempotencyToken,
|
||||
voice_conversion_model_token: props.maybeSelectedVoiceConversionModel.token,
|
||||
voice_conversion_model_token:
|
||||
props.maybeSelectedVoiceConversionModel.token,
|
||||
source_media_upload_token: mediaUploadToken,
|
||||
};
|
||||
|
||||
Analytics.voiceConversionGenerate(props.maybeSelectedVoiceConversionModel.token);
|
||||
Analytics.voiceConversionGenerate(
|
||||
props.maybeSelectedVoiceConversionModel.token
|
||||
);
|
||||
|
||||
let result = await EnqueueVoiceConversion(request);
|
||||
|
||||
if (EnqueueVoiceConversionIsSuccess(result)) {
|
||||
props.enqueueInferenceJob(result.inference_job_token, FrontendInferenceJobType.VoiceConversion);
|
||||
props.enqueueInferenceJob(
|
||||
result.inference_job_token,
|
||||
FrontendInferenceJobType.VoiceConversion
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -129,9 +166,10 @@ function VcModelListPage(props: Props) {
|
||||
? "btn btn-primary w-100 disabled"
|
||||
: "btn btn-primary w-100";
|
||||
|
||||
const enableConvertButton = canConvert
|
||||
&& mediaUploadToken !== undefined
|
||||
&& props.maybeSelectedVoiceConversionModel !== undefined;
|
||||
const enableConvertButton =
|
||||
canConvert &&
|
||||
mediaUploadToken !== undefined &&
|
||||
props.maybeSelectedVoiceConversionModel !== undefined;
|
||||
|
||||
return (
|
||||
<motion.div initial="hidden" animate="visible" variants={container}>
|
||||
@@ -149,7 +187,8 @@ function VcModelListPage(props: Props) {
|
||||
>
|
||||
{/* Explore Rollout */}
|
||||
<label className="sub-title">
|
||||
Choose Target Voice ({voiceConversionModels.length} to choose from)
|
||||
Choose Target Voice ({voiceConversionModels.length} to choose
|
||||
from)
|
||||
</label>
|
||||
<div className="input-icon-search pb-4">
|
||||
<span className="form-control-feedback">
|
||||
@@ -159,10 +198,11 @@ function VcModelListPage(props: Props) {
|
||||
<VcModelListSearch
|
||||
voiceConversionModels={props.voiceConversionModels}
|
||||
setVoiceConversionModels={props.setVoiceConversionModels}
|
||||
maybeSelectedVoiceConversionModel={props.maybeSelectedVoiceConversionModel}
|
||||
maybeSelectedVoiceConversionModel={
|
||||
props.maybeSelectedVoiceConversionModel
|
||||
}
|
||||
setMaybeSelectedVoiceConversionModel={interceptModelChange}
|
||||
/>
|
||||
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="row gx-5 gy-5">
|
||||
@@ -210,12 +250,14 @@ function VcModelListPage(props: Props) {
|
||||
Upload Input Audio
|
||||
</label>
|
||||
<div className="d-flex flex-column gap-3 upload-component">
|
||||
<UploadComponent
|
||||
<UploadComponent
|
||||
setMediaUploadToken={setMediaUploadToken}
|
||||
formIsCleared={formIsCleared}
|
||||
setFormIsCleared={setFormIsCleared}
|
||||
setCanConvert={setCanConvert}
|
||||
changeConvertIdempotencyToken={changeConvertIdempotencyToken}
|
||||
changeConvertIdempotencyToken={
|
||||
changeConvertIdempotencyToken
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -247,9 +289,7 @@ function VcModelListPage(props: Props) {
|
||||
</div>*/}
|
||||
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Convert Audio
|
||||
</label>
|
||||
<label className="sub-title">Convert Audio</label>
|
||||
|
||||
<div className="d-flex gap-3">
|
||||
<button
|
||||
@@ -267,7 +307,6 @@ function VcModelListPage(props: Props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -280,20 +319,20 @@ function VcModelListPage(props: Props) {
|
||||
<div>
|
||||
<label className="sub-title">Record Audio</label>
|
||||
<div className="d-flex flex-column gap-3 upload-component">
|
||||
<RecordComponent
|
||||
<RecordComponent
|
||||
setMediaUploadToken={setMediaUploadToken}
|
||||
formIsCleared={formIsCleared}
|
||||
setFormIsCleared={setFormIsCleared}
|
||||
setCanConvert={setCanConvert}
|
||||
changeConvertIdempotencyToken={changeConvertIdempotencyToken}
|
||||
changeConvertIdempotencyToken={
|
||||
changeConvertIdempotencyToken
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="sub-title">
|
||||
Convert Audio
|
||||
</label>
|
||||
<label className="sub-title">Convert Audio</label>
|
||||
|
||||
<div className="d-flex gap-3">
|
||||
<button
|
||||
@@ -311,7 +350,6 @@ function VcModelListPage(props: Props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -326,9 +364,15 @@ function VcModelListPage(props: Props) {
|
||||
Session VC Results
|
||||
</h4>
|
||||
<div className="d-flex flex-column gap-3 session-tts-section">
|
||||
<SessionVoiceConversionResultsList
|
||||
inferenceJobs={props.inferenceJobsByCategory.get(FrontendInferenceJobType.VoiceConversion)!}
|
||||
sessionSubscriptionsWrapper={props.sessionSubscriptionsWrapper}
|
||||
<SessionVoiceConversionResultsList
|
||||
inferenceJobs={
|
||||
props.inferenceJobsByCategory.get(
|
||||
FrontendInferenceJobType.VoiceConversion
|
||||
)!
|
||||
}
|
||||
sessionSubscriptionsWrapper={
|
||||
props.sessionSubscriptionsWrapper
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user