Adding fix to the logo pause narration

This commit is contained in:
2026-08-08 11:19:57 +02:00
parent 3b0439a00c
commit a550ee8b6b
2 changed files with 59 additions and 14 deletions
+12 -1
View File
@@ -1506,9 +1506,20 @@ def _extract_video_events(
# it), so a clip spanning a chunk boundary survives into the later chunk. # it), so a clip spanning a chunk boundary survives into the later chunk.
if end_time <= range_start or start_time >= range_end: if end_time <= range_start or start_time >= range_end:
continue continue
skip_override = None
if pause_narration:
# A pause-narration CUTSCENE must render WHOLE in the single chunk where it
# starts. Its end = start + pause_narration deliberately overshoots the
# pre-pause timeline (the 18s freeze doesn't exist yet at extraction), so
# clamping it to this chunk's pre-pause range_end would truncate the freeze,
# AND it would otherwise ALSO be pulled into the next chunk as a "spanning"
# clip — duplicating the freeze (the video6 "two 18s pauses / logo shows one
# frame" bug). Own it only where it starts; never seek or clamp it.
if start_time < range_start:
continue # earlier chunk owns this cutscene
else:
# A clip that began before this window is already mid-playback at the seam; # A clip that began before this window is already mid-playback at the seam;
# seek into it so it resumes at the right frame instead of restarting. # seek into it so it resumes at the right frame instead of restarting.
skip_override = None
if start_time < range_start: if start_time < range_start:
into = range_start - start_time # elapsed since the clip started into = range_start - start_time # elapsed since the clip started
base = skip # resolved per-occurrence skip base = skip # resolved per-occurrence skip
+34
View File
@@ -134,10 +134,44 @@ def test_video():
check("full render includes bg with no seek", bg3 is not None and bg3.skip_override is None) check("full render includes bg with no seek", bg3 is not None and bg3.skip_override is None)
def test_pause_cutscene_chunk_ownership():
# A pause_narration cutscene must live WHOLLY in the chunk where it starts: its
# end = start + pause_narration overshoots the pre-pause timeline, so it must not be
# truncated by range_end nor duplicated into the next chunk (the video6 double-freeze
# / one-frame-logo bug).
print("pause cutscene chunk ownership:")
cutouts = {"fullscreen": CutoutDefinition(x=0, y=0, height=1080, width=1920)}
videos = {
"logo": VideoSource(source_file="logo.mov", cutout="fullscreen", layer="above",
duration=18.0, pause_narration=18.0),
}
slides = {f"S{i}": SlideDefinition(image=f"S{i}.png", type="slide") for i in range(1, 6)}
markers = [MarkerTiming(marker_id=f"S{i}", timestamp=(i - 1) * 30.0, context="", confidence=1.0)
for i in range(1, 6)]
# Cutscene triggers at t=100 (between S4=90 and S5=120). Its end = 100+18 = 118.
markers.append(MarkerTiming(marker_id="vftp:logo", timestamp=100.0, context="", confidence=1.0))
total = 200.0
# Owning chunk [90, 110): starts inside it. End must NOT be clamped to 110 → full 18s.
evs, _ = _extract_video_events(markers, videos, cutouts, slides, total, time_range=(90.0, 110.0))
lg = next((e for e in evs if e.video_id == "logo"), None)
check("cutscene INCLUDED in the chunk it starts in", lg is not None)
if lg is not None:
check("cutscene end NOT clamped to range_end (full pause length)",
abs((lg.end_time - lg.start_time) - 18.0) < 1e-6,
f"duration={lg.end_time - lg.start_time}")
# Next chunk [110, 200): the cutscene started earlier → must be EXCLUDED (no dupe freeze).
evs2, _ = _extract_video_events(markers, videos, cutouts, slides, total, time_range=(110.0, 200.0))
check("cutscene EXCLUDED from the next chunk (no duplicate freeze)",
not any(e.video_id == "logo" for e in evs2))
if __name__ == "__main__": if __name__ == "__main__":
test_audio() test_audio()
test_crossfade_phase() test_crossfade_phase()
test_video() test_video()
test_pause_cutscene_chunk_ownership()
print() print()
if _fails: if _fails:
print(f"FAILED: {len(_fails)} check(s): {', '.join(_fails)}") print(f"FAILED: {len(_fails)} check(s): {', '.join(_fails)}")