Files
UHD_Media_Tool/scripts/asset-spec-backfill.ts
T
rootandClaude Opus 5.5 bf9e73e86e feat(library): show stored versions per episode and movie (LIBV-1)
- domain versionSpecOf: file name + ffprobe + ingest quality -> version spec;
  summarizeVersions; matchVersions (satisfied / missing / upgradeable, single target)
- GET /library/{id}/versions: per-season/episode versions, summaries, matches[]
- organize writes full spec into media_asset.delivery (specVersion 1)
- scripts/asset-spec-backfill.ts: dry-run by default, --probe local only, --apply
- web: season summary line, one-line spec per episode, N versions expand,
  tech info details (TODO: DEAI-2 TechInfo), movie versions panel

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 21:02:37 +08:00

56 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// LIBV-1 回填已入库视频资产的版本规格(media_asset.delivery)。默认只读(dry-run),加 --apply 才改库。
//
// 用法(DATABASE_URL 必须显式给出,脚本不带默认库):
// DATABASE_URL=… deno run -A scripts/asset-spec-backfill.ts # 看清单:哪些资产会更新、前后规格
// DATABASE_URL=… deno run -A scripts/asset-spec-backfill.ts --entity <作品 id> # 只看一部作品
// DATABASE_URL=… deno run -A scripts/asset-spec-backfill.ts --probe # 对缺探测结果的本地文件跑 ffprobe(只读文件)
// DATABASE_URL=… deno run -A scripts/asset-spec-backfill.ts --apply # 写库
// --json 输出 JSON;--limit N 只处理前 N 个资产
//
// 规格来源:库内文件名解析 + 已有 media_info.probe + 入库时记下的资源解析(media_info._umt.quality)。
// 不请求任何站点;--probe 只读库根里的本地文件。写回只合并 delivery 的键,可重复执行。
import { ffprobe } from "@umt/adapters";
import { createDb } from "@umt/db";
import { backfillVersionSpecs } from "../apps/server/src/modules/acquisition-organize/services/version-backfill.ts";
const argv = [...Deno.args];
const APPLY = argv.includes("--apply");
if (APPLY && argv.includes("--dry-run")) {
console.error("--apply 与 --dry-run 不能同时给出");
Deno.exit(2);
}
const arg = (k: string) => {
const i = argv.indexOf(k);
return i >= 0 ? argv[i + 1] : undefined;
};
const url = Deno.env.get("DATABASE_URL");
if (!url) {
console.error("需要 DATABASE_URL(脚本不带默认库)");
Deno.exit(2);
}
const db = createDb({ connectionString: url, max: 2 });
try {
const report = await backfillVersionSpecs(db, {
apply: APPLY,
entityId: arg("--entity"),
limit: arg("--limit") ? Number(arg("--limit")) : undefined,
probe: argv.includes("--probe") ? (p) => ffprobe(p, { timeoutMs: 30_000 }) : undefined,
});
if (argv.includes("--json")) console.log(JSON.stringify(report, null, 2));
else {
console.log(`# asset-spec-backfill (${APPLY ? "APPLY" : "DRY-RUN"})\n`);
console.log(
`扫描 ${report.scanned} 个视频资产:已是当前口径 ${report.upToDate},${APPLY ? "已更新" : "将更新"} ${report.changed}` +
`,本次探测 ${report.probed},无库内位置 ${report.noLocation}\n`,
);
for (const it of report.items) {
console.log(`- [${it.reason}] ${it.entityTitle ?? "(无作品)"} · ${it.path ?? it.assetId}`);
console.log(` 前:${it.before}`);
console.log(` 后:${it.after}(来源 ${it.specFrom.join("+") || "无"})`);
}
}
} finally {
await db.destroy();
}