From 0a46423717f127a1b60c559bbc7c2a1d813e9087 Mon Sep 17 00:00:00 2001 From: shrimbly Date: Thu, 19 Feb 2026 20:21:29 +1300 Subject: [PATCH] feat(quick-009): add VideoFrameGrabNodeData type, defaults, and connected inputs wiring - Add 'videoFrameGrab' to NodeType union and VideoFrameGrabNodeData interface - Register default dimensions (320x320) and default data in nodeDefaults - Wire getSourceOutput to return image type from videoFrameGrab.outputImage - Add videoFrameGrab dimensions to local Record types in WorkflowCanvas and validation --- src/components/WorkflowCanvas.tsx | 1 + src/lib/quickstart/validation.ts | 1 + src/store/utils/connectedInputs.ts | 3 +++ src/store/utils/nodeDefaults.ts | 9 +++++++++ src/types/nodes.ts | 12 ++++++++++++ 5 files changed, 26 insertions(+) diff --git a/src/components/WorkflowCanvas.tsx b/src/components/WorkflowCanvas.tsx index 9327e1ad..6b247e67 100644 --- a/src/components/WorkflowCanvas.tsx +++ b/src/components/WorkflowCanvas.tsx @@ -1136,6 +1136,7 @@ export function WorkflowCanvas() { videoStitch: { width: 400, height: 280 }, easeCurve: { width: 340, height: 480 }, videoTrim: { width: 360, height: 360 }, + videoFrameGrab: { width: 320, height: 320 }, glbViewer: { width: 360, height: 380 }, }; const dims = defaultDimensions[nodeType]; diff --git a/src/lib/quickstart/validation.ts b/src/lib/quickstart/validation.ts index f762e86a..14eb9630 100644 --- a/src/lib/quickstart/validation.ts +++ b/src/lib/quickstart/validation.ts @@ -45,6 +45,7 @@ const DEFAULT_DIMENSIONS: Record = videoStitch: { width: 400, height: 280 }, easeCurve: { width: 340, height: 480 }, videoTrim: { width: 360, height: 360 }, + videoFrameGrab: { width: 320, height: 320 }, glbViewer: { width: 360, height: 380 }, }; diff --git a/src/store/utils/connectedInputs.ts b/src/store/utils/connectedInputs.ts index 8e3a87e2..e848bdf2 100644 --- a/src/store/utils/connectedInputs.ts +++ b/src/store/utils/connectedInputs.ts @@ -18,6 +18,7 @@ import { VideoStitchNodeData, EaseCurveNodeData, VideoTrimNodeData, + VideoFrameGrabNodeData, PromptNodeData, PromptConstructorNodeData, LLMGenerateNodeData, @@ -86,6 +87,8 @@ function getSourceOutput(sourceNode: WorkflowNode): { type: "image" | "text" | " return { type: "text", value: pcData.outputText ?? pcData.template ?? null }; } else if (sourceNode.type === "llmGenerate") { return { type: "text", value: (sourceNode.data as LLMGenerateNodeData).outputText }; + } else if (sourceNode.type === "videoFrameGrab") { + return { type: "image", value: (sourceNode.data as VideoFrameGrabNodeData).outputImage }; } else if (sourceNode.type === "glbViewer") { return { type: "image", value: (sourceNode.data as GLBViewerNodeData).capturedImage }; } diff --git a/src/store/utils/nodeDefaults.ts b/src/store/utils/nodeDefaults.ts index ba71fca6..5933c04a 100644 --- a/src/store/utils/nodeDefaults.ts +++ b/src/store/utils/nodeDefaults.ts @@ -16,6 +16,7 @@ import { ImageCompareNodeData, EaseCurveNodeData, VideoTrimNodeData, + VideoFrameGrabNodeData, GLBViewerNodeData, WorkflowNodeData, GroupColor, @@ -45,6 +46,7 @@ export const defaultNodeDimensions: Record { progress: 0, encoderSupported: null, } as VideoTrimNodeData; + case "videoFrameGrab": + return { + framePosition: "first", + outputImage: null, + status: "idle", + error: null, + } as VideoFrameGrabNodeData; case "glbViewer": return { glbUrl: null, diff --git a/src/types/nodes.ts b/src/types/nodes.ts index 5a5daa7d..94d26bda 100644 --- a/src/types/nodes.ts +++ b/src/types/nodes.ts @@ -39,6 +39,7 @@ export type NodeType = | "videoStitch" | "easeCurve" | "videoTrim" + | "videoFrameGrab" | "generate3d" | "glbViewer"; @@ -319,6 +320,16 @@ export interface VideoTrimNodeData extends BaseNodeData { encoderSupported: boolean | null; } +/** + * Video Frame Grab node - extracts the first or last frame from a video as a full-resolution PNG image + */ +export interface VideoFrameGrabNodeData extends BaseNodeData { + framePosition: "first" | "last"; // Which frame to extract + outputImage: string | null; // Extracted frame as base64 PNG data URL + status: NodeStatus; + error: string | null; +} + /** * Split Grid node - splits image into grid cells for parallel processing */ @@ -375,6 +386,7 @@ export type WorkflowNodeData = | VideoStitchNodeData | EaseCurveNodeData | VideoTrimNodeData + | VideoFrameGrabNodeData | GLBViewerNodeData; /**