Nodes/comfyui-imgmake/ebsynth_main
ComfyUI Node

ebsynth_main

One node to drive the whole EBSynth style-transfer pipeline — almost

By dafeng012·Created 2 years ago·Updated 2 years ago· 17
ebsynth_main
  • color_matcher_ref_image
  • debug
  • info
◄stage_index▾►
◄project_dir—►
◄original_movie_path—►
◄frame_width-1►
◄frame_height-1►
◄st1_masking_method_index0►
◄st1_mask_threshold0.1►
◄tb_use_fast_modetrue►
◄tb_use_jittrue►
◄clipseg_mask_prompt►
◄clipseg_exclude_prompt►
◄clipseg_mask_threshold0►
◄clipseg_mask_blur_size11►
◄clipseg_mask_blur_size211►
◄key_min_gap10►
◄key_max_gap300►
◄key_th8.5►
◄key_add_last_frametrue►
◄color_matcher_methodhm-mvgd-hm►
◄st3_5_use_masktrue►
◄st3_5_use_mask_reffalse►
◄st3_5_use_mask_orgfalse►
◄color_matcher_ref_type0►
◄blend_rate1.0►
◄export_typemp4►
◄mask_modeNormal►
◄is_invert_maskfalse►
◄devices▾►
◄SYNTHS_PER_PROJECT15►
◄bg_src►
◄bg_type▾►
◄mask_blur_size5►
◄mask_threshold0.0►
◄fg_transparency0.0►

ebsynth_main is the flagship of the comfyui-imgmake pack, and it's a lot to look at. This is a ComfyUI port of the old A1111 extension ebsynth_utility (by s9roll7), which turned the EBSynth desktop app into a keyframe-driven style-transfer workflow: you paint or img2img a handful of frames, EBSynth carries that style through every frame in between, and you get back a stylized video. Here it all lives in one node with a stage_index switch instead of tabs.

If you've ever wanted to do the classic "anime style transfer on a real video" thing - or "enhance a few frames and propagate the detail to the rest of the clip" - this is the workflow you're looking for. EBSynth itself is old and a little forgotten (community mentions have been sliding since 2024), but it's still the reliable way to get frame-to-frame consistency that img2img per frame can't give you.

How it works

The node doesn't do everything at once. You pick a stage, run it, then move the widget and run the next. Each stage reads and writes folders inside your project_dir:

  • stage 0 - splits the video into frames (video_frame/) and builds masks. st1_masking_method_index picks the method: 0 is transparent-background (InSPyReNet-style removal, the author's default), 1 is CLIPSeg with a text prompt (clipseg_mask_prompt), 2 runs both and combines.
  • stage 1 - picks keyframes by detecting scene changes (key_min_gap, key_max_gap, key_th, key_add_last_frame). This is where your "frames to paint" come from.
  • stage 3 - color-matches the keyframes (color_matcher_method, default hm-mvgd-hm).
  • stage 5 - writes .ebs project files. This is the manual bit, see below.
  • stage 7 - blends the EBSynth output back with the original at blend_rate and exports (export_type: mp4, gif, webm, rawvideo), re-muxing the original audio.
  • stage 8 - background replacement, using bg_src, bg_type (Fit video length / Loop), mask_blur_size, mask_threshold, fg_transparency. Requires mask_mode = Normal.

Between stages you go into ComfyUI and img2img / ControlNet / inpaint the keyframes however you like, so the "painted" frames land in img2img_key/. That's the creative core of the workflow and this node never touches it.

The inputs that actually matter

Don't panic at the wall of widgets. Set these first: project_dir (where all the stage folders live), original_movie_path (the source video), stage_index, devices (cuda:0 or cpu), and export_type. Then blend_rate - at 1.0 the EBSynth style wins completely; lower it to let the original bleed through and hide EBSynth's warpy artifacts. SYNTHS_PER_PROJECT (default 15) chunks the synth work into smaller .ebs files, which matters if you crash halfway through a long clip. mask_mode Invert is the escape hatch for masking the background instead of the subject.

The node returns two STRINGs, debug and info, which are plain-text logs of what the stage just did. Wire them into a ShowText node - when a stage silently does nothing, the message there is your only clue.

Installing it

ComfyUI Manager → search comfyui-imgmake, or:

cd ComfyUI/custom_nodes
git clone https://github.com/dafeng012/comfyui-imgmake

Then restart. requirements.txt pulls transformers and transparent_background. Two non-Python deps the README is very clear about: ffmpeg on your PATH and the EBSynth app itself from ebsynth.com. transparent-background downloads its weights to ~/.transparent-background on first run - the README warns this can fail in China and suggests a proxy or manual download, and there's a model pack on Baidu Pan if you need it.

Where people get burned

The big one: stage 5 doesn't run EBSynth for you. It writes .ebs project files into the project dir, then you open/run them in the EBSynth app, which produces out-* folders that stage 7 picks up. If you skip that, stage 7 finds nothing and the merge silently does nothing. It's a clunky handoff, but it's how the original utility worked too.

Also: paths here are raw STRING fields, no browser. Windows backslashes are fine, but typos are not - a wrong project_dir or original_movie_path makes the node bail early with just a debug message. And since transparent-background loads a torch model, your first stage 0 run is slow and GPU-hungry; if it's dragging, flip tb_use_fast_mode/tb_use_jit off.

The author's tutorial is on Bilibili (linked in the README), which is a sign of where this pack's real audience lives - the English-speaking ComfyUI community barely mentions it. Don't let that put you off; the pipeline works, it's just not famous here.

CategoryIMAGEmake

Inputs (35)

NameTypeDefaultDescription
stage_indexCOMBO6 options: 0, 1, 3, 5, 7, 8
project_dirSTRING—
original_movie_pathSTRING—
frame_widthINT-1—
frame_heightINT-1—
st1_masking_method_indexINT0—
st1_mask_thresholdFLOAT0.10–1—
tb_use_fast_modeBOOLEANtrue—
tb_use_jitBOOLEANtrue—
clipseg_mask_promptSTRING—
clipseg_exclude_promptSTRING—
clipseg_mask_thresholdINT00–1—
clipseg_mask_blur_sizeINT11—
clipseg_mask_blur_size2INT11—
key_min_gapINT101–100—
key_max_gapINT3001–1000—
key_thFLOAT8.50–100—
key_add_last_frameBOOLEANtrue—
color_matcher_methodSTRINGhm-mvgd-hm—
st3_5_use_maskBOOLEANtrue—
st3_5_use_mask_refBOOLEANfalse—
st3_5_use_mask_orgBOOLEANfalse—
color_matcher_ref_typeINT0—
blend_rateFLOAT1.00–1—
export_typeSTRINGmp4—
mask_modeSTRINGNormal—
is_invert_maskBOOLEANfalse—
devicesCOMBO2 options: cuda:0, cpu
SYNTHS_PER_PROJECTINT151–20—
color_matcher_ref_imageoptIMAGE—
bg_srcoptSTRING—
bg_typeoptCOMBO2 options: Fit video length, Loop
mask_blur_sizeoptINT5—
mask_thresholdoptFLOAT0.00–1—
fg_transparencyoptFLOAT0.00–1—

Outputs (2)

NameTypeDescription
debugSTRING—
infoSTRING—