commit fc93770247132926044fc160ee62ed2d6bc498aa
parent fff366c4bfff0ea9bdaa84337985ba9e5eb6ff9d
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sun, 20 Sep 2026 17:40:31 -0400
build-video: split the cached-window predicate into I/O and arithmetic
The same question -- does a cached file hold this window -- is asked by the
build, the bench, the project page and now the walk. Keeping it one predicate
means splitting the readdir off the parse, so a caller with a listing already
in hand can answer for every clip without reading the directory again.
cachedWindowsFor and findContainingWindow are those halves composed and behave
exactly as before.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/umtool/report-to-video/build-video.mjs b/umtool/report-to-video/build-video.mjs
@@ -288,15 +288,26 @@ const WINDOW_RE = /^(\d+(?:\.\d+)?)-(\d+(?:\.\d+)?)$/;
// A window read back from a 2 dp manifest can sit a hair outside the file that
// produced it; the same tolerance resolve-windows.mjs uses for the same reason.
-const WIN_EPS = 0.02;
+export const WIN_EPS = 0.02;
-export async function cachedWindowsFor(rawDir, video) {
- let names;
+/**
+ * The question is asked FOUR times per page -- the build, the bench, the
+ * project page's pill and the walk -- so it is one predicate in one place,
+ * split into the I/O and the arithmetic. A caller with a directory listing
+ * already in hand (the bench reads clips-raw ONCE per request and answers for
+ * every clip) uses the pure halves; the two original functions are those halves
+ * composed, and behave exactly as they did.
+ */
+export async function listRawNames(rawDir) {
try {
- names = await readdir(rawDir);
+ return await readdir(rawDir);
} catch {
return [];
}
+}
+
+/** The windows THIS video's files hold, parsed out of a directory listing. */
+export function windowsFromNames(names, rawDir, video) {
const prefix = `${video}_`;
const out = [];
for (const name of names) {
@@ -310,17 +321,30 @@ export async function cachedWindowsFor(rawDir, video) {
return out;
}
-/** The tightest cached file containing [from, to], or null. */
-export async function findContainingWindow(rawDir, video, from, to) {
- const windows = await cachedWindowsFor(rawDir, video);
+/** Does this cached file hold [from, to] whole, to the manifest's tolerance? */
+export function windowContains(w, from, to) {
+ return !(w.from > from + WIN_EPS || w.to < to - WIN_EPS);
+}
+
+/** The tightest of `windows` containing [from, to], or null. */
+export function tightestContaining(windows, from, to) {
let best = null;
for (const w of windows) {
- if (w.from > from + WIN_EPS || w.to < to - WIN_EPS) continue;
+ if (!windowContains(w, from, to)) continue;
if (!best || w.to - w.from < best.to - best.from) best = w;
}
return best;
}
+export async function cachedWindowsFor(rawDir, video) {
+ return windowsFromNames(await listRawNames(rawDir), rawDir, video);
+}
+
+/** The tightest cached file containing [from, to], or null. */
+export async function findContainingWindow(rawDir, video, from, to) {
+ return tightestContaining(await cachedWindowsFor(rawDir, video), from, to);
+}
+
async function fetchClip(entry, meta, render, rawDir, opts) {
// Deliberately over-fetch: the snapping pass below needs room on both sides to
// find a silence, and a clip that has no slack can only be cut where the cue