From 3e023a5d8155126587a0b4eefb93cdb8c1922b19 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 15 Feb 2024 14:48:04 -0500 Subject: [PATCH] control panel ui is done --- packages/fakeyou.com/src/App.tsx | 1 - .../common/VideoFakeyou/VideoFakeyou.tsx | 19 +- .../src/components/common/index.tsx | 2 + .../components/pageVSTApp/helpers.tsx | 105 +++++++++++ .../components/pageVSTApp/initialValues.tsx | 45 +++++ .../components/pageVSTApp/pageVSTApp.tsx | 176 +++++++++++++++++- 6 files changed, 336 insertions(+), 12 deletions(-) create mode 100644 packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/helpers.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/initialValues.tsx diff --git a/packages/fakeyou.com/src/App.tsx b/packages/fakeyou.com/src/App.tsx index 2de4c54291..8c2da1974f 100644 --- a/packages/fakeyou.com/src/App.tsx +++ b/packages/fakeyou.com/src/App.tsx @@ -211,7 +211,6 @@ function initInferenceJobsByCategoryMap(): Map< inferenceJobsByCategory.set(FrontendInferenceJobType.ImageGeneration, []); inferenceJobsByCategory.set(FrontendInferenceJobType.ConvertFbxtoGltf, []); inferenceJobsByCategory.set(FrontendInferenceJobType.VideoWorkflow, []) - return inferenceJobsByCategory; inferenceJobsByCategory.set(FrontendInferenceJobType.VideoStyleTransfer, []) return inferenceJobsByCategory; } diff --git a/packages/fakeyou.com/src/components/common/VideoFakeyou/VideoFakeyou.tsx b/packages/fakeyou.com/src/components/common/VideoFakeyou/VideoFakeyou.tsx index 18e1c3f105..3f21f85221 100644 --- a/packages/fakeyou.com/src/components/common/VideoFakeyou/VideoFakeyou.tsx +++ b/packages/fakeyou.com/src/components/common/VideoFakeyou/VideoFakeyou.tsx @@ -1,23 +1,29 @@ -import React, { useState } from "react"; +import React, { useState, forwardRef } from "react"; import { useMedia } from "hooks"; import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; import makeClass from "resources/makeClass"; +import { Label } from "components/common" + interface Props { className?: string; src?: string; mediaToken?: string; + label?: string; } -export default function VideoFromFakeyou({ +type Ref = HTMLVideoElement; + +const VideoFromFakeyou = forwardRef(({ className, src, mediaToken, + label, ...rest -}: Props) { +}: Props, ref) => { const [mediaFile, setMediaFile] = useState(); useMedia({ mediaToken: mediaToken, @@ -31,11 +37,14 @@ export default function VideoFromFakeyou({ if (mediaLink){ return (
-
) } return null; -}; \ No newline at end of file +}); + +export default VideoFromFakeyou; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/index.tsx b/packages/fakeyou.com/src/components/common/index.tsx index f6a1675b7b..5ad6a2010c 100644 --- a/packages/fakeyou.com/src/components/common/index.tsx +++ b/packages/fakeyou.com/src/components/common/index.tsx @@ -39,6 +39,7 @@ import TextArea from "./TextArea"; import TextAreaV2 from "./TextAreaV2"; import TintSpinner from "./TintSpinner"; import VideoBasic from "./VideoBasic"; +import VideoFakeyou from "./VideoFakeyou"; import VideoInput from "./VideoInput"; export { @@ -83,5 +84,6 @@ export { TextAreaV2, TintSpinner, VideoBasic, + VideoFakeyou, VideoInput }; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/helpers.tsx b/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/helpers.tsx new file mode 100644 index 0000000000..25ba7dfa98 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/helpers.tsx @@ -0,0 +1,105 @@ +import React from 'react'; +import { v4 as uuidv4 } from "uuid"; + +export type WorkflowValuesType = { + // File Settings + fileToken: string; + outputPath: string; + // Video Settings + width: number; + height: number; + maxFrames: number; + framesCap: number; + skipFrames: number; + everyNthFrame: number; + inputFps: number; + interpolationMultiplier: number; + // Basic Inputs + workflowConfig: string; + seed: string; + sdModelToken: string; + loraModelToken: string; + posPrompt: string; + negPrompt: string; + // Advance Options Values + firstPass: number; + upscalePass: number; + motionScale: number; + upscaleMultiplier: number; + useEmptyLatent: boolean; + useFaceDetailer: boolean; + denoiseFaceDetailer: number; + useLCM: boolean; + lcmCFG: number; + lcmSteps: number; + // Control Net Values + cnCanny: number; + cnDepth: number; + cnLinearAnime: number; + cnLinearRealistic: number; + cnOpenPose: number; + cnPipeFace: number; + cnSparse: number; + cnTile: number; +} +export function isInputValid(keyValues: {[key:string]:number|string|boolean|undefined}){ + return ( + keyValues.sdModelToken + && keyValues.sdModelToken !== "" + && keyValues.posPrompt + && keyValues.posPrompt !== "" + ); +} + +export function mapRequest(workflowValues: WorkflowValuesType){ + //TODO: improve the typing of this + return { + "uuid_idempotency_token": uuidv4(), + "maybe_sd_model": workflowValues.sdModelToken, + "maybe_workflow_config": workflowValues.workflowConfig, + "maybe_input_file": workflowValues.fileToken, + "maybe_output_path": workflowValues.outputPath, + "maybe_json_modifications": { + "$.510.inputs.Text": workflowValues.posPrompt, + "$.8.inputs.text": workflowValues.negPrompt, + "$.173.inputs.seed": workflowValues.seed, + "$.401.inputs.Value": workflowValues.firstPass, + "$.918.inputs.Value": workflowValues.motionScale, + "$.137.inputs.Value": workflowValues.framesCap, + "$.186.inputs.Value": workflowValues.skipFrames, + "$.140.inputs.Value": workflowValues.everyNthFrame, + "$.154.inputs.Value": workflowValues.inputFps, + "$.445.inputs.number": workflowValues.interpolationMultiplier, + "$.947.inputs.Value": workflowValues.cnTile, + "$.800.inputs.Value": workflowValues.cnCanny, + "$.797.inputs.Value": workflowValues.cnLinearAnime, + "$.796.inputs.Value": workflowValues.cnLinearRealistic, + "$.772.inputs.Value": workflowValues.cnDepth, + "$.771.inputs.Value": workflowValues.cnOpenPose, + "$.527.inputs.Value": workflowValues.cnPipeFace, + "$.403.inputs.Value": workflowValues.cnSparse + }, + } +} + +export function TableOfKeyValues( +{ + keyValues, + maxHeight=500 +}:{ + keyValues:{ + [key:string]:number|string|boolean|undefined + }; + maxHeight?: number +}){ + return({ + Object.entries(keyValues).map(([key, val], index: number)=>{ + return + }) + }
{`${key}`}{`${val}`}
); +} \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/initialValues.tsx b/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/initialValues.tsx new file mode 100644 index 0000000000..9d80945d9f --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/initialValues.tsx @@ -0,0 +1,45 @@ +const initialValues = { + //config + outputPath: "vid2vid/SparseUpscaleInterp_00001.mp4", + workflowConfig: "weight_q8sz47gmfw2zx02snrbz88ns9", + + //video Settings + width: 544, + height: 544, + maxFrames: 17, + framesCap: 16, + skipFrames: 0, + everyNthFrame: 2, + inputFps: 24, + interpolationMultiplier: 2, + + //basics + seed: "", + sdModelToken: "", + loraModelToken: "", + posPrompt: "", + negPrompt: "", + + //advance + firstPass: 1, + upscalePass: 0.42, + motionScale:1, + upscaleMultiplier: 1.5, + useEmptyLatent: false, + useFaceDetailer: false, + denoiseFaceDetailer: 0.45, + useLCM: false, + lcmCFG: 2, + lcmSteps: 8, + + //Control Net + cnCanny: 0, + cnDepth: 0, + cnLinearAnime: 0, + cnLinearRealistic: 0, + cnOpenPose: 0, + cnPipeFace: 0, + cnSparse: 0.7, + cnTile: 0, +}; +export default initialValues; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/pageVSTApp.tsx b/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/pageVSTApp.tsx index 45126a55d0..56f2a3b44c 100644 --- a/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/pageVSTApp.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/video_styletransfer/components/pageVSTApp/pageVSTApp.tsx @@ -1,13 +1,29 @@ -import React from "react"; +import React, { useRef, useState } from "react"; import { useParams, useHistory } from "react-router-dom"; -import { useMedia } from "hooks"; -import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; + import { EnqueueVideoWorkflow } from "@storyteller/components/src/api/video_workflow"; import { states, Action, State } from "../../reducer"; +import ivs from "./initialValues"; +import { + isInputValid, + mapRequest, + WorkflowValuesType, + TableOfKeyValues +} from "./helpers"; -export default function pageVSTApp({ - debug, t, pageState, dispatchPageState, parentPath +import { + Button, + Label, + NumberSliderV2, + Panel, + SelectModal, + TextArea, + VideoFakeyou +} from "components/common"; + +export default function PageVSTApp({ + debug=true, t, pageState, dispatchPageState, parentPath }: { debug?: boolean; t: Function; @@ -15,7 +31,155 @@ export default function pageVSTApp({ parentPath: string; dispatchPageState: (action: Action) => void; }) { + const { mediaToken } = useParams(); + + const [workflowValues, setWorkflowValues] = useState({ + fileToken: pageState.mediaFileToken || mediaToken, + ...ivs + }); + + const videoRef = useRef(null); + if(videoRef?.current){ + const ve = videoRef.current + ve.onloadedmetadata = () =>{ + if (ve.videoWidth && ve.videoHeight) { + const aspectRatio = ve.videoWidth/ve.videoHeight + if (aspectRatio > 1){ + handleOnChange("width",960); + } + else if (aspectRatio < 1) { + handleOnChange("height",960); + }else{ + if (debug) console.log(`aspectRaio: ${aspectRatio}`); + } + } + if(ve.duration){ + handleOnChange("maxFrames", + Math.floor(ve.duration)*workflowValues.inputFps + ); + } + //TODO: Optimizer to make ONE handleOnChange only + //TODO: deal with maxFrames with more reliable math + } + } + + + const handleOnChange = (key: string, newValue:any,) => { + setWorkflowValues((curr)=>({...curr, [key]: newValue})); + } + const history = useHistory(); + const handleGenerate = ()=>{ + if(debug) console.log(workflowValues) + + if (isInputValid(workflowValues)){ + const request = mapRequest(workflowValues); + console.log(request); + EnqueueVideoWorkflow(request).then(res => { + if (res.success && res.inference_job_token) { + dispatchPageState({ + type: 'enqueueFilterSuccess', + payload: { + inferenceJobToken: res.inference_job_token + } + }) + }else{ + console.log(res); + } + }) + dispatchPageState({type: 'enqueueFilter'}) + history.push(`${parentPath}/jobs`); + }else{ + alert("you must pick an sd weight and input a prompt"); + } + } + return( -

hi

+ +
+
+ +
+
+
+
+
+
+ { + handleOnChange("sdModelToken", token); + }} + tabs={[ + { + label: "All Weights", + tabKey: "allWeights", + typeFilter: "sd_1.5", + searcher: true, + type: "weights", + }, + { + label: "Bookmarked", + tabKey: "bookmarkedWeights", + typeFilter: "sd_1.5", + searcher: false, + type: "weights", + }, + ]} + /> +
+ {handleOnChange("upscaleMultiplier",val)} + }}/> +
+
+