From e1cd699b798164ce453a395f02485730dbb5fc60 Mon Sep 17 00:00:00 2001 From: ergosteur Date: Sun, 26 Jul 2026 13:07:33 -0400 Subject: [PATCH] Add CLAUDE.md with context not covered by README or code comments Documents things a future session would otherwise have to rediscover: no test suite/fixtures exist (verification requires real sample clips and ffprobe checks), the libvmaf stderr spam is a dev-machine quirk not a bug, detection thresholds were empirically tuned on one real dataset, the -r 30 normalization is load-bearing for bitrate targeting and shouldn't be removed casually, and a cross-platform GUI was considered and deliberately deferred. --- CLAUDE.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..369b5c2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,70 @@ +# CLAUDE.md + +Guidance for working in this repo that isn't already covered by README.md +or the scripts' own docstrings/comments. + +## There is no test suite, and no fixture files in the repo + +`.gitignore` excludes `*.mov`/`*.MOV`, so there are no sample clips checked +in. The overlap-detection logic depends on real iPhone HEVC/PCM quirks +(variable frame rate, the exact multi-track Live Photo container structure, +genuinely-correlated real-world audio at clip boundaries) that aren't +practical to fake convincingly with synthetic ffmpeg test inputs. To verify +a change to `concat_live_clips.py`, ask the user for a real set of +sequential Live Photo `.MOV` files (or reuse ones from earlier in the +conversation if still on disk) and check results with `ffprobe`: + +- `ffprobe -show_entries format=duration` — output duration should equal + the sum of (each clip's duration − its detected overlap). +- `ffprobe -select_streams v -show_entries frame=pts_time` — verify strictly + increasing timestamps (no reordering artifacts at the joins). +- `ffprobe -show_entries format_tags` — confirm GPS/device/Live-Photo tags + made it through from the source clip. +- Cross-check detected overlap/gap values against the clips' + `com.apple.quicktime.creationdate` tags by hand for a sanity read before + trusting a change to the correlation math. + +## The `libvmaf` stderr spam is an environment quirk, not a bug + +Every `libx265` encode on this dev machine prints repeated +`libvmaf ERROR could not read model from path: ...` / `problem loading +model file` lines. This reproduces with a trivial synthetic +`-c:v libx265` encode with zero flags, and `-x265-params log-level=none` +does not suppress it — it comes from `libvmaf` itself, not from anything +this script requests, and doesn't affect output correctness (exit code 0, +correct output every time this was checked). Don't spend time chasing it as +if it were caused by this codebase; the user has explicitly said they're +fine with it showing. + +## Detection thresholds are empirically tuned on one real dataset, not derived analytically + +`--confidence-threshold` (0.9), `--min-signal-rms` (25), +`--bitrate-multiplier` (1.2), and `--bitrate-floor` (10M) were chosen by +testing against two real clip sets from one iPhone (see conversation +history / commit messages for the actual numbers observed: correlation +scores landed either ~1.000 or well below ~0.6, RMS values were in the +hundreds for real audio content). They aren't validated across other +devices, iOS versions, or recording environments. If a user reports a false +abort or a false pass, prefer surfacing the actual score/RMS numbers +(already printed) over silently loosening a default. + +## Rate-control depends on the `-r 30` normalization — don't remove it + +`concat_live_clips.py` forces constant 30fps output (see the comment above +`video_args += ["-r", "30", ...]`). This was added after the bitrate-target +mode was found to silently undershoot by >10x (target ~13Mbps, actual +~1Mbps, x265 hitting max QP) because the source clips' irregular VFR +timestamps confused x265's ABR rate control once concatenated. If touching +the encoding args, keep this normalization or re-verify bitrate targeting +actually hits its target (check `ffprobe -show_entries +stream=bit_rate` on the output, not just that the encode succeeds). + +## A cross-platform GUI was considered and explicitly deferred + +The user asked about a GUI, wanted it to look good on Mac/Windows/Linux and +possibly iOS, then decided against it once the iOS scope implication became +clear (iOS would require either a full native rewrite or a client-server +model, not just a new frontend on the same script). Don't reintroduce that +scope unprompted; if asked again, the open question is specifically +desktop-only vs. desktop+mobile, since that decision determines the whole +architecture (e.g. Tkinter/PySide6 vs. a local web app).