feat: bootstrap commercial AI drama platform

This commit is contained in:
xz
2026-08-24 10:24:34 +08:00
commit ffb27d845b
100 changed files with 35314 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
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 { dbGet, dbRun, withTransaction } from "../server/db.mjs";
import { registerJobArtifacts } from "../server/media-artifacts.mjs";
const projectRoot = resolve(import.meta.dirname, "..");
const orgId = "org-studio-lab";
const workspaceId = "ws-local-aidrama";
const projectId = "thunder-mouth";
const shotId = "shot-01";
const shot = dbGet("SELECT * FROM shots WHERE id = ?", [shotId]);
assert.ok(shot, "smoke shot must exist");
const nextShot = dbGet("SELECT id, first_frame_path FROM shots WHERE episode_id = ? AND shot_number = ?", [shot.episode_id, Number(shot.shot_number) + 1]);
const originalLastFrame = shot.last_frame_path;
const originalNextFirstFrame = nextShot?.first_frame_path || "";
const jobId = `smoke-media-${Date.now()}`;
const relative = `storage/jobs/${jobId}/output.mp4`;
const absolute = resolve(projectRoot, relative);
const context = {
organization: { id: orgId },
workspace: { id: workspaceId },
project: { id: projectId },
user: { id: "u-owner" }
};
try {
await mkdir(resolve(projectRoot, `storage/jobs/${jobId}`), { recursive: true });
execFileSync("ffmpeg", ["-y", "-v", "error", "-f", "lavfi", "-i", "color=c=0x1f5f8b:s=320x568:d=1", "-c:v", "libx264", "-pix_fmt", "yuv420p", absolute], { stdio: "pipe" });
const timestamp = new Date().toISOString();
dbRun("INSERT INTO generation_jobs(id, organization_id, workspace_id, project_id, episode_id, shot_id, kind, adapter_id, status, output_path, qa_status, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, '视频片段', 'owned-i2v', 'completed', ?, 'wait', 'u-owner', ?, ?)", [jobId, orgId, workspaceId, projectId, shot.episode_id, shotId, relative, timestamp, timestamp]);
const artifacts = await registerJobArtifacts(context, { id: jobId, episode_id: shot.episode_id, shot_id: shotId, kind: "视频片段", output_path: relative, created_by: "u-owner" }, { outputPath: relative });
const artifact = artifacts.find((item) => item.kind === "video");
assert.equal(artifact?.status, "inspected", "视频文件必须通过 FFprobe 检查");
assert.equal((artifact.sha256 || "").length, 64, "视频证据必须登记 SHA-256");
assert.ok(artifact.last_frame_path, "视频证据必须提取实际末帧路径");
await stat(resolve(projectRoot, artifact.last_frame_path));
assert.equal(dbGet("SELECT last_frame_path FROM shots WHERE id = ?", [shotId]).last_frame_path, artifact.last_frame_path, "镜头必须继承实际末帧");
if (nextShot) assert.equal(dbGet("SELECT first_frame_path FROM shots WHERE id = ?", [nextShot.id]).first_frame_path, artifact.last_frame_path, "下一镜头必须继承上一镜头实际末帧");
console.log(`media evidence smoke passed: ${artifact.path} -> ${artifact.last_frame_path}`);
} finally {
withTransaction(() => {
dbRun("DELETE FROM media_artifacts WHERE job_id = ?", [jobId]);
dbRun("DELETE FROM generation_jobs WHERE id = ?", [jobId]);
dbRun("UPDATE shots SET last_frame_path = ?, updated_at = ? WHERE id = ?", [originalLastFrame, new Date().toISOString(), shotId]);
if (nextShot) dbRun("UPDATE shots SET first_frame_path = ?, updated_at = ? WHERE id = ?", [originalNextFirstFrame, new Date().toISOString(), nextShot.id]);
});
await rm(resolve(projectRoot, `storage/jobs/${jobId}`), { recursive: true, force: true });
}