Nodes/Simple Video Effects/Zoom Sequence (Video File, Direction + Amount Type)
ComfyUI Node

Zoom Sequence (Video File, Direction + Amount Type)

Ken Burns zoom on a video file, audio intact

By scofano·Created 10 months ago·Updated 20 days ago· 0
Zoom Sequence (Video File, Direction + Amount Type)
    • output_path
    video_path
    directionZoom In
    amount_typePixels per Frame
    pixels_per_frame1.0
    zoom_percentage110
    easeLinear
    random_seed0
    smooth_subpixeltrue
    prefixzoom_sequence

    A slow zoom is the cheapest way to make a static-looking video feel alive. Zoom Sequence (Video File, Direction + Amount Type) - class ZoomSequenceVideoNode - applies exactly that: a smooth zoom in or out across a video file, keeping the canvas size and aspect ratio, and hands you back a new MP4 with the original audio still attached. It's the file-based sibling of the pack's tensor ZoomSequenceNode, and for most people the more practical one, because it starts from a video path and ends at a video path.

    It's part of scofano's Simple Video Effects pack, alongside the camera-move and camera-shake video nodes. They share a design: probe the file, extract frames, transform them in PyTorch, re-encode, copy the audio. This one is the Ken Burns / dolly-zoom workhorse of the set.

    How it works

    The mechanism is honest about what it's doing. It probes the video for duration, FPS and resolution, extracts every frame to temporary PNG files at the source frame rate, loads them as a (B, H, W, C) tensor, and runs the same zoom math as the image version: per-frame eased progress converted into a margin, cropped proportionally on both axes to keep aspect ratio, then resized back to the original canvas.

    Two sampling modes matter here. With smooth_subpixel on (the default), margins become continuous zoom factors applied with grid_sample - smoother for slow, long zooms. With it off, you get classic integer crop-and-resize: faster, marginally less smooth. For most footage the subpixel default is the right call.

    Then it saves the processed frames and re-encodes with libx264 at the original FPS, copying the audio stream across losslessly. Output lands in the same folder as the source as zoom_sequence_001.mp4, incrementing if that name is taken.

    The inputs that matter

    • direction - Zoom In, Zoom Out, or Random.
    • amount_type - this is the one that confuses people. Pixels per Frame means a fixed zoom speed, so a long video can over-zoom (the node clamps at a safe margin). Target Percentage means "reach 110% zoom by the end of the clip," which scales to any length. If you don't know the clip duration, Target Percentage is usually the safer choice.
    • pixels_per_frame (default 1.0) and zoom_percentage (default 110, range 100–10000) - the values those two modes consume.
    • ease - Linear, Ease_In, Ease_Out, Ease_In_Out, or Random. Ease-Out (fast start, slow landing) is the classic film-look zoom.
    • random_seed - only matters if direction or ease is Random. 0 means auto-random, and the node deliberately busts ComfyUI's cache so you get a fresh roll every run; a positive seed makes it reproducible.
    • prefix - output filename prefix, default zoom_sequence.

    The output is output_path, a STRING with the absolute path to the new video.

    Installing it

    No models, no special setup beyond the pack itself:

    cd ComfyUI/custom_nodes
    git clone https://github.com/scofano/ComfyUI-Simple-video-effects
    pip install -r requirements.txt
    

    Restart ComfyUI, or search "Simple Video Effects" in ComfyUI Manager. Dependencies are ffmpeg-python, soundfile, numpy, Pillow and torch.

    Where people get burned

    This node extracts every frame as a PNG to disk, transforms them, then re-encodes. For a 30-second 1080p clip that's ~900 frames of temp files and a real chunk of time. It's fine for shorts; don't point it at an hour-long video and expect speed. And since it re-encodes the whole thing, you're taking one generation hit - keep the source file around.

    Second, ffmpeg must be on your PATH or the node refuses to load at all (it checks for both ffmpeg and ffprobe at import). This is the pack's recurring gotcha: the ffmpeg-python pip package is just bindings, not the binary.

    Third, the two amount modes have very different failure signatures. In Pixels-per-Frame mode a long clip just hits the safe-margin clamp and you get a zoom that stops early - which reads as a bug if you don't know it's the safety limit. In Target-Percentage mode a percentage below 100 or a silly-high one can produce an unexpectedly fast or trivially slow zoom. If the motion looks off, check which mode you're in before tweaking ease.

    One light aside: if you have a clip with dialogue, this is a nice final step precisely because it copies the audio untouched - a fade-to-zoom on the outro frame is a cheap way to make a render feel finished.

    CategorySimple Video Effects/Video Processing

    Inputs (9)

    NameTypeDefaultDescription
    video_pathSTRING
    directionCOMBOZoom In3 options: Zoom In, Zoom Out, Random
    amount_typeCOMBOPixels per Frame2 options: Pixels per Frame, Target Percentage
    pixels_per_frameFLOAT1.0
    zoom_percentageINT110100–10000
    easeCOMBOLinear5 options: Linear, Ease_In, Ease_Out, Ease_In_Out, Random
    random_seedINT00–2147483647
    smooth_subpixelBOOLEANtrue
    prefixSTRINGzoom_sequence

    Outputs (1)

    NameTypeDescription
    output_pathSTRING