commit 3da6cc254d868f17c66df2363a6f540290a6070b
parent ee8e96e668c1fb2818988dc71516d39dd816aa99
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 19 Sep 2026 01:38:37 -0400
clip bench: play the cached file that holds THIS clip's window, not the widest for the video
out/clips-raw is keyed by VIDEO, and a report cites the same stream more than
once -- ElfpireEva cites 07ZaDnyzO1g four times -- so the directory holds one
file per clip and "the widest file for this video" is another clip's file as
often as not. The bench plays windows[0] and seeks `start - from` into it: for
a01's 44-second file and f01's window that is 1146 s past the end, so the
player showed nothing, or the wrong seconds, on every clip after the first.
windowsFor() now filters to files that actually overlap the clip's own
[start,end] and sorts containing first, then by overlap, then by width, with
build-video's own 0.02 s tolerance. A clip whose material is not cached gets an
empty list -- "nothing fetched for this clip yet", which is true -- instead of
somebody else's window. A caller with no window (the raw route's ledger-claim
path, which asks for a VIDEO's files) still gets every file, widest first.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/umtool/lib/report/serve.mjs b/umtool/lib/report/serve.mjs
@@ -23,18 +23,39 @@ export async function resolveClip(projectId, clipId) {
return { project, manifest, clip };
}
+/** build-video's own tolerance for "this file holds that window". */
+const WIN_EPS = 0.02;
+
/**
- * The cached source windows for a clip, widest first.
+ * The cached source windows for a clip: the ones that hold ITS window, widest
+ * first, then any that merely overlap it.
*
* The bench wants the WIDEST containing file, because that is how much room
* there is to drag before anything has to be fetched. The BUILD wants the
* tightest, because it decodes the whole file to find a silence. They are
* different questions and both are asked here.
+ *
+ * "Containing" is not optional. clips-raw is keyed by VIDEO, and a report
+ * cites the same stream more than once -- ElfpireEva cites one video four
+ * times -- so the directory holds a file per clip and "widest for this video"
+ * is another clip's file as often as not. The bench then seeks `start - from`
+ * into a 44-second file, i.e. 1146 s past its end, and plays nothing or the
+ * wrong seconds. A caller with no window (a ledger claim asking for the raw
+ * files of its video) still gets every file, widest first.
*/
export async function windowsFor(project, clip) {
const rawDir = path.join(project.dir, "out", "clips-raw");
const all = await cachedWindowsFor(rawDir, clip.video);
- return all.sort((a, b) => b.to - b.from - (a.to - a.from));
+ const width = (w) => w.to - w.from;
+ const { start, end } = clip;
+ if (!Number.isFinite(start) || !Number.isFinite(end)) {
+ return all.sort((a, b) => width(b) - width(a));
+ }
+ const overlap = (w) => Math.max(0, Math.min(w.to, end) - Math.max(w.from, start));
+ const contains = (w) => (w.from <= start + WIN_EPS && w.to >= end - WIN_EPS ? 1 : 0);
+ return all
+ .filter((w) => overlap(w) > 0)
+ .sort((a, b) => contains(b) - contains(a) || overlap(b) - overlap(a) || width(b) - width(a));
}
export function pickWindow(windows, wantedName) {