copy pasting page

This commit is contained in:
wil committed 2024-02-14 22:47:07 -05:00
1 parent ec5ef41fed
commit f0acf491a9
13 files changed
+501 -1

No files matched your search

@@ -13,6 +13,7 @@ export enum FrontendInferenceJobType {
ConvertFbxtoGltf,
EngineComposition,
VideoWorkflow,
VideoStyleTransfer,
}
// NB: Many of these fields are optional despite the response payload containing them
+2
View File
@@ -212,6 +212,8 @@ function initInferenceJobsByCategoryMap(): Map<
inferenceJobsByCategory.set(FrontendInferenceJobType.ConvertFbxtoGltf, []);
inferenceJobsByCategory.set(FrontendInferenceJobType.VideoWorkflow, [])
return inferenceJobsByCategory;
inferenceJobsByCategory.set(FrontendInferenceJobType.VideoStyleTransfer, [])
return inferenceJobsByCategory;
}
function isMacOs() {
@@ -8,6 +8,7 @@ import { ModerationIpBanListFc } from "./pages/moderation/moderation_ip_ban_list
import { ModerationViewIpBanFc } from "./pages/moderation/moderation_view_ip_ban/ModerationViewIpBanFc";
import FaceAnimator from "./pages/face_animator";
import VideoMocap from "./pages/video_mocap";
import VideoStyleTransfer from "./pages/video_styletransfer";
import { ProfileEditFc } from "./pages/profile/profile_edit/ProfileEditFc";
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
@@ -866,6 +867,20 @@ class PageContainer extends React.Component<
/>
</Route>
<Route path="/video-styletransfer">
<VideoStyleTransfer
{...{
enqueueInferenceJob: this.props.enqueueInferenceJob,
sessionSubscriptionsWrapper:
this.props.sessionSubscriptionsWrapper,
inferenceJobs: this.props.inferenceJobs,
inferenceJobsByCategory:
this.props.inferenceJobsByCategory,
sessionWrapper: this.props.sessionWrapper,
}}
/>
</Route>
<Route path="/text-to-image">
<TextToImagePage
sessionSubscriptionsWrapper={
@@ -0,0 +1,65 @@
import React, {useReducer, useEffect} from 'react';
import { SessionWrapper } from '@storyteller/components/src/session/SessionWrapper';
import { StudioNotAvailable } from 'v2/view/_common/StudioNotAvailable';
import { useInferenceJobs, useLocalize } from "hooks";
import { FrontendInferenceJobType, InferenceJob } from '@storyteller/components/src/jobs/InferenceJob';
import { Container } from "components/common";
import PageHeader from "components/layout/PageHeader";
import { states, reducer } from "./reducer";
import SubRoutes from "./routes";
export default function VideoStyleTransfer(props:{
enqueueInferenceJob: (
jobToken: string,
frontendInferenceJobType: FrontendInferenceJobType
) => void;
inferenceJobs: Array<InferenceJob>;
inferenceJobsByCategory: Map<FrontendInferenceJobType, Array<InferenceJob>>;
sessionWrapper: SessionWrapper;
}){
const debug = false;
const {t} = useLocalize("VideoStyleTransfer");
const { NO_FILE } = states;
const [pageState, dispatchPageState] = useReducer(reducer, {
status: NO_FILE,
});
const { enqueueInferenceJob } = props;
useInferenceJobs(
FrontendInferenceJobType.VideoWorkflow
);
useEffect(() => {
if (
pageState.status === states.WORKFLOW_ENQUEUED &&
pageState.inferenceJobToken
) {
enqueueInferenceJob(
pageState.inferenceJobToken,
FrontendInferenceJobType.VideoWorkflow
);
dispatchPageState({
type: "enqueueFilterSuccess",
payload: { inferenceJobToken: undefined },
});
}
}, [pageState, enqueueInferenceJob]);
if (!props.sessionWrapper.canAccessStudio()) {
return <StudioNotAvailable />
}
return(
<Container type="panel" className="mb-5">
{debug && <p>{`Status:${pageState.status} MediaToken:${pageState.mediaFileToken}`}</p>}
<PageHeader
title={t("headings.title")}
subText={t("headings.subtitle")}
/>
<SubRoutes {...{debug, t, pageState, dispatchPageState}}/>
</Container>
);
}
@@ -0,0 +1,27 @@
import React from 'react';
import { Analytics } from "common/Analytics";
import InferenceJobsList from "components/layout/InferenceJobsList";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
export default function CompVideoStyleTransferJobList({
showNoJobs = false
}:{
showNoJobs?:boolean
}){
const failures = (fail = "") => {
switch (fail) {
case "sample case":
return "Sample Case, this should not have been shown";
default:
return "Unknown failure";
}
};
return (
<InferenceJobsList {...{
showNoJobs,
failures,
onSelect: () => Analytics.voiceConversionClickDownload(),
jobType: FrontendInferenceJobType.VideoStyleTransfer,
}}/>
);
}
@@ -0,0 +1,37 @@
import React, { memo } from 'react'
import { NavLink } from 'react-router-dom';
import { states, Action, State } from "../reducer";
import { Button, Spinner } from 'components/common';
import CompJoblist from './compJoblist';
export default memo (function PageWorkflowJoblist({
t, pageState, dispatchPageState, parentPath
}: {
debug?: boolean;
t: Function;
pageState: State;
parentPath: string
dispatchPageState: (action: Action) => void;
}) {
return(
<>
<div className="row mb-3">
<NavLink to={`${parentPath}`}>
<Button
label={t("button.generateNewWorkflow")}
variant="primary"
/>
</NavLink>
</div>
{pageState.status === states.WORKFLOW_ENQUEUEING &&
<div>
<h2> Requesting Filter Job</h2>
<Spinner />
</div>
}
<CompJoblist showNoJobs />
</>
);
});
@@ -0,0 +1,54 @@
import React from "react";
import { Panel, Tabs } from "components/common";
import { State, Action } from "../reducer";
import TabContentUpload from "./tabContentUpload";
import TabContentLibrary from "./tabContentLibrary";
import CompJoblist from "./compJoblist";
export default function PageVideoProvision({
debug=false, parentPath, t, pageState, dispatchPageState
}: {
debug?: boolean;
parentPath: string;
t: Function;
pageState: State;
dispatchPageState: (action: Action) => void;
}) {
const tabs = [
{
label: t("tabTitle.upload"),
content: <TabContentUpload {...{
debug, t, pageState, dispatchPageState
}} />,
to: `${parentPath}/upload`,
padding: true,
},
{
label: t("tabTitle.library"),
content: <TabContentLibrary {...{
debug, t, pageState, dispatchPageState
}} />,
to: `${parentPath}/select-media`,
padding: true,
},
];
return(
<>
<Panel className="mb-4">
<div className="row g-0">
<div className="col-12 col-md-6">
<Tabs tabs={tabs} />
</div>
<div className="col-12 col-md-6 p-5 mt-3">
<p>{t("video.instruction")}</p>
</div>
</div>
</Panel>
<CompJoblist />
</>
);
}
@@ -0,0 +1,62 @@
import React from "react";
import { NavLink } from "react-router-dom";
import { states, Action, State } from "../reducer";
import { Button } from "components/common";
import SelectModal, { SelectModalData } from "components/common/SelectModal/SelectModal";
import VideoFakeyou from "components/common/VideoFakeyou";
export default function TabContentLibrary({
t, pageState, dispatchPageState
}: {
t: Function;
pageState: State;
dispatchPageState: (action: Action) => void;
}){
const handleProceed = ()=>{
dispatchPageState({type: "loadFile"})
}
const handleOnSelect = (data:SelectModalData)=>{
if (data.token !== ""){
dispatchPageState({
type: "selectedFile",
payload: {mediaFileToken: data.token}
});
}else{
dispatchPageState({type: "clearedFile"});
};
};
return (
<div className="row g-3">
<div className="col-12">
<SelectModal
modalTitle="Select a Video"
label="Select a Video"
onSelect={handleOnSelect}
tabs={[
{
label: "All Videos",
tabKey: "allVideos",
typeFilter: "video",
searcher: false,
type: "media",
},
]}
/>
{pageState.mediaFileToken &&
<VideoFakeyou mediaToken={pageState.mediaFileToken} />
}
</div>
{pageState.status === states.FILE_SELECTED &&
<div className="col-12 d-flex justify-content-center mt-5">
<NavLink to={`load/${pageState.mediaFileToken}`}>
<Button
label={t("button.proceed")}
onClick={handleProceed}
/>
</NavLink>
</div>
}
</div>
);
}
@@ -0,0 +1,98 @@
import React from "react";
import { Redirect } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import { UploadMedia } from "@storyteller/components/src/api/media_files/UploadMedia";
import { useFile } from "hooks";
import { ErrorMessage, VideoInput, Spinner } from "components/common";
import { states, Action, State } from "../reducer";
export default function TabContentUpload({
debug=false, t, pageState, dispatchPageState
}: {
debug?: boolean;
t: Function;
pageState: State;
dispatchPageState: (action: Action) => void;
}) {
const videoProps = useFile({});
const {NO_FILE, FILE_STAGED, FILE_SELECTED, FILE_UPLOADING, FILE_UPLOADED} = states;
const makeVideoUploadRequest = () => ({
uuid_idempotency_token: uuidv4(),
file: videoProps.file,
source: "file",
type: "video",
});
const handleUploadVideo = () => {
dispatchPageState({type: 'uploadFile'});
UploadMedia(makeVideoUploadRequest()).then(res => {
if (res.success && res.media_file_token) {
dispatchPageState({
type: 'uploadFileSuccess',
payload:{
mediaFileToken :res.media_file_token
}
})
}
});
};
// contains upload inout state and controls, see docs
if (pageState.status === NO_FILE
|| pageState.status === FILE_STAGED
|| pageState.status === FILE_SELECTED
) {
return (
<>
<div className="row">
<div className="col-12">
<VideoInput
{...{
t,
...videoProps,
onStateChange: () =>{
if (pageState.status === NO_FILE && videoProps.file)
dispatchPageState({type: "stagedFile"})
else if (pageState.status === FILE_STAGED && !videoProps.file)
dispatchPageState({type: "clearedFile"})
}
}}
/>
</div>
</div>
<div className="row py-3">
<div className="col-12">
<div className="d-flex justify-content-end gap-3">
<button
className="btn btn-primary"
disabled={pageState.status !== FILE_STAGED}
onClick={handleUploadVideo}
>
{t("button.upload")}
</button>
</div>
</div>
</div>
</>
);
}else if (pageState.status === FILE_UPLOADING){
return(
<div className="row">
<div className="col-12">
<h1>{t("message.fileUploading")}</h1>
</div>
<div className="col-12">
<Spinner />
</div>
</div>
);
}else if (pageState.status === FILE_UPLOADED){
return(
<Redirect to={`load/${pageState.mediaFileToken}`}/>
)
}
return <ErrorMessage />;
}
@@ -0,0 +1,2 @@
export {default} from "./VideoStyleTransfer";
@@ -0,0 +1,87 @@
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile";
export enum states{
NO_FILE,
FILE_STAGED,
FILE_SELECTED,
FILE_UPLOADING,
FILE_UPLOADED,
FILE_LOADING,
FILE_LOADED,
WORKFLOW_ENQUEUEING,
WORKFLOW_ENQUEUED
}
export type State = {
status: number;
mediaFileToken?: string;
mediaFile?: MediaFile;
inferenceJobToken?: string;
}
export type Action =
| {type: 'reset'}
| {type: 'stagedFile'}
| {type: 'clearedFile'}
| {type: 'selectedFile', payload: { mediaFileToken: string}}
| {type: 'uploadFile'}
| {type: 'uploadFileSuccess', payload:{ mediaFileToken: string}}
| {type: 'loadFile'}
| {type: 'loadFileSuccess', payload:{
mediaFileToken: string, mediaFile: MediaFile
}}
| {type: 'enqueueFilter'}
| {type: 'enqueueFilterSuccess', payload: {inferenceJobToken: string|undefined}}
export function reducer (state: State, action: Action): State {
switch(action.type){
case 'stagedFile':
return {...state, status: states.FILE_STAGED}
case 'clearedFile':
return {...state,
status: states.NO_FILE,
mediaFileToken: ""
}
case 'selectedFile':
return {
...state,
status: states.FILE_SELECTED,
mediaFileToken: action.payload.mediaFileToken
}
case 'uploadFile':
return {...state,status: states.FILE_UPLOADING};
case 'uploadFileSuccess':
return {
...state,
status: states.FILE_UPLOADED,
mediaFileToken: action.payload.mediaFileToken
}
case 'loadFile':
return {...state, status: states.FILE_LOADING}
case 'loadFileSuccess':
console.log("LOAD FILE SUCCESS");
return {
...state,
status: states.FILE_LOADED,
mediaFile: action.payload.mediaFile,
mediaFileToken : action.payload.mediaFileToken,
}
case 'enqueueFilter':
return {
...state,
status: states.WORKFLOW_ENQUEUEING
}
case 'enqueueFilterSuccess':
return {
...state,
status: states.WORKFLOW_ENQUEUED,
inferenceJobToken: action.payload.inferenceJobToken
}
case 'reset':
default:
return {status: states.NO_FILE};
}
}
@@ -0,0 +1,50 @@
import React from "react";
import {Switch, Route, useRouteMatch, Redirect, useHistory} from "react-router-dom";
// import PageWorkflowControls from "./components/pageWorkflowControls";
import PageVideoProvision from "./components/pageVideoProvision";
import PageJoblist from "./components/pageJoblist";
import {states,State,Action} from "./reducer";
export default function SubRoutes ({
debug, t, pageState, dispatchPageState
}:{
debug?:boolean,
t:Function,
pageState:State,
dispatchPageState: (action: Action) => void
}){
const { path } = useRouteMatch();
const history = useHistory();
history.listen(({pathname}, action) => {
if ((pathname === path || pathname.match(/upload|select-media/g)) && pageState.status >= states.FILE_LOADING){
//reset page if landed on page "Freshly"
dispatchPageState({type: 'reset'})
}
})
const commonPageProps = {
debug, parentPath: path, t, pageState, dispatchPageState
};
return(
<Switch>
{/* <Route exact path={`${path}/load/:mediaToken`} >
<PageWorkflowControls {...commonPageProps}/>
</Route> */}
<Route exact path={`${path}/upload`}>
<PageVideoProvision {...commonPageProps}/>
</Route>
<Route exact path={`${path}/select-media`}>
<PageVideoProvision {...commonPageProps}/>
</Route>
<Route exact path={`${path}/jobs`}>
<PageJoblist {...commonPageProps}/>
</Route>
<Route path={`${path}`}>
<Redirect to={`${path}/upload`} />
</Route>
</Switch>
)
}
@@ -11,7 +11,7 @@ import SubRoutes from "./videoWorkflowRoutes";
import { SessionWrapper } from '@storyteller/components/src/session/SessionWrapper';
import { StudioNotAvailable } from 'v2/view/_common/StudioNotAvailable';
export default function StorytellerFilter(props:{
export default function VideoWorkflow(props:{
enqueueInferenceJob: (
jobToken: string,
frontendInferenceJobType: FrontendInferenceJobType