Fixes to video6

This commit is contained in:
2026-08-04 16:37:21 +02:00
parent d2550d9432
commit f328759eab
+33 -17
View File
@@ -172,8 +172,15 @@ Examples:
parser.add_argument(
"--realign",
action="store_true",
help="For build/render: discard existing events.json times and re-align "
"manuscript markers to the transcript from scratch (e.g. after re-recording)",
help="(build re-aligns by default now) Explicitly re-align manuscript markers "
"to the transcript, recomputing narration_time. Your `adjustment` offsets are "
"always carried forward.",
)
parser.add_argument(
"--no-realign",
action="store_true",
help="For build: DON'T re-align — keep events.json's stored times verbatim "
"(freeze the timing layer, e.g. to preserve direct narration_time edits).",
)
parser.add_argument(
"--slides",
@@ -397,7 +404,9 @@ Examples:
args.slides,
args.res,
args.force,
realign=args.realign,
# build re-aligns by default (keeping your adjustments); --no-realign
# freezes events.json's stored times instead.
realign=not args.no_realign,
)
elif action == "render":
return cmd_render(
@@ -5050,7 +5059,12 @@ def _cmd_render_impl(
# all the rig ever needs and the output can't silently diverge from the build.
from . import scaffold as _scaffold
_existing_events = None if realign else _scaffold.read_events(project_path)
# Always read the previous events.json: even when re-aligning we carry each
# event's manual `adjustment` (a relative nudge) forward. `_existing_events`
# (the timing OVERRIDE — use stored times instead of aligning) is only set when
# NOT re-aligning, so render / `all` are unaffected by the always-read.
_old_events = _scaffold.read_events(project_path)
_existing_events = None if realign else _old_events
if not plan_only:
if _existing_events is None or _scaffold.read_scaffold(project_path) is None:
print(
@@ -5143,21 +5157,23 @@ def _cmd_render_impl(
# only consumes the files — so the timing layer is written exactly once, by build.
if plan_only and slide_range is None and _output_path_override is None:
_events = _scaffold.derive_events(marker_timings, slides, videos, audio)
# merge restores each id's human `adjustment` (the relative tweak).
_events = _scaffold.merge_events(_events, _existing_events)
if _existing_events:
# Override path: the marker_timings the plan used were EFFECTIVE
# narration (narration_time + adjustment). narration_time itself is
# owned by events.json — restore it so the effective value doesn't leak
# into the stored narration_time. Pair by ordinal (not id) so a marker
# reused several times keeps each occurrence's own narration_time
# instead of collapsing onto the last occurrence's value.
for e, _old in _scaffold.pair_events_by_ordinal(_events, _existing_events):
# Carry each id's human `adjustment` (a relative nudge) forward from the
# previous events.json — matched by (id, ordinal) — so re-aligning keeps your
# offsets even though narration_time is recomputed from the transcript.
_events = _scaffold.merge_events(_events, _old_events)
if realign:
# Re-align (default): narration_time comes fresh from the transcript;
# recompute the interpolated markers between the aligned anchors.
_scaffold.reinterpolate_events(_events)
elif _old_events:
# Freeze (--no-realign): the marker_timings the plan used were EFFECTIVE
# narration (narration_time + adjustment). narration_time itself is owned
# by events.json — restore it so the effective value doesn't leak into the
# stored narration_time. Pair by ordinal (not id) so a marker reused
# several times keeps each occurrence's own narration_time.
for e, _old in _scaffold.pair_events_by_ordinal(_events, _old_events):
if _old is not None and _old.get("narration_time") is not None:
e["narration_time"] = _old["narration_time"]
else:
# Fresh align: recompute interpolated narration times between anchors.
_scaffold.reinterpolate_events(_events)
# final_time = (narration + adjustment) shifted by preceding pauses.
_scaffold.compute_final_times(_events)
# events.json carries representation-only narration-track events so a GUI