Adding symmetric up down

This commit is contained in:
2026-07-25 21:43:21 +02:00
parent e7dc402d9e
commit f79a0cb082
+36 -15
View File
@@ -7,16 +7,17 @@ Workflow:
Design:
- commit appends a timestamped entry to commits.log
- up checks server commits.log for newer entry (aborts if found),
then rsyncs a manifest of only the *inputs* needed to render
(manuscript, slides, narration, audio, videos, keynote). For
narration it pushes the raw raw_mov/ recordings, NOT the processed
segments — the rig runs preprocess to produce the large
processed/*_processed.mov files itself. It also does NOT push the
rendered output (out/*.mp4/.srt) — that is produced on the rig, so
pushing a stale local copy would clobber it.
- down rsyncs everything the server has back to local, including the
freshly rendered out/*.mp4. Rendered output flows one way: rig → local.
- up checks server commits.log for newer entry (aborts if found), then
rsyncs the WHOLE project tree, excluding only the large/derived files
in _SYNC_EXCLUDES. Everything else — manuscript, slides, narration
raw_mov/, per-segment transcripts, events.json, audio, videos, keynote
— is carried automatically, so a new kind of input file can never be
silently left behind.
- down rsyncs the WHOLE project tree back, with the same _SYNC_EXCLUDES.
Sync model: move everything, exclude a small denylist. The exclusions are large
derived artifacts each side regenerates or ships on its own (rendered output,
preprocessed segments, downscales, chunk scratch), so they never travel over SSH.
"""
import json
@@ -27,16 +28,27 @@ from typing import Optional
_COMMITS_LOG = "commits.log"
# Dirs/patterns excluded on down (mirrors what up never pushes). Note: events.json
# and scaffold.json are NOT excluded — they must reach the rig so `down` + `render`
# is all that's needed there. The render never rewrites them, so they stay identical
# on both ends (no clobbering).
_DOWN_EXCLUDES = [
# Files/dirs NEVER transferred in either direction. Everything else syncs, so new
# artifacts (transcripts, manuscript_transcribed.txt, events.json, scaffold.json, …)
# are carried automatically without touching this list. These are large, derived,
# or machine-local outputs that each side regenerates or ships itself:
# - out/ rendered video (produced on the rig; `handoff` ships it for review)
# - processed/ heavy preprocessed *_processed.mov segments (rig regenerates)
# - intermediate/ ffmpeg work files
# - low/ proxy/ derived downscales
# - **/chunks/ per-chunk preprocess scratch
# Note: events.json / scaffold.json are deliberately NOT excluded — they must reach
# the rig so `down` + `render` is all that's needed there, and render never rewrites
# them, so they stay identical on both ends.
_SYNC_EXCLUDES = [
"out/",
"media/narration/processed/",
"media/narration/intermediate/",
"media/videos/intermediate/",
"media/narration/low/",
"media/videos/low/",
"media/narration/proxy/",
"media/videos/proxy/",
"**/chunks/",
"*.tmp",
".*", # rsync in-progress temp files (.filename.XXXXXX) and .DS_Store
@@ -125,6 +137,15 @@ def _build_manifest(project_path: Path) -> list[str]:
for f in sorted(raw_mov_dir.glob("*.mov")):
if f.is_file() and not f.name.startswith("."):
files.add(str(f.relative_to(project_path)))
# Per-segment Whisper transcripts. These are the ONLY non-deterministic input
# to marker alignment (Whisper is not bit-reproducible across platforms), so
# syncing them makes `build` produce identical events.json on any machine — the
# rig can no longer diverge by re-transcribing locally.
transcripts_dir = narration_dir / "transcripts"
if transcripts_dir.is_dir():
for f in sorted(transcripts_dir.glob("*.json")):
if f.is_file() and not f.name.startswith("."):
files.add(str(f.relative_to(project_path)))
# Audio — standard location, non-shared entries only
audio_json = project_path / "media" / "audio" / "audio.json"