Remove long video plan integration
This commit is contained in:
@@ -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 scene’s 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
@@ -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 "") + \
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
Reference in New Issue
Block a user