add progress to live portrait jobs

This commit is contained in:
bflatastic committed 2024-08-17 00:09:01 +07:00
1 parent 829d05b225
commit 5b1e130fbb
3 files changed
+66 -7

No files matched your search

@@ -46,6 +46,7 @@ import SessionLpInferenceResultsList from "./SessionLpInferenceResultsList";
import { GetMedia } from "@storyteller/components/src/api/media_files/GetMedia";
import { useLocation } from "react-router-dom";
import { LivePortraitDetails } from "@storyteller/components/src/api/model_inference/GetModelInferenceJobStatus";
import { useDocumentTitle } from "@storyteller/components/src/hooks/UseDocumentTitle";
interface LivePortraitProps {
sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
@@ -64,6 +65,7 @@ interface GeneratedVideo {
export default function LivePortrait({
sessionSubscriptionsWrapper,
}: LivePortraitProps) {
useDocumentTitle("Live Portrait AI. Free Video Animation");
const { enqueueInferenceJob } = useInferenceJobs();
const { open, close } = useModal();
const [isEnqueuing, setIsEnqueuing] = useState(false);
@@ -99,6 +101,9 @@ export default function LivePortrait({
const [currentlyGeneratingList, setCurrentlyGeneratingList] = useState<
{ sourceIndex: number; motionIndex: number }[]
>([]);
const [jobProgressPercentage, setJobProgressPercentage] = useState<
number | null
>(null);
const location = useLocation();
@@ -146,6 +151,15 @@ export default function LivePortrait({
}
};
const handleJobProgress = (progress: number | null) => {
setJobProgressPercentage(prevProgress => {
if (prevProgress !== progress) {
return progress;
}
return prevProgress;
});
};
const handleSourceSelect = (index: number) => {
setIsUserUploaded(index >= numberOfInitialSourceTokens);
setSelectedSourceIndex(index);
@@ -201,6 +215,10 @@ export default function LivePortrait({
});
};
useEffect(() => {
console.log("Updated jobProgressPercentage:", jobProgressPercentage);
}, [jobProgressPercentage]);
const renderVideoOrPlaceholder = () => {
// Check if the current combination is being generated
const isCurrentlyGenerating = currentlyGeneratingList.some(
@@ -225,7 +243,9 @@ export default function LivePortrait({
<h4 className="fw-medium">
<div className="d-flex flex-column align-items-center gap-3 justify-content-center">
<LoadingSpinner padding={false} />
Generating video...
{jobProgressPercentage !== null
? `Generating video... ${jobProgressPercentage}%`
: "Generating video..."}
</div>
</h4>
</div>
@@ -238,7 +258,7 @@ export default function LivePortrait({
</div>
);
} else if (generatedVideoSrc) {
// Show dynamically generated video if available
// Show generated video if available
return (
<video
loop
@@ -270,7 +290,7 @@ export default function LivePortrait({
</video>
);
} else {
// Show "Click to Animate" if nothing is generating or precomputed
// Show "Click to Animate" if nothing is generating or samples
return (
<div className="w-100 h-100 position-relative">
<div
@@ -440,7 +460,7 @@ export default function LivePortrait({
sourceToken: livePortraitDetails.source_media_file_token,
motionToken: livePortraitDetails.face_driver_media_file_token,
videoSrc: mediaLink,
jobToken, // Store the job token with the video
jobToken,
createdAt,
};
@@ -678,6 +698,7 @@ export default function LivePortrait({
onUploadClick={handleOpenUploadSourceModal}
onSelectedMediaChange={handleSelectedMediaChange}
uploadFocusPoint={uploadFocusPointSource}
uploadButtonText="Upload your image/video"
/>
</div>
@@ -705,6 +726,7 @@ export default function LivePortrait({
stepNumber={2}
onUploadClick={handleOpenUploadMotionModal}
uploadFocusPoint={uploadFocusPointMotion}
uploadButtonText="Upload your motion video"
/>
</div>
@@ -822,6 +844,7 @@ export default function LivePortrait({
)
}
onJobClick={handleJobClick}
onJobProgress={handleJobProgress}
/>
</div>
</div>
@@ -25,6 +25,7 @@ interface SessionLpInferenceResultsListProps {
addSourceToken: (token: string) => void;
addMotionToken: (token: string) => void;
onJobClick: (job: InferenceJob) => void;
onJobProgress: (progress: number | null) => void;
}
export default function SessionLpInferenceResultsList({
@@ -33,10 +34,13 @@ export default function SessionLpInferenceResultsList({
addMotionToken,
addSourceToken,
onJobClick,
onJobProgress,
}: SessionLpInferenceResultsListProps) {
const { inferenceJobsByCategory } = useInferenceJobs();
const hasInitialized = useRef(false);
const lastProgressRef = useRef<{ [key: string]: number | null }>({});
const livePortraitJobs = useMemo(() => {
return (
inferenceJobsByCategory.get(FrontendInferenceJobType.LivePortrait) || []
@@ -77,6 +81,34 @@ export default function SessionLpInferenceResultsList({
}
}, [livePortraitJobs, onJobTokens, addSourceToken, addMotionToken]);
useEffect(() => {
livePortraitJobs.forEach((job: InferenceJob) => {
const currentProgress = job.progressPercentage;
if (job.jobState === JobState.STARTED && currentProgress !== null) {
if (lastProgressRef.current[job.jobToken] !== currentProgress) {
console.log(
`Updating progress for Job ${job.jobToken}: ${currentProgress}%`
);
onJobProgress(currentProgress);
lastProgressRef.current[job.jobToken] = currentProgress;
}
}
if (
(job.jobState === JobState.COMPLETE_SUCCESS ||
job.jobState === JobState.COMPLETE_FAILURE) &&
lastProgressRef.current[job.jobToken] !== null
) {
console.log(
`Job ${job.jobToken} is complete. Resetting progress to null.`
);
onJobProgress(null);
lastProgressRef.current[job.jobToken] = null;
}
});
}, [livePortraitJobs, onJobProgress]);
const [mediaSrc, setMediaSrc] = useState<{ [key: string]: string }>({});
useEffect(() => {
@@ -166,7 +198,9 @@ export default function SessionLpInferenceResultsList({
More Details
</Link>
) : (
<div className="fs-7 opacity-50 mt-1">Waiting...</div>
<div className="fs-7 opacity-50 fw-medium mt-1">
{job.progressPercentage}% complete
</div>
)}
</div>
</div>
@@ -36,6 +36,7 @@ interface ThumbnailMediaPickerProps {
onUploadClick?: () => void;
onSelectedMediaChange?: (media: any) => void;
uploadFocusPoint?: boolean;
uploadButtonText?: string;
}
interface MediaData {
@@ -58,6 +59,7 @@ const ThumbnailMediaPicker: React.FC<ThumbnailMediaPickerProps> = React.memo(
onUploadClick,
onSelectedMediaChange,
uploadFocusPoint,
uploadButtonText = "Upload your own media",
}) => {
const [zoom, setZoom] = useState(1);
const [isCropping, setIsCropping] = useState(false);
@@ -289,8 +291,8 @@ const ThumbnailMediaPicker: React.FC<ThumbnailMediaPickerProps> = React.memo(
<Button
icon={faUpload}
label="Upload your media"
variant="secondary"
label={uploadButtonText}
variant="action"
className="order-3 order-lg-4"
onClick={onUploadClick}
focusPoint={uploadFocusPoint}