Nodes/ComfyUI-FFmpeg-Video/Video Resize (FFmpeg)
ComfyUI Node

Video Resize (FFmpeg)

Resize a Clip Without Loading Its Frames

By bbaudio-2025·Created about a month ago·Updated 4 days ago· 2
Video Resize (FFmpeg)
  • video
  • video
width512
height512
upscale_methodlanczos
keep_proportionresize
pad_color0, 0, 0
crop_positioncenter
divisible_by2

The memory tax this node avoids

Resizing a video the normal ComfyUI way is expensive before it's even useful. The standard path - VHS Load Video → an IMAGE batch of every frame → a resize node → re-encode - turns your clip into a tensor first. Ten seconds of 1080p at 30fps is 300 float32 RGB frames, north of 7 GB of RAM, before a model has even loaded. If all you wanted was a smaller clip, that's a stupid way to spend it.

Video Resize (FFmpeg) is the other door. It takes a VIDEO object, hands the whole thing to FFmpeg, and gives you back a VIDEO. No frames become tensors. Memory use stays flat whether you feed it a 3-second 480p test or a 4K minute, which is why it belongs at the front of a pipeline: normalizing a clip before a Wan or LTX run, shrinking an upload before a face-swap workflow, or putting a clip on a fixed canvas before an upscaler touches it. It works on the file, not on decoded frames - that's the whole trick.

It ships in ComfyUI-FFmpeg-Video, a five-node utility belt from bbaudio (u/bbaudio2024), who also built the VACE long-video and VACE video-upscale nodes that got real traction on r/comfyui. That's the reputation; this is the plainer job. The README is disarmingly honest that it was vibe-coded by GLM and says to debug problems by asking an AI - useful, but not a hardened pipeline component.

How it works

Three stages, all FFmpeg.

It resolves the VIDEO input down to a real file on disk - ComfyUI's v3 API exposes the underlying stream source, so nothing round-trips through memory - then FFprobes width, height and pixel aspect ratio. It also honours lazy trim windows: nodes like Crop Video (Temporal) don't rewrite the file, they just record an offset, so this node seeks to that start at the input and re-applies the duration on output. Skip that and a temporal crop would silently vanish.

Next it builds a filter chain from your keep_proportion choice - scale, crop, pad, overlay, plus split/gblur/lutyuv for the fancy border modes. Same vocabulary as KJNodes' ImageResizeKJv2, deliberately. Then it encodes: libx264, preset medium, CRF 18, yuv420p, audio stream-copied untouched with an AAC retry if the source codec won't fit an MP4. The escape hatch is the interesting part - if the requested size equals the source and no crop or pad is needed, it remuxes with -c:v copy: no re-encode, no quality loss, near-instant.

Inputs you actually set

width and height are the whole conversation. Default 512×512, and 0 means "keep the source dimension." In the aspect-preserving modes they're a bounding box, not a destination.

keep_proportion decides what happens when the box doesn't match the clip:

  • resize (default) - fit inside the box, aspect kept.
  • stretch - force the exact size; aspect ignored.
  • crop - cut to the box's aspect ratio, then scale; crop_position picks which side.
  • total_pixels - scale so w*h equals width*height, aspect kept.
  • pad - fit, then letterbox with pad_color ("0, 0, 0", "#ff8800", a colour name).
  • pad_edge / pad_edge_pixel - as pad, but the border comes from the frame's own edges: mean edge colour, or replicated edge pixels. crop_position also aligns the image inside the padding.
  • pillarbox_blur - the vertical-video look: fill the sides with a blurred, dimmed cover frame.

upscale_method defaults to lanczos - plain interpolation, which the KB's upscaling notes is still correct when you want more pixels and nothing invented for you. area is the pick when you're shrinking; nearest-exact maps to FFmpeg's neighbor, so pixel-art and masks only.

divisible_by (default 2) rounds dimensions down, because yuv420p needs even numbers. Bump it to 8/16/32 only if a downstream model demands it.

Output is a single video (VIDEO). Wire it into Save Video, another node from this pack, or anything that accepts a VIDEO socket.

Install

ComfyUI Manager, search the pack title - it publishes to the Comfy registry automatically. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/bbaudio-2025/ComfyUI-FFmpeg-Video
pip install -r ComfyUI-FFmpeg-Video/requirements.txt
ffmpeg -version   # must print a build

The Python dependency is ffmpeg-python, a thin wrapper - the ffmpeg binary itself must be on PATH, and the node checks for it every run. ffprobe ships in the same build. On Windows, winget install Gyan.FFmpeg, then restart ComfyUI so the new PATH is picked up.

Where it bites

"FFmpeg binary is not installed or not found in PATH" is the number one error, and it's never the pip package. Launch ComfyUI from a shell where ffmpeg -version works.

PyAV, quietly. requirements.txt lists only ffmpeg-python, but the in-memory fallback path needs av and raises PyAV is not installed without it. ComfyUI core usually ships it, so few people hit this.

Re-encode drift compounds. Every geometry change re-encodes at CRF 18, and the community's long-running complaint about video round-trips through ComfyUI is exactly this drift. Resize once, early.

Old cores. This needs the VIDEO type and comfy_api.latest, both 2025-era ComfyUI. Older builds get a plain file path back instead, which won't type-match the next VIDEO input. Update ComfyUI first.

CategoryFFmpeg Video

Inputs (8)

NameTypeDefaultDescription
videoVIDEOThe video to resize.
widthINT5120–16384Target width in pixels (0 = keep the source width). For the aspect-preserving modes this is a bounding box.
heightINT5120–16384Target height in pixels (0 = keep the source height). For the aspect-preserving modes this is a bounding box.
upscale_methodCOMBOlanczosScaling interpolation — mapped to the FFmpeg scale filter: nearest-exact -> neighbor, bilinear, area, bicubic, lanczos.
keep_proportionCOMBOresizestretch: force width x height, aspect ratio ignored. resize: scale to fit inside width x height, aspect kept. crop: crop to the width/height aspect ratio (crop_position), then scale. total_pixels: scale so that w*h == width*height, aspect kept. pad: fit + pad with pad_color. pad_edge: fit + pad, border = mean colour of each edge line. pad_edge_pixel: fit + pad, border = nearest edge pixels. pillarbox_blur: fit + pad, border = blurred/dimmed cover frame.
pad_colorSTRING0, 0, 0Padding colour for the 'pad' mode: '0, 0, 0' (0-255), '0.0, 0.0, 0.0' (0-1), a colour name or '#rrggbb'.
crop_positionCOMBOcenterWhere to crop from, and where to align the image inside the padded area.
divisible_byINT20–512Width/height are rounded down to a multiple of this value. yuv420p needs even dimensions, so values below 2 are treated as 2.

Outputs (1)

NameTypeDescription
videoVIDEO