diff --git a/dumas_h3_longvideos.py b/dumas_h3_longvideos.py index ef4b79f..604e7ce 100644 --- a/dumas_h3_longvideos.py +++ b/dumas_h3_longvideos.py @@ -6331,10 +6331,27 @@ class H3LongVideos: override_notes = [beat_override_summary(beat, index) for index, beat in enumerate(beats, 1)] override_notes = [note for note in override_notes if note] any_tags_anywhere = any(picture_tags(g) for g in gens) + anatomy_shots = [ + shot_index + 1 + for shot_index, gen in enumerate(gens) + if ANATOMY_STATE.strip() in gen + ] + anatomy_mode = ("forced" if anatomy_guard == "on" else + "auto" if anatomy_guard == "auto" else + "off") + anatomy_note = "" + if anatomy_shots: + if anatomy_mode == "forced": + anatomy_note = (f" ANATOMY -- guard injected on shot(s) " + f"{','.join(str(n) for n in anatomy_shots)}") + elif anatomy_mode == "auto": + anatomy_note = (f" ANATOMY -- guard injected on shot(s) " + f"{','.join(str(n) for n in anatomy_shots)} " + f"(auto: multi-person beats and/or sub-native or LoRA-biased runs)") if plan_only: - # Preview the split using THIS node's own settings -- no render, near-instant. - shots = len(gens) + # Preview the split using THIS node's own settings -- no render, near-instant. + shots = len(gens) plan_lens = (lens + [ln] * shots)[:shots] total = round(sum(plan_lens) / fps, 2) uniform = len(set(plan_lens)) == 1 @@ -6398,9 +6415,10 @@ class H3LongVideos: (("DIALOGUE MAY BE CUT OFF -- " + "; ".join(fit_warnings) + ". ") if fit_warnings else "") + \ (f"PLAN (no render): {shape} = ~{total:g}s at {w}x{h}. " f"{len(beats) or 1} beat(s). decode {'tiled' if tiled else 'full'}. {vram_str}." - + (f" {beats_note}." if beats_note else "") - + (" ANCHOR: " + "; ".join(anchor_hazards) + "." - if anchor_hazards else "") + + (f" {beats_note}." if beats_note else "") + + (" ANCHOR: " + "; ".join(anchor_hazards) + "." + if anchor_hazards else "") + + (f"{anatomy_note}." if anatomy_note else "") + (f"{plan_audio}." if plan_audio else "") + (" EXPOSURE -- " + "; ".join(wardrobe_notes) + "." if wardrobe_notes else "") @@ -6814,13 +6832,14 @@ class H3LongVideos: + ("LoRA active -- count front-loaded so it binds before the scene" if lora_on else "") + ").") if count_subjects else "") - + ((" " + preflight_txt.strip()) if preflight_txt else "") - + (f" MOUTH -- shot(s) {','.join(str(n) for n in mouth_settled)} were seeded " - f"from a settled mouth ({MOUTH_SETTLE_FRAMES}f before the cut), because the " - f"shot before them ended on dialogue." if mouth_settled else "") - + (f"{latent_note}." if latent_note else "") - + (f" SLA LoRA '{os.path.basename(str(sla_name))}' paired with sparse attention." - if sla_name and sparse_on else "") + + ((" " + preflight_txt.strip()) if preflight_txt else "") + + (f" MOUTH -- shot(s) {','.join(str(n) for n in mouth_settled)} were seeded " + f"from a settled mouth ({MOUTH_SETTLE_FRAMES}f before the cut), because the " + f"shot before them ended on dialogue." if mouth_settled else "") + + (f"{anatomy_note}." if anatomy_note else "") + + (f"{latent_note}." if latent_note else "") + + (f" SLA LoRA '{os.path.basename(str(sla_name))}' paired with sparse attention." + if sla_name and sparse_on else "") + (f" {beats_note}." if beats_note else "") + (f"{audio_note}." if audio_note else "") + (" EXPOSURE -- " + "; ".join(wardrobe_notes) + "." diff --git a/tests/test_dumas_h3_longvideos.py b/tests/test_dumas_h3_longvideos.py index f05722d..458c577 100644 --- a/tests/test_dumas_h3_longvideos.py +++ b/tests/test_dumas_h3_longvideos.py @@ -437,7 +437,7 @@ class DumasH3LongVideosHelperTests(unittest.TestCase): module.dialogue_filler_warnings = lambda *_args, **_kwargs: [] module.distribute_generations = lambda anchor, beats, *_args, **_kwargs: [ f"[Generation 1] {anchor}. {beats[0]}", - f"[Generation 2] {anchor}. {beats[1]}", + f"[Generation 2] {anchor}. {beats[1]}{module.ANATOMY_STATE}", ] module.continuity_warnings = lambda _gens: [] module._empty_av_latent = lambda *_args, **_kwargs: ({"samples": "latent"},) @@ -459,13 +459,17 @@ class DumasH3LongVideosHelperTests(unittest.TestCase): plan_only=True, ) - self.assertEqual( + self.assertIn( + "[Generation 1] editorial room, soft practical lighting. Francine stands alone.", result[3], - "[Generation 1] editorial room, soft practical lighting. Francine stands alone.\n---\n" + ) + self.assertIn( "[Generation 2] editorial room, soft practical lighting. Francine and Frankie walk together.", + result[3], ) self.assertIn("2 beat(s)", result[2]) self.assertIn("2 shot(s)", result[2]) + self.assertIn("ANATOMY -- guard injected on shot(s) 2", result[2]) self.assertEqual(result[-2:], ([], [])) finally: module.torch = original_torch