Nodes/ComfyUI-mAI-FrameCanvas/mAI Frame Canvas Recut
ComfyUI Node

mAI Frame Canvas Recut

The node that pads your video frames to a model-safe size — and remembers how to undo it

By mAI-mathieu·Created 2 months ago·Updated 2 months ago· 0
mAI Frame Canvas Recut
  • frames
  • recut_frames
  • preview_first_frame
  • extended_area_mask
  • final_canvas_width
  • final_canvas_height
  • processing_canvas_width
  • processing_canvas_height
  • crop_x
  • crop_y
  • crop_width
  • crop_height
canvas_width1280
canvas_height720
processing_multiple32
min_width512
min_height512
max_width2048
max_height2048
padding_strategycentered
extra_padding_width0
extra_padding_height0
target_width1280
target_height720
anchortop_left
x_offset0
y_offset0
background_r0
background_g0
background_b0
resize_algorithmbicubic
mask_expand0
mask_feather0

Every serious video model has opinions about resolution, and most of them aren't nice. LTX-2.3 wants width and height divisible by 32 - off-grid values hard-fail instead of rounding. Others have a min-resolution window below which they smear and a max above which they OOM. So when you're outpainting a clip or feeding frames into a video model, your composition size is almost never the size the model accepts, and the usual "fix" is a pile of hand-wired padding and crop nodes.

mAI Frame Canvas Recut exists so you don't do that arithmetic. It takes an IMAGE batch, recuts it onto a canvas you define, re-pads that canvas to a model-safe processing size, and hands you the exact crop box to undo the padding afterward. The name's a little fancy, but the two-canvas design is genuinely the right way to think about this problem.

How it works: two canvases, not one

Feed it frames (a batch from Load Video or a frame sequence). Three sizes are in play:

  1. Your source frames get resized to target_width × target_height. Note the README is explicit: there's no resize mode, it's always target-size logic, so keep the aspect ratio in mind or you'll get distortion.
  2. The content canvas (canvas_width × canvas_height) is where you actually want the video to live - your composition.
  3. The processing canvas is what the model sees: content canvas plus extra_padding_width/height if asked, floored at min_width/min_height, then rounded up to a multiple of processing_multiple (default 32 - the LTX-2.3 number). max_width/max_height act as a hard ceiling and can scale the whole composition down if your canvas exceeds them.

The frame gets positioned on the content canvas with anchor plus x_offset/y_offset, and everything not covered fills with your background_r/g/b (black by default). Fractional sizes round up so the node never undershoots the requested size - worth knowing, because your "720p" canvas can come out a bit larger.

The inputs that matter

You'll actually touch maybe five of these:

  • frames - your IMAGE batch. The only required connection.
  • canvas_width / canvas_height - your composition size.
  • processing_multiple - 32 for LTX-2.3; 1 effectively disables multiple alignment.
  • min_width / min_height - the model's floor resolution.
  • padding_strategy - where extra padding goes: centered, keep_anchor, or pinned to one corner. If you're outpainting one side only, this decides which edge your content sits on.

The rest (anchor, offsets, resize_algorithm, mask_expand/mask_feather) are fine to leave at defaults until you need them. mask_expand and mask_feather only affect the mask output, not the frames - a common first misread.

The outputs and the post-process loop

Beyond recut_frames (the batch on the processing canvas) and preview_first_frame (wire that straight into a Preview Image node), the star outputs are the metadata:

  • final_canvas_width/height - your exact requested size.
  • processing_canvas_width/height - what the model actually got.
  • crop_x/crop_y/crop_width/crop_height - the content box inside the processing canvas.

After generation, resize the model output to the processing size, crop with those values, then optionally resize to final_canvas_*. There's also extended_area_mask - white where the canvas is extended beyond the frame - which doubles as an outpainting mask if your model is mask-aware.

The frontend is the sleeper feature: the node draws a blue outline (content canvas) and white outline (frame) right on the node, and you can drag the image, drag handles to resize (Shift for free resize), and scroll to zoom - updating target_width/target_height live.

Install

No dependencies, no model downloads - it's pure PyTorch/PIL with no requirements.txt. Two ways:

  • ComfyUI Manager: search "ComfyUI-mAI-FrameCanvas" and install, then restart.
  • Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/mAI-mathieu/ComfyUI-mAI-FrameCanvas

Restart ComfyUI and hard-refresh the browser (Ctrl+Shift+R) so the JS frontend loads.

Where people get burned

  • Black bars you didn't ask for: default background is pure black, visible wherever your frame doesn't cover the canvas. Set background_r/g/b before judging the output.
  • The min/max trap: if your min_* and max_* contradict each other (say, min 1024 over a max of 512), the node just scales your composition down again rather than erroring. Set them to the model's real window and let processing_multiple do the work.
  • Output node quirks: it's marked as an output node and hides its default image previews in favor of the custom canvas - if the interactive overlay isn't showing, it's almost always the stale-browser problem, not the node.

This is a young, low-traffic pack, so expect it to move. But the two-canvas plus crop-metadata pattern is solid, and once you've used it for one LTX or outpainting workflow, you'll keep reaching for it.

CategorymAI/video

Inputs (22)

NameTypeDefaultDescription
framesIMAGE
canvas_widthINT12801–16384
canvas_heightINT7201–16384
processing_multipleINT321–2048
min_widthINT5121–16384
min_heightINT5121–16384
max_widthINT20481–16384
max_heightINT20481–16384
padding_strategyCOMBOcentered4 options: centered, keep_anchor, pad_right_bottom, pad_left_top
extra_padding_widthINT00–16384
extra_padding_heightINT00–16384
target_widthINT12801–16384
target_heightINT7201–16384
anchorCOMBOtop_left6 options: top_left, center, top_center, bottom_center, left_center, right_center
x_offsetINT0-16384–16384
y_offsetINT0-16384–16384
background_rINT00–255
background_gINT00–255
background_bINT00–255
resize_algorithmCOMBObicubic7 options: nearest, bilinear, bicubic, area, box, hamming, +1
mask_expandINT00–512
mask_featherINT00–512

Outputs (11)

NameTypeDescription
recut_framesIMAGE
preview_first_frameIMAGE
extended_area_maskMASK
final_canvas_widthINT
final_canvas_heightINT
processing_canvas_widthINT
processing_canvas_heightINT
crop_xINT
crop_yINT
crop_widthINT
crop_heightINT