72 lines
3.3 KiB
JavaScript
72 lines
3.3 KiB
JavaScript
// 抓图:视频阶段「合成完整视频 / 播放成片 / 下载成片」+ 项目列表播放键播成片
|
|
import { chromium } from "playwright";
|
|
import { mkdirSync } from "node:fs";
|
|
|
|
const BASE = process.env.BASE || "http://127.0.0.1:5173";
|
|
const API = process.env.API || "http://127.0.0.1:8010";
|
|
const OUT = process.argv[2] || "shots-merge";
|
|
mkdirSync(OUT, { recursive: true });
|
|
|
|
const login = await (await fetch(`${API}/api/auth/login/`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ username: "airshelf", password: "Restraint2026" })
|
|
})).json();
|
|
const tok = login.token;
|
|
const auth = { Authorization: `Token ${tok}`, "Content-Type": "application/json" };
|
|
|
|
// 挑一个「所有场次都已出片」的项目:合成按钮才是可点态
|
|
const projects = (await (await fetch(`${API}/api/projects/?page_size=100`, { headers: auth })).json()).results || [];
|
|
console.log("项目数:", projects.length, "· 已有成片:", projects.filter((p) => p.final_video_url).length);
|
|
let target = null;
|
|
for (const p of projects.filter((p) => p.status === "completed" || p.current_stage === "video")) {
|
|
const detail = await (await fetch(`${API}/api/projects/${p.id}/`, { headers: auth })).json();
|
|
const segs = detail.video_segments || [];
|
|
if (segs.length && segs.every((s) => s.status === "succeeded" && s.adopted_asset)) {
|
|
target = detail;
|
|
break;
|
|
}
|
|
}
|
|
if (!target) throw new Error("没有全部场次出片的项目,无法抓合成态");
|
|
console.log("target:", target.id, target.name, "· 场次:", target.video_segments.length, "· 成片:", target.final_video_url || "(未合成)");
|
|
|
|
const browser = await chromium.launch();
|
|
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 2 });
|
|
await ctx.addInitScript((t) => localStorage.setItem("airshelf_token", t), tok);
|
|
const page = await ctx.newPage();
|
|
page.on("pageerror", (e) => console.error(" pageerror:", e.message));
|
|
|
|
await page.goto(`${BASE}/pipeline/${target.id}#stage-4`, { waitUntil: "networkidle", timeout: 40000 });
|
|
await page.waitForTimeout(2500);
|
|
const foot = page.locator('[data-stage-pane="4"] .stage-foot');
|
|
await foot.waitFor({ timeout: 15000 });
|
|
await page.screenshot({ path: `${OUT}/1-stage4-merge-bar.png`, clip: await foot.boundingBox() });
|
|
console.log("shot 1-stage4-merge-bar");
|
|
|
|
// 点「播放成片」→ 灯箱播成片
|
|
const play = page.locator('[data-stage-pane="4"] .stage-foot button', { hasText: "播放成片" });
|
|
if (await play.count()) {
|
|
await play.click();
|
|
await page.waitForTimeout(2500);
|
|
await page.screenshot({ path: `${OUT}/2-stage4-play-final.png` });
|
|
console.log("shot 2-stage4-play-final");
|
|
await page.keyboard.press("Escape");
|
|
}
|
|
|
|
await page.goto(`${BASE}/projects`, { waitUntil: "networkidle", timeout: 40000 });
|
|
await page.waitForTimeout(1500);
|
|
await page.screenshot({ path: `${OUT}/3-projects-list.png`, fullPage: false });
|
|
console.log("shot 3-projects-list");
|
|
|
|
// 列表行末播放键:有成片 → 直接弹窗播,不再跳流水线
|
|
const row = page.locator(`tr[data-name="${target.name}"] .row-action a`).first();
|
|
if (await row.count()) {
|
|
await row.click();
|
|
await page.waitForTimeout(2500);
|
|
await page.screenshot({ path: `${OUT}/4-projects-play-final.png` });
|
|
console.log("shot 4-projects-play-final · 当前地址:", page.url());
|
|
}
|
|
|
|
await browser.close();
|
|
console.log("DONE ->", OUT);
|