feat: bootstrap commercial AI drama platform
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdir, rm, stat } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
import { dbRun } from "../server/db.mjs";
|
||||
|
||||
const api = process.env.AI_DRAMA_API_BASE || "http://127.0.0.1:8787";
|
||||
const projectRoot = resolve(import.meta.dirname, "..");
|
||||
const scope = { "x-organization-id": "org-studio-lab", "x-workspace-id": "ws-local-aidrama", "x-project-id": "thunder-mouth" };
|
||||
const rootRelative = "storage/compositions/smoke-compose-evidence";
|
||||
const rootAbsolute = resolve(projectRoot, rootRelative);
|
||||
const clips = [`${rootRelative}/a.mp4`, `${rootRelative}/b.mp4`];
|
||||
const outputPath = `${rootRelative}/final.mp4`;
|
||||
|
||||
async function request(path, options = {}) {
|
||||
const response = await fetch(`${api}${path}`, { ...options, headers: { "content-type": "application/json", ...(options.headers || {}) } });
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
return { response, payload };
|
||||
}
|
||||
|
||||
const login = await request("/api/auth/login", { method: "POST", body: JSON.stringify({ email: "producer@local.test", password: "Demo@123456" }) });
|
||||
assert.equal(login.response.ok, true, "compose smoke login must pass");
|
||||
const headers = { authorization: `Bearer ${login.payload.session.token}`, ...scope };
|
||||
let compositionId = "";
|
||||
|
||||
try {
|
||||
await mkdir(rootAbsolute, { recursive: true });
|
||||
for (const [index, clip] of clips.entries()) {
|
||||
execFileSync("ffmpeg", ["-y", "-v", "error", "-f", "lavfi", "-i", `color=c=${index ? "0x3d7f54" : "0x7f4b2f"}:s=320x568:d=0.6`, "-c:v", "libx264", "-pix_fmt", "yuv420p", resolve(projectRoot, clip)], { stdio: "pipe" });
|
||||
}
|
||||
const composed = await request("/api/production/compose", { method: "POST", headers, body: JSON.stringify({ version: "smoke-compose-evidence", clips, outputPath }) });
|
||||
assert.equal(composed.response.ok, true, `compose failed: ${composed.payload.detail || ""}`);
|
||||
compositionId = composed.payload.composition.id;
|
||||
assert.equal(composed.payload.composition.status, "completed", "FFmpeg 合成必须完成");
|
||||
assert.equal(composed.payload.composition.result.artifact.status, "inspected", "合成结果必须登记媒体证据");
|
||||
assert.ok(composed.payload.composition.result.artifact.sha256, "合成结果必须登记 SHA-256");
|
||||
assert.ok(composed.payload.composition.result.artifact.last_frame_path, "合成结果必须提取实际末帧");
|
||||
await stat(resolve(projectRoot, outputPath));
|
||||
console.log(`compose evidence smoke passed: ${outputPath} -> ${composed.payload.composition.result.artifact.last_frame_path}`);
|
||||
} finally {
|
||||
if (compositionId) {
|
||||
dbRun("DELETE FROM media_artifacts WHERE composition_id = ?", [compositionId]);
|
||||
dbRun("DELETE FROM media_compositions WHERE id = ?", [compositionId]);
|
||||
}
|
||||
await rm(rootAbsolute, { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user