Report per-shot ref matches in H3 script

This commit is contained in:
2026-08-27 07:48:04 +00:00
parent 04c403e1d0
commit 32fc9b39df
2 changed files with 43 additions and 2 deletions
+41 -2
View File
@@ -3273,6 +3273,45 @@ def annotate_script_guards(gens, anatomy_shots, anatomy_mode):
return "\n".join(lines + ["", body]) if body else "\n".join(lines) return "\n".join(lines + ["", body]) if body else "\n".join(lines)
def annotate_script_debug(gens, anatomy_shots, anatomy_mode, ref_slots):
parts = [annotate_script_guards(gens, anatomy_shots, anatomy_mode)]
ref_report = annotate_script_refs(gens, ref_slots)
if ref_report:
parts.insert(1, ref_report)
return "\n".join(part for part in parts if part)
def annotate_script_refs(gens, ref_slots):
"""Per-shot reference routing summary for the script socket."""
lines = []
for shot_index, gen in enumerate(gens or [], 1):
tagged = _slot_refs_for_text(gen, ref_slots)
named = _named_character_refs_for_text(gen, ref_slots)
seen = set()
merged = []
for slot_number, ref in tagged:
key = (slot_number, "tag")
if key in seen:
continue
seen.add(key)
merged.append((slot_number, ref, "tag"))
for slot_number, ref in named:
key = (slot_number, "name")
if key in seen or any(slot_number == existing[0] for existing in merged):
continue
seen.add(key)
merged.append((slot_number, ref, "name"))
if not merged:
lines.append(f"# shot {shot_index} refs: none")
continue
labels = []
for slot_number, ref, source in merged:
label = _reference_text(ref.get("name")) or _reference_text(ref.get("id")) or f"reference {slot_number}"
labels.append(f"Picture {slot_number} {label} (by {source})")
lines.append(f"# shot {shot_index} refs: " + "; ".join(labels))
return "\n".join(lines)
def speech_flags(beats): def speech_flags(beats):
"""Per-beat: does it contain scripted (quoted) dialogue? Same rule the prompt """Per-beat: does it contain scripted (quoted) dialogue? Same rule the prompt
builder uses to decide silencing, exposed so the renderer can also MUTE the builder uses to decide silencing, exposed so the renderer can also MUTE the
@@ -6455,7 +6494,7 @@ class H3LongVideos:
# correctly-SHAPED empty one rather than None: a downstream LATENT input # correctly-SHAPED empty one rather than None: a downstream LATENT input
# would choke on None, and this keeps the preview wireable exactly like # would choke on None, and this keeps the preview wireable exactly like
# a real run. # a real run.
return (ph_img, ph_audio, plan, annotate_script_guards(gens, anatomy_shots, anatomy_mode), max(plan_lens), return (ph_img, ph_audio, plan, annotate_script_debug(gens, anatomy_shots, anatomy_mode, ref_slots), max(plan_lens),
sum(plan_lens), shots, total, float(fps), int(fps), sum(plan_lens), shots, total, float(fps), int(fps),
_empty_av_latent(w, h, 5, fps)[0], global_soundscape, [], []) _empty_av_latent(w, h, 5, fps)[0], global_soundscape, [], [])
@@ -6762,7 +6801,7 @@ class H3LongVideos:
watermark_opacity, watermark_margin, intro_text, intro_seconds, watermark_opacity, watermark_margin, intro_text, intro_seconds,
intro_fade, intro_size, intro_position, overlay_font, overlay_stroke) intro_fade, intro_size, intro_position, overlay_font, overlay_stroke)
script = annotate_script_guards(gens, anatomy_shots, anatomy_mode) script = annotate_script_debug(gens, anatomy_shots, anatomy_mode, ref_slots)
actual = all_frames.shape[0] / fps actual = all_frames.shape[0] / fps
uniform_len = len(set(shot_lens)) == 1 uniform_len = len(set(shot_lens)) == 1
shape_str = (f"{len(gens)} shot(s) x {shot_lens[0]}f (~{shot_lens[0] / fps:.1f}s each) " shape_str = (f"{len(gens)} shot(s) x {shot_lens[0]}f (~{shot_lens[0] / fps:.1f}s each) "
+2
View File
@@ -473,6 +473,8 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
) )
self.assertIn("# anatomy_guard: injected on shot(s) 2", result[3]) self.assertIn("# anatomy_guard: injected on shot(s) 2", result[3])
self.assertIn("# shot 1 refs: none", result[3])
self.assertIn("# shot 2 refs: none", result[3])
self.assertIn( self.assertIn(
"[Generation 1] editorial room, soft practical lighting. Francine stands alone.", "[Generation 1] editorial room, soft practical lighting. Francine stands alone.",
result[3], result[3],