ComfyUI Extension: Simple Video Effects

Authored by scofano

Created

Updated

0 stars

Nodes for Video effects. Zoom In/Out - new features soon.

Custom Nodes (0)

    README

    ComfyUI Simple Video Effects

    A collection of lightweight, production-ready video manipulation nodes for ComfyUI. All nodes operate on batched IMAGE tensors (B, H, W, C) and are designed for smooth, high-quality transformations without breaking aspect ratio.

    This bundle includes:

    1. Zoom Sequence – per-batch zoom in/out with easing
    2. Batched Zoom Sequence – persistent zoom across multiple batches
    3. Camera Move – pan/slide across the frame
    4. Camera Shake – procedural handheld/chaotic motion
    5. Video Overlay – alpha-blend / composite one video over another
    6. Image Transition – create transition videos between two images
    7. Video Splitter (ASS Subtitles) – split videos based on subtitle punctuation
    8. Camera Move (Video File) – apply camera movement to video files with audio preservation
    9. Camera Shake (Video File) – apply camera shake effects to video files with audio preservation
    10. Zoom Sequence (Video File) – apply zoom effects to video files with audio preservation
    11. Close Up (Face Centered) – face-centered zoom using eye detection from SEGS

    📦 Installation

    Place all .py files into:

    ComfyUI/custom_nodes/ComfyUI_SimpleVideoEffects/
    

    Restart ComfyUI.


    🎥 1. ZoomSequenceNode

    Single-batch smooth zoom-in/out with aspect-correct cropping Source: comfy_zoom_sequence.py

    What it does

    Creates a smooth zoom-in or zoom-out animation across a batch of frames while maintaining the original canvas size and aspect ratio.

    Key Features

    • Zoom in or out across the batch
    • Progressive zoom per frame
    • Choose from: Linear, Ease-In, Ease-Out, Ease-In-Out
    • Automatic aspect-correct cropping
    • Prevents over-zooming using safe margin clamp

    Inputs

    | Name | Type | Description | | ------------------ | ----------------------------------------- | --------------------------------------------- | | images | IMAGE | Batched frames | | mode | Zoom In / Zoom Out | | | pixels_per_frame | FLOAT | Zoom speed, based on smaller canvas dimension | | ease | Linear / Ease_In / Ease_Out / Ease_In_Out | |

    Outputs

    • images – transformed frames
    • info – diagnostics, safe-limit notes, applied margins

    How it works

    The node computes a per-frame eased progress value, converts it into a small-dimension margin, and crops proportionally on both axes to retain aspect ratio before resizing back to original resolution. All cropping is done with integer-accurate bounds.


    🎥 2. ZoomSequenceNode (Batched / Persistent)

    Persistent zoom across multiple batches Source: comfy_zoom_sequence_batched.py

    What it does

    Extends ZoomSequence to support streamed / chunked video processing. Zoom state is stored in a temporary JSON file and automatically resumes between node calls.

    Key Features

    • Continues zoom from previous batch
    • Automatically clears state when end-of-video is reached
    • Fully aspect-correct
    • Same easing options and zoom behavior as single-batch version

    Inputs

    | Name | Type | Description | | -------------------- | ----------- | ------------------------------------- | | images | IMAGE | Batch of frames | | source_frame_count | INT | Total number of frames in whole video | | mode | Zoom In/Out | | | pixels_per_frame | FLOAT | Zoom speed | | ease | Easing mode | |

    How it works

    The node tracks:

    • Last processed global frame index
    • Max zoom margin
    • Canvas dimensions
    • Easing + mode consistency

    State resets when the node reaches frame source_frame_count - 1.


    🎥 3. CameraMoveNode

    Smooth pan / slide / 2D translation Source: comfy_camera_move.py

    What it does

    Moves the camera viewport across the frame in X/Y over the batch, creating a pan or tracking-shot effect.

    Typical Controls

    • move_x_start, move_x_end
    • move_y_start, move_y_end
    • ease
    • clamp_edges
    • pixels_per_frame or percentage-based movement

    Output

    • Frames translated with border fill (usually black or edge-clamped)
    • Handy for synthetic dolly, parallax, or motion-graphics effects

    🎥 4. CameraShakeNode

    Procedural handheld shake Source: comfy_camera_shake.py

    What it does

    Adds natural-feeling camera shake using Perlin/random noise.

    Features

    • Adjustable shake amplitude
    • Frequency control
    • Random seed for reproducibility
    • Optional motion-blur-friendly smoothness

    Great for action shots, handheld look, or simulating vibrations.


    🎥 5. VideoOverlayNode

    Composite one video onto another Source: comfy_video_overlay.py

    What it does

    Alpha-blends a foreground video onto a background video.

    Features

    • Supports per-pixel alpha channel
    • Automatic batch alignment
    • Position + scale controls
    • Optional auto-fit

    🎥 6. ImageTransitionNode

    Create smooth transition videos between two images Source: comfy_image_transition.py

    What it does

    Generates an MP4 video that transitions from one image to another using a mask-based reveal effect, with optional line visualization.

    Key Features

    • Horizontal or vertical reveal direction
    • Adjustable duration in seconds
    • Optional visible line at the reveal edge with customizable thickness and color
    • Automatic filename generation with prefix + "_001.mp4"
    • Saves to ComfyUI's default output directory

    Inputs

    | Name | Type | Description | | ------------ | ------------- | ------------------------------------ | | image1 | IMAGE | Bottom layer image | | image2 | IMAGE | Top layer image (revealed) | | duration | FLOAT | Transition duration in seconds | | direction | Select | Reveal direction: Vertical-Down, Vertical-Up, Horizontal-Left, Horizontal-Right | | line_toggle| BOOLEAN | Enable/disable visible line | | thickness | INT | Line thickness in pixels | | hex_color | STRING | Line color as hex (e.g., #FFFFFF) | | prefix | STRING | Filename prefix |

    Outputs

    • output_path – Full path to the generated MP4 file

    How it works

    The node creates a frame-by-frame animation where image2 is gradually revealed over image1 using a dynamic mask. If enabled, a colored line marks the current reveal position. Frames are encoded into an MP4 video using ffmpeg at 24 FPS.


    🎥 7. Comfy Video Combiner

    This script provides a ComfyUI-compatible node for automatically combining multiple video files from a directory into a single edited output. It offers robust handling of transitions, fades, audio overlays, randomization, and resolution normalization—all wrapped in an easy-to-use, configurable ComfyUI node.

    Inspired by: DarioFT / ComfyUI-VideoDirCombiner


    ✨ Features

    🔍 Directory Scanning & File Control

    • Scans a target directory for video files matching a pattern (e.g., *.mp4).
    • Supports alphabetical sorting.
    • Supports randomized order with optional seed.
    • Guarantees no repeated clips.

    🎬 Video Transitions & Fades

    • Optional crossfade transitions between clips.
    • Optional fade-in from a solid color.
    • Optional fade-out to a solid color.
    • All fade colors sanitized to #RRGGBB.

    🔊 Audio Integration (VideoHelperSuite)

    • Accepts VHS/ComfyUI audio format input.

    • Supports both:

      • Direct audio file paths, or
      • Waveform + sample rate tensors (auto-converted to WAV).
    • Optional trimming of final video to match audio duration.

    • Final fade-out will automatically adjust to audio length if needed.

    ⚙️ Resolution & FPS Normalization

    • Detects the first video’s:

      • width
      • height
      • FPS
    • Normalizes all clips (and color fades) to match it, ensuring alignment and avoiding FPS-related errors.

    🚀 Performance

    • Uses parallel duration probing (ThreadPoolExecutor).
    • Uses optimized ffmpeg filter-graphs for transitions.
    • Automatic cleanup of temporary files.

    🧪 Safety & Robustness

    • Unique output filenames (avoids overwriting).

    • Detailed validation and error messages.

    • Proper handling of edge cases like:

      • Clips shorter than transition duration
      • Invalid hex color input
      • Missing or malformed audio dicts

    🛠️ Inputs

    Required Inputs

    | Name | Type | Description | | --------------------- | ------ | --------------------------------- | | directory_path | String | Folder containing video files | | output_filename | String | Name of final output file | | file_pattern | String | File glob pattern (e.g., *.mp4) | | transition | Select | none or fade between clips | | transition_duration | Float | Fade duration between clips |

    Optional Inputs

    | Name | Type | Purpose | | ------------------- | ------- | ------------------------------ | | sort_files | Boolean | Sort clips alphabetically | | random_order | Boolean | Shuffle order (overrides sort) | | seed | Int | Seeded randomization | | music_track | AUDIO | VideoHelperSuite audio object | | trim_to_audio | Boolean | End video when audio ends | | fade_in_enabled | Bool | Prepend a color fade-in | | fade_in_color | String | Hex color | | fade_in_duration | Float | Fade-in length | | fade_out_enabled | Bool | Append/force fade-out | | fade_out_color | String | Hex color | | fade_out_duration | Float | Fade-out length |


    📤 Output

    The node returns a single string: output_path → Full path to the generated video file.


    🧩 How It Works Internally

    1. Load & Order Files

    Uses glob pattern matching and optional sorting/shuffling.

    2. Extract Video Metadata

    Parallel ffprobe calls retrieve durations and video stream info.

    3. Build FFmpeg Filtergraph

    Depending on settings:

    • Simple concatenation OR

    • Complex graph with:

      • normalized FPS
      • color clip generation
      • chained xfade transitions
      • final fade-out tied to audio
      • overlaying custom audio

    4. Render via FFmpeg

    Quiet ffmpeg execution ensures efficient rendering.

    5. Cleanup

    Temporary files (WAV audio, concat lists) are deleted automatically.


    📝 Notes

    • If audio trimming is enabled, the script ensures fade-outs occur before the audio ends.
    • Fades and transitions never exceed clip lengths; they are automatically clamped.
    • Color fade-ins and fade-outs use ffmpeg's color source generator.

    🎥 8. Video Splitter (ASS Subtitles)

    Split videos based on punctuation marks in ASS subtitle files Source: comfy_video_splitter.py

    What it does

    Automatically splits a video into segments based on punctuation marks (., !, ?) found at the end of dialogue lines in ASS subtitle files. Each segment is saved as a separate MP4 file in a timestamped output folder.

    Key Features

    • Parses ASS subtitle files to extract dialogue timings and text
    • Splits video at the end times of dialogues ending with specified divider characters
    • Ensures minimum segment duration to avoid very short clips
    • Adds configurable padding to segment ends (except the last segment)
    • Maintains 1-frame gaps between segments for clean transitions
    • Re-encodes segments for precise cutting and audio synchronization
    • Automatic folder creation with incremental naming to avoid overwrites

    Inputs

    | Name | Type | Description | | --------------------- | ------ | ------------------------------------------------ | | video_path | STRING | Full path to the input video file | | ass_path | STRING | Full path to the ASS subtitle file | | divider_chars | STRING | Characters to split on (default: ".!?") | | folder_prefix | STRING | Prefix for output folder name | | min_audio_duration | INT | Minimum segment duration in seconds (default: 5) | | end_padding | FLOAT | Seconds to add to end of each segment (default: 0.2) |

    Outputs

    • output_folder – Full path to the folder containing split video segments

    How it works

    1. Parses the ASS file to find dialogues ending with divider characters
    2. Filters split points to ensure each segment meets the minimum duration
    3. Splits the video using ffmpeg with precise start/end times
    4. Adds padding to segment ends while maintaining frame-accurate gaps
    5. Saves segments as original_filename_[000].mp4, [001].mp4, etc.

    Special Handling

    • Treats "…" (ellipsis) as "." for splitting
    • Ignores sequences like ".." or "..." as invalid dividers
    • Cleans ASS formatting tags from subtitle text
    • Ensures no segments are shorter than the minimum duration by combining when necessary

    🎥 9. Camera Move (Video File)

    Apply camera movement effects to video files with audio preservation Source: comfy_camera_move_video.py

    What it does

    Takes a video file path and applies the same camera movement effects as the image-based Camera Move node, then outputs a new video file with the original audio intact (if present).

    Key Features

    • All camera movement options from the image version (pan, slide, diagonal)
    • Extracts frames from input video at original FPS
    • Applies movement effects using the same algorithm
    • Re-encodes frames back to video while preserving audio stream
    • Automatic output filename generation with incrementing numbers
    • Supports random direction selection with proper cache invalidation

    Inputs

    | Name | Type | Description | | --------------------- | ------ | ------------------------------------------------ | | video_path | STRING | Full path to the input video file | | horizontal_direction| Select | None, Left, Right, Random | | vertical_direction | Select | None, Top, Bottom, Random | | distance_px | FLOAT | Camera travel distance in pixels (default: 100.0)| | ease | Select | Linear, Ease_In, Ease_Out, Ease_In_Out | | prefix | STRING | Output filename prefix (default: "camera_move") |

    Outputs

    • output_path – Full path to the processed video file

    How it works

    1. Extracts video metadata (duration, FPS, resolution) using ffprobe
    2. Extracts all frames from the video using ffmpeg
    3. Applies camera movement transformations to the frame sequence
    4. Saves processed frames as temporary PNG files
    5. Re-encodes frames to video at original FPS with H.264 codec
    6. Copies original audio stream (if present) into the final video
    7. Cleans up temporary frame files automatically

    Movement Directions

    Supports the same movement options as the image Camera Move node:

    • Horizontal: Left (right-to-left pan), Right (left-to-right pan)
    • Vertical: Top (bottom-to-top pan), Bottom (top-to-bottom pan)
    • Combined: Diagonal movement by selecting both horizontal and vertical directions
    • Random: Randomly chooses direction each execution

    Audio Handling

    • Automatically detects and preserves audio streams from the original video
    • Uses ffmpeg stream copying for lossless audio preservation
    • Works with any audio codec supported by the input video

    🎥 10. Camera Shake (Video File)

    Apply camera shake effects to video files with audio preservation Source: comfy_camera_shake_video.py

    What it does

    Takes a video file path and applies procedural camera shake effects (circular or random patterns), then outputs a new video file with the original audio intact (if present).

    Key Features

    • All camera shake options from the image version (circular/random modes, intensity, easing)
    • Extracts frames from input video at original FPS
    • Applies shake effects using the same algorithm with safe cropping
    • Re-encodes frames back to video while preserving audio stream
    • Automatic output filename generation with incrementing numbers
    • Supports configurable shake radius and easing envelopes

    Inputs

    | Name | Type | Description | | ----------------- | ------ | -------------------------------------------------- | | video_path | STRING | Full path to the input video file | | mode | Select | Circular Shake, Random Shake | | pixels_per_frame| FLOAT | Shake radius on smaller dimension (default: 5.0) | | ease | Select | Linear, Ease_In, Ease_Out, Ease_In_Out | | prefix | STRING | Output filename prefix (default: "camera_shake") |

    Outputs

    • output_path – Full path to the processed video file

    How it works

    1. Extracts video metadata (duration, FPS, resolution) using ffprobe
    2. Extracts all frames from the video using ffmpeg
    3. Applies camera shake transformations using aspect-corrected cropping
    4. Saves processed frames as temporary PNG files
    5. Re-encodes frames to video at original FPS with H.264 codec
    6. Copies original audio stream (if present) into the final video
    7. Cleans up temporary frame files automatically

    Shake Modes

    Supports the same shake patterns as the image Camera Shake node:

    • Circular Shake: Smooth sinusoidal circular motion with configurable cycles
    • Random Shake: Constant-magnitude random directional steps (±1 pixel steps)

    Shake Control

    • Radius: Controls maximum shake displacement based on smaller canvas dimension
    • Easing: Applies envelope over time (0..1) to modulate shake intensity
    • Safe Cropping: Uses aspect-corrected margins to prevent black borders during shake

    Audio Handling

    • Automatically detects and preserves audio streams from the original video
    • Uses ffmpeg stream copying for lossless audio preservation
    • Works with any audio codec supported by the input video

    🎥 11. Zoom Sequence (Video File)

    Apply zoom effects to video files with audio preservation Source: comfy_zoom_sequence_video.py

    What it does

    Takes a video file path and applies smooth zoom in/out effects with aspect correction, then outputs a new video file with the original audio intact (if present).

    Key Features

    • All zoom options from the image version (zoom in/out, easing, speed control)
    • Extracts frames from input video at original FPS
    • Applies zoom effects using aspect-corrected cropping
    • Re-encodes frames back to video while preserving audio stream
    • Automatic output filename generation with incrementing numbers
    • Supports configurable zoom speed and easing functions

    Inputs

    | Name | Type | Description | | ----------------- | ------ | -------------------------------------------------- | | video_path | STRING | Full path to the input video file | | mode | Select | Zoom In, Zoom Out | | pixels_per_frame| FLOAT | Zoom speed per frame (default: 1.0) | | ease | Select | Linear, Ease_In, Ease_Out, Ease_In_Out | | prefix | STRING | Output filename prefix (default: "zoom_sequence") |

    Outputs

    • output_path – Full path to the processed video file

    How it works

    1. Extracts video metadata (duration, FPS, resolution) using ffprobe
    2. Extracts all frames from the video using ffmpeg
    3. Applies zoom transformations using aspect-corrected cropping
    4. Saves processed frames as temporary PNG files
    5. Re-encodes frames to video at original FPS with H.264 codec
    6. Copies original audio stream (if present) into the final video
    7. Cleans up temporary frame files automatically

    Zoom Modes

    • Zoom In: Progressively zooms in from the original view to a cropped detail
    • Zoom Out: Progressively zooms out from a cropped detail to the full view

    Zoom Control

    • Speed: Controls zoom progression rate per frame
    • Easing: Applies smooth acceleration/deceleration to zoom movement
    • Aspect Correction: Maintains proper aspect ratio during zoom transitions
    • Safe Limits: Prevents over-zooming beyond canvas boundaries

    Audio Handling

    • Automatically detects and preserves audio streams from the original video
    • Uses ffmpeg stream copying for lossless audio preservation
    • Works with any audio codec supported by the input video

    🎥 12. Close Up (Face Centered)

    Face-centered zoom using eye detection from SEGS data Source: comfy_close_up.py

    What it does

    Takes a video file and SEGS segmentation data to detect eyes, calculates the center point between them (face center), and applies a zoom effect centered on that point. Outputs a new video with preserved audio.

    Key Features

    • Processes SEGS data to find eye detections with confidence > 0.4
    • Calculates face center as midpoint between detected eye positions
    • Applies zoom factor centered on the calculated face center
    • Maintains aspect ratio and prevents over-zooming
    • Preserves original audio streams
    • Automatic output filename generation with incrementing numbers

    Requirements

    This node requires a specific workflow setup to generate the SEGS data for eye detection:

    1. Download the eye segmentation model: Download PitEyeDetailer-v2-seg.pt from the Ultralytics models or compatible sources
    2. Use the provided workflow: The node requires SEGS data generated from video frames using segmentation detection

    Example Workflow Setup:

    Video Path String → VHS_LoadVideoPath → SegmDetectorSEGS → CloseUpNode
                              ↓
    UltralyticsDetectorProvider (with PitEyeDetailer-v2-seg.pt)
    

    The workflow uses:

    • UltralyticsDetectorProvider: Load the segm/PitEyeDetailer-v2-seg.pt model
    • VHS_LoadVideoPath: Load video frames (set frame_load_cap to 1 for single frame detection)
    • SegmDetectorSEGS: Generate SEGS data from eye segmentation on the video frame
    • CloseUpNode: Process the video with face-centered zoom

    Inputs

    | Name | Type | Description | | --------------| ------ | ------------------------------------------------ | | video_path | STRING | Full path to the input video file | | segs | SEGS | Segmentation data containing eye detections | | zoom_factor | FLOAT | Zoom multiplier (default: 1.5, min: 1.0) | | prefix | STRING | Output filename prefix (default: "close_up") |

    Outputs

    • output_path – Full path to the processed video file

    How it works

    1. Extracts video metadata (duration, FPS, resolution) using ffprobe
    2. Extracts all frames from the video using ffmpeg
    3. Processes SEGS data to find valid eye detections (label='eye', confidence > 0.4)
    4. Calculates face center as midpoint between the first two detected eye centers
    5. Applies zoom by cropping centered on the face center and resizing back to original dimensions
    6. Saves processed frames as temporary PNG files
    7. Re-encodes frames to video at original FPS with H.264 codec
    8. Copies original audio stream (if present) into the final video
    9. Cleans up temporary frame files automatically

    Eye Detection

    • Filters SEGS for segments with label 'eye' and confidence > 0.4
    • Requires at least 2 valid eye detections
    • Calculates eye centers from bounding box coordinates: (x1+x2)/2, (y1+y2)/2
    • Face center = midpoint between eye centers

    Zoom Implementation

    • Crop region is calculated as original_size / zoom_factor
    • Crop is centered on the calculated face center point
    • Clamped to prevent going outside video boundaries
    • Resized back to original dimensions using bicubic interpolation

    Audio Handling

    • Automatically detects and preserves audio streams from the original video
    • Uses ffmpeg stream copying for lossless audio preservation
    • Works with any audio codec supported by the input video

    🧪 Troubleshooting

    “Clamped margin” warnings

    Zoom margin exceeded safe limit; node automatically prevents invalid cropping.

    Zoom looks too slow

    Increase pixels_per_frame.

    Zoom resets unexpectedly

    Ensure:

    • Same canvas size
    • Same parameters
    • Same source_frame_count
    • Same mode & ease between batches.

    Overlay misaligned

    Make sure both videos have identical batch length or use a repeater.


    📄 License

    MIT