@@ -218,7 +220,7 @@ export default memo(function VideoQuickTrim({
@@ -232,12 +234,14 @@ export default memo(function VideoQuickTrim({
className="button-mute"
icon={isMuted ? faVolumeSlash : faVolume}
variant="secondary"
- onClick={()=>setIsMuted((curr)=>(!curr))}
+ onClick={() => setIsMuted(curr => !curr)}
/>
- {`${formatSecondsToHHMMSSCS(videoRef.current?.currentTime || 0)}`}
+ {`${formatSecondsToHHMMSSCS(
+ videoRef.current?.currentTime || 0
+ )}`}
/
@@ -251,6 +255,7 @@ export default memo(function VideoQuickTrim({
diff --git a/packages/fakeyou.com/src/components/common/VideoQuickTrim/styles.scss b/packages/fakeyou.com/src/components/common/VideoQuickTrim/styles.scss
index bb3c5b87fc..dac5941c2e 100644
--- a/packages/fakeyou.com/src/components/common/VideoQuickTrim/styles.scss
+++ b/packages/fakeyou.com/src/components/common/VideoQuickTrim/styles.scss
@@ -3,7 +3,7 @@
$playbar-height: 2rem;
.fy-video-quicktrim {
- .video-wrapper{
+ .video-wrapper {
position: relative;
background-color: $bg;
border-radius: 0.5rem 0.5rem 0 0;
@@ -11,71 +11,76 @@ $playbar-height: 2rem;
border-left: $panel-inner-border 1px solid;
border-right: $panel-inner-border 1px solid;
}
- .fy-video{
- height: 500px;
+ .fy-video {
+ max-height: 500px;
+ margin-bottom: -7px;
+
+ video {
+ border-radius: 0.5rem 0.5rem 0 0;
+ }
}
- .playpause-overlay{
+ .playpause-overlay {
position: absolute;
cursor: pointer;
height: 100%;
width: 100%;
- top:0;
- left:0;
+ top: 0;
+ left: 0;
display: flex;
justify-content: center;
align-items: center;
- svg{
+ svg {
opacity: 0;
- transition: opacity 0.5s;
+ transition: opacity 0.5s;
}
- &:hover svg{
+ &:hover svg {
opacity: 1;
}
}
- .warning-too-short{
+ .warning-too-short {
position: absolute;
height: 100%;
width: 100%;
- top:0;
- left:0;
+ top: 0;
+ left: 0;
display: flex;
justify-content: center;
align-items: center;
- div{
+ div {
position: absolute;
height: 100%;
width: 100%;
- top:0;
- left:0;
+ top: 0;
+ left: 0;
background-color: #e66462;
opacity: 70%;
}
- p{
+ p {
position: absolute;
margin-top: 230px;
width: 100%;
- top:0;
+ top: 0;
}
}
- .playbar{
- position:relative;
+ .playbar {
+ position: relative;
height: $playbar-height;
width: 100%;
}
- .playbar-bg{
+ .playbar-bg {
position: absolute;
height: 100%;
width: 100%;
- top:0;
+ top: 0;
left: 0;
background-color: $panel-inner-border;
border-radius: 0 0 0.5rem 0.5rem;
}
.trim-scrubber{
position: absolute;
- top:-1rem;
+ top: -1rem;
height: 3rem;
background-color: #e66462;
opacity: 0.8;
@@ -92,16 +97,16 @@ $playbar-height: 2rem;
color: $panel-inner-border;
}
}
- .playcursor{
+ .playcursor {
position: absolute;
- top:0;
+ top: 0;
width: 0.5rem;
height: $playbar-height;
background-color: $white;
}
- .playpause-external{
- .button-playpause{
+ .playpause-external {
+ .button-playpause {
width: 55px;
height: 40px;
margin-right: 0.5rem;
@@ -116,7 +121,7 @@ $playbar-height: 2rem;
span{
width: 50px;
}
- div{
+ div {
width: 10px;
margin-left: 3px;
margin-right: 5px;
@@ -124,4 +129,4 @@ $playbar-height: 2rem;
}
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.tsx b/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.tsx
index 5c502019f6..3e8da898f9 100644
--- a/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.tsx
+++ b/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.tsx
@@ -24,6 +24,7 @@ const resultPaths = {
EngineComposition: "/media",
FaceAnimation: "/media",
TextToSpeech: "/media",
+ VideoStyleTransfer: "/media",
VoiceConversion: "/media",
VoiceDesignerCreateVoice: "/voice-designer/voice",
VoiceDesignerTts: "/media",
diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx
index afcbc616b2..73c2c0820e 100644
--- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx
+++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx
@@ -123,6 +123,9 @@ import TextToImagePage from "./pages/text_to_image/TextToImagePage";
import DomainConfigProvider from "context/DomainConfigContext";
import DevUpload from "./pages/dev_upload/DevUpload";
import DevMediaInput from "./pages/dev_upload/DevMediaInput";
+import { StudioIntroPage } from "./pages/storyteller_studio_intro/StudioIntroPage";
+import StudioVSTPage from "./pages/storyteller_studio_intro/StudioVST/StudioVSTPage";
+import { StudioIntroResultPage } from "./pages/storyteller_studio_intro/StudioIntroResultPage";
interface Props {
sessionWrapper: SessionWrapper;
@@ -755,6 +758,28 @@ class PageContainer extends React.Component<
/>
+
+
+
+
+
+
+
+
+
+
+
+
@@ -783,6 +808,11 @@ class PageContainer extends React.Component<
+ {
+ //
+ //
+ //
+ }
{/* Route for initial voice creation */}
-
-
-
-
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntro.scss b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntro.scss
new file mode 100644
index 0000000000..d5314fae00
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntro.scss
@@ -0,0 +1,9 @@
+.studio-intro-page {
+ display: flex;
+ flex-direction: column;
+ height: calc(100vh - 66px);
+}
+
+.result-video-wrapper {
+ max-width: 1100px;
+}
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntroPage.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntroPage.tsx
new file mode 100644
index 0000000000..98b020d084
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntroPage.tsx
@@ -0,0 +1,72 @@
+import React from "react";
+import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
+import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
+import { StudioNotAvailable } from "v2/view/_common/StudioNotAvailable";
+import { Button, Scene3D } from "components/common";
+import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle";
+import { useParams, useHistory } from "react-router-dom";
+import { useInferenceJobs } from "hooks";
+import { EnqueueEngineCompositing } from "@storyteller/components/src/api/engine_compositor/EnqueueEngineCompositing";
+import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
+import { v4 as uuidv4 } from "uuid";
+import "./StudioIntro.scss";
+
+interface Props {
+ sessionWrapper: SessionWrapper;
+ sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
+}
+
+function StudioIntroPage(props: Props) {
+ const { mediaToken } = useParams<{ mediaToken: string }>();
+ const history = useHistory();
+ const inferenceJobs = useInferenceJobs(
+ FrontendInferenceJobType.EngineComposition
+ );
+
+ usePrefixedDocumentTitle("Storyteller Studio");
+
+ if (!props.sessionWrapper.canAccessStudio()) {
+ return
;
+ }
+
+ let engineParams = {};
+
+ if (mediaToken) {
+ engineParams = {
+ sceneMediaFileToken: mediaToken,
+ };
+ } else {
+ engineParams = {
+ objectId: "sample-room.gltf",
+ };
+ }
+
+ const onClick = () => {
+ // This opens the job modal. Needs to be disabled.
+ EnqueueEngineCompositing("", {
+ uuid_idempotency_token: uuidv4(),
+ media_file_token: mediaToken || "",
+ }).then((res: any) => {
+ if (res && res.success) {
+ inferenceJobs.enqueue(res.inference_job_token);
+ history.push(`/studio-intro/style/${res.inference_job_token}`);
+ }
+ });
+ };
+
+ return (
+
+ );
+}
+
+export { StudioIntroPage };
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntroResultPage.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntroResultPage.tsx
new file mode 100644
index 0000000000..e1cd967d77
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioIntroResultPage.tsx
@@ -0,0 +1,79 @@
+import React, { useState } from "react";
+import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
+import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
+import { Button, Container, Panel } from "components/common";
+import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle";
+import { useHistory, useParams } from "react-router-dom";
+import "./StudioIntro.scss";
+import LoadingSpinner from "components/common/LoadingSpinner";
+import { useMedia } from "hooks";
+import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
+import { MediaFileType } from "@storyteller/components/src/api/media_files";
+
+interface Props {
+ sessionWrapper: SessionWrapper;
+ sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
+}
+
+// This page just needs to poll the job and show the video when it's done.
+
+function StudioIntroResultPage(props: Props) {
+ const { jobToken } = useParams<{ jobToken: string }>();
+ const history = useHistory();
+ const [mediaToken, setMediaToken] = useState(
+ "m_f5kp3hm74qeq16eq7536jb73jkbvkh"
+ ); // Set the media token after polling success
+
+ // const [jobExists, setJobExists] = useState
(null);
+
+ const [mediaFile, setMediaFile] = useState();
+
+ useMedia({
+ mediaToken: mediaToken,
+ onSuccess: (res: any) => {
+ setMediaFile(res);
+ },
+ });
+
+ const mediaLink =
+ mediaFile && new BucketConfig().getGcsUrl(mediaFile.public_bucket_path);
+
+ usePrefixedDocumentTitle("Storyteller Studio");
+
+ if (!jobToken) {
+ history.push("/");
+ }
+
+ // Should also check if job actually exists or not
+ //
+ // if (!jobExists) {
+ // history.push("/");
+ // }
+
+ return (
+
+
+ Generation Result
+
+
+
+ {mediaToken ? (
+
+ ) : (
+
+ )}
+
+
+ {mediaToken ? (
+
+
+
+ ) : null}
+
+ );
+}
+
+export { StudioIntroResultPage };
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/StudioVSTPage.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/StudioVSTPage.tsx
new file mode 100644
index 0000000000..4a8f5a0bef
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/StudioVSTPage.tsx
@@ -0,0 +1,161 @@
+import React, { useRef, useState } from "react";
+import { NavLink, useParams, useHistory } from "react-router-dom";
+import {
+ Button,
+ Container,
+ Panel,
+ SelectionBubbles,
+ TextArea,
+} from "components/common";
+import VideoQuickTrim, {
+ QuickTrimData,
+} from "components/common/VideoQuickTrim";
+import EnqueueVideoStyleTransfer from "@storyteller/components/src/api/video_styleTransfer";
+import { initialValues } from "./defaultValues";
+import { mapRequest, VSTType } from "./helpers";
+import LoadingSpinner from "components/common/LoadingSpinner";
+// import SectionAdvanceOptions from "./sectionAdvanceOptions";
+
+export default function PageVSTApp() {
+ const { jobToken } = useParams<{ jobToken: string }>();
+ const videoRef = useRef(null);
+ const history = useHistory();
+ const [mediaToken, setMediaToken] = useState(
+ "m_wnnz9jey96dwhss9qk1891v9gmvnj8" // Currently hardcoded video media token value. Let a job polling function set the value when job returns media on success.
+ );
+ // const [jobExists, setJobExists] = useState(null);
+ const [vstValues, setVstValues] = useState({
+ ...initialValues,
+ fileToken: mediaToken,
+ });
+
+ const handleOnChange = (val: {
+ [key: string]: number | string | boolean | undefined;
+ }) => {
+ setVstValues(curr => ({ ...curr, ...val }));
+ };
+
+ const handleGenerate = () => {
+ const request = mapRequest(vstValues);
+ EnqueueVideoStyleTransfer(request).then(res => {
+ if (res.success && res.inference_job_token) {
+ console.log("Job enqueued successfully", res.inference_job_token);
+ history.push(`/studio-intro/result/${res.inference_job_token}`);
+ } else {
+ console.log("Failed to enqueue job", res);
+ }
+ });
+ };
+
+ if (videoRef?.current) {
+ const ve = videoRef.current;
+ ve.onloadedmetadata = () => {
+ const newValues: {
+ width?: number;
+ height?: number;
+ maxDuration?: number;
+ } = {};
+ if (ve.duration) {
+ newValues.maxDuration = ve.duration;
+ }
+ setVstValues(curr => ({
+ ...curr,
+ ...newValues,
+ }));
+ };
+ }
+
+ const styleMap: { [key: string]: string } = {
+ Anime: "weight_yqexh77ntqyawzgh9fzash798", // set SD Model Weight Tokens, currently hardcoded all to Anime style
+ Pixel: "weight_yqexh77ntqyawzgh9fzash798",
+ Painting: "weight_yqexh77ntqyawzgh9fzash798",
+ };
+
+ const handleStyleSelection = (selected: string) => {
+ const selectedSdModelToken = styleMap[selected];
+ setVstValues(curr => ({ ...curr, sdModelToken: selectedSdModelToken }));
+ };
+
+ const styleOptions = Object.keys(styleMap);
+
+ if (!jobToken) {
+ history.push("/");
+ }
+
+ // Should also check if job actually exists or not
+ //
+ // if (!jobExists) {
+ // history.push("/");
+ // }
+
+ return (
+
+
+ Style Your Scene
+
+
+
+
+ {vstValues.fileToken ? (
+
+ handleOnChange({
+ trimStart: val.trimStartSeconds,
+ trimEnd: val.trimEndSeconds,
+ })
+ }
+ />
+ ) : (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/cnPresets.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/cnPresets.tsx
new file mode 100644
index 0000000000..5e6a3dcb15
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/cnPresets.tsx
@@ -0,0 +1,98 @@
+type CNPreset =
+ 'custom'|
+ 'closeup'|
+ 'default' |
+ 'halfbody'|
+ 'fullbody'|
+ 'landscape'|
+ 'typog';
+
+const defaultPreset = {
+ cnCanny: 0,
+ cnDepth: 0,
+ cnLineArtAnime: 0.7,
+ cnLineArtRealistic: 0,
+ cnLipsStrength: 0,
+ cnOpenPose: 1,
+ cnPipeFace: 0,
+ cnSparseScribble: 0,
+ cnSoftEdge: 1,
+ cnRegularSteps: 20,
+}
+
+const closeupPreset = {
+ cnCanny: 0,
+ cnDepth: 0,
+ cnLineArtAnime: 0.7,
+ cnLineArtRealistic: 0,
+ cnLipsStrength: 0,
+ cnOpenPose: 0,
+ cnPipeFace: 0,
+ cnSparseScribble: 0.7,
+ cnSoftEdge: 0.7,
+ cnRegularSteps: 20,
+}
+
+const halfbodyPreset = {
+ cnCanny: 0,
+ cnDepth: 0,
+ cnLineArtAnime: 0.7,
+ cnLineArtRealistic: 0,
+ cnLipsStrength: 0,
+ cnOpenPose: 0.7,
+ cnPipeFace: 0,
+ cnSparseScribble: 0,
+ cnSoftEdge: 1,
+ cnRegularSteps: 20,
+}
+
+const fullbodyPreset = {
+ cnCanny: 0,
+ cnDepth: 0,
+ cnLineArtAnime: 0.7,
+ cnLineArtRealistic: 0,
+ cnLipsStrength: 0,
+ cnOpenPose: 1,
+ cnPipeFace: 0,
+ cnSparseScribble: 0,
+ cnSoftEdge: 1,
+ cnRegularSteps: 20,
+}
+
+const landscapePreset = {
+ cnCanny: 0,
+ cnDepth: 0.4,
+ cnLineArtAnime: 0.7,
+ cnLineArtRealistic: 0,
+ cnLipsStrength: 0,
+ cnOpenPose: 0,
+ cnPipeFace: 0,
+ cnSparseScribble: 0,
+ cnSoftEdge: 0,
+ cnRegularSteps: 20,
+}
+
+const typogPreset = {
+ cnCanny: 0,
+ cnDepth: 0,
+ cnLineArtAnime: 0.7,
+ cnLineArtRealistic: 0,
+ cnLipsStrength: 0,
+ cnOpenPose: 0,
+ cnPipeFace: 0,
+ cnSparseScribble: 0,
+ cnSoftEdge: 0.7,
+ cnRegularSteps: 20,
+}
+
+export type {
+ CNPreset
+}
+export {
+ defaultPreset,
+ closeupPreset,
+ halfbodyPreset,
+ fullbodyPreset,
+ landscapePreset,
+ typogPreset,
+};
\ No newline at end of file
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/defaultValues.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/defaultValues.tsx
new file mode 100644
index 0000000000..97fdeaaa14
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/defaultValues.tsx
@@ -0,0 +1,36 @@
+import { defaultPreset as defaultCN } from "./cnPresets";
+
+export { initialValues, hiddenValues };
+const initialValues = {
+ //files Settings
+ fileToken: "",
+ outputPath: "vid2vid/SparseUpscaleInterp_00001.mp4",
+
+ //video Settings
+ width: 1024,
+ height: 1024,
+ maxDuration: 0,
+ trimStart: 0,
+ trimEnd: 0,
+
+ //Presents
+ workflowConfig: "weight_99tz2nzbp5x9v55gqn5ekj1sd",
+ sdModelToken: "weight_yqexh77ntqyawzgh9fzash798",
+ loraModelToken: "",
+ loraModelStrength: 0,
+
+ //basics
+ inputFps: 24,
+ posPrompt: "",
+ negPrompt: "",
+ visibility: "private",
+
+ //Control Net
+ ...defaultCN,
+};
+
+const hiddenValues = {
+ posPrompt: "",
+ negPrompt:
+ "flare, lens flare, glare,naked, nsfw, text, logo, watermark:1.3, letterboxed,embedding:easynegative, embedding:badhandv4,(worst quality, low quality:1.4), lowres, blurry, monochrome, ",
+};
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/helpers.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/helpers.tsx
new file mode 100644
index 0000000000..319466736d
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/helpers.tsx
@@ -0,0 +1,92 @@
+import { v4 as uuidv4 } from "uuid";
+import { hiddenValues } from "./defaultValues";
+
+export type VSTType = {
+ // File Settings
+ fileToken: string;
+ outputPath: string;
+ // Video Settings
+ width: number;
+ height: number;
+ maxDuration: number;
+ trimStart: number;
+ trimEnd: number;
+
+ // Presets
+ workflowConfig: string;
+ sdModelToken: string;
+ // loraModelToken: string;
+ // loraModelStrength: number;
+
+ //basics
+ inputFps: number;
+ posPrompt: string;
+ negPrompt: string;
+ visibility: string;
+
+ //advance
+ cnCanny: number;
+ cnDepth: number;
+ cnLineArtAnime: number;
+ cnLineArtRealistic: number;
+ cnLipsStrength: number;
+ cnOpenPose: number;
+ cnPipeFace: number;
+ cnSparseScribble: number;
+ cnSoftEdge: number;
+ cnRegularSteps: number
+}
+
+export function isInputValid(keyValues: {[key:string]:number|string|boolean|undefined}){
+ return (
+ keyValues.sdModelToken
+ && keyValues.sdModelToken !== ""
+ && keyValues.posPrompt
+ && keyValues.posPrompt !== ""
+ );
+}
+
+export function mapRequest(vstValues: VSTType){
+ //TODO: improve the typing of this
+ return{
+ "uuid_idempotency_token": uuidv4(),
+ "maybe_sd_model": vstValues.sdModelToken,
+ "maybe_workflow_config":vstValues.workflowConfig,
+ "maybe_input_file": vstValues.fileToken,
+ "maybe_trim_start_seconds": vstValues.trimStart,
+ "maybe_trim_end_seconds": vstValues.trimEnd,
+ "maybe_output_path": vstValues.outputPath,
+ "creator_set_visibility": vstValues.visibility,
+ "maybe_json_modifications": {
+ "$.154.inputs.Value": vstValues.inputFps,
+ "$.510.inputs.Text":
+ hiddenValues.posPrompt + vstValues.posPrompt,
+ "$.8.inputs.text":
+ hiddenValues.negPrompt+ vstValues.negPrompt,
+
+ "$.401.inputs.Value": 0.7, //Denoise First Pass
+ "$.140.inputs.Value": 1, // Every nth frame
+ "$.536.inputs.boolean_number": 1, // use LCM
+ "$.1075.inputs.Value": 1280,
+ "$.1076.inputs.Value": 720,
+ "$.1079.inputs.Value": 1280,
+ "$.1080.inputs.Value": 720,
+
+ "$.403.inputs.Value": vstValues.cnSparseScribble,
+ "$.771.inputs.Value": vstValues.cnOpenPose,
+ "$.772.inputs.Value": vstValues.cnDepth,
+ "$.796.inputs.Value": vstValues.cnLineArtRealistic,
+ "$.797.inputs.Value": vstValues.cnLineArtAnime,
+ "$.1398.inputs.Value": vstValues.cnSoftEdge,
+ "$.1531.inputs.Value": vstValues.cnRegularSteps,
+
+ //"$.800.inputs.Value": 0, // vstValues.cnCanny,
+ //"$.1636.inputs.Value": 0, //vstValues.cnLipsStrength,
+
+ // "$.208.inputs.lora_01": vstValues.loraModelToken,
+ // "$.208.inputs.strength_01": vstValues.loraModelStrength
+ // "$.1449.inputs.filename_prefix": "vid2vid/SparseUpscaleInterp",
+ },
+
+ }
+}
\ No newline at end of file
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/index.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/index.tsx
new file mode 100644
index 0000000000..a594d306e4
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/index.tsx
@@ -0,0 +1 @@
+export { default } from "./StudioVSTPage";
diff --git a/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/sectionAdvanceOptions.tsx b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/sectionAdvanceOptions.tsx
new file mode 100644
index 0000000000..d57f976c0c
--- /dev/null
+++ b/packages/fakeyou.com/src/v2/view/pages/storyteller_studio_intro/StudioVST/sectionAdvanceOptions.tsx
@@ -0,0 +1,273 @@
+import React, {useState} from 'react';
+
+import {
+ faBuildingColumns,
+ faFaceViewfinder,
+ faPerson,
+ // faRotateLeft,
+ faStar,
+ // faSparkles,
+ faText,
+ faUser,
+
+}
+from "@fortawesome/pro-solid-svg-icons";
+
+import {
+ // Accordion,
+ Button,
+ Label,
+ // NumberSliderV2
+} from 'components/common';
+import { VSTType } from './helpers';
+import {
+ CNPreset,
+ closeupPreset,
+ halfbodyPreset,
+ fullbodyPreset,
+ landscapePreset,
+ typogPreset,
+ defaultPreset,
+} from './cnPresets';
+
+
+export default function SectionAdvanceOptions({
+ vstValues: vstVal,
+ onChange: handleOnChange
+}:{
+ vstValues : VSTType,
+ onChange: (val:{[key: string]: number|string|boolean|undefined})=>void
+}){
+
+ const [preset, pickPreset] = useState('default')
+ function handlePreset(newPreset: CNPreset){
+ switch (newPreset){
+ case 'closeup':
+ handleOnChange(closeupPreset);
+ break;
+ case 'halfbody':
+ handleOnChange(halfbodyPreset);
+ break;
+ case 'fullbody':
+ handleOnChange(fullbodyPreset);
+ break;
+ case 'landscape':
+ handleOnChange(landscapePreset);
+ break;
+ case 'typog':
+ handleOnChange(typogPreset);
+ break;
+ case 'custom':
+ default:
+ handleOnChange(defaultPreset);
+ break;
+ }
+ pickPreset(newPreset);
+ }
+ return (
+ <>
+
+ {/*
+
+
+
+
+
+
*/}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/*
+
+
+
+ {
+ handleOnChange({cnCanny: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+ {
+ handleOnChange({cnDepth: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+
+
+
+ {
+ handleOnChange({cnLineArtAnime: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+ {
+ handleOnChange({cnLineArtRealistic: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+
+
+ {
+ handleOnChange({cnOpenPose: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+ {
+ handleOnChange({cnPipeFace: val})
+ pickPreset('custom');
+ }
+ }}/>
+
+
+
+
+ {
+ handleOnChange({cnSparseScribble: val})
+ pickPreset('custom');
+ }
+ }}/>
+
+
+ {
+ handleOnChange({cnSoftEdge: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+ {/*
+
+ {
+ handleOnChange({cnRegularSteps: val});
+ pickPreset('custom');
+ }
+ }}/>
+
+
+
+
+
+ */}
+ >
+ );
+}
\ No newline at end of file