Restore legacy H3 ref image inputs
This commit is contained in:
+20
-1
@@ -5731,6 +5731,15 @@ class H3LongVideos:
|
|||||||
"ref_7": ("REFERENCE", {"tooltip": "Reference object for <Picture 7>."}),
|
"ref_7": ("REFERENCE", {"tooltip": "Reference object for <Picture 7>."}),
|
||||||
"ref_8": ("REFERENCE", {"tooltip": "Reference object for <Picture 8>."}),
|
"ref_8": ("REFERENCE", {"tooltip": "Reference object for <Picture 8>."}),
|
||||||
"ref_9": ("REFERENCE", {"tooltip": "Reference object for <Picture 9>."}),
|
"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_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."}),
|
||||||
|
"ref_image_5": ("*", {"tooltip": "Legacy alias for ref_5. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||||
|
"ref_image_6": ("*", {"tooltip": "Legacy alias for ref_6. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||||
|
"ref_image_7": ("*", {"tooltip": "Legacy alias for ref_7. Accepts old IMAGE wiring or a REFERENCE payload."}),
|
||||||
|
"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,
|
"plan_only": ("BOOLEAN", {"default": False,
|
||||||
"tooltip": "Preview the shot split WITHOUT rendering. Uses THIS node's own settings (no "
|
"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 "
|
"second node, no duplicate entry): returns the plan in 'info' and the "
|
||||||
@@ -6245,6 +6254,9 @@ class H3LongVideos:
|
|||||||
ref_1=None, ref_2=None, ref_3=None, ref_4=None,
|
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_5=None, ref_6=None, ref_7=None, ref_8=None,
|
||||||
ref_9=None,
|
ref_9=None,
|
||||||
|
ref_image_1=None, ref_image_2=None, ref_image_3=None, ref_image_4=None,
|
||||||
|
ref_image_5=None, ref_image_6=None, ref_image_7=None, ref_image_8=None,
|
||||||
|
ref_image_9=None,
|
||||||
ref_mode="where tagged", ref_image_size="match", ref_noise_aug=0.999,
|
ref_mode="where tagged", ref_image_size="match", ref_noise_aug=0.999,
|
||||||
detail_pass=False, detail_sampler_name="euler", detail_scheduler="karras",
|
detail_pass=False, detail_sampler_name="euler", detail_scheduler="karras",
|
||||||
detail_steps=8, detail_denoise=0.4,
|
detail_steps=8, detail_denoise=0.4,
|
||||||
@@ -6267,9 +6279,16 @@ class H3LongVideos:
|
|||||||
f"computed at {H3_FPS}; set your video-save node to {H3_FPS} too")
|
f"computed at {H3_FPS}; set your video-save node to {H3_FPS} too")
|
||||||
fps = H3_FPS
|
fps = H3_FPS
|
||||||
w, h = parse_resolution(resolution)
|
w, h = parse_resolution(resolution)
|
||||||
direct_ref_slots = (
|
legacy_ref_slots = (
|
||||||
|
ref_image_1, ref_image_2, ref_image_3, ref_image_4, ref_image_5,
|
||||||
|
ref_image_6, ref_image_7, ref_image_8, ref_image_9,
|
||||||
|
)
|
||||||
|
direct_ref_slots = tuple(
|
||||||
|
current if current is not None else legacy
|
||||||
|
for current, legacy in zip((
|
||||||
ref_1, ref_2, ref_3, ref_4, ref_5,
|
ref_1, ref_2, ref_3, ref_4, ref_5,
|
||||||
ref_6, ref_7, ref_8, ref_9,
|
ref_6, ref_7, ref_8, ref_9,
|
||||||
|
), legacy_ref_slots)
|
||||||
)
|
)
|
||||||
ref_slots = direct_ref_slots
|
ref_slots = direct_ref_slots
|
||||||
direct_ref_count = len(_connected_refs(direct_ref_slots))
|
direct_ref_count = len(_connected_refs(direct_ref_slots))
|
||||||
|
|||||||
@@ -369,6 +369,12 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
for index in range(1, 10):
|
for index in range(1, 10):
|
||||||
self.assertIn(f"ref_{index}", optional)
|
self.assertIn(f"ref_{index}", optional)
|
||||||
|
|
||||||
|
def test_input_types_keep_legacy_ref_image_aliases(self):
|
||||||
|
optional = self.module.H3LongVideos.INPUT_TYPES()["optional"]
|
||||||
|
|
||||||
|
for index in range(1, 10):
|
||||||
|
self.assertIn(f"ref_image_{index}", optional)
|
||||||
|
|
||||||
def test_node_appends_per_beat_list_outputs_without_reordering_existing_slots(self):
|
def test_node_appends_per_beat_list_outputs_without_reordering_existing_slots(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.module.H3LongVideos.RETURN_NAMES[-2:],
|
self.module.H3LongVideos.RETURN_NAMES[-2:],
|
||||||
@@ -418,7 +424,104 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
self.assertIn("Persistent appearance for Mara: silver hair.", context)
|
self.assertIn("Persistent appearance for Mara: silver hair.", context)
|
||||||
self.assertIn("Persistent wardrobe/style for Mara: red jacket.", context)
|
self.assertIn("Persistent wardrobe/style for Mara: red jacket.", context)
|
||||||
self.assertIn("Character notes for Mara: wears a long grey coat.", context)
|
self.assertIn("Character notes for Mara: wears a long grey coat.", context)
|
||||||
self.assertIn("Location context for Hangar: wet concrete floor.", context)
|
|
||||||
|
def test_run_uses_legacy_ref_image_inputs_when_new_slots_are_empty(self):
|
||||||
|
calls = {}
|
||||||
|
original_parse_resolution = self.module.parse_resolution
|
||||||
|
original_connected_refs = self.module._connected_refs
|
||||||
|
original_reference_character_memory = self.module._reference_character_memory
|
||||||
|
original_vram_gb = self.module.vram_gb
|
||||||
|
original_dit_resident_gb = self.module.dit_resident_gb
|
||||||
|
original_lora_overhead_gb = self.module.lora_overhead_gb
|
||||||
|
original_resolve_shot_frames = self.module.resolve_shot_frames
|
||||||
|
original_lora_active = self.module.lora_active
|
||||||
|
original_sla_pairing = self.module.sla_pairing
|
||||||
|
original_apply_h3_model_sampling = self.module.apply_h3_model_sampling
|
||||||
|
original_split_paragraphs = self.module.split_paragraphs
|
||||||
|
original_expand_beats = self.module.expand_beats
|
||||||
|
original_anchor_warnings = self.module.anchor_warnings
|
||||||
|
original_anchor_contributes_nothing = self.module.anchor_contributes_nothing
|
||||||
|
original_anchor_is_action_beat = self.module.anchor_is_action_beat
|
||||||
|
original_distribute_generations = self.module.distribute_generations
|
||||||
|
original_continuity_warnings = self.module.continuity_warnings
|
||||||
|
original_speech_flags = self.module.speech_flags
|
||||||
|
original_annotate_script_debug = self.module.annotate_script_debug
|
||||||
|
original_empty_av_latent = self.module._empty_av_latent
|
||||||
|
original_torch_zeros = getattr(self.module.torch, "zeros", None)
|
||||||
|
try:
|
||||||
|
self.module.torch.zeros = lambda shape: shape
|
||||||
|
self.module.parse_resolution = lambda _resolution: (640, 360)
|
||||||
|
self.module._connected_refs = lambda refs: [ref for ref in refs if ref is not None]
|
||||||
|
self.module._reference_character_memory = lambda refs: (calls.setdefault("refs", tuple(refs)), "")[1]
|
||||||
|
self.module.vram_gb = lambda: (0, 0)
|
||||||
|
self.module.dit_resident_gb = lambda _model: 0
|
||||||
|
self.module.lora_overhead_gb = lambda _model: 0
|
||||||
|
self.module.resolve_shot_frames = lambda *args, **kwargs: (53, "")
|
||||||
|
self.module.lora_active = lambda _model: False
|
||||||
|
self.module.sla_pairing = lambda *_args, **_kwargs: ("", False, "")
|
||||||
|
self.module.apply_h3_model_sampling = lambda model, *_args: (model, "")
|
||||||
|
self.module.split_paragraphs = lambda _prompt, _sep: ["Anchor.", "Beat."]
|
||||||
|
self.module.expand_beats = lambda beat_paras, _split: (list(beat_paras), "")
|
||||||
|
self.module.anchor_warnings = lambda _anchor: []
|
||||||
|
self.module.anchor_contributes_nothing = lambda *_args, **_kwargs: False
|
||||||
|
self.module.anchor_is_action_beat = lambda *_args, **_kwargs: False
|
||||||
|
self.module.distribute_generations = lambda _anchor, beats, *_args, **_kwargs: list(beats)
|
||||||
|
self.module.continuity_warnings = lambda _gens: []
|
||||||
|
self.module.speech_flags = lambda _beats: []
|
||||||
|
self.module.annotate_script_debug = lambda *_args, **_kwargs: "script"
|
||||||
|
self.module._empty_av_latent = lambda *_args, **_kwargs: ({"samples": "latent"}, 5)
|
||||||
|
|
||||||
|
clip = types.SimpleNamespace(
|
||||||
|
tokenize=lambda text, **kwargs: text,
|
||||||
|
encode_from_tokens_scheduled=lambda tokens: tokens,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = self.module.H3LongVideos().run(
|
||||||
|
model=object(),
|
||||||
|
clip=clip,
|
||||||
|
vae=object(),
|
||||||
|
audio_vae=object(),
|
||||||
|
prompt="Anchor only.",
|
||||||
|
resolution="16:9",
|
||||||
|
steps=6,
|
||||||
|
cfg=1,
|
||||||
|
sampler_name="res_multistep",
|
||||||
|
scheduler="simple",
|
||||||
|
seed=1,
|
||||||
|
plan_only=True,
|
||||||
|
ref_image_1={"image": "legacy-1"},
|
||||||
|
ref_image_3={"image": "legacy-3"},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(calls["refs"][0]["image"], "legacy-1")
|
||||||
|
self.assertIsNone(calls["refs"][1])
|
||||||
|
self.assertEqual(calls["refs"][2]["image"], "legacy-3")
|
||||||
|
self.assertEqual(result[2].count("ref2va: 2 reference image(s)"), 1)
|
||||||
|
finally:
|
||||||
|
self.module.parse_resolution = original_parse_resolution
|
||||||
|
self.module._connected_refs = original_connected_refs
|
||||||
|
self.module._reference_character_memory = original_reference_character_memory
|
||||||
|
self.module.vram_gb = original_vram_gb
|
||||||
|
self.module.dit_resident_gb = original_dit_resident_gb
|
||||||
|
self.module.lora_overhead_gb = original_lora_overhead_gb
|
||||||
|
self.module.resolve_shot_frames = original_resolve_shot_frames
|
||||||
|
self.module.lora_active = original_lora_active
|
||||||
|
self.module.sla_pairing = original_sla_pairing
|
||||||
|
self.module.apply_h3_model_sampling = original_apply_h3_model_sampling
|
||||||
|
self.module.split_paragraphs = original_split_paragraphs
|
||||||
|
self.module.expand_beats = original_expand_beats
|
||||||
|
self.module.anchor_warnings = original_anchor_warnings
|
||||||
|
self.module.anchor_contributes_nothing = original_anchor_contributes_nothing
|
||||||
|
self.module.anchor_is_action_beat = original_anchor_is_action_beat
|
||||||
|
self.module.distribute_generations = original_distribute_generations
|
||||||
|
self.module.continuity_warnings = original_continuity_warnings
|
||||||
|
self.module.speech_flags = original_speech_flags
|
||||||
|
self.module.annotate_script_debug = original_annotate_script_debug
|
||||||
|
self.module._empty_av_latent = original_empty_av_latent
|
||||||
|
if original_torch_zeros is None:
|
||||||
|
delattr(self.module.torch, "zeros")
|
||||||
|
else:
|
||||||
|
self.module.torch.zeros = original_torch_zeros
|
||||||
|
|
||||||
def test_reference_context_matches_tagged_character_without_name_in_text(self):
|
def test_reference_context_matches_tagged_character_without_name_in_text(self):
|
||||||
refs = [
|
refs = [
|
||||||
|
|||||||
Reference in New Issue
Block a user