Fix to the placement of

This commit is contained in:
2026-08-05 21:53:54 +02:00
parent 06d2d27dad
commit eac1d7968d
5 changed files with 42 additions and 54 deletions
+5 -2
View File
@@ -1503,9 +1503,12 @@
},
"Logo": {
"source_file": "Logo.mov",
"duration": 14.0,
"duration": 18.0,
"has_audio": true,
"is_shared": true
"is_shared": true,
"cutout": "fullscreen",
"layer": "above",
"pause_narration": 14.0
},
"MontageZoom": {
"source_file": "MontageZoom.mp4",
+5 -4
View File
@@ -1501,12 +1501,13 @@
"has_audio": false,
"is_shared": true
},
"Logo": {
"source_file": "Logo.mov",
"duration": 14.0,
"duration": 18.0,
"has_audio": true,
"is_shared": true
},
"is_shared": true,
"cutout": "fullscreen",
"layer": "above",
"pause_narration": 14.0
"MontageZoom": {
"source_file": "MontageZoom.mp4",
"duration": 17.0,
+26 -47
View File
@@ -3744,6 +3744,7 @@ def _print_render_plan_details(plan, marker_timings, slides: dict, events=None)
so markers the raw alignment marks unaligned still show their real position.
"""
from .models import CAMERA_PRESETS
from .transformer import _SHORTHAND_PREFIXES
events_by_id = {e["id"]: e for e in (events or [])}
@@ -3817,44 +3818,13 @@ def _print_render_plan_details(plan, marker_timings, slides: dict, events=None)
else:
aligned_count += 1
print(f' {marker_id:6} {_st}{conf_str} "{context}"')
elif any(
marker_id.startswith(p)
for p in (
"video:",
"vft:",
"vfb:",
"vf2t:",
"vf2b:",
"vst:",
"vsb:",
"vftp:",
"vfbp:",
"vf2tp:",
"vf2bp:",
"vstp:",
"vsbp:",
elif (
_vpfx := next(
(p for p in _SHORTHAND_PREFIXES if marker_id.startswith(p)), None
)
):
) or marker_id.startswith("video:"):
aligned_count += 1
pfx_len = next(
len(p)
for p in (
"video:",
"vft:",
"vfb:",
"vf2t:",
"vf2b:",
"vst:",
"vsb:",
"vftp:",
"vfbp:",
"vf2tp:",
"vf2bp:",
"vstp:",
"vsbp:",
)
if marker_id.startswith(p)
)
pfx_len = len(_vpfx) if _vpfx else len("video:")
# Handles are stored lowercased in videos.json (and the plan's video
# events), so lowercase before the lookup — otherwise a camel-cased
# marker like vst:KnightRotating misses and shows '?'.
@@ -3863,33 +3833,42 @@ def _print_render_plan_details(plan, marker_timings, slides: dict, events=None)
event = video_events_by_id.get(video_id)
if event:
cutout_name = event.cutout_name
end_on = event.video_source.end_on or "next_slide"
# The resolved per-occurrence policy (incl. inline overrides), not
# just the videos.json default.
end_on = event.end_on or event.video_source.end_on or "next_slide"
layer_tag = f" [{event.layer}]"
# FINAL (output-time) window from the plan — pause-shifted, same
# base as the slides above. Showing start→end makes end_on visible:
# the clip should stop at the next slide/video's time. (Previously
# this printed the RAW pre-pause marker time, which looked like an
# 18s drift against the pause-shifted slides.)
t_str = (
f"{_format_time(event.start_time)}{_format_time(event.end_time)}"
)
else:
# No resolved event — but the shorthand prefix itself fixes the
# cutout and layer (vst: = square/above), so never show '?'.
from .transformer import _SHORTHAND_PREFIXES
_pfx = next(
(p for p in _SHORTHAND_PREFIXES if marker_id.startswith(p)), None
)
if _pfx:
cutout_name, _layer = _SHORTHAND_PREFIXES[_pfx]
if _vpfx:
cutout_name, _layer = _SHORTHAND_PREFIXES[_vpfx]
layer_tag = f" [{_layer}]"
else:
cutout_name = "?"
layer_tag = ""
end_on = "next_slide"
t_str = _format_time(timing.timestamp) # no event → raw fallback
cache_ind = " 📁" if video_id in plan.cached_files else ""
print(
f" {marker_id:20} {time_str} in '{cutout_name}' [{end_on}]{layer_tag}{cache_ind}"
f" {marker_id:28} {t_str} in '{cutout_name}' [{end_on}]{layer_tag}{cache_ind}"
)
elif marker_id.startswith("narration:"):
aligned_count += 1
video_id = marker_id[10:]
video_id = marker_id[10:].lower()
cache_ind = " 📁" if video_id in plan.cached_files else ""
print(f" {marker_id:20} {time_str} (continuous){cache_ind}")
# Final (output-time) start from the plan, consistent with slides/videos.
_nev = video_events_by_id.get(video_id)
_nt = _format_time(_nev.start_time) if _nev else time_str
print(f" {marker_id:20} {_nt} (continuous){cache_ind}")
elif marker_id in CAMERA_PRESETS:
aligned_count += 1
print(f" {time_str} [{marker_id}]")
+4
View File
@@ -450,6 +450,10 @@ class VideoEvent:
cutout: "CutoutDefinition"
cutout_name: str = "" # resolved cutout name (e.g. "fullscreen"), for display
layer: str = "above" # "above" = on top of slides; "below" = behind slides
# Resolved per-occurrence end policy (next_slide/next_video/end/loop/…). Kept so
# the render-plan listing can report the ACTUAL end rule (incl. inline overrides),
# not just the videos.json default. Purely informational; end_time is authoritative.
end_on: str = ""
# Resolved per-occurrence CSS-like cutout placement (see VideoSource).
object_fit: str = "cover"
object_position: str = "center"
+1
View File
@@ -1512,6 +1512,7 @@ def _extract_video_events(
cutout=cutout,
cutout_name=cutout_name,
layer=layer,
end_on=end_on or "",
volume=volume,
object_fit=object_fit,
object_position=object_position,