Remove long video plan integration

This commit is contained in:
2026-08-26 22:13:18 +00:00
parent f90068adea
commit c4cd4121b8
3 changed files with 3 additions and 107 deletions
+1 -2
View File
@@ -34,14 +34,13 @@
- Reads back the nine optional images for a selected MiniMax H3 plan scene, for example by connecting the current `clip_index`.
- `Dumas H3 Long Videos (FL2VA + REF2VA)`
- Inputs: H3 model stack, prompt socket, optional `first_frame`, optional `ref_1`..`ref_9`, optional `plan`, optional `plan_scene_index`, plus the upstream long-video control surface for pacing, continuity, audio, overlays, and guards
- Inputs: H3 model stack, prompt socket, optional `first_frame`, optional `ref_1`..`ref_9`, plus the upstream long-video control surface for pacing, continuity, audio, overlays, and guards
- Outputs: `images`, `audio`, `info`, `script`, `frames_per_shot`, `total_frames`, `shots`, `video_seconds`, `fps`, `fps_int`, `latent`, `soundscape`
- First-pass Dumas port of the `MiniMax-H3-Longvideos` sampler, brought in as a local starting point for long-form H3 chaining work.
- Keeps the upstream split-beats / handoff / ref-routing behavior close to source so future Dumas-specific improvements can be compared against a known baseline.
- Only the canonical `DumasH3LongVideos` node key is exposed now; the older FL2VA/REF2VA alias entries are no longer duplicated in the Add Node menu.
- Prompt `<Picture N>` tags now map to the actual ref socket numbers you wire, even with gaps such as only `ref_2` and `ref_7` connected.
- Character refs now contribute appearance and wardrobe context from the same structured object, while location refs contribute environment context from theirs.
- A connected H3 plan can now supply the current scenes 9-image bundle directly; any directly-wired `ref_*` socket overrides the same numbered plan slot.
- The default ref2v bias is now stronger: `ref_mode` defaults to `auto ref2v` so untagged prompts condition every shot instead of only shot 1, and `ref_noise_aug` defaults to `0.95` rather than the upstream-literal `0.999`.
- `Dumas H3 Shot Length`
+2 -58
View File
@@ -276,7 +276,6 @@ ADDED_WIDGETS = (
"motion_guard", "contact_guard",
"auto_soundscape", "allow_nonspeech_vocals",
"ref_5", "ref_6", "ref_7", "ref_8", "ref_9",
"plan", "plan_scene_index",
)
NL = "\n"
@@ -4176,33 +4175,6 @@ def _connected_refs(ref_slots):
return [ref for ref in (ref_slots or []) if _reference_image(ref) is not None]
def _plan_scene_refs(plan, scene_index):
"""Nine ref slots for one plan scene, or all-empty when no usable binding exists."""
if plan is None:
return (None,) * _image_nodes._H3_PLAN_IMAGE_SLOTS
extracted = _image_nodes.DumasH3PlanExtractSceneImagesNode().extract(plan, scene_index)
refs = []
for slot_number, image in enumerate(
extracted[1:1 + _image_nodes._H3_PLAN_IMAGE_SLOTS],
1,
):
refs.append(_reference_slot(image, slot_number) if image is not None else None)
return tuple(refs)
def _merge_ref_slots(direct_slots, plan_slots):
"""Directly-wired refs win; plan-scene refs fill the empty sockets."""
direct_slots = tuple(direct_slots or ())
plan_slots = tuple(plan_slots or ())
width = max(len(direct_slots), len(plan_slots), _image_nodes._H3_PLAN_IMAGE_SLOTS)
out = []
for index in range(width):
direct = direct_slots[index] if index < len(direct_slots) else None
plan_ref = plan_slots[index] if index < len(plan_slots) else None
out.append(direct if direct is not None else plan_ref)
return tuple(out)
def resolve_tagged_refs(text, ref_list):
"""(rewritten text, images, dropped) for the <Picture N> tags in ONE shot.
@@ -5473,26 +5445,6 @@ class H3LongVideos:
"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>."}),
"plan": (
"H3_CHAIN_PLAN",
{
"tooltip": "Optional H3 plan enriched by Dumas H3 Plan Attach Scene Images. "
"When connected, this node can pull the selected scene's nine "
"image slots directly instead of rewiring them by hand."
},
),
"plan_scene_index": (
"INT",
{
"default": 1,
"min": 1,
"max": 9999,
"step": 1,
"tooltip": "1-based plan scene index to read from `plan`. "
"Any directly-wired ref socket overrides the same slot "
"from the plan scene."
},
),
"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 "
@@ -5989,7 +5941,6 @@ class H3LongVideos:
ref_1=None, ref_2=None, ref_3=None, ref_4=None,
ref_5=None, ref_6=None, ref_7=None, ref_8=None,
ref_9=None,
plan=None, plan_scene_index=1,
ref_mode="where tagged", ref_image_size="match", ref_noise_aug=0.999,
graph=None, node_id=None):
@@ -6014,9 +5965,7 @@ class H3LongVideos:
ref_1, ref_2, ref_3, ref_4, ref_5,
ref_6, ref_7, ref_8, ref_9,
)
plan_ref_slots = _plan_scene_refs(plan, plan_scene_index)
ref_slots = _merge_ref_slots(direct_ref_slots, plan_ref_slots)
plan_ref_count = len(_connected_refs(plan_ref_slots))
ref_slots = direct_ref_slots
direct_ref_count = len(_connected_refs(direct_ref_slots))
derived_character_memory = _reference_character_memory(ref_slots)
effective_character_memory = (character_memory or "").strip() or derived_character_memory
@@ -6311,8 +6260,6 @@ class H3LongVideos:
src = []
if direct_ref_count:
src.append(f"{direct_ref_count} direct")
if plan_ref_count:
src.append(f"{plan_ref_count} from plan scene {int(plan_scene_index)}")
plan_ref = (f" ref2va: {n_refs} reference image(s) at '{ref_image_size}' on shot(s) "
f"{','.join(str(n) for n in on) or 'none'} ({how}) -> those shots keep "
f"the previous frame as their keyframe too, unless ref_noise_aug was lowered"
@@ -6664,8 +6611,6 @@ class H3LongVideos:
ref_source = []
if direct_ref_count:
ref_source.append(f"{direct_ref_count} direct")
if plan_ref_count:
ref_source.append(f"{plan_ref_count} from plan scene {int(plan_scene_index)}")
ref_note = (f" ref2va: {connected_ref_count} reference image(s) at '{ref_image_size}' on shot(s) "
f"{','.join(str(n) for n in ref_shots)} "
f"({ref_placement})"
@@ -6687,8 +6632,7 @@ class H3LongVideos:
elif connected_ref_count:
ref_note = (f" ref2va: {connected_ref_count} reference image(s) connected but ref_mode "
f"'{ref_mode}' applied them to no shot"
+ (f" (source {' + '.join(([f'{direct_ref_count} direct'] if direct_ref_count else []) + ([f'{plan_ref_count} from plan scene {int(plan_scene_index)}'] if plan_ref_count else []))})"
if (direct_ref_count or plan_ref_count) else ""))
+ (f" (source {direct_ref_count} direct)" if direct_ref_count else ""))
else:
ref_note = ""
info = ((anchor_note + " ") if anchor_note else "") + \
-47
View File
@@ -230,53 +230,6 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
for index in range(1, 10):
self.assertIn(f"ref_{index}", optional)
self.assertIn("plan", optional)
self.assertIn("plan_scene_index", optional)
def test_plan_scene_refs_reads_bound_images(self):
attach = self.image_module.DumasH3PlanAttachSceneImagesNode()
plan = {"shots": [{"id": "one"}, {"id": "two"}]}
image2 = object()
image7 = object()
plan, _ = attach.attach(plan=plan, scene_index=2, image2=image2, image7=image7)
refs = self.module._plan_scene_refs(plan, 2)
self.assertEqual(len(refs), 9)
self.assertIsNone(refs[0])
self.assertIs(self.module._reference_image(refs[1]), image2)
self.assertIs(self.module._reference_image(refs[6]), image7)
def test_merge_ref_slots_prefers_direct_refs_over_plan_refs(self):
merged = self.module._merge_ref_slots(
(
None,
{"kind": "character", "image": "direct2"},
None,
None,
{"kind": "character", "image": "direct5"},
None,
None,
None,
None,
),
(
{"kind": "location", "image": "plan1"},
{"kind": "location", "image": "plan2"},
{"kind": "location", "image": "plan3"},
None,
{"kind": "location", "image": "plan5"},
None,
{"kind": "location", "image": "plan7"},
None,
None,
),
)
self.assertEqual(
[self.module._reference_image(ref) if ref is not None else None for ref in merged],
["plan1", "direct2", "plan3", None, "direct5", None, "plan7", None, None],
)
def test_reference_context_matches_character_names_and_location_tags(self):
refs = [