Nodes/ComfyUI Video Comparer/Video Comparer (Swipe)
ComfyUI Node

Video Comparer (Swipe)

Side-by-Side Video A/B That Records Its Own Verdict

By AIEGOBOT·Created 29 days ago·Updated 22 days ago· 2
Video Comparer (Swipe)
  • video_a
  • video_b
  • recorded_video
label_aA
label_bB
autoplaytrue
looptrue
mutedtrue
initial_split0.50
sync_tolerance_ms80
recording_file

Video generation is a lot of GPU time for a decision you end up making by squinting at two clips. You've rendered an original, then an upscaled or refined pass, and now you need to know which one is actually better. Tabbing between two players doesn't work - they're never in sync, so the flicker you think you spotted is usually just playback drift. That's the gap Video Comparer (Swipe) (IndiVideoComparer, part of the AIEGOBOT/ComfyUI-VideoComparer pack) exists for: it takes two core VIDEO inputs, plays them in lockstep, and lets you drag a vertical divider across the preview to wipe between A and B. Then - the clever part - it records the whole comparison, divider and labels included, and hands you a file you can wire straight into Save Video.

How the swipe works

The node is is_output_node and lives under video/preview, so you'll find it next to the other preview gadgets. When you queue, it saves both inputs to ComfyUI's temp directory as MP4/H.264 (ComfyUI remuxes where it can and transcodes otherwise), then ships the browser a small UI payload. In the browser, two video elements are stacked under a draggable divider. On every animation frame the frontend checks whether B has drifted from A by more than sync_tolerance_ms and, if so, snaps B back to A's position. That constant drift correction is the whole reason this works better than opening two windows.

The inputs you'll actually touch

  • video_a / video_b - the two VIDEO inputs. video_a is your base/original, video_b is the improved one revealed as you push the divider right. Hook these to core Load Video nodes (or the output of an upscale/refine chain).
  • label_a / label_b - text shown on the preview, defaults "A" and "B". Rename them "original"/"upscaled" and the recording becomes self-documenting.
  • muted - defaults to true. When you unmute, audio comes from A only.
  • initial_split - where the divider starts (0.5 = halfway).
  • sync_tolerance_ms - advanced, 80 by default. Lower it if B visibly skips; raise it if A and B are slightly different lengths and B keeps fighting you.

recording_file is a socketless, auto-managed string - don't touch it. The one output, recorded_video, is a VIDEO you connect to the core Save Video node.

The recording part is the trick

The preview itself is nice, but the recording is why this node earns its place. Hit REC and the frontend composites both videos, the divider, the handle, and the A/B labels onto a canvas, captures it with captureStream + MediaRecorder into a WebM, and uploads it to the node's /indi_video_comparer/recording endpoint. The backend checks it's a real WebM, parks it in ComfyUI/input/video_comparer_recordings, and on the next queue pass recorded_video resolves to that file. So you end up with a timestamped .webm of you doing the A/B wipe - which is exactly the clip to send someone when you say "look at the eyes when the divider crosses."

Two gotchas built into the design. Before any recording exists, recorded_video deliberately blocks execution (an ExecutionBlocker), so your first queue is preview-only and Save Video does nothing - that's intentional, so you can't accidentally save a raw input as if it were a comparison. And the shared timeline is the shorter input's duration, with recording capped at 2 minutes and 512 MiB.

Installing it

Search "video-comparer" in ComfyUI Manager, or:

cd ComfyUI/custom_nodes
git clone https://github.com/AIEGOBOT/ComfyUI-VideoComparer.git

Then restart ComfyUI and hard-refresh the browser. There's no requirements.txt and no models - it's pure browser + backend plumbing. The one real requirement: ComfyUI 0.33.1 or newer and Python 3.10+. This pack is written against ComfyUI's newer extension API, so if you're sitting on an old install, update ComfyUI first or the node simply won't appear.

When it bites you

  • Empty preview - connect two real VIDEO inputs and queue once. It needs both to render anything.
  • Recording won't start - you need a current Chromium-based browser. MediaRecorder + captureStream is spotty in Firefox and Safari.
  • Node missing after install - restart, refresh, and read the startup log.
  • Your VHS path doesn't connect - VHS_FILENAMES is a different type. Load MP4s with core Load Video, which gives you the VIDEO sockets this node wants.
  • Recordings pile up - completed WebMs stay in video_comparer_recordings until you delete them; preview temp files prune themselves (keeps the last 12).

For a young pack with zero name recognition, the implementation is suspiciously polished - drift-corrected sync, safe recording paths, size caps, and a model-free smoke-test workflow included. If you review more than one video render a week, it pays for itself in the first A/B session.

Categoryvideo/preview

Inputs (10)

NameTypeDefaultDescription
video_aVIDEOBase/original video.
video_bVIDEOImproved video revealed progressively as the divider moves right.
label_aSTRINGALabel for the base/original video.
label_bSTRINGBLabel for the improved video.
autoplayBOOLEANtrue
loopBOOLEANtrue
mutedBOOLEANtrueMute preview audio. When unmuted, audio comes from video A only.
initial_splitFLOAT0.500.05–0.95Initial position of the A/B divider.
sync_tolerance_msINT8010–500Resynchronize video B when drift exceeds this value.
recording_fileSTRINGManaged automatically after browser recording. Connect the recorded_video output to the core Save Video node.

Outputs (1)

NameTypeDescription
recorded_videoVIDEOThe latest completed swipe recording.