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( parser.add_argument(
"--realign", "--realign",
action="store_true", action="store_true",
help="For build/render: discard existing events.json times and re-align " help="(build re-aligns by default now) Explicitly re-align manuscript markers "
"manuscript markers to the transcript from scratch (e.g. after re-recording)", "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( parser.add_argument(
"--slides", "--slides",
@@ -397,7 +404,9 @@ Examples:
args.slides, args.slides,
args.res, args.res,
args.force, 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": elif action == "render":
return cmd_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. # all the rig ever needs and the output can't silently diverge from the build.
from . import scaffold as _scaffold 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 not plan_only:
if _existing_events is None or _scaffold.read_scaffold(project_path) is None: if _existing_events is None or _scaffold.read_scaffold(project_path) is None:
print( print(
@@ -5143,21 +5157,23 @@ def _cmd_render_impl(
# only consumes the files — so the timing layer is written exactly once, by build. # 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: if plan_only and slide_range is None and _output_path_override is None:
_events = _scaffold.derive_events(marker_timings, slides, videos, audio) _events = _scaffold.derive_events(marker_timings, slides, videos, audio)
# merge restores each id's human `adjustment` (the relative tweak). # Carry each id's human `adjustment` (a relative nudge) forward from the
_events = _scaffold.merge_events(_events, _existing_events) # previous events.json — matched by (id, ordinal) — so re-aligning keeps your
if _existing_events: # offsets even though narration_time is recomputed from the transcript.
# Override path: the marker_timings the plan used were EFFECTIVE _events = _scaffold.merge_events(_events, _old_events)
# narration (narration_time + adjustment). narration_time itself is if realign:
# owned by events.json — restore it so the effective value doesn't leak # Re-align (default): narration_time comes fresh from the transcript;
# into the stored narration_time. Pair by ordinal (not id) so a marker # recompute the interpolated markers between the aligned anchors.
# reused several times keeps each occurrence's own narration_time _scaffold.reinterpolate_events(_events)
# instead of collapsing onto the last occurrence's value. elif _old_events:
for e, _old in _scaffold.pair_events_by_ordinal(_events, _existing_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: if _old is not None and _old.get("narration_time") is not None:
e["narration_time"] = _old["narration_time"] 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. # final_time = (narration + adjustment) shifted by preceding pauses.
_scaffold.compute_final_times(_events) _scaffold.compute_final_times(_events)
# events.json carries representation-only narration-track events so a GUI # events.json carries representation-only narration-track events so a GUI