ComfyUI Bruxos do VFX
https://github.com/NyckM/Bruxos-do-VFX-Nodes/tree/main
Custom nodes for video VFX with Wan 2.2 / Bernini: object and people removal, batch upscaling, face swap, A/B comparison, and production-ready utilities — all designed for real-world VFX workflows.
<img width="832" height="480" alt="Workflow for object and people removal" src="https://github.com/user-attachments/assets/6745a8ce-00ce-4915-a60d-ed1354099311" />
Why this exists
Developed at Bruxos do VFX during the production of two feature films — Dr. Monstro (Marcos Jorge) and Alice Júnior 2 (Gil Baroni). The complexity of compositing and scene integration created the need for a dedicated object-removal workflow built on top of Bernini/Wan.
Current performance averages 96 frames in 204 seconds.
https://github.com/user-attachments/assets/1575f97f-34b9-492a-accb-818e97a6cbde
https://github.com/user-attachments/assets/d1e47486-ac3b-4030-be42-56a0f16b0128
Installation
Easy (recommended)
Run the included .bat installer from your ComfyUI installation folder. It will automatically install the node pack and download all required models.
(RunPod version is still under development.)
Manual
Copy the package into:
ComfyUI/custom_nodes/ComfyUI-Bruxos-do-VFXRestart ComfyUI.
Required Models
ModelDownloadDestinationUNET GGUF (high/low)https://huggingface.co/neuregex/Bernini-R-GGUF/tree/mainComfyUI/models/unetDistill LoRA (4 steps)https://huggingface.co/Cyph3r/lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16ComfyUI/models/lorasText Encoder (umt5)https://huggingface.co/Osrivers/umt5_xxl_fp8_e4m3fn_scaled.safetensorsComfyUI/models/text_encodersVAEhttps://huggingface.co/Kijai/WanVideo_comfy/blob/main/Wan2_1_VAE_bf16.safetensorsComfyUI/models/vae
Important: Download the models using the Hugging Face CLI or a download manager. Browser downloads may produce incomplete or corrupted files.
Nodes
<img width="226" height="557" alt="Bernini Long Condition" src="https://github.com/user-attachments/assets/934fd9b3-087f-47db-aeb2-6ca01967c556" />
Bernini / Generation
Bernini Infinity — Main renderer for videos longer than the standard 81-frame limit without requiring a custom sampler. It injects
context_latentsper chunk (with optionaltail_memory) instead of relying on a single conditioning, taking advantage of Bernini/Wan's native architecture.Bernini Region Mask — Converts colored masks (SAM2/SAM3/Scail2Color) into black-and-white masks with invert, grow, and blur controls.
Bernini Long (Conditioning / ChunkSelect / VideoMerge / AppendVideoChunk / EmptyVideoChunks / Info) — Helper nodes for long video generation.
FaceStitchUpscale — Blends the upscaled face back into the video using the
face_bboxesgenerated by Pose and Face Detection.SAM3 Point Editor — Green click = positive point, purple click = negative point directly on the frame, providing much more stable tracking than text prompts alone.
Video
Load Video / Save Video — Native VIDEO (ComfyUI 2.0) equivalents to Video Helper Suite, including preview trimming (skip, cap, nth frame, force rate) and extended export controls for codec and CRF.
Compare Videos A/B — Built-in comparison player with wipe, side-by-side, difference, and toggle modes, allowing before/after inspection without leaving ComfyUI.
Mask BBox Preview — Displays the bounding box that
bboxmode would crop before rendering.
Upscaling
Upscale Config / Batch Blend — Super-nodes that replace the original Settings and Blend Frames subgraphs.
Utilities
Grow + Blur Mask
Block Mask
Smart Sharpen
Text Utilities / Show Text
Seed Generator
Load Images From Folder
Video Info
Wan All-in-One Loader
Qwen-VL Caption
Prompt Guide (official Bernini presets)
Sequential vs Context Window
SequentialContext WindowProcessingProcesses chunks sequentially, advancing chunk_size - overlap frames each stepProcesses the full video using a sliding context windowVRAM UsageLowerSlightly highermask_mode = bbox❌ Falls back to inpaint✅ SupportedTemporal ConsistencyGood (via tail_memory)Better (native)Recommended UseVery long videos or limited VRAMVideos that fit in a single generation or when using bbox mode
⚠️ Using a very small chunk_size together with a large overlap dramatically increases the number of passes (for example: chunk=17, overlap=16 results in 61 passes). Larger chunks with smaller overlaps are generally recommended.
Mask Modes
off — Regenerates the entire frame.
inpaint — Only edits the masked region while preserving the original image elsewhere.
bbox — Crops the masked region and generates it at a smaller resolution for significantly lower VRAM usage. (Available only in Context Window mode.)
Changelog (Major Milestones)
v0.2
Automatic 4n+1 frame correction (mirrored padding + final trimming)
Added
mask_mode(off,inpaint,bbox)Added
mask_growAdded
mask_blur
v0.3
Added FaceStitchUpscale
v0.5
Added native VIDEO Load/Save nodes (ComfyUI 2.0)
v0.6–0.9
Complete suite of native utility nodes (reducing third-party dependencies)
Compare Videos A/B
Mask BBox Preview
Upscale Config / Batch Blend
Server-side preview trimming in Load Video
v0.10
Added SAM3 Point Editor (green positive / purple negative points) for significantly more stable object tracking.
Why isn't there a "Bernini Long Sampler"?
Because Bernini already passes temporal information through conditioning, and the Wan patch already accepts context_latents as a list. The important part is generating the correct conditionings:
context_latents = [
encoded_chunk,
tail_latent,
]This approach leverages the native Bernini architecture instead of duplicating an entire sampler, making the package easier to maintain and fully compatible with existing Bernini workflows.
An automatic chunk executor may be added in the future, but it would depend on the exact node names and class implementations installed on each user's system.
🙏 Acknowledgements
Built on top of Kijai's work and the Bernini models.
Many thanks to the original authors and the open-source community.
📄 License
Apache License 2.0.
Description
Performance: 39 frames at 1920×1080 generated in 325 seconds.
Workflow: https://github.com/NyckM/Bruxos-do-VFX-Nodes/blob/main/Bernini_workflow_BruxosdoVFX/BERNINI_BdVFX_Upscale_Tiled.json
Nodes: https://github.com/NyckM/Bruxos-do-VFX-Nodes
Tiles (new)
Replaces the entire "Tile Settings" subgraph (Rounding up num, Set dimension properly, Padding, imageSplitTiles, Total tiles, ImageComposite+, Split Images...) with just three nodes.
Tile Split (Bruxos) — Splits an image or video into tiles based on the tile grid (tile_count_width × tile_count_height). Each tile size is calculated automatically and aligned to Wan's required multiple of 16. A 1×1 grid means the entire image is used with no splitting.
Tile Select (Bruxos) — Extracts tile N (connect the For Loop index) while preserving all video frames, which is exactly what Wan expects.
Tile Merge (Bruxos) — Stitches the tiles back together using feathered overlap (no visible seams) and automatically detects upscaling. If the processed tiles are returned at 2× the original size, the merged output is automatically 2× larger as well.
Real-world examples using a 1920×1080 source (tile_padding = 80):
Grid
Tiles
Calculated tile size
1×1
1
1920×1088 — full image
2×2
4
1120×704
8×8
64
400×304
16×16
256
288×240
Since 1080 is not a multiple of 16, Tile Split pads the canvas to 1088 by replicating the image borders, and Tile Merge crops it back to 1080. Without this padding, 8 rows of pixels would be lost. A complete round trip (Split → Merge) reconstructs the original source exactly.
Tiles: Tile Split / Tile Select / Tile Merge — Split by tile count (2×2, 8×8, etc.) with automatic tile sizing aligned to multiples of 16, feathered stitching (no visible seams), and automatic upscale detection. These nodes replace the entire "Tile Settings" subgraph.
0.19 — Pixel-based tiling: run the entire pipeline on each tile, with the source image/video cropped alongside it. Tile position is never lost because the tile's content is its position—the model sees "a complete small video" (its own corner of the original) and edits that video directly. No global RoPE misalignment.
To address tile-to-tile drift (my other concern), I reimplemented live stitching: within the overlap region, each tile receives the already-generated output from its neighboring tiles (left, top, and top-left corner) composited onto the source, with the mask set to zero in that area. The model therefore treats those pixels as "already finished" and matches its output to them. I verified in testing that the composited overlap strip contains the neighbor's generated output, not the original source.
Installer redesigned: includes Bernini-R INT8 ConvRot models and LightX2V 4-step LoRAs, automatic CUDA detection for onnxruntime-gpu, and idempotent downloads.
Bernini paper features: Bernini Prompt Enhancer (self-text CoT via local Qwen), First-Frame CoT (self vision-language reasoning), Bernini Multi-Guidance (Equations 8–12, experimental), and
guidance_modein Infinity. Prompt Guide expanded to cover all 22 Bernini-Bench tasks (35 presets in total).
sequential vs context_window
sequential
context_window
Processing
Processes chunks sequentially, advancing by chunk_size − overlap
VRAM
More memory-efficient
mask_mode: bbox
❌ Falls back to inpaint
Temporal consistency
Good, using tail_memory
Recommended for
Very long videos or limited VRAM
⚠️ A small chunk_size combined with a large overlap dramatically increases the number of passes (e.g. chunk_size=17, overlap=16 → 61 passes). Prefer a larger chunk_size with a smaller overlap whenever possible.
mask_modeoff— Regenerates the entire frame.inpaint— Edits only the masked region.bbox— Crops the masked region and generates it at a smaller resolution, providing the real performance optimization. Available only incontext_windowmode.
bbox_composesilhouette— Uses the mask silhouette as the alpha channel for compositing.rectangle— Composites the entire bounding box with feathering (mask_blur), eliminating the visible outline seam.
100%|██████████████████████████████████████████████████████████████████████████████████████████| 4/4 [02:25<00:00, 36.35s/it]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 2/2 [01:13<00:00, 36.70s/it]
done: 39 frames (alvo do usuario=39). 1920x1088 -
Prompt executed in 325.19 seconds