# ComfyUI – Animated Mask Editor 🎨 A ComfyUI custom node for drawing **animated, keyframed masks** directly on your video / image batch β€” with a full-screen, Roto-style editor that launches right from the node. Draw circles, rectangles and bΓ©zier shapes, move them across frames to keyframe them automatically, and export a frame-accurate mask sequence for inpainting, effects, compositing or video editing. Shapes are **persistent**: they serialize into your workflow (and a disk backup), so your roto survives restarts and travels with the `.json`. --- ## ✨ Features - πŸ–ŒοΈ **Interactive editor** β€” Circle, Rectangle and BΓ©zier (free-form) shapes on a zoomable, pannable canvas overlaid on your real video frames. - 🎞️ **Automatic keyframing** β€” move/resize/rotate a shape on a different frame and a keyframe is created; values interpolate smoothly in between. - 🟦🟧 **Readable timeline** β€” position/size/rotation keyframes are **blue**, opacity-only keyframes are **orange**. - 🌫️ **Feathering & invert** β€” soft edges and one-click mask inversion. - πŸ’Ύ **Persistent masks** β€” stored in the workflow + a per-node disk backup, so nothing is lost on restart. - πŸ”Œ **Three outputs** β€” the mask sequence plus two ready-to-view preview overlays. --- ## 🧩 The Node ![Animated Mask Drawer node in ComfyUI](docs/screenshots/comfyui-node-v2.png) *Drop in the node, connect a video/image batch to **video**, and hit **🎨 Launch Mask Editor**. It outputs the `mask_sequence` plus two preview overlays.* --- ## πŸ–₯️ The Editor ![Animated Mask Editor interface](docs/screenshots/editor-interface.png) *The editor opens in its own window: tools on the left, your video frame with mask overlays in the center, and the keyframe timeline on the right. Scrub frames along the bottom; move a shape on a new frame and it keyframes automatically.* --- ## πŸ“¦ Installation Clone into your ComfyUI `custom_nodes` folder and restart ComfyUI: ```bash cd ComfyUI/custom_nodes git clone https://github.com/BISAM20/ComfyUI-AnimatedMaskEditor.git ``` **Dependencies:** `torch`, `numpy`, `Pillow` (already present in ComfyUI). `scipy` is optional β€” it's only used for feathering; without it, `feather` is a no-op. After restarting, the node appears under **Add Node β†’ mask β†’ animation β†’ `Animated Mask Drawer 🎨`**. --- ## πŸš€ Quick Start 1. **Add the node** `Animated Mask Drawer 🎨` and connect an `IMAGE` (a video / image batch) to its **video** input. 2. **Queue the prompt once.** This hands the frames to the node so the editor can display them. *(The editor will say "⚠️ No video loaded" until you've queued at least once.)* 3. **Click `🎨 Launch Mask Editor`** on the node. The editor opens in a new window. *(Allow pop-ups for ComfyUI if prompted.)* 4. **Draw your masks** (see below), scrubbing frames and moving shapes to animate them. 5. **Click `πŸ’Ύ Save & Return to ComfyUI`.** The shapes are saved back into the node. 6. **Queue the prompt again** to generate the final mask sequence. --- ## ✍️ Drawing & Animating | Tool | What it does | |------|--------------| | **Select / Move** | Select, drag, resize and rotate existing shapes. | | **Circle** | Click-drag to create a circular mask. | | **Rectangle** | Click-drag to create a rectangular mask. | | **BΓ©zier Path** | Click to add points, **Enter** to close the shape, **Esc** to cancel. | **To animate:** with **Auto-Keyframe** on, go to a new frame and move/resize/rotate a shape β€” a keyframe is created automatically and the motion interpolates between keyframes. Adjust **Opacity** on different frames to create fades (these show as **orange** keyframes). ### ⌨️ Shortcuts | Key | Action | |-----|--------| | **← / β†’** | Previous / next frame | | **Ctrl+Z** | Undo | | **Shift+Click** | Add to selection (multi-select) | | **Delete** | Delete selected shape / keyframe | | **Enter** | Finish bΓ©zier path | | **Esc** | Cancel current bΓ©zier | | Scroll wheel | Zoom Β· Middle-drag (or Shift+drag) | Pan Β· βŠ™ | Fit & center | --- ## πŸ”§ Node Reference ### Inputs | Input | Type | Default | Description | |-------|------|---------|-------------| | **video** | `IMAGE` | β€” | Input video / image batch to mask. *(required)* | | **width** | `INT` | `512` | Output mask width. Leave at `512` to auto-detect from the video. | | **height** | `INT` | `512` | Output mask height. Leave at `512` to auto-detect from the video. | | **feather** | `INT` | `0` | Gaussian blur radius for soft edges (β‰ˆ10–20 for smooth masks; needs `scipy`). | | **invert** | `BOOLEAN` | `False` | Swap masked / unmasked areas. | | **refresh** | `INT` | `0` | Increment to force mask regeneration. | | *mask_data* | `STRING` | β€” | Hidden β€” managed by the editor; stores your shapes/keyframes in the workflow. | ### Outputs | Output | Type | Description | |--------|------|-------------| | **mask_sequence** | `MASK` | The animated mask batch β€” feed to inpainting, effects, compositing. | | **mask_preview** | `IMAGE` | Your video with a **red** mask overlay β€” connect to *Preview Image* to check masks. | | **masked_video** | `IMAGE` | Your video with the mask burned in **white** (100% opacity). | --- ## πŸ’Ύ Persistence Your shapes and keyframes are stored in two places, so they're never lost: - **In the workflow** β€” via a hidden `mask_data` widget, so they survive restarts and travel with the saved `.json`. - **On disk** β€” a per-node backup under `roto_data/` next to the node (git-ignored, regenerated by the editor). --- ## 🩹 Troubleshooting - **"⚠️ No video loaded" in the editor** β†’ queue the workflow once first so the frames reach the node. - **Editor window doesn't open** β†’ allow pop-ups for the ComfyUI site. - **Masks didn't update** β†’ bump the **refresh** input, or re-queue after saving in the editor. - **`feather` has no effect** β†’ install `scipy` (`pip install scipy`). --- ## πŸ“„ License Released under the MIT License. See [`LICENSE`](LICENSE) if present, otherwise treat as MIT.