78 lines
3.7 KiB
JavaScript
78 lines
3.7 KiB
JavaScript
// 二期第5段验收:1.11 上传视频提炼 —— 三入口、真视频拆解、拆解稿可编辑、生成后来源徽标
|
|
import { chromium } from "playwright";
|
|
import { mkdirSync, existsSync } 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-seg5";
|
|
const VIDEO = process.env.VIDEO || "/tmp/_probe_tshirt.mp4";
|
|
mkdirSync(OUT, { recursive: true });
|
|
if (!existsSync(VIDEO)) throw new Error(`测试视频不存在: ${VIDEO}`);
|
|
|
|
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 prods = (await (await fetch(`${API}/api/products/`, { headers: auth })).json()).results || [];
|
|
const target = await (await fetch(`${API}/api/projects/`, {
|
|
method: "POST", headers: auth,
|
|
body: JSON.stringify({ name: `二期第5段抓图-${Date.now() % 100000}`, product: prods[0].id })
|
|
})).json();
|
|
console.log("project:", target.id, "product:", prods[0].title);
|
|
|
|
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));
|
|
|
|
const pane = () => page.locator(".chat-pane").first();
|
|
async function shot(name) {
|
|
await page.screenshot({ path: `${OUT}/${name}.png`, clip: await pane().boundingBox() });
|
|
console.log("shot", name);
|
|
}
|
|
|
|
await page.goto(`${BASE}/pipeline/${target.id}?st=1#stage-1`, { waitUntil: "networkidle", timeout: 40000 });
|
|
await page.waitForTimeout(2000);
|
|
|
|
// ① 空态三入口
|
|
const modes = await page.locator(".chat-mode").allTextContents();
|
|
console.log("入口:", modes);
|
|
if (modes.length !== 3) throw new Error(`应有三个入口,实际 ${modes.length}`);
|
|
await shot("1-three-entries");
|
|
|
|
// ② 选「上传视频提炼」→ 自动拉起选文件,喂真视频
|
|
const chooser = page.waitForEvent("filechooser");
|
|
await page.locator('.chat-mode[data-mode="video"]').click();
|
|
await (await chooser).setFiles(VIDEO);
|
|
await page.waitForTimeout(800);
|
|
await shot("2-digesting");
|
|
|
|
// ③ 等拆解回来(抽帧 + 读帧,真调模型,给足 3 分钟)
|
|
await page.locator(".chat-attach-row .chip").first().waitFor({ timeout: 180000 });
|
|
await page.waitForTimeout(600);
|
|
const digest = await page.locator("#chat-textarea").inputValue();
|
|
console.log("拆解稿字数:", digest.length);
|
|
console.log("镜数:", (digest.match(/【第 \d+ 镜】/g) || []).length, "| 有存疑节:", digest.includes("【拆解存疑】"));
|
|
console.log("----- 前 260 字 -----\n" + digest.slice(0, 260));
|
|
await shot("3-digest-in-editor");
|
|
|
|
// ④ 拆解稿必须可编辑 —— 这是 1.11 的硬要求(AI 拆解有已知毛病)
|
|
await page.locator("#chat-textarea").fill(digest + "\n【人工补充】第 1 镜改成室内暖光。");
|
|
await page.waitForTimeout(300);
|
|
const edited = await page.locator("#chat-textarea").inputValue();
|
|
console.log("可编辑:", edited.includes("【人工补充】"));
|
|
await shot("4-manually-edited");
|
|
|
|
// ⑤ 设定卡(表现形式/结构/人物/时长)照常出现,确定后进生成
|
|
console.log("设定卡可见:", await page.locator(".setup-card").isVisible());
|
|
console.log("设定卡引导语:", await page.locator(".setup-lead").textContent());
|
|
|
|
await browser.close();
|
|
await fetch(`${API}/api/projects/${target.id}/`, { method: "DELETE", headers: auth });
|
|
console.log("DONE ->", OUT);
|