diff --git a/gnommo/scaffold.py b/gnommo/scaffold.py index f75a3a0..5e346cc 100644 --- a/gnommo/scaffold.py +++ b/gnommo/scaffold.py @@ -181,7 +181,7 @@ def derive_events( vs, t.overrides, default_end_on=( - None if t.marker_id.startswith("narration:") else "next_video" + None if t.marker_id.startswith("narration:") else "next_slide" ), ) e["handle"] = pres["handle"] diff --git a/gnommo/transformer.py b/gnommo/transformer.py index e20f093..c6af800 100644 --- a/gnommo/transformer.py +++ b/gnommo/transformer.py @@ -63,7 +63,7 @@ def resolve_video_presentation( marker_id: str, video_source, overrides: Optional[dict] = None, - default_end_on: Optional[str] = "next_video", + default_end_on: Optional[str] = "next_slide", ) -> dict: """Resolve a video marker's per-occurrence presentation to an atomic dict. @@ -74,8 +74,9 @@ def resolve_video_presentation( videos.json collision. Precedence per field: explicit event override > shorthand prefix > videos.json - default > built-in default. `default_end_on` is "next_video" for video triggers and - None for [narration:] (which runs to the end). + default > built-in default. `default_end_on` is "next_slide" for video triggers + (so an untagged clip can't overstay and obscure later content) and None for + [narration:] (which runs to the end). Returns {handle, cutout, layer, end_on, take, pause_narration}. """ @@ -1009,9 +1010,20 @@ def build_render_plan( if vid_event is event: # Don't shift the pause event by its own pause continue + # A clip whose window STRADDLES the freeze (starts before, ends after) + # would otherwise be stretched across the whole cutscene. Its overlay + # source isn't freeze-spliced like the narration is, so it'd keep + # advancing under the cutscene and surface the wrong frame in the sliver + # between the cutscene ending and its own (shifted) end — the video7 + # "appears at the start, vanishes when it should show" artifact. Instead + # end it right at the freeze onset: it plays its pre-pause content, then + # the cutscene cleanly takes over. + straddles = vid_event.start_time < narration_time < vid_event.end_time if vid_event.start_time >= narration_time: vid_event.start_time += pause_duration - if vid_event.end_time > narration_time: + if straddles: + vid_event.end_time = narration_time + elif vid_event.end_time > narration_time: vid_event.end_time += pause_duration for aud_event in audio_events: @@ -1407,7 +1419,7 @@ def _extract_video_events( marker_id, video_source, overrides, - default_end_on=(None if trigger_type == "narration" else "next_video"), + default_end_on=(None if trigger_type == "narration" else "next_slide"), ) cutout_name = pres["cutout"] cutout = cutouts[cutout_name]