Merge pull request #518 from storytold/feature/page/video_transfer

Feature/page/video transfer
This commit is contained in:
wil authored and GitHub committed 2024-02-28 11:17:46 -05:00
commit ef1b137e60
12 files changed
+161 -100

No files matched your search

@@ -11,6 +11,7 @@ import './styles.scss';
export interface VideoFakeyouProps{
wrapperClassName?: string;
controls?:boolean;
muted?:boolean;
className?:string;
src?:string;
mediaToken?: string;
@@ -23,6 +24,7 @@ type Ref = HTMLVideoElement;
const VideoFakeyou = forwardRef<Ref, VideoFakeyouProps>(({
wrapperClassName,
controls,
muted,
className,
src,
mediaToken,
@@ -43,10 +45,11 @@ const VideoFakeyou = forwardRef<Ref, VideoFakeyouProps>(({
if (mediaLink){
return (
<div {...{ ...makeClass("fy-video vh50",wrapperClassName) }}>
<div {...{ ...makeClass("fy-video",wrapperClassName) }}>
{label && <Label label={label}/>}
<video
controls={controls}
muted={muted}
ref={ref}
key={mediaToken}
{...{
@@ -9,9 +9,7 @@
&.fit-content {
height: fit-content;
}
&.vh50{
height: 50vh;
}
video, .video-overlay {
border-radius: .5rem;
width: 100%;
@@ -1,15 +1,17 @@
import React, {
memo,
useCallback,
useEffect,
useLayoutEffect,
useState,
useRef,
PointerEvent
PointerEvent,
} from "react";
import {
faPlay,
faPause,
faGripDots
faGripDots,
faVolume,
faVolumeSlash,
} from "@fortawesome/pro-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
@@ -19,79 +21,53 @@ import {
} from "components/common";
import { VideoFakeyouProps } from "../VideoFakeyou/VideoFakeyou";
import { QuickTrimData, TrimStates, PlaybarStates } from "./types";
import { formatSecondsToHHMMSSCS } from "./helpers";
import './styles.scss'
function roundTo2Dec(floaty:number){
return Math.round(floaty*100)/100;
}
function fractionToPercentage(fraction:number){
return roundTo2Dec(fraction * 100);
}
function formatSecondsToHHMMSS(seconds:number){
if(seconds < 3600)
return new Date(seconds * 1000).toISOString().substring(14, 19)
else
return new Date(seconds * 1000).toISOString().slice(11, 19);
}
export type QuickTrimType = {
trimStartSeconds: number;
trimEndSeconds: number;
}
interface VideoQuickTrimProps extends VideoFakeyouProps{
onSelect: (val: QuickTrimType)=>void;
onSelect: (values: QuickTrimData)=>void;
}
type TrimState = {
isScrubbingTrim: boolean;
trimDuration: number;
trimStart: number;
trimEnd: number;
maxDuration: number;
}
const initialTrimState = {
const trimOptions: { [key: string]: number } = {
"3s": 3,
"5s": 5,
"10s": 10,
"15s" : 15,
};
const initialTrimState:TrimStates = {
isScrubbingTrim: false,
trimDuration: 3,
trimStart: 0,
trimEnd: 0,
maxDuration: 0,
}
type PlaybarState = {
playbarWidth: number;
timeCursorOffset: number;
}
const initialPlaybarState = {
const initialPlaybarState:PlaybarStates = {
playbarWidth: 0,
timeCursorOffset: 0,
}
export default function VideoQuickTrim({
export default memo(function VideoQuickTrim({
onSelect,
...rest
}: VideoQuickTrimProps){
console.log("Rerender!!");
const trimOptions: { [key: string]: number } = {
"3s": 3,
"5s": 5,
"10s": 10,
"15s" : 15,
"20s" : 20,
};
console.log("VideoQuickTrim Rerender!!");
const videoRef = useRef<HTMLVideoElement | null>(null);
const playbarRef = useRef<HTMLDivElement | null>(null);
const trimZoneRef = useRef<HTMLDivElement>(null);
const [{playbarWidth, timeCursorOffset}, setPlaybarState] = useState<PlaybarState>(initialPlaybarState);
const [{playbarWidth, timeCursorOffset}, setPlaybarState] = useState<PlaybarStates>(initialPlaybarState);
const [playpause, setPlaypause] = useState<'playing'|'paused'|'stopped'>('paused');
const [isMuted, setIsMuted] = useState<boolean>(false);
const [{
trimStart,
trimEnd,
// trimEnd,
trimDuration,
isScrubbingTrim,
}, setTrimState] = useState<TrimState>(initialTrimState);
}, setTrimState] = useState<TrimStates>(initialTrimState);
@@ -137,15 +113,13 @@ export default function VideoQuickTrim({
setTrimState((curr)=>({
...curr,
trimDuration: trimOptions[selected],
trimEnd: curr.trimStart+ trimOptions[selected],
trimEnd: trimStart+ trimOptions[selected],
}))
}
useEffect(()=>{
onSelect({
trimStartSeconds: trimStart,
trimEndSeconds: trimEnd,
trimEndSeconds: trimStart+ trimOptions[selected],
});
},[trimStart, trimEnd, onSelect]);
}
const handlePlaypause = ()=>{
if (playpause === 'paused' || playpause === 'stopped'){
@@ -156,11 +130,13 @@ export default function VideoQuickTrim({
setPlaypause('paused');
}
}
return (
<div className="fy-video-quicktrim">
<div className="video-wrapper">
<VideoFakeyou
controls={false}
muted={isMuted}
ref={videoRefCallback}
{...rest}
/>
@@ -175,7 +151,6 @@ export default function VideoQuickTrim({
icon={faPause} size="8x"
/>
}
</div>
</div>{/* END of Video Wrapper */}
<div className="playbar" ref={playbarRefCallback}>
@@ -207,9 +182,9 @@ export default function VideoQuickTrim({
}}
onPointerMove={(e: PointerEvent<HTMLDivElement>)=>{
if(trimZoneRef.current && playbarRef.current && isScrubbingTrim){
console.log(fractionToPercentage(
(e.clientX - trimZoneRef.current.getBoundingClientRect().left) / (playbarRef.current.getBoundingClientRect().width)
) + "%");
// console.log(fractionToPercentage(
// (e.clientX - trimZoneRef.current.getBoundingClientRect().left) / (playbarRef.current.getBoundingClientRect().width)
// ) + "%");
}
}}
>
@@ -221,12 +196,29 @@ export default function VideoQuickTrim({
<div className="d-flex w-100 justify-content-between mt-3 flex-wrap">
<div className="playpause-external d-flex align-items-center flex-wrap mb-2">
<Button
className="button-playpause"
icon={playpause === 'playing' ? faPause : faPlay}
variant="secondary"
onClick={handlePlaypause}
/>
<div className="playtime ms-3">
<p>{`${formatSecondsToHHMMSS(videoRef.current?.currentTime || 0)} / ${formatSecondsToHHMMSS(videoRef.current?.duration || 0)}`}</p>
<Button
className="button-mute"
icon={isMuted ? faVolumeSlash : faVolume}
variant="secondary"
onClick={()=>setIsMuted((curr)=>(!curr))}
/>
<div className="playtime ms-2 d-flex">
<span >
<p>
{`${formatSecondsToHHMMSSCS(videoRef.current?.currentTime || 0)}`}
</p>
</span>
<div>/</div>
<span>
<p>
{`${formatSecondsToHHMMSSCS(videoRef.current?.duration || 0)}`}
</p>
</span>
</div>
</div>
<SelectionBubbles
@@ -236,4 +228,4 @@ export default function VideoQuickTrim({
</div>
</div>
);
}
});
@@ -0,0 +1,14 @@
export function roundTo2Dec(floaty:number){
return Math.round(floaty*100)/100;
}
export function fractionToPercentage(fraction:number){
return roundTo2Dec(fraction * 100);
}
export function formatSecondsToHHMMSSCS(seconds:number){
//example of the ISO String: 1970-01-01T00:01:40.774Z
const isoString = new Date(seconds * 1000).toISOString();
if(seconds > 3600)
return isoString.substring(11, 19) + "." + isoString.substring(20, 22)
else
return isoString.substring(14, 19) + "." + isoString.substring(20, 22);
}
@@ -1 +1,5 @@
export { default } from './VideoQuickTrim';
import VideoQuickTrim from './VideoQuickTrim'
import { QuickTrimData } from './types';
export type { QuickTrimData };
export default VideoQuickTrim;
@@ -11,6 +11,9 @@ $playbar-height: 2rem;
border-left: $panel-inner-border 1px solid;
border-right: $panel-inner-border 1px solid;
}
.fy-video{
height: 500px;
}
.playpause-overlay{
position: absolute;
cursor: pointer;
@@ -70,4 +73,26 @@ $playbar-height: 2rem;
height: $playbar-height;
background-color: $white;
}
.playpause-external{
.button-playpause{
width: 55px;
height: 40px;
margin-right: 0.5rem;
}
.button-mute{
width: 40px;
height: 40px;
}
.playtime{
span{
width: 60px;
}
div{
width: 10px;
margin-left: 3px;
margin-right: 5px;
text-align: center;
}
}
}
}
@@ -0,0 +1,19 @@
//For integration into other components
export type QuickTrimData = {
trimStartSeconds: number;
trimEndSeconds: number;
}
// INTERNALS
export type TrimStates = {
isScrubbingTrim: boolean;
trimDuration: number;
trimStart: number;
trimEnd: number;
maxDuration: number;
}
export type PlaybarStates = {
playbarWidth: number;
timeCursorOffset: number;
}
@@ -48,6 +48,7 @@ import TintSpinner from "./TintSpinner";
import VideoBasic from "./VideoBasic";
import VideoFakeyou from "./VideoFakeyou";
import VideoInput from "./VideoInput";
// import VideoQuickTrim, {QuickTrimType} from "./VideoQuickTrim";
import SelectionBubbles from "./SelectionBubbles";
import Scene3D from "./Scene3D";
@@ -109,6 +110,7 @@ export {
VideoBasic,
VideoFakeyou,
VideoInput,
// VideoQuickTrim,
SelectionBubbles,
Scene3D,
};
@@ -9,16 +9,17 @@ type CNPreset =
const defaultPreset = {
cnCanny: 0,
cnDepth: 0.7,
cnDepth: 0,
cnLineArtAnime: 0.7,
cnLineArtRealistic: 0.7,
cnLineArtRealistic: 0,
cnLipsStrength: 0,
cnOpenPose: 0.7,
cnPipeFace: 0.7,
cnSparseScribble: 0.7,
cnSoftEdge: 0.7,
cnOpenPose: 1,
cnPipeFace: 0,
cnSparseScribble: 0,
cnSoftEdge: 1,
cnRegularSteps: 20,
}
const closeupPreset = {
cnCanny: 0,
cnDepth: 0,
@@ -29,20 +30,22 @@ const closeupPreset = {
cnPipeFace: 0,
cnSparseScribble: 0.7,
cnSoftEdge: 0.7,
cnRegularSteps: 30,
cnRegularSteps: 20,
}
const halfbodyPreset = {
cnCanny: 0,
cnDepth: 0,
cnLineArtAnime: 0.7,
cnLineArtRealistic: 0,
cnLipsStrength: 0,
cnOpenPose: 0.5,
cnOpenPose: 0.7,
cnPipeFace: 0,
cnSparseScribble: 0.7,
cnSoftEdge: 0.7,
cnRegularSteps: 30,
cnSparseScribble: 0,
cnSoftEdge: 1,
cnRegularSteps: 20,
}
const fullbodyPreset = {
cnCanny: 0,
cnDepth: 0,
@@ -51,21 +54,22 @@ const fullbodyPreset = {
cnLipsStrength: 0,
cnOpenPose: 1,
cnPipeFace: 0,
cnSparseScribble: 0.7,
cnSoftEdge: 0.7,
cnRegularSteps: 30,
cnSparseScribble: 0,
cnSoftEdge: 1,
cnRegularSteps: 20,
}
const landscapePreset = {
cnCanny: 0.7,
cnDepth: 0.7,
cnCanny: 0,
cnDepth: 0.4,
cnLineArtAnime: 0.7,
cnLineArtRealistic: 0,
cnLipsStrength: 0,
cnOpenPose: 0,
cnPipeFace: 0,
cnSparseScribble: 0.7,
cnSoftEdge: 0.7,
cnRegularSteps: 30,
cnSparseScribble: 0,
cnSoftEdge: 1,
cnRegularSteps: 20,
}
const typogPreset = {
@@ -78,7 +82,7 @@ const typogPreset = {
cnPipeFace: 0,
cnSparseScribble: 0,
cnSoftEdge: 0.7,
cnRegularSteps: 30,
cnRegularSteps: 20,
}
export type {
@@ -8,9 +8,9 @@ const initialValues = {
//video Settings
width: 1024,
height: 1024,
maxDuration: 2,
maxDuration: 3,
trimStart: 0,
trimEnd: 5,
trimEnd: 3,
//Presents
workflowConfig: "weight_99tz2nzbp5x9v55gqn5ekj1sd",
@@ -4,12 +4,11 @@ import { useParams, useHistory } from "react-router-dom";
import {
Button,
// Label,
Panel,
NumberSliderV2,
TextArea,
VideoFakeyou
} from "components/common";
import VideoQuickTrim, {QuickTrimData} from 'components/common/VideoQuickTrim';
import EnqueueVideoStyleTransfer from "@storyteller/components/src/api/video_styleTransfer";
@@ -25,7 +24,6 @@ import {
import SectionAdvanceOptions from "./sectionAdvanceOptions";
export default function PageVSTApp({
debug, t, pageState, dispatchPageState, parentPath
}: {
@@ -52,7 +50,6 @@ export default function PageVSTApp({
width?: number;
height?: number;
maxDuration?: number;
// trim?: number;
} = {};
// if (ve.videoWidth && ve.videoHeight) {
// const aspectRatio = ve.videoWidth/ve.videoHeight
@@ -108,10 +105,14 @@ export default function PageVSTApp({
<Panel className="mb-4 p-4">
<div className="row g-3 mb-4">
<div className="col-12 col-md-6">
<VideoFakeyou
label={t("video.label.original")}
<VideoQuickTrim
// label={t("video.label.original")}
mediaToken={vstValues.fileToken}
ref={videoRef}
// ref={videoRef}
onSelect={(val:QuickTrimData)=>handleOnChange({
trimStart: val.trimStartSeconds,
trimEnd: val.trimEndSeconds
})}
onResponse={(res)=>{
dispatchPageState({
type: 'loadFileSuccess',
@@ -175,14 +176,13 @@ export default function PageVSTApp({
<NavLink to={`${parentPath}`}>
<Button
label={t("button.cancel")}
// onClick={handleGenerate}
variant="primary"
/>
</NavLink>
<Button
label="Fake Gen"
onClick={handleFakeGen}
variant="primary"
variant="secondary"
/>
<Button
label={t("button.enqueue")}
@@ -39,7 +39,7 @@ export default function SectionAdvanceOptions({
onChange: (val:{[key: string]: number|string|boolean|undefined})=>void
}){
const [preset, pickPreset] = useState<CNPreset>('custom')
const [preset, pickPreset] = useState<CNPreset>('default')
function handlePreset(newPreset: CNPreset){
switch (newPreset){
case 'closeup':
@@ -234,10 +234,10 @@ export default function SectionAdvanceOptions({
}}/>
</div>
</div>
<div className="row g-3 p-3">
{/* <div className="row g-3 p-3">
<div className="col-md-6">
<NumberSliderV2 {...{
min: 1, max: 64, step: 30,
min: 1, max: 64, step: 1,
initialValue: vstVal.cnRegularSteps,
label: "Regular Steps",
thumbTip: "Regular Steps",
@@ -247,7 +247,7 @@ export default function SectionAdvanceOptions({
}
}}/>
</div>
</div>
</div> */}
<div className="d-flex p-3 justify-content-end">
<Button
icon={faRotateLeft}