festifun/plan/status/lane-A.md
m3ultra 157c783e25 Lane A (M1): ingest + GCC-PHAT audio sync
Fills the foundation stubs in ingest.py and audio_sync.py.

- ingest: ffprobe probe + mono 16 kHz WAV extraction per video (ffmpeg);
  idempotent run_ingest reuses existing rows so synthetic -> ingest -> sync
  works without unique-constraint collisions.
- sync: PHAT-whitened GCC-PHAT pairwise offsets with sub-sample parabolic
  peak refinement, scored by peak-to-second-peak ratio; confidence-weighted
  global least-squares solve with cycle-consistency rejection (>50 ms);
  windowed drift estimation (ppm) with a 5 ppm deadband; disconnected
  sync-graph components -> offset_ms=None (spec pitfall #5).
- Persists offset_ms/drift_ppm/sync_confidence via db.update_video_sync and
  exports data/work/sync.json.

Verified on the synthetic fixture: synthetic -> ingest -> sync recovers the
ground-truth offsets (0 / +1370 / -842 ms) to <0.001 ms and drift 0 ppm,
well inside the spec M1 tolerances (+/-10 ms, +/-3 ppm). pytest: 43 passed
(24 foundation + 19 new in test_ingest.py and test_audio_sync.py).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 01:13:56 +10:00

1.8 KiB
Raw Blame History

Status — lane-A

Round 0 — 2026-07-16 — STATUS: in_progress

Directives acknowledged: round 0 of plan/DIRECTIVES.md (run order & protocol; Lane A = spec M1).

Acceptance checklist (spec M1 + lane brief):

  • ingest: ffprobe each file in data/raw, register in videos, extract mono 16 kHz WAV per video into data/work/audio/.
  • sync: GCC-PHAT (PHAT-whitened, not raw xcorr) pairwise offsets, scored by peak-to-second-peak ratio.
  • Global least-squares solve over the offset graph, confidence-weighted, cycle-consistency rejection (>50 ms).
  • Drift: windowed GCC-PHAT, line fit → drift_ppm; store 0 if |drift| < 5 ppm.
  • Disconnected sync-graph components → offset_ms = None (spec pitfall #5).
  • Persist offset_ms/drift_ppm/sync_confidence via db.update_video_sync; export config.SYNC_JSON.
  • python -m festival4d ingest && python -m festival4d sync recovers GT offsets (±10 ms) and drift (±3 ppm).
  • pytest green (new test_ingest.py, test_audio_sync.py); synthetic end-to-end intact.

Done this round: branched lane/a-media from main; baseline pytest green (24 passed). Verified env: ffmpeg/ffprobe present, librosa 0.11, scipy 1.18; synthetic fixtures (data/raw/cam{0,1,2}.mp4, DB rows GT offsets 0/+1370/842) in place. Implementing ingest.py + audio_sync.py.

Blockers / questions for coordinator: none. sync.json schema is unspecified by the spec — designing a self-describing schema (reference id, per-video offset/drift/confidence, raw edges, components); no consumer depends on it (API reads the DB), so no change request needed.

Next: implement both modules, validate GCC-PHAT against the real extracted fixture audio, write tests, run acceptance, then update status → ready_to_merge.