"use client"; import { useActionState } from "react"; import type { SiteSettings } from "yt-dlp-transcript-common/lib/settings"; import { formatBytes } from "yt-dlp-transcript-common/lib/format"; import { Field } from "../../../components/forms/Field"; import { seedChecked } from "../../../lib/formState"; import { saveBackfillLaneSettingsAction } from "../../settingsActions"; import type { SaveResult } from "../../../settings/actions"; // The `backfill` block of settings.json — the speaker work LANE, not any one // operation's settings. It governs BACKFILL_QUEUE, which diarization, // attribution-text and attribution-diarized share, so it is rendered once per // LANE and therefore appears on all three of their pages, exactly as the // shared pause and the shared sweep above it already do. // // That is why it takes no operation: there is nothing here that belongs to one. // The live numbers behind the re-acquire checkbox's warning. The page builds // them from the widget-sync payload (`sync.backfill.reachable` / // `.needsMedia`) plus one statfs of the corpus volume; absent, the copy falls // back to the sentence measured by hand in 2026-08. export type ReacquireFigures = { reachable: number; needsMedia: number; freeBytes: number | null; }; // The 2026-08 measurement, kept verbatim as the fallback for a caller that // passes no figures. It is STALE by construction — the live copy below is // derived from the widget-sync payload whenever the page supplies it. function reacquireFiguresCopy(figures: ReacquireFigures | undefined): string { if (!figures) { return ( "836 videos still have media on disk and ~76,270 would need " + "re-downloading — 91× the reachable work, against 45 GB free." ); } const n = (v: number) => v.toLocaleString("en-US"); const ratio = figures.reachable > 0 ? ` — ${n(Math.round(figures.needsMedia / figures.reachable))}× the reachable work` : ""; const free = figures.freeBytes === null ? "" : `, against ${formatBytes(figures.freeBytes)} free`; return ( `${n(figures.reachable)} videos still have media on disk and ` + `${n(figures.needsMedia)} would need re-downloading${ratio}${free}.` ); } export function LaneSettingsForm({ initial, // THE LANE'S GATE, read by the caller through `isGateHeld`. The gate is // `autoQueue.backfill.held` (slice 1.4); the `backfill.enabled` this checkbox // used to read was the retired field it migrated FROM, and S0-pause deleted // it — `initial` no longer has one. There is one key, and the pause button // beside this checkbox writes it too. held, figures, }: { initial: SiteSettings["backfill"]; held: boolean; figures?: ReacquireFigures; }) { const [state, formAction, pending] = useActionState< SaveResult | undefined, FormData >(saveBackfillLaneSettingsAction, undefined); return (
{/* THE ONE FIELDSET THAT STILL SAYS "LANE", and it is the right one: this is where the shared pause and the shared sweep live, and that these operations share a queue is a load-bearing fact rather than a leaked implementation detail. Everywhere an operator reads a FIGURE they now read an operation name instead. */} Speaker work lane

Catch-up for derived data the existing corpus predates — speaker diarization and the two speaker-name operations. These operations share one queue and one pause: the settings here decide how much of the machine all of them together may use, not any one of them individually. Each feature declares what it needs and how to tell whether a video already has it.

Which operations the lane runs, and over which channels, is not set here. {" "} That scope is the lane's rule list, on the runner console above — where it sits beside the work each rule is holding, which is what lets you read the commitment before making it.

{state?.ok === true && ( Saved. )} {state?.ok === false && ( {state.error} )}
); }