Tidy H3 long videos input layout
This commit is contained in:
+86
-56
@@ -264,10 +264,11 @@ def split_paragraphs(text, delimiter):
|
||||
return [p.strip() for p in re.split(r"\n\s*\n", raw) if p.strip()]
|
||||
|
||||
|
||||
# Widgets added after the node's original 36-widget layout. Kept LAST in
|
||||
# INPUT_TYPES so a workflow saved before they existed still maps its stored values
|
||||
# onto the right widgets (ComfyUI matches them by position, not by name).
|
||||
# APPEND to this tuple when adding a widget; never insert into the middle.
|
||||
# Widgets added after the node's original 36-widget layout. Kept LAST in
|
||||
# INPUT_TYPES so a workflow saved before they existed still maps its stored values
|
||||
# onto the right widgets (ComfyUI matches them by position, not by name).
|
||||
# APPEND widget names to this tuple; never insert into the middle. Pure sockets
|
||||
# that carry no widget value can stay grouped in INPUT_TYPES without being listed.
|
||||
ADDED_WIDGETS = (
|
||||
"beat_split", "per_beat_length",
|
||||
"watermark_text", "watermark_position", "watermark_size", "watermark_opacity",
|
||||
@@ -277,7 +278,6 @@ ADDED_WIDGETS = (
|
||||
"exposed_terms", "anatomy_guard", "lock_restraints", "solidity_guard",
|
||||
"motion_guard", "contact_guard",
|
||||
"auto_soundscape", "allow_nonspeech_vocals",
|
||||
"ref_5", "ref_6", "ref_7", "ref_8", "ref_9",
|
||||
"detail_pass", "detail_sampler_name", "detail_scheduler",
|
||||
"detail_steps", "detail_denoise",
|
||||
)
|
||||
@@ -5744,13 +5744,26 @@ class H3LongVideos:
|
||||
"tooltip": "Base H3 wants ~20 (res_multistep + simple). Drop to 6-8 ONLY with a "
|
||||
"working distill/turbo LoRA or a low-step MXFP8 checkpoint -- on the "
|
||||
"bare base model, low steps are the #1 cause of soft output."}),
|
||||
"cfg": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 30.0, "step": 0.1}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"default": "res_multistep"}),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default": "simple"}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "control_after_generate": True}),
|
||||
"cfg": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 30.0, "step": 0.1,
|
||||
"tooltip": "H3 is effectively CFG-free here. Leave this at 1.0 unless you are "
|
||||
"deliberately testing unusual sampler behaviour; higher values do not act "
|
||||
"like a normal SD/Flux CFG boost and are not the fix for weak identity."}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"default": "res_multistep",
|
||||
"tooltip": "Main-pass sampler. Base H3 is tuned around res_multistep; changing this is "
|
||||
"a real behaviour change, not a cosmetic preference. Treat it as an advanced "
|
||||
"override."}),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default": "simple",
|
||||
"tooltip": "Main-pass scheduler. Base H3 is tuned around simple when paired with "
|
||||
"res_multistep and the default model-sampling shifts."}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "control_after_generate": True,
|
||||
"tooltip": "Base seed for the whole chain. With vary_seed_per_shot OFF, every beat is "
|
||||
"sampled from the same noise field for better continuity. With it ON, this "
|
||||
"becomes the first seed and later beats use seed+1, seed+2, ..."}),
|
||||
},
|
||||
"optional": {
|
||||
"first_frame": ("IMAGE",),
|
||||
"first_frame": ("IMAGE", {"tooltip": "Optional opening keyframe for shot 1. Leave empty to "
|
||||
"start from pure text/reference conditioning. On later shots the node normally uses the "
|
||||
"previous shot's last frame automatically; this socket is only the initial handoff."}),
|
||||
# ref2va inputs. SOCKET NUMBER matters: prompt tags refer to these
|
||||
# exact slots, even when some intermediate sockets are left empty.
|
||||
# A shot using only ref_image_7 is still tagged as <Picture 7> in the
|
||||
@@ -5760,19 +5773,20 @@ class H3LongVideos:
|
||||
# the order they are handed that shot.
|
||||
# Refer to socket tags in the prompt if you want a reference bound to
|
||||
# a named character ("Kristy, <Picture 7>, walks in").
|
||||
"ref_1": ("REFERENCE", {"tooltip": "Reference object for <Picture 1> -- image plus identity/environment metadata "
|
||||
"carried into the shots. Which shots receive it is set by ref_mode (or <Picture N> "
|
||||
"tags in the beats); a referenced shot ALSO carries the previous frame as its "
|
||||
"keyframe, so taking a reference never costs continuity."}),
|
||||
"ref_2": ("REFERENCE", {"tooltip": "Reference object for <Picture 2>."}),
|
||||
"ref_3": ("REFERENCE", {"tooltip": "Reference object for <Picture 3>."}),
|
||||
"ref_4": ("REFERENCE", {"tooltip": "Reference object for <Picture 4>."}),
|
||||
"ref_5": ("REFERENCE", {"tooltip": "Reference object for <Picture 5>."}),
|
||||
"ref_6": ("REFERENCE", {"tooltip": "Reference object for <Picture 6>."}),
|
||||
"ref_7": ("REFERENCE", {"tooltip": "Reference object for <Picture 7>."}),
|
||||
"ref_8": ("REFERENCE", {"tooltip": "Reference object for <Picture 8>."}),
|
||||
"ref_9": ("REFERENCE", {"tooltip": "Reference object for <Picture 9>."}),
|
||||
"ref_image_1": ("*", {"tooltip": "Legacy alias for ref_1. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||
"ref_1": ("REFERENCE", {"tooltip": "Reference slot <Picture 1>. Feed a Dumas Character "
|
||||
"Reference or Dumas Location Reference here. The image is used for real H3 visual "
|
||||
"conditioning; the structured metadata is also used for prompt context."}),
|
||||
"ref_2": ("REFERENCE", {"tooltip": "Reference slot <Picture 2>. Socket numbers matter: "
|
||||
"tag this exact slot as <Picture 2> when you want explicit placement in a beat."}),
|
||||
"ref_3": ("REFERENCE", {"tooltip": "Reference slot <Picture 3>."}),
|
||||
"ref_4": ("REFERENCE", {"tooltip": "Reference slot <Picture 4>."}),
|
||||
"ref_5": ("REFERENCE", {"tooltip": "Reference slot <Picture 5>."}),
|
||||
"ref_6": ("REFERENCE", {"tooltip": "Reference slot <Picture 6>."}),
|
||||
"ref_7": ("REFERENCE", {"tooltip": "Reference slot <Picture 7>."}),
|
||||
"ref_8": ("REFERENCE", {"tooltip": "Reference slot <Picture 8>."}),
|
||||
"ref_9": ("REFERENCE", {"tooltip": "Reference slot <Picture 9>."}),
|
||||
"ref_image_1": ("*", {"tooltip": "Legacy alias for ref_1. Accepts old IMAGE wiring or a "
|
||||
"REFERENCE payload. Keep old graphs working without rewiring."}),
|
||||
"ref_image_2": ("*", {"tooltip": "Legacy alias for ref_2. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||
"ref_image_3": ("*", {"tooltip": "Legacy alias for ref_3. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||
"ref_image_4": ("*", {"tooltip": "Legacy alias for ref_4. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||
@@ -5782,9 +5796,10 @@ class H3LongVideos:
|
||||
"ref_image_8": ("*", {"tooltip": "Legacy alias for ref_8. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||
"ref_image_9": ("*", {"tooltip": "Legacy alias for ref_9. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||
"plan_only": ("BOOLEAN", {"default": False,
|
||||
"tooltip": "Preview the shot split WITHOUT rendering. Uses THIS node's own settings (no "
|
||||
"second node, no duplicate entry): returns the plan in 'info' and the "
|
||||
"shots/frames/seconds outputs near-instantly. Turn off to render for real."}),
|
||||
"tooltip": "Preview the shot split and timing WITHOUT sampling pixels. Uses this "
|
||||
"node's current settings and returns the plan in `info` almost instantly. "
|
||||
"Good for checking beat counts, shot ceilings, ref placement and clamps "
|
||||
"before a long render."}),
|
||||
"fps": ("INT", {"default": 24, "min": 1, "max": 60,
|
||||
"tooltip": "DISPLAY ONLY -- H3 always renders 24 fps. The model's frame grid and its "
|
||||
"audio latent are both defined against 24, so this node computes every "
|
||||
@@ -5844,23 +5859,29 @@ class H3LongVideos:
|
||||
"shot instead of the literal last frame. Set 2-4 if chained shots open "
|
||||
"with moving/talking mouths -- it avoids seeding the next shot with a "
|
||||
"mid-word open-mouth pose. Trims the matching audio tail too. 0 = last frame."}),
|
||||
"shot_seconds": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 15.1, "step": 0.5,
|
||||
"forceInput": True,
|
||||
"tooltip": "Length of EACH shot in seconds, taken from a connected input -- "
|
||||
"H3 Shot Length is the intended source, since it also reports the "
|
||||
"matching frame count on the 17k+5 grid.\n\n"
|
||||
"Leave it UNCONNECTED for auto: the largest shot that fits at the "
|
||||
"chosen size, which is what a 0 in the old widget did. One "
|
||||
"paragraph = one shot, so total video = (paragraph count) x this. "
|
||||
"Max ~15s."}),
|
||||
"allow_oversize_shots": ("BOOLEAN", {"default": False,
|
||||
"tooltip": "OFF (default): a forced shot_seconds that won't fit VRAM is clamped DOWN to "
|
||||
"what fits, and the clamp is reported in info. ON: honor the requested length "
|
||||
"even if it exceeds the budget -- the render may spill into system RAM (slow) "
|
||||
"or OOM. Only affects forced shot_seconds, not auto."}),
|
||||
"vram_headroom_gb": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 32.0, "step": 0.5}),
|
||||
"allow_res_backoff": ("BOOLEAN", {"default": True,
|
||||
"tooltip": "If VRAM is tight, step resolution down instead of failing."}),
|
||||
"shot_seconds": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 15.1, "step": 0.5,
|
||||
"forceInput": True,
|
||||
"tooltip": "GLOBAL per-shot ceiling in seconds, not 'force every beat to exactly "
|
||||
"this length'. H3 Shot Length is the intended source because it snaps to "
|
||||
"H3's frame grid and reports the real duration.\n\n"
|
||||
"Leave UNCONNECTED for auto: the node picks the largest shot that fits "
|
||||
"the current size/VRAM budget. Connect a value to cap every beat at that "
|
||||
"length. A beat's own `seconds:` directive can still ask for less, and any "
|
||||
"request above H3's hard ~15.1s single-shot limit is clamped. Total video "
|
||||
"length is the sum of the beat shots, not simply beat-count x this value."}),
|
||||
"allow_oversize_shots": ("BOOLEAN", {"default": False,
|
||||
"tooltip": "OFF (default): a forced shot_seconds that won't fit VRAM is clamped DOWN to "
|
||||
"what fits, and the clamp is reported in info. ON: honor the requested length "
|
||||
"even if it exceeds the budget -- the render may spill into system RAM (slow) "
|
||||
"or OOM. Only affects forced shot_seconds, not auto."}),
|
||||
"vram_headroom_gb": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 32.0, "step": 0.5,
|
||||
"tooltip": "Safety margin RESERVED from free VRAM before the node budgets shot length. "
|
||||
"Higher = shorter safer shots. Lower = longer shots but more risk of spill or "
|
||||
"OOM during sampling/decode peaks. 1.5GB is the conservative default."}),
|
||||
"allow_res_backoff": ("BOOLEAN", {"default": True,
|
||||
"tooltip": "If a render does not fit, try stepping the resolution down instead of just "
|
||||
"failing. Helps salvage long jobs automatically, but the later shots may come "
|
||||
"back smaller and the latent output can no longer join cleanly across sizes."}),
|
||||
# ON by default: the prompt-side clauses ASK H3 not to vocalize (and now
|
||||
# condition the soundscape field too), but asking is not a guarantee --
|
||||
# babble under a silent shot was the one artifact that survived both.
|
||||
@@ -5886,11 +5907,11 @@ class H3LongVideos:
|
||||
"decode_tile_size": ("INT", {"default": 0, "min": 0, "max": 1024, "step": 32,
|
||||
"tooltip": "Spatial tile size for the VAE decode (tile_x/tile_y). 0 = ComfyUI default. "
|
||||
"Try 256 on a tight card at 1344x768."}),
|
||||
"cleanup_between_shots": ("BOOLEAN", {"default": True,
|
||||
"tooltip": "Between beats, move each shot's decoded video+audio to system RAM and run "
|
||||
"a full VRAM+RAM purge (GC + CUDA cache), so a long chain doesn't accumulate "
|
||||
"on the GPU and OOM. Recommended on 16GB. Turn off only on a big card where "
|
||||
"you want to skip the per-shot cleanup cost."}),
|
||||
"cleanup_between_shots": ("BOOLEAN", {"default": True,
|
||||
"tooltip": "Between beats, move each shot's decoded video+audio to system RAM and run "
|
||||
"a full VRAM+RAM purge (GC + CUDA cache), so a long chain doesn't accumulate "
|
||||
"on the GPU and OOM. Recommended on 16GB. Turn off only on a big card where "
|
||||
"you want to skip the per-shot cleanup cost."}),
|
||||
"upscale": (["off", "rtx", "model", "lanczos"], {"default": "off",
|
||||
"tooltip": "Optional post-pass on the finished frames. 'rtx' = NVIDIA RTX Video Super "
|
||||
"Resolution (Tensor Cores -- fastest and best for video; needs the "
|
||||
@@ -5944,7 +5965,7 @@ class H3LongVideos:
|
||||
"white as asked; 2-3 makes it survive a bright sky or a white wall."}),
|
||||
"ref_mode": (["auto ref2v", "where tagged", "first shot", "every shot", "every shot + handoff ref"],
|
||||
{"default": "auto ref2v",
|
||||
"tooltip": "Which shots the ref_image inputs condition. 'auto ref2v' (default) is "
|
||||
"tooltip": "Which shots the reference IMAGE inputs condition. 'auto ref2v' (default) is "
|
||||
"the reference-to-video bias: if the prompt uses <Picture N> tags, those "
|
||||
"tags decide which shot gets which ref; if there are NO tags anywhere, the "
|
||||
"node conditions EVERY shot with the connected refs rather than collapsing "
|
||||
@@ -5952,7 +5973,9 @@ class H3LongVideos:
|
||||
"for long chains where identity drift matters more than strict per-shot "
|
||||
"routing. 'where tagged' keeps the old strict behavior, including the "
|
||||
"first-shot fallback when no tags are found. Tags are renumbered per shot, "
|
||||
"so <Picture 2> alone still resolves. 'first shot' / 'every shot' / "
|
||||
"so <Picture 2> alone still resolves. Character names in the beat can also "
|
||||
"pull their matching character refs into the real image-conditioning list. "
|
||||
"'first shot' / 'every shot' / "
|
||||
"'every shot + handoff ref' go purely by position. Ignored when no "
|
||||
"ref_image is connected."}),
|
||||
"ref_noise_aug": ("FLOAT", {"default": 0.95, "min": 0.50, "max": 1.0, "step": 0.005,
|
||||
@@ -6189,16 +6212,23 @@ class H3LongVideos:
|
||||
"detail_pass": ("BOOLEAN", {"default": False,
|
||||
"tooltip": "Run a second refinement sampler on each beat BEFORE any upscale. "
|
||||
"It reuses the same conditioning and keeps the output video-only by "
|
||||
"preserving the first pass's audio latent. Good for extra detail without "
|
||||
"building a separate graph."}),
|
||||
"preserving the first pass's audio latent. Use it for detail cleanup, not "
|
||||
"for huge rewrites: too many steps or too much denoise can pull identity or "
|
||||
"continuity away from the main pass."}),
|
||||
"detail_sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"default": "euler",
|
||||
"tooltip": "Sampler used for the optional refinement pass."}),
|
||||
"tooltip": "Sampler for the optional refinement pass. Euler is the maintained default "
|
||||
"direction for this lane."}),
|
||||
"detail_scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default": "beta",
|
||||
"tooltip": "Scheduler used for the optional refinement pass."}),
|
||||
"tooltip": "Scheduler for the optional refinement pass. Beta is the maintained default "
|
||||
"direction for the H3 enhancement lane."}),
|
||||
"detail_steps": ("INT", {"default": 8, "min": 1, "max": 200,
|
||||
"tooltip": "Steps for the optional refinement pass."}),
|
||||
"tooltip": "Extra steps for the refinement pass only. Start around 4-8. More is not "
|
||||
"automatically better; once the pass starts rewriting instead of polishing, "
|
||||
"identity and continuity can drift."}),
|
||||
"detail_denoise": ("FLOAT", {"default": 0.4, "min": 0.0, "max": 1.0, "step": 0.01,
|
||||
"tooltip": "How hard the refinement pass is allowed to rewrite the beat latent."}),
|
||||
"tooltip": "How hard the refinement pass is allowed to rewrite the beat latent. Start "
|
||||
"around 0.20-0.35 for gentle cleanup; 0.4+ is stronger and can noticeably "
|
||||
"change faces, motion or composition."}),
|
||||
},
|
||||
# Read-only graph access, for SLA-LoRA detection: a LoRA's filename is
|
||||
# the only thing that identifies an SLA build, and the graph is the only
|
||||
|
||||
Reference in New Issue
Block a user