// A clip window cut from a saved container (release 21 D2): which pointer // answers which way, and the cut itself. // // Real ffmpeg over tiny lavfi containers (160×90, a few seconds), so a run // costs a second or two. // // Run with: pnpm --filter yt-dlp-transcript-common exec tsx --test lib/savedVideoWindow-server.test.ts import { after, before, test } from "node:test"; import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { copyFile, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { cutSavedVideoWindow, savedWindowSource } from "./savedVideoWindow-server"; import { findContainingClipWindow } from "./clipWindow-server"; import { probeMedia } from "./evidenceClip-server"; import { SAVED_VIDEOS_MARKER_FILENAME } from "./savedVideoStore"; const SLUG = "demo-channel"; const ID = "abc123"; let ROOT = ""; // 8 s of 160×90 picture with sound, and 8 s of sound alone. let PICTURE = ""; let SOUND = ""; function ff(args: string[]): void { execFileSync("ffmpeg", ["-nostdin", "-v", "error", "-y", ...args]); } before(async () => { ROOT = await mkdtemp(path.join(tmpdir(), "saved-window-")); const fx = path.join(ROOT, "fixtures"); await mkdir(fx, { recursive: true }); PICTURE = path.join(fx, "picture.mp4"); SOUND = path.join(fx, "sound.m4a"); ff([ "-f", "lavfi", "-i", "testsrc=size=160x90:rate=10:duration=8", "-f", "lavfi", "-i", "sine=frequency=440:duration=8", "-c:v", "libx264", "-preset", "ultrafast", "-pix_fmt", "yuv420p", "-c:a", "aac", "-shortest", PICTURE, ]); ff(["-f", "lavfi", "-i", "sine=frequency=220:duration=8", "-c:a", "aac", SOUND]); }); after(() => rm(ROOT, { recursive: true, force: true })); let n = 0; // A fresh corpus per test: `//transcripts/channels//data//` // and its saved-video store `//transcripts/saved-videos///`, // holding `container` (when given) under the pointer's name. async function corpus(container?: string, opts: { pointer?: boolean } = {}) { const root = path.join(ROOT, String(++n)); const transcriptsDir = path.join(root, "transcripts"); const savedVideosDir = path.join(transcriptsDir, "saved-videos"); const videoDir = path.join(transcriptsDir, "channels", SLUG, "data", ID); const storeDir = path.join(savedVideosDir, SLUG, ID); await mkdir(videoDir, { recursive: true }); await mkdir(storeDir, { recursive: true }); const file = `source-media${container ? path.extname(container) : ".mp4"}`; if (container) await copyFile(container, path.join(storeDir, file)); if (opts.pointer !== false) { await writeFile( path.join(videoDir, "saved-video.json"), JSON.stringify({ storedAt: "2026-10-10T00:00:00.000Z", dir: storeDir, file, bytes: 1, keepReason: "pin", origin: { requestedBy: "attach-media", kind: "local-archive", archive: "/archive/example.zip", entry: "Example (abc123)/example.mp4", }, }), ); } const paths = { transcriptsDir, savedVideosDir, ffmpegBin: "ffmpeg", ffprobeBin: "ffprobe" }; return { paths, videoDir, storeDir, transcriptsDir }; } test("no pointer: none — the caller goes to the network", async () => { const c = await corpus(undefined, { pointer: false }); const r = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 3 }); assert.deepEqual(r, { kind: "none" }); }); test("a container that ends before the window: not-covering", async () => { const c = await corpus(PICTURE); const r = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 5, to: 12 }); assert.equal(r.kind, "not-covering"); assert.ok(r.kind === "not-covering" && Math.abs(r.durationSec - 8) < 0.2); }); test("a pointer whose container is missing: unreadable, in the media guard's words", async () => { const c = await corpus(undefined); const r = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 3 }); assert.equal(r.kind, "unreadable"); assert.match( (r as { error: string }).error, /^Channel "demo-channel": media is not reachable — its saved video .*source-media\.mp4 is not there \(drive not mounted\?\)$/, ); }); test("a pointer whose store is unmounted (its directory gone): unreadable", async () => { const c = await corpus(PICTURE); await rm(c.storeDir, { recursive: true, force: true }); const r = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 3 }); assert.equal(r.kind, "unreadable"); assert.match((r as { error: string }).error, /media is not reachable/); }); test("a missing container while the store is being moved: the store guard's sentence", async () => { const c = await corpus(undefined); await writeFile( path.join(c.transcriptsDir, SAVED_VIDEOS_MARKER_FILENAME), JSON.stringify({ target: "/mnt/elsewhere/saved-videos", direction: "out", startedAt: "", phase: "swap" }), ); const r = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 3 }); assert.equal(r.kind, "unreadable"); assert.match((r as { error: string }).error, /^The saved-video store is being moved \(out to \/mnt\/elsewhere\/saved-videos, phase "swap"\)/); }); test("a container ffprobe cannot read: unreadable, never a guess", async () => { const c = await corpus(undefined); await writeFile(path.join(c.storeDir, "source-media.mp4"), "not a container"); const r = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 3 }); assert.equal(r.kind, "unreadable"); assert.match((r as { error: string }).error, /could not be read by ffprobe/); }); test("a covering container is cut into clips/ with a saved-video sidecar, and the cache then answers it", async () => { const c = await corpus(PICTURE); const src = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 2, to: 5 }); assert.equal(src.kind, "covers"); if (src.kind !== "covers") return; const logs: string[] = []; const w = await cutSavedVideoWindow({ paths: c.paths, videoDir: c.videoDir, source: src, from: 2, to: 5, provenance: { requestedBy: "test", manifest: "m", clipId: "c1", pad: 1, requestedAt: "2026-10-10T01:00:00.000Z" }, onLog: (l) => logs.push(l), }); assert.equal(w.file, "2.00-5.00.mp4"); assert.equal(path.dirname(w.path), path.join(c.videoDir, "clips")); // Only the window and its sidecar: no temp file left behind. assert.deepEqual((await readdir(path.join(c.videoDir, "clips"))).sort(), ["2.00-5.00.json", "2.00-5.00.mp4"]); const probe = await probeMedia(w.path); assert.ok(probe?.hasVideo && probe.hasAudio); assert.ok(Math.abs((probe?.durationSec ?? 0) - 3) < 0.25, `duration ${probe?.durationSec}`); const sidecar = JSON.parse(await readFile(path.join(c.videoDir, "clips", "2.00-5.00.json"), "utf8")); assert.equal(sidecar.source, "saved-video"); assert.equal(sidecar.requestedBy, "test"); assert.equal(sidecar.manifest, "m"); assert.equal(sidecar.clipId, "c1"); assert.equal(sidecar.pad, 1); assert.equal(sidecar.bytes, w.bytes); assert.equal(sidecar.ytdlp, undefined, "nothing was fetched"); assert.match(logs.join(""), /Cut 2\.00–5\.00 from the saved video source-media\.mp4/); // The fetched-window cache reads it back like any window. const hit = await findContainingClipWindow(c.videoDir, 2.5, 4.5); assert.equal(hit?.file, "2.00-5.00.mp4"); assert.equal(hit?.provenance?.source, "saved-video"); }); test("a container with no picture is cut as sound", async () => { const c = await corpus(SOUND); const src = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 4 }); assert.equal(src.kind, "covers"); if (src.kind !== "covers") return; const w = await cutSavedVideoWindow({ paths: c.paths, videoDir: c.videoDir, source: src, from: 1, to: 4, provenance: { requestedBy: "test" }, }); const probe = await probeMedia(w.path); assert.equal(probe?.hasVideo, false); assert.equal(probe?.hasAudio, true); }); test("an ffmpeg that fails leaves no window behind", async () => { const c = await corpus(PICTURE); const src = await savedWindowSource({ paths: c.paths, slug: SLUG, videoDir: c.videoDir, from: 1, to: 2 }); assert.equal(src.kind, "covers"); if (src.kind !== "covers") return; await assert.rejects( cutSavedVideoWindow({ paths: { ...c.paths, ffmpegBin: "false" }, videoDir: c.videoDir, source: src, from: 1, to: 2, provenance: { requestedBy: "test" }, }), /ffmpeg failed cutting 1\.00–2\.00 from the saved video source-media\.mp4/, ); assert.deepEqual(await readdir(path.join(c.videoDir, "clips")), []); });