commit ea22b2fc9ce785df013dd03872c775b50a16870c
parent 5397363fa1ff78a0c1bf031a768b6ed3b71e8b50
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 26 Sep 2026 17:26:59 -0400
common: persistKeptForceMedia.test — "Persist kept now" on a youtube-handling kept video with a transcript runs the media pass and persists the container with no audio; removing persistKept's forceMedia fails it (review L1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
1 file changed, 137 insertions(+), 0 deletions(-)
diff --git a/common/controller/persistKeptForceMedia.test.ts b/common/controller/persistKeptForceMedia.test.ts
@@ -0,0 +1,137 @@
+import { test } from "node:test";
+import assert from "node:assert/strict";
+import { chmod, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
+import { tmpdir } from "node:os";
+import path from "node:path";
+import type { Paths } from "../lib/paths";
+import type { ChannelConfig } from "../lib/channelConfig";
+import { persistKept } from "./persistKept";
+
+// Run with:
+// pnpm --filter yt-dlp-transcript-common exec tsx --test controller/persistKeptForceMedia.test.ts
+//
+// "PERSIST KEPT" MEANS PERSIST (release 10 slice N, review L1). On a
+// youtube-handling channel every kept video has a transcript or captions, so
+// without `forceMedia` the bulk pass ran two subtitle-shaped yt-dlp passes per
+// video and persisted nothing — the same silent no-op "Persist source video"
+// had. `persistKept.test.ts` never reaches downloadOneManaged, and the e2e
+// "Persist kept now" check uses a transcribe fixture, so this is the one test
+// that fails when persistKept stops passing the flag. A separate file because
+// persistKept reads settings through `getPaths()`, which caches the first
+// SETTINGS_FILE it sees: this process sets it before anything else can.
+
+const ID = "H64QQZuw-aA";
+const VIDEO = `https://www.youtube.com/watch?v=${ID}`;
+
+// The same fake as ytdlp/forceMedia.test.ts: the prefetch copies meta.json in
+// as the info json, the subtitle pass writes nothing, and only a media pass
+// (the `source-media` output template) writes a container.
+const FAKE_YTDLP = `#!/usr/bin/env node
+const fs = require("node:fs");
+const path = require("node:path");
+const argv = process.argv.slice(2);
+const root = process.env.FAKE_ROOT;
+fs.appendFileSync(path.join(root, "argv.log"), JSON.stringify(argv) + "\\n");
+const has = (f) => argv.includes(f);
+const arg = (f) => { const i = argv.indexOf(f); return i < 0 ? undefined : argv[i + 1]; };
+const info = arg("--load-info-json");
+const id = info ? path.basename(path.dirname(info)) : "${ID}";
+const dir = path.join("data", id);
+fs.mkdirSync(dir, { recursive: true });
+if (has("--skip-download") && has("--write-info-json") && has("--no-write-subs")) {
+ fs.copyFileSync(path.join(root, "meta.json"), path.join(dir, "metadata.info.json"));
+ process.exit(0);
+}
+if (has("--skip-download") && has("--write-auto-subs")) {
+ console.log("DLOM_ARCHIVE youtube " + id);
+ process.exit(0);
+}
+if ((arg("-o") || "").includes("source-media")) {
+ fs.writeFileSync(path.join(dir, "source-media.mp4"), "container bytes for " + id);
+ console.log("DLOM_ARCHIVE youtube " + id);
+ process.exit(0);
+}
+console.error("fake: unknown invocation " + argv.join(" "));
+process.exit(2);
+`;
+
+test("persistKept forces the media pass: a kept youtube-handling video with a transcript is persisted, with no audio", async () => {
+ const root = await mkdtemp(path.join(tmpdir(), "persist-kept-force-"));
+ try {
+ // Disk floor off, so the per-item gate cannot turn this into a skip on a
+ // full disk. Set before persistKept's first getSettings() → getPaths().
+ const settingsFile = path.join(root, "settings.json");
+ await writeFile(settingsFile, JSON.stringify({ minFreeDiskGB: 0 }));
+ process.env.SETTINGS_FILE = settingsFile;
+ process.env.TRANSCRIPTS_DIR = root;
+ process.env.FAKE_ROOT = root;
+
+ const ytdlp = path.join(root, "fake-ytdlp.cjs");
+ await writeFile(ytdlp, FAKE_YTDLP);
+ await chmod(ytdlp, 0o755);
+ const meta = {
+ id: ID,
+ title: "A kept video",
+ upload_date: "20260101",
+ duration: 60,
+ webpage_url: VIDEO,
+ subtitles: {},
+ automatic_captions: { en: [{ url: "https://example/cap" }] },
+ };
+ await writeFile(path.join(root, "meta.json"), JSON.stringify(meta));
+
+ const paths = {
+ transcriptsDir: root,
+ channelsDir: path.join(root, "channels"),
+ savedVideosDir: path.join(root, "saved-videos"),
+ ytdlpBin: ytdlp,
+ ffmpegBin: path.join(root, "no-ffmpeg"),
+ ffprobeBin: path.join(root, "no-ffprobe"),
+ } as Paths;
+ const videoDir = path.join(paths.channelsDir, "c", "data", ID);
+ await mkdir(videoDir, { recursive: true });
+ await writeFile(path.join(videoDir, "metadata.info.json"), JSON.stringify(meta));
+ const transcript = '{"transcription":[{"text":"kept"}]}';
+ await writeFile(path.join(videoDir, "transcript.json"), transcript);
+
+ let log = "";
+ const result = await persistKept({
+ paths,
+ channelSlug: "c",
+ channelConfig: {
+ handling: "youtube",
+ url: "https://www.youtube.com/@c/videos",
+ keepLatest: 1,
+ } as ChannelConfig,
+ onLog: (s) => {
+ log += s;
+ },
+ });
+
+ assert.equal(result.kept, 1);
+ assert.equal(result.persisted, 1);
+ assert.match(log, /forceMedia: downloading the source although a transcript is on disk/);
+ // The media pass ran: three spawns, the last without --skip-download.
+ const argvs = (await readFile(path.join(root, "argv.log"), "utf8"))
+ .split("\n")
+ .filter(Boolean)
+ .map((l) => JSON.parse(l) as string[]);
+ assert.equal(argvs.length, 3);
+ assert.ok(!argvs[2].includes("--skip-download"));
+ // Persisted, and nothing else: the pointer is there, the container is in
+ // the store, no audio beside the transcript, the transcript untouched.
+ const pointer = JSON.parse(
+ await readFile(path.join(videoDir, "saved-video.json"), "utf8"),
+ ) as { dir: string; file: string; keepReason?: string };
+ assert.equal(pointer.keepReason, "override");
+ assert.equal(
+ await readFile(path.join(pointer.dir, pointer.file), "utf8"),
+ `container bytes for ${ID}`,
+ );
+ const files = await readdir(videoDir);
+ assert.deepEqual(files.filter((f) => /^(audio|source-media)\./.test(f)), []);
+ assert.equal(await readFile(path.join(videoDir, "transcript.json"), "utf8"), transcript);
+ } finally {
+ await rm(root, { recursive: true, force: true });
+ }
+});