@mevdragon/vidfarm-devcli 0.2.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/SKILL.director.md +97 -0
- package/SKILL.platform.md +66 -6
- package/dist/src/cli.js +137 -1524
- package/dist/src/dev-serve.js +169 -0
- package/package.json +5 -24
- package/.env.example +0 -60
- package/auto-create-hyperframe-templates/AUTO_CREATE_HYPERFRAME_TEMPLATES.md +0 -275
- package/auto-create-hyperframe-templates/extractor-system-prompt.md +0 -128
- package/auto-create-hyperframe-templates/input-manifest.schema.json +0 -56
- package/auto-create-hyperframe-templates/lambda-memory-estimator.md +0 -118
- package/auto-create-hyperframe-templates/production-graph.schema.json +0 -314
- package/auto-create-hyperframe-templates/runbook.md +0 -198
- package/auto-create-hyperframe-templates/scripts/create-hyperframe-template.mjs +0 -368
- package/auto-create-hyperframe-templates/template-plan.schema.json +0 -311
- package/auto-create-hyperframe-templates/template-planner-prompt.md +0 -144
- package/auto-create-templates/AUTO_CREATE_TEMPLATES.md +0 -599
- package/auto-create-templates/extractor-system-prompt.md +0 -119
- package/auto-create-templates/production-graph.schema.json +0 -276
- package/auto-create-templates/runbook.md +0 -140
- package/auto-create-templates/template-plan.schema.json +0 -301
- package/auto-create-templates/template-planner-prompt.md +0 -137
- package/dist/src/account-pages-legacy.js +0 -9336
- package/dist/src/account-pages-legacy.js.map +0 -1
- package/dist/src/account-pages.js +0 -61
- package/dist/src/account-pages.js.map +0 -1
- package/dist/src/app.js +0 -14023
- package/dist/src/app.js.map +0 -1
- package/dist/src/cli.js.map +0 -1
- package/dist/src/composition-runtime.js +0 -581
- package/dist/src/composition-runtime.js.map +0 -1
- package/dist/src/config.js +0 -140
- package/dist/src/config.js.map +0 -1
- package/dist/src/context.js +0 -492
- package/dist/src/context.js.map +0 -1
- package/dist/src/dev-app-legacy.js +0 -694
- package/dist/src/dev-app-legacy.js.map +0 -1
- package/dist/src/dev-app.js +0 -6
- package/dist/src/dev-app.js.map +0 -1
- package/dist/src/domain.js +0 -2
- package/dist/src/domain.js.map +0 -1
- package/dist/src/editor-chat-history.js +0 -82
- package/dist/src/editor-chat-history.js.map +0 -1
- package/dist/src/editor-chat.js +0 -311
- package/dist/src/editor-chat.js.map +0 -1
- package/dist/src/frontend/flockposter-cache-store.js +0 -124
- package/dist/src/frontend/flockposter-cache-store.js.map +0 -1
- package/dist/src/frontend/homepage-client.js +0 -117
- package/dist/src/frontend/homepage-client.js.map +0 -1
- package/dist/src/frontend/homepage-shared.js +0 -4
- package/dist/src/frontend/homepage-shared.js.map +0 -1
- package/dist/src/frontend/homepage-store.js +0 -28
- package/dist/src/frontend/homepage-store.js.map +0 -1
- package/dist/src/frontend/homepage-view.js +0 -260
- package/dist/src/frontend/homepage-view.js.map +0 -1
- package/dist/src/frontend/page-runtime-client.js +0 -103
- package/dist/src/frontend/page-runtime-client.js.map +0 -1
- package/dist/src/frontend/page-runtime-store.js +0 -9
- package/dist/src/frontend/page-runtime-store.js.map +0 -1
- package/dist/src/frontend/sentry.js +0 -42
- package/dist/src/frontend/sentry.js.map +0 -1
- package/dist/src/frontend/template-editor-chat.js +0 -3767
- package/dist/src/frontend/template-editor-chat.js.map +0 -1
- package/dist/src/help-page.js +0 -333
- package/dist/src/help-page.js.map +0 -1
- package/dist/src/homepage.js +0 -919
- package/dist/src/homepage.js.map +0 -1
- package/dist/src/hyperframes/composition.js +0 -180
- package/dist/src/hyperframes/composition.js.map +0 -1
- package/dist/src/index.js +0 -16
- package/dist/src/index.js.map +0 -1
- package/dist/src/instrument.js +0 -30
- package/dist/src/instrument.js.map +0 -1
- package/dist/src/lib/crypto.js +0 -45
- package/dist/src/lib/crypto.js.map +0 -1
- package/dist/src/lib/dev-log.js +0 -54
- package/dist/src/lib/dev-log.js.map +0 -1
- package/dist/src/lib/display-name.js +0 -11
- package/dist/src/lib/display-name.js.map +0 -1
- package/dist/src/lib/ids.js +0 -24
- package/dist/src/lib/ids.js.map +0 -1
- package/dist/src/lib/images.js +0 -19
- package/dist/src/lib/images.js.map +0 -1
- package/dist/src/lib/json.js +0 -15
- package/dist/src/lib/json.js.map +0 -1
- package/dist/src/lib/template-dna.js +0 -543
- package/dist/src/lib/template-dna.js.map +0 -1
- package/dist/src/lib/template-paths.js +0 -28
- package/dist/src/lib/template-paths.js.map +0 -1
- package/dist/src/lib/template-style-options.js +0 -203
- package/dist/src/lib/template-style-options.js.map +0 -1
- package/dist/src/lib/time.js +0 -7
- package/dist/src/lib/time.js.map +0 -1
- package/dist/src/lib/video-quality-harness.js +0 -60
- package/dist/src/lib/video-quality-harness.js.map +0 -1
- package/dist/src/page-runtime.js +0 -2
- package/dist/src/page-runtime.js.map +0 -1
- package/dist/src/page-shell.js +0 -2393
- package/dist/src/page-shell.js.map +0 -1
- package/dist/src/primitive-context.js +0 -299
- package/dist/src/primitive-context.js.map +0 -1
- package/dist/src/primitive-registry.js +0 -2181
- package/dist/src/primitive-registry.js.map +0 -1
- package/dist/src/primitive-sdk.js +0 -4
- package/dist/src/primitive-sdk.js.map +0 -1
- package/dist/src/primitives/remotion/html-image.js +0 -30
- package/dist/src/primitives/remotion/html-image.js.map +0 -1
- package/dist/src/primitives/remotion/media-slideshow.js +0 -60
- package/dist/src/primitives/remotion/media-slideshow.js.map +0 -1
- package/dist/src/react-page-shell.js +0 -35
- package/dist/src/react-page-shell.js.map +0 -1
- package/dist/src/ready-post-schedule-component.js +0 -1515
- package/dist/src/ready-post-schedule-component.js.map +0 -1
- package/dist/src/registry.js +0 -296
- package/dist/src/registry.js.map +0 -1
- package/dist/src/runtime.js +0 -31
- package/dist/src/runtime.js.map +0 -1
- package/dist/src/services/api-call-history.js +0 -249
- package/dist/src/services/api-call-history.js.map +0 -1
- package/dist/src/services/auth.js +0 -152
- package/dist/src/services/auth.js.map +0 -1
- package/dist/src/services/billing.js +0 -231
- package/dist/src/services/billing.js.map +0 -1
- package/dist/src/services/chat-threads.js +0 -92
- package/dist/src/services/chat-threads.js.map +0 -1
- package/dist/src/services/fork-access.js +0 -94
- package/dist/src/services/fork-access.js.map +0 -1
- package/dist/src/services/ghostcut.js +0 -132
- package/dist/src/services/ghostcut.js.map +0 -1
- package/dist/src/services/hyperframes.js +0 -1014
- package/dist/src/services/hyperframes.js.map +0 -1
- package/dist/src/services/job-capacity.js +0 -14
- package/dist/src/services/job-capacity.js.map +0 -1
- package/dist/src/services/job-logs.js +0 -197
- package/dist/src/services/job-logs.js.map +0 -1
- package/dist/src/services/jobs.js +0 -136
- package/dist/src/services/jobs.js.map +0 -1
- package/dist/src/services/media-processing.js +0 -743
- package/dist/src/services/media-processing.js.map +0 -1
- package/dist/src/services/primitive-media-lambda.js +0 -280
- package/dist/src/services/primitive-media-lambda.js.map +0 -1
- package/dist/src/services/providers.js +0 -2870
- package/dist/src/services/providers.js.map +0 -1
- package/dist/src/services/rate-limits.js +0 -237
- package/dist/src/services/rate-limits.js.map +0 -1
- package/dist/src/services/remotion.js +0 -688
- package/dist/src/services/remotion.js.map +0 -1
- package/dist/src/services/serverless-auth.js +0 -374
- package/dist/src/services/serverless-auth.js.map +0 -1
- package/dist/src/services/serverless-jobs.js +0 -1074
- package/dist/src/services/serverless-jobs.js.map +0 -1
- package/dist/src/services/serverless-provider-keys.js +0 -401
- package/dist/src/services/serverless-provider-keys.js.map +0 -1
- package/dist/src/services/serverless-records.js +0 -1086
- package/dist/src/services/serverless-records.js.map +0 -1
- package/dist/src/services/serverless-template-configs.js +0 -67
- package/dist/src/services/serverless-template-configs.js.map +0 -1
- package/dist/src/services/storage.js +0 -382
- package/dist/src/services/storage.js.map +0 -1
- package/dist/src/services/template-certification.js +0 -475
- package/dist/src/services/template-certification.js.map +0 -1
- package/dist/src/services/template-loader.js +0 -99
- package/dist/src/services/template-loader.js.map +0 -1
- package/dist/src/services/template-runtime-bundles.js +0 -217
- package/dist/src/services/template-runtime-bundles.js.map +0 -1
- package/dist/src/services/template-sources.js +0 -1017
- package/dist/src/services/template-sources.js.map +0 -1
- package/dist/src/services/video-normalization.js +0 -2
- package/dist/src/services/video-normalization.js.map +0 -1
- package/dist/src/services/webhooks.js +0 -62
- package/dist/src/services/webhooks.js.map +0 -1
- package/dist/src/template-editor-pages.js +0 -6624
- package/dist/src/template-editor-pages.js.map +0 -1
- package/dist/src/template-editor-shell.js +0 -2713
- package/dist/src/template-editor-shell.js.map +0 -1
- package/dist/src/template-sdk.js +0 -4
- package/dist/src/template-sdk.js.map +0 -1
- package/dist/src/worker.js +0 -17
- package/dist/src/worker.js.map +0 -1
- package/public/assets/homepage-app.js +0 -54
- package/public/assets/homepage-client-app.js +0 -80
- package/public/assets/page-runtime-client-app.js +0 -94
- package/readme.secret.md +0 -89
- package/templates/vidfarm_template_0000/README.md +0 -106
- package/templates/vidfarm_template_0000/SKILL.md +0 -266
- package/templates/vidfarm_template_0000/assets/Abel-Regular.ttf +0 -0
- package/templates/vidfarm_template_0000/assets/DMSerifDisplay-Regular.ttf +0 -0
- package/templates/vidfarm_template_0000/assets/Montserrat[wght].ttf +0 -0
- package/templates/vidfarm_template_0000/assets/SourceCodePro[wght].ttf +0 -0
- package/templates/vidfarm_template_0000/assets/TikTokSans-SemiBold.ttf +0 -0
- package/templates/vidfarm_template_0000/assets/Yesteryear-Regular.ttf +0 -0
- package/templates/vidfarm_template_0000/composition.json +0 -11
- package/templates/vidfarm_template_0000/src/lib/images.js +0 -221
- package/templates/vidfarm_template_0000/src/remotion/Root.js +0 -33
- package/templates/vidfarm_template_0000/src/remotion/index.js +0 -3
- package/templates/vidfarm_template_0000/src/sdk.js +0 -3
- package/templates/vidfarm_template_0000/src/style-options.js +0 -200
- package/templates/vidfarm_template_0000/src/template-dna.js +0 -9
- package/templates/vidfarm_template_0000/src/template.js +0 -1566
- package/templates/vidfarm_template_0000/template.config.json +0 -21
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, watch, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
// vidfarm dev-serve — a tiny HTTP layer that lets the browser editor point at
|
|
6
|
+
// a local directory of composition files instead of the deployed API. The
|
|
7
|
+
// editor detects dev mode from `?dev=<url>` (or localStorage) and rewrites
|
|
8
|
+
// its fork API calls to hit this server. File changes fan out via SSE so the
|
|
9
|
+
// editor can reload the composition on save-from-disk (e.g. Claude Code
|
|
10
|
+
// edits the file directly).
|
|
11
|
+
const CORS_HEADERS = {
|
|
12
|
+
"access-control-allow-origin": "*",
|
|
13
|
+
"access-control-allow-methods": "GET,PUT,PATCH,POST,OPTIONS",
|
|
14
|
+
"access-control-allow-headers": "content-type,authorization",
|
|
15
|
+
"access-control-max-age": "600"
|
|
16
|
+
};
|
|
17
|
+
export async function runDevServeCommand(argv) {
|
|
18
|
+
const parsed = parseArgs({
|
|
19
|
+
args: argv,
|
|
20
|
+
options: {
|
|
21
|
+
dir: { type: "string", default: "." },
|
|
22
|
+
port: { type: "string", default: "4321" }
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const rootDir = path.resolve(process.cwd(), parsed.values.dir);
|
|
26
|
+
const port = Number(parsed.values.port);
|
|
27
|
+
if (!existsSync(rootDir)) {
|
|
28
|
+
mkdirSync(rootDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
let nextClientId = 1;
|
|
31
|
+
const clients = new Set();
|
|
32
|
+
function broadcast(event, data) {
|
|
33
|
+
const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
34
|
+
for (const client of clients) {
|
|
35
|
+
try {
|
|
36
|
+
client.res.write(payload);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
clients.delete(client);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// fs.watch fires on any child change. Coalesce bursts so a single save
|
|
44
|
+
// doesn't spam the editor with 3 reload events.
|
|
45
|
+
let reloadTimer = null;
|
|
46
|
+
const scheduleReload = (filename) => {
|
|
47
|
+
if (reloadTimer)
|
|
48
|
+
clearTimeout(reloadTimer);
|
|
49
|
+
reloadTimer = setTimeout(() => {
|
|
50
|
+
reloadTimer = null;
|
|
51
|
+
broadcast("reload", { file: filename, at: Date.now() });
|
|
52
|
+
console.log(`[dev-serve] reload → ${filename ?? "(unknown)"}`);
|
|
53
|
+
}, 80);
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
watch(rootDir, { recursive: true }, (_type, filename) => {
|
|
57
|
+
scheduleReload(filename ?? null);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.warn(`[dev-serve] watch failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
|
+
}
|
|
63
|
+
const server = createServer((req, res) => handleRequest(req, res, rootDir, clients, nextClientId++));
|
|
64
|
+
server.listen(port, () => {
|
|
65
|
+
console.log(`[dev-serve] serving ${rootDir}`);
|
|
66
|
+
console.log(`[dev-serve] listening on http://localhost:${port}`);
|
|
67
|
+
console.log(`[dev-serve] editor: open with ?dev=${encodeURIComponent(`http://localhost:${port}`)}`);
|
|
68
|
+
});
|
|
69
|
+
process.on("SIGINT", () => {
|
|
70
|
+
console.log("\n[dev-serve] shutting down");
|
|
71
|
+
server.close(() => process.exit(0));
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function handleRequest(req, res, rootDir, clients, clientId) {
|
|
75
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
76
|
+
const url = new URL(req.url ?? "/", `http://localhost`);
|
|
77
|
+
const pathname = url.pathname;
|
|
78
|
+
if (method === "OPTIONS") {
|
|
79
|
+
res.writeHead(204, CORS_HEADERS);
|
|
80
|
+
res.end();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (pathname === "/_events" && method === "GET") {
|
|
84
|
+
res.writeHead(200, {
|
|
85
|
+
...CORS_HEADERS,
|
|
86
|
+
"content-type": "text/event-stream",
|
|
87
|
+
"cache-control": "no-cache",
|
|
88
|
+
connection: "keep-alive"
|
|
89
|
+
});
|
|
90
|
+
res.write(`event: hello\ndata: ${JSON.stringify({ at: Date.now() })}\n\n`);
|
|
91
|
+
const client = { res, id: clientId };
|
|
92
|
+
clients.add(client);
|
|
93
|
+
req.on("close", () => clients.delete(client));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const filePath = resolveFilePath(rootDir, pathname);
|
|
97
|
+
if (!filePath) {
|
|
98
|
+
respondJson(res, 404, { ok: false, error: `Not found: ${pathname}` });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (method === "GET") {
|
|
102
|
+
if (!existsSync(filePath)) {
|
|
103
|
+
respondJson(res, 404, { ok: false, error: `Missing ${path.basename(filePath)}` });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const body = readFileSync(filePath);
|
|
107
|
+
const contentType = pathname.endsWith(".html") ? "text/html; charset=utf-8" : "application/json";
|
|
108
|
+
res.writeHead(200, { ...CORS_HEADERS, "content-type": contentType });
|
|
109
|
+
res.end(body);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (method === "PUT" && pathname.endsWith("/composition.html")) {
|
|
113
|
+
readBody(req).then((body) => {
|
|
114
|
+
const html = body.toString("utf8");
|
|
115
|
+
if (!html.includes("data-composition-id=")) {
|
|
116
|
+
respondJson(res, 400, { ok: false, error: "Composition HTML is missing data-composition-id" });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
120
|
+
writeFileSync(filePath, html, "utf8");
|
|
121
|
+
respondJson(res, 200, { ok: true, bytes: html.length });
|
|
122
|
+
}).catch((error) => respondJson(res, 500, { ok: false, error: String(error) }));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (method === "PATCH" && pathname.endsWith("/composition.json")) {
|
|
126
|
+
readBody(req).then((body) => {
|
|
127
|
+
const patch = JSON.parse(body.toString("utf8") || "{}");
|
|
128
|
+
const existing = existsSync(filePath) ? JSON.parse(readFileSync(filePath, "utf8") || "{}") : {};
|
|
129
|
+
const merged = { ...existing, ...patch };
|
|
130
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
131
|
+
writeFileSync(filePath, JSON.stringify(merged, null, 2), "utf8");
|
|
132
|
+
respondJson(res, 200, merged);
|
|
133
|
+
}).catch((error) => respondJson(res, 500, { ok: false, error: String(error) }));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
respondJson(res, 405, { ok: false, error: `Method ${method} not allowed on ${pathname}` });
|
|
137
|
+
}
|
|
138
|
+
// Restrict served paths to the working/version composition files. Anything
|
|
139
|
+
// else 404s so this server isn't a random static host.
|
|
140
|
+
function resolveFilePath(rootDir, pathname) {
|
|
141
|
+
const clean = pathname.replace(/^\/+/, "");
|
|
142
|
+
const parts = clean.split("/").filter(Boolean);
|
|
143
|
+
if (parts.length === 0)
|
|
144
|
+
return null;
|
|
145
|
+
const filename = parts[parts.length - 1];
|
|
146
|
+
const allowed = ["composition.html", "composition.json", "manifest.json"];
|
|
147
|
+
if (!allowed.includes(filename))
|
|
148
|
+
return null;
|
|
149
|
+
// Allow: `composition.html`, `versions/1/composition.html`.
|
|
150
|
+
if (parts.length === 1)
|
|
151
|
+
return path.join(rootDir, filename);
|
|
152
|
+
if (parts.length === 3 && parts[0] === "versions" && /^\d+$/.test(parts[1])) {
|
|
153
|
+
return path.join(rootDir, "versions", parts[1], filename);
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
function respondJson(res, status, body) {
|
|
158
|
+
res.writeHead(status, { ...CORS_HEADERS, "content-type": "application/json" });
|
|
159
|
+
res.end(JSON.stringify(body));
|
|
160
|
+
}
|
|
161
|
+
function readBody(req) {
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
const chunks = [];
|
|
164
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
165
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
166
|
+
req.on("error", reject);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=dev-serve.js.map
|
package/package.json
CHANGED
|
@@ -1,37 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mevdragon/vidfarm-devcli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"deprecated": "This CLI targeted the old REST-API template paradigm. Vidfarm now uses the Trackpad Editor (composition-based editing in the browser). See SKILL.platform.md.",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Local bridge for the Vidfarm Trackpad Editor. Point it at a template id, edit composition.html on disk (Claude Code, Codex, etc.), preview live in the browser at https://vidfarm.cc/editor/.",
|
|
6
5
|
"type": "module",
|
|
7
6
|
"bin": {
|
|
8
7
|
"vidfarm": "dist/src/cli.js",
|
|
9
8
|
"vidfarm-devcli": "dist/src/cli.js"
|
|
10
9
|
},
|
|
11
10
|
"files": [
|
|
12
|
-
"dist/src",
|
|
13
|
-
"
|
|
14
|
-
"auto-create-templates/AUTO_CREATE_TEMPLATES.md",
|
|
15
|
-
"auto-create-templates/extractor-system-prompt.md",
|
|
16
|
-
"auto-create-templates/production-graph.schema.json",
|
|
17
|
-
"auto-create-templates/runbook.md",
|
|
18
|
-
"auto-create-templates/template-plan.schema.json",
|
|
19
|
-
"auto-create-templates/template-planner-prompt.md",
|
|
20
|
-
"auto-create-hyperframe-templates/AUTO_CREATE_HYPERFRAME_TEMPLATES.md",
|
|
21
|
-
"auto-create-hyperframe-templates/extractor-system-prompt.md",
|
|
22
|
-
"auto-create-hyperframe-templates/input-manifest.schema.json",
|
|
23
|
-
"auto-create-hyperframe-templates/lambda-memory-estimator.md",
|
|
24
|
-
"auto-create-hyperframe-templates/production-graph.schema.json",
|
|
25
|
-
"auto-create-hyperframe-templates/runbook.md",
|
|
26
|
-
"auto-create-hyperframe-templates/scripts/create-hyperframe-template.mjs",
|
|
27
|
-
"auto-create-hyperframe-templates/template-plan.schema.json",
|
|
28
|
-
"auto-create-hyperframe-templates/template-planner-prompt.md",
|
|
29
|
-
"dist/templates/vidfarm_template_0000",
|
|
30
|
-
"templates/vidfarm_template_0000",
|
|
11
|
+
"dist/src/cli.js",
|
|
12
|
+
"dist/src/dev-serve.js",
|
|
31
13
|
"README.md",
|
|
32
14
|
"SKILL.director.md",
|
|
33
15
|
"SKILL.platform.md",
|
|
34
|
-
".env.example",
|
|
35
16
|
"!readme.secret.md"
|
|
36
17
|
],
|
|
37
18
|
"publishConfig": {
|
|
@@ -47,7 +28,7 @@
|
|
|
47
28
|
"scripts": {
|
|
48
29
|
"dev": "tsx --import ./src/instrument.ts watch src/index.ts",
|
|
49
30
|
"dev:frontend": "node scripts/build-homepage-client.mjs --watch",
|
|
50
|
-
"dev:cli": "tsx src/cli.ts
|
|
31
|
+
"dev:cli": "tsx src/cli.ts --help",
|
|
51
32
|
"build:frontend": "node scripts/build-homepage-client.mjs",
|
|
52
33
|
"build:hyperframes-editor": "cd demo && node scripts/build.mjs",
|
|
53
34
|
"operator:template-artifact": "node scripts/platform-operator-template-artifact.mjs",
|
package/.env.example
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
NODE_ENV="development"
|
|
2
|
-
PORT="3000"
|
|
3
|
-
MOCK_PROVIDER_RESPONSES="false"
|
|
4
|
-
MAX_ACTIVE_JOBS_PER_CUSTOMER="30"
|
|
5
|
-
PROVIDER_LEASE_INLINE_WAIT_SECONDS="5"
|
|
6
|
-
PROVIDER_LEASE_STEP_WAIT_SECONDS="60"
|
|
7
|
-
PROVIDER_LEASE_MAX_STEP_WAIT_SECONDS="43200"
|
|
8
|
-
MAX_JOB_WALL_CLOCK_SECONDS="86400"
|
|
9
|
-
|
|
10
|
-
OPENAI_API_KEY=""
|
|
11
|
-
OPENROUTER_API_KEY=""
|
|
12
|
-
GEMINI_API_KEY=""
|
|
13
|
-
PERPLEXITY_API_KEY=""
|
|
14
|
-
GHOSTCUT_KEY=""
|
|
15
|
-
GHOSTCUT_SECRET=""
|
|
16
|
-
|
|
17
|
-
# Optional. Production CDK wires these automatically. Browser-facing Lambda calls still callback to PUBLIC_BASE_URL for auth.
|
|
18
|
-
VIDFARM_ZIP_LAMBDA_URL=""
|
|
19
|
-
VIDFARM_ZIP_LAMBDA_SECRET=""
|
|
20
|
-
VIDFARM_BILLING_URL=""
|
|
21
|
-
VIDFARM_BILLING_SECRET=""
|
|
22
|
-
VIDFARM_RATE_LIMITS_TABLE_NAME=""
|
|
23
|
-
# Optional production CDK overrides. Leave empty to use deterministic per-account/per-region names.
|
|
24
|
-
VIDFARM_STORAGE_S3_BUCKET_NAME=""
|
|
25
|
-
|
|
26
|
-
# Optional when calling a hosted Vidfarm API directly.
|
|
27
|
-
VIDFARM_USER_ID=""
|
|
28
|
-
VIDFARM_API_KEY=""
|
|
29
|
-
# Optional director override for production debugging. Send as x-superagency-key.
|
|
30
|
-
SUPERAGENCY_KEY=""
|
|
31
|
-
|
|
32
|
-
# Optional local overrides. The CLI will choose sensible local defaults.
|
|
33
|
-
PUBLIC_BASE_URL="http://localhost:3310"
|
|
34
|
-
# Optional public browser-facing chat endpoint. Leave empty locally unless you want the UI to hit a separate chat host directly.
|
|
35
|
-
PUBLIC_EDITOR_CHAT_URL=""
|
|
36
|
-
|
|
37
|
-
# Optional Sentry setup. SENTRY_DSN powers the Hono Node backend.
|
|
38
|
-
# SENTRY_LAMBDA_DSN powers the CDK-managed AWS Lambdas.
|
|
39
|
-
# PUBLIC_SENTRY_DSN powers the browser React bundles and may be the same DSN or a separate browser project DSN.
|
|
40
|
-
SENTRY_DSN=""
|
|
41
|
-
SENTRY_ENVIRONMENT="development"
|
|
42
|
-
SENTRY_RELEASE=""
|
|
43
|
-
SENTRY_TRACES_SAMPLE_RATE=""
|
|
44
|
-
SENTRY_ENABLE_LOGS="true"
|
|
45
|
-
SENTRY_SEND_DEFAULT_PII="false"
|
|
46
|
-
SENTRY_DEBUG_ROUTE="false"
|
|
47
|
-
SENTRY_LAMBDA_DSN=""
|
|
48
|
-
SENTRY_LAMBDA_TRACES_SAMPLE_RATE="1.0"
|
|
49
|
-
PUBLIC_SENTRY_DSN=""
|
|
50
|
-
PUBLIC_SENTRY_TRACES_SAMPLE_RATE=""
|
|
51
|
-
PUBLIC_SENTRY_REPLAYS_SESSION_SAMPLE_RATE=""
|
|
52
|
-
PUBLIC_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE=""
|
|
53
|
-
PUBLIC_SENTRY_ENABLE_LOGS="true"
|
|
54
|
-
PUBLIC_SENTRY_SEND_DEFAULT_PII="true"
|
|
55
|
-
PUBLIC_SENTRY_TRACE_PROPAGATION_TARGETS=""
|
|
56
|
-
REMOTION_MODE="local"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
GHOSTCUT_KEY="_________"
|
|
60
|
-
GHOSTCUT_SECRET="_________"
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
# Auto-Create HyperFrame Templates Harness
|
|
2
|
-
|
|
3
|
-
This harness turns a simple MP4, image, or PNG/JPG/WebP slideshow into an editable HyperFrames composition that can be rendered through the production AWS Lambda stack.
|
|
4
|
-
|
|
5
|
-
Use this when the desired output is not a Vidfarm operation package, but a decomposed HyperFrames project:
|
|
6
|
-
|
|
7
|
-
```txt
|
|
8
|
-
drafts/<format_slug>/
|
|
9
|
-
source.md
|
|
10
|
-
preview/
|
|
11
|
-
source.mp4
|
|
12
|
-
composition.html
|
|
13
|
-
composition.json
|
|
14
|
-
lambda-site.json
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
The goal is to make the source editable in the HyperFrames editor while keeping publish behavior faithful. If a user deletes a source video scene, the final render must show a blank/background gap unless another timed layer covers that range. Do not rely on an always-on source video for publish output.
|
|
18
|
-
|
|
19
|
-
## Start Here
|
|
20
|
-
|
|
21
|
-
Give a Codex agent these two things:
|
|
22
|
-
|
|
23
|
-
1. this entry file: `auto-create-hyperframe-templates/AUTO_CREATE_HYPERFRAME_TEMPLATES.md`
|
|
24
|
-
2. one source media folder, preferably shaped like:
|
|
25
|
-
|
|
26
|
-
```txt
|
|
27
|
-
drafts/<format_slug>/
|
|
28
|
-
source.md
|
|
29
|
-
preview/
|
|
30
|
-
source.mp4
|
|
31
|
-
slide-01.png
|
|
32
|
-
slide-02.png
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Then ask:
|
|
36
|
-
|
|
37
|
-
```txt
|
|
38
|
-
Use auto-create-hyperframe-templates/AUTO_CREATE_HYPERFRAME_TEMPLATES.md as the harness. Analyze drafts/<format_slug>/, create the run artifacts, generate the HyperFrames production graph and template plan, then write composition.html, composition.json, and lambda-site.json.
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
For the current local bridge, you can run:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
node auto-create-hyperframe-templates/scripts/create-hyperframe-template.mjs drafts/<format_slug>/preview/source.mp4
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
For a slideshow, pass the folder containing the images:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
node auto-create-hyperframe-templates/scripts/create-hyperframe-template.mjs drafts/<format_slug>/preview
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Add `--stage-site` when you want the script to call the production HyperFrames Lambda site upload after writing the local artifacts.
|
|
54
|
-
|
|
55
|
-
The source can be:
|
|
56
|
-
|
|
57
|
-
- one MP4
|
|
58
|
-
- a folder of PNG/JPG/WebP slides
|
|
59
|
-
- a mixed folder with source video, screenshots, overlay images, audio, and notes
|
|
60
|
-
|
|
61
|
-
If `source.md` is missing, create it with the source URL, adaptation goal, expected audience, and any constraints that can be inferred from the files.
|
|
62
|
-
|
|
63
|
-
For programmatic runs, write an input manifest matching `input-manifest.schema.json`:
|
|
64
|
-
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"mode": "autocreate-hyperframe-template",
|
|
68
|
-
"input_path": "drafts/my-format/preview/source.mp4",
|
|
69
|
-
"output_path": "drafts/my-format",
|
|
70
|
-
"slug_id": "my-format",
|
|
71
|
-
"source_mode": "auto",
|
|
72
|
-
"render_defaults": {
|
|
73
|
-
"width": 720,
|
|
74
|
-
"height": 1280,
|
|
75
|
-
"fps": 30
|
|
76
|
-
},
|
|
77
|
-
"lambda": {
|
|
78
|
-
"stack_name": "hyperframes-vidfarm-prod",
|
|
79
|
-
"region": "us-east-1",
|
|
80
|
-
"memory_strategy": "estimate"
|
|
81
|
-
},
|
|
82
|
-
"publish": {
|
|
83
|
-
"prestage_site": false,
|
|
84
|
-
"output_url_policy": "signed_https_final_output_only"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Output Contract
|
|
90
|
-
|
|
91
|
-
Every successful run should produce:
|
|
92
|
-
|
|
93
|
-
- `composition.html`: a self-contained HyperFrames composition using deterministic HTML/CSS and timed media elements.
|
|
94
|
-
- `composition.json`: the editable editor manifest: source assets, scene cuts, layers, caption geometry, viral/visual DNA, and Lambda estimate.
|
|
95
|
-
- `lambda-site.json`: the production Lambda site/render metadata: stack, region, memory estimate, site id if pre-staged, and render defaults.
|
|
96
|
-
- optional `frames/contact-sheet.jpg`, `source/ffprobe.json`, `transcripts/stt.json`, `ocr/frame_text.json`, and `motion/scene-cuts.json`.
|
|
97
|
-
|
|
98
|
-
The `composition.json` should follow `template-plan.schema.json` after planning. The lower-level extraction artifact should follow `production-graph.schema.json`.
|
|
99
|
-
|
|
100
|
-
## Core Principle
|
|
101
|
-
|
|
102
|
-
HyperFrames is the editor and deterministic renderer. The harness should decompose the source into layers that remain individually editable:
|
|
103
|
-
|
|
104
|
-
- source video scene clips
|
|
105
|
-
- source audio
|
|
106
|
-
- images or slide frames
|
|
107
|
-
- deterministic captions
|
|
108
|
-
- deterministic HTML overlays
|
|
109
|
-
- shapes, chips, arrows, circles, masks, UI shells, and stickers
|
|
110
|
-
- generated assets only when the visual cannot be rebuilt deterministically
|
|
111
|
-
|
|
112
|
-
Important readable text should not be baked into generated media unless the source format is explicitly poster/artifact-native and OCR validation is part of the quality harness.
|
|
113
|
-
|
|
114
|
-
## Timeline Rules
|
|
115
|
-
|
|
116
|
-
Use absolute seconds in manifests and data attributes. Convert to frames only at render time.
|
|
117
|
-
|
|
118
|
-
Required layer fields:
|
|
119
|
-
|
|
120
|
-
- `id`
|
|
121
|
-
- `kind`
|
|
122
|
-
- `start`
|
|
123
|
-
- `duration`
|
|
124
|
-
- `track`
|
|
125
|
-
- `z`
|
|
126
|
-
- `mode`
|
|
127
|
-
- `source_of_truth`
|
|
128
|
-
- `geometry`
|
|
129
|
-
- `viral_alignment`
|
|
130
|
-
|
|
131
|
-
For video decomposition, split source video into scene layers:
|
|
132
|
-
|
|
133
|
-
```json
|
|
134
|
-
{
|
|
135
|
-
"id": "scene-2",
|
|
136
|
-
"kind": "video",
|
|
137
|
-
"start": 3.567,
|
|
138
|
-
"duration": 3.033,
|
|
139
|
-
"track": 0,
|
|
140
|
-
"z": 0,
|
|
141
|
-
"mode": "both",
|
|
142
|
-
"media": {
|
|
143
|
-
"src": "/drafts/example/source.mp4",
|
|
144
|
-
"media_start": 3.567,
|
|
145
|
-
"fit": "cover"
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
For publish correctness, timed video scene layers should become real timed media layers or publish-time timeline proxies that are rewritten into real timed media. A preview-only playback source may exist for editor scrubbing, but it must be ignored or normalized out during publish.
|
|
151
|
-
|
|
152
|
-
Blank gaps are valid. If no layer covers a time range, render the composition background for that range.
|
|
153
|
-
|
|
154
|
-
## Slideshow Rules
|
|
155
|
-
|
|
156
|
-
For an image slideshow, create one timed image layer per slide:
|
|
157
|
-
|
|
158
|
-
```json
|
|
159
|
-
{
|
|
160
|
-
"id": "slide-01-image",
|
|
161
|
-
"kind": "image",
|
|
162
|
-
"start": 0,
|
|
163
|
-
"duration": 3,
|
|
164
|
-
"track": 0,
|
|
165
|
-
"z": 0,
|
|
166
|
-
"mode": "both",
|
|
167
|
-
"media": {
|
|
168
|
-
"src": "/drafts/example/slide-01.png",
|
|
169
|
-
"fit": "cover"
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Caption text should be separate `caption` or `html` layers unless the source is intentionally a flattened image/poster template.
|
|
175
|
-
|
|
176
|
-
## Caption And Overlay Rules
|
|
177
|
-
|
|
178
|
-
Captions are deterministic layout, not an afterthought. Record:
|
|
179
|
-
|
|
180
|
-
- font family and fallback
|
|
181
|
-
- font weight
|
|
182
|
-
- font size in px at the target composition size
|
|
183
|
-
- line height
|
|
184
|
-
- max width
|
|
185
|
-
- x/y/width/height in percentages
|
|
186
|
-
- text alignment
|
|
187
|
-
- safe-area constraints
|
|
188
|
-
- outline, radial halo, shadow, or inline highlight chip behavior
|
|
189
|
-
- whether text can wrap and how many lines are allowed
|
|
190
|
-
|
|
191
|
-
Caption positions must account for TikTok/Reels unsafe zones. For vertical 9:16 output, preserve:
|
|
192
|
-
|
|
193
|
-
- top 8-12 percent for app chrome risk
|
|
194
|
-
- right 12-16 percent for action buttons
|
|
195
|
-
- bottom 14-20 percent for username, caption, and scrubber risk
|
|
196
|
-
- center subject-safe zone when faces/products matter
|
|
197
|
-
|
|
198
|
-
Use inline chips that hug measured wrapped lines when the source has caption backgrounds. Do not turn inline chips into full-width bars or large paragraph washes.
|
|
199
|
-
|
|
200
|
-
For white TikTok-native captions, prefer a radial halo or outline. Avoid a single directional web drop shadow when the source uses a native black glyph halo.
|
|
201
|
-
|
|
202
|
-
For multiline captions, wrap once, choose one shared font size and line height, render one block, then measure per-line chips after layout. Do not render each wrapped line as an independently trimmed text image.
|
|
203
|
-
|
|
204
|
-
## Lambda Memory Estimate
|
|
205
|
-
|
|
206
|
-
Each plan must include a `lambda_memory_estimate` with:
|
|
207
|
-
|
|
208
|
-
- `recommended_memory_mb`
|
|
209
|
-
- `confidence`
|
|
210
|
-
- `complexity_scores`
|
|
211
|
-
- `rationale`
|
|
212
|
-
- `risk_flags`
|
|
213
|
-
- `benchmark_override`
|
|
214
|
-
|
|
215
|
-
Default to `3072` MB for ordinary 720x1280 or 1080x1920 social-video compositions with one active video stream and deterministic overlays. Use `2048` MB only for static/slideshow/simple 720p outputs or after local evidence that video decode is light. Use `4096` MB for 1080p video, multiple simultaneous videos, heavy DOM/caption effects, or long audio mixing. Reserve `6144+` MB for high-resolution or failure-prone compositions.
|
|
216
|
-
|
|
217
|
-
Do not default to `10240` MB. Use it only after timeouts, Chromium memory failures, or a measured case that requires it.
|
|
218
|
-
|
|
219
|
-
See `lambda-memory-estimator.md` for the scoring rubric.
|
|
220
|
-
|
|
221
|
-
## Production Lambda Site
|
|
222
|
-
|
|
223
|
-
The generated plan should be ready for the deployed production Lambda stack:
|
|
224
|
-
|
|
225
|
-
- stack: `hyperframes-vidfarm-prod`
|
|
226
|
-
- default region: `us-east-1`
|
|
227
|
-
- default memory: `3072`
|
|
228
|
-
- output policy: frontend should show only the final downloadable/signed output URL, not AWS console links that require login
|
|
229
|
-
|
|
230
|
-
For repeat publishing, pre-stage the project as a Lambda site and write `lambda-site.json`:
|
|
231
|
-
|
|
232
|
-
```json
|
|
233
|
-
{
|
|
234
|
-
"schema": "vidfarm.hyperframe.lambda-site.v1",
|
|
235
|
-
"stack_name": "hyperframes-vidfarm-prod",
|
|
236
|
-
"region": "us-east-1",
|
|
237
|
-
"site_id": "content-addressed-site-id",
|
|
238
|
-
"project_dir": "drafts/example",
|
|
239
|
-
"composition_file": "composition.html",
|
|
240
|
-
"memory_mb": 3072,
|
|
241
|
-
"render_defaults": {
|
|
242
|
-
"width": 720,
|
|
243
|
-
"height": 1280,
|
|
244
|
-
"fps": 30
|
|
245
|
-
},
|
|
246
|
-
"output_url_policy": "signed_https_final_output_only"
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
If the site has not been uploaded yet, set `site_id` to `null` and include `site_upload_command` or `site_upload_api`.
|
|
251
|
-
|
|
252
|
-
## Pipeline
|
|
253
|
-
|
|
254
|
-
1. Intake source media and notes.
|
|
255
|
-
2. Extract `ffprobe`, contact sheet, scene cuts, OCR, transcript, and simple layout/subject regions.
|
|
256
|
-
3. Generate `production_graph.json` with `extractor-system-prompt.md`.
|
|
257
|
-
4. Generate `template_plan.json` with `template-planner-prompt.md`.
|
|
258
|
-
5. Write `composition.html`, `composition.json`, and `lambda-site.json`.
|
|
259
|
-
6. Validate locally in the editor.
|
|
260
|
-
7. Stage the project with the production Lambda site flow.
|
|
261
|
-
8. Publish through Lambda and verify the final output URL.
|
|
262
|
-
|
|
263
|
-
## Required Validation
|
|
264
|
-
|
|
265
|
-
Before publishing:
|
|
266
|
-
|
|
267
|
-
- every timed layer has non-negative `start` and positive `duration`
|
|
268
|
-
- no two editable layers overlap on the same track unless the track is intentionally composited
|
|
269
|
-
- scene video layers use `media_start`/`playbackStart` rather than an always-on background dependency
|
|
270
|
-
- deleting a scene removes that visual range from publish output
|
|
271
|
-
- captions are legible at phone size
|
|
272
|
-
- caption boxes avoid unsafe TikTok/Reels zones unless the source intentionally uses them
|
|
273
|
-
- source audio and source video are separate layers when audio is reused continuously
|
|
274
|
-
- Lambda memory estimate has a concrete rationale
|
|
275
|
-
- `lambda-site.json` does not contain credentials
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
# HyperFrames Production Graph Extractor Prompt
|
|
2
|
-
|
|
3
|
-
You are a HyperFrames production analyst.
|
|
4
|
-
|
|
5
|
-
Your job is to inspect one MP4, screenshot set, or PNG/JPG/WebP slideshow and extract the repeatable HyperFrames production process as structured JSON. Do not merely describe the media. Convert it into an editable composition graph that can become `composition.html`, `composition.json`, and a production Lambda site.
|
|
6
|
-
|
|
7
|
-
Return only JSON matching `production-graph.schema.json`.
|
|
8
|
-
|
|
9
|
-
## Inputs You May Receive
|
|
10
|
-
|
|
11
|
-
- source notes
|
|
12
|
-
- source video or slides
|
|
13
|
-
- contact sheet
|
|
14
|
-
- representative frames
|
|
15
|
-
- ffprobe metadata
|
|
16
|
-
- scene cut list
|
|
17
|
-
- STT transcript with word timestamps
|
|
18
|
-
- OCR text from frames
|
|
19
|
-
- layout analysis with bounding boxes
|
|
20
|
-
- existing `composition.html` or `composition.json`
|
|
21
|
-
- desired output dimensions and fps
|
|
22
|
-
|
|
23
|
-
## Extraction Rules
|
|
24
|
-
|
|
25
|
-
- Treat all supplied media as one reusable HyperFrames format.
|
|
26
|
-
- Separate source media, deterministic overlays, captions, audio, and generated assets.
|
|
27
|
-
- Identify which visual surfaces are editable layers and which are source-media content.
|
|
28
|
-
- Important readable text should default to deterministic HTML/caption layers, not baked generated media.
|
|
29
|
-
- Extract exact or inferred timing for scenes, slides, captions, overlays, transitions, zooms, holds, and loop points.
|
|
30
|
-
- Record source media slices with `media_start` when a layer uses a segment from a longer MP4.
|
|
31
|
-
- Preserve blank gaps as intentional timeline ranges when no layer should be visible.
|
|
32
|
-
- Do not depend on an always-on source video for publish correctness. Preview playback sources are allowed only as editor affordances.
|
|
33
|
-
- Distinguish `mode: "both"`, `mode: "editor"`, and `mode: "publish"`.
|
|
34
|
-
- Use percent geometry for layer placement: `x`, `y`, `width`, `height`.
|
|
35
|
-
- Use seconds for `start`, `duration`, `media_start`, and `media_end`.
|
|
36
|
-
- Track source audio separately from source video if audio should continue across scene cuts.
|
|
37
|
-
- Keep one editable timeline track collision-free unless the track is explicitly marked as composited.
|
|
38
|
-
- Identify caption safe areas and collisions with TikTok/Reels chrome.
|
|
39
|
-
- Record Lambda memory estimate inputs: resolution, duration, active video streams, source resolution, layer count, DOM complexity, effects, audio mixing, and known risk flags.
|
|
40
|
-
|
|
41
|
-
## Required Analysis Dimensions
|
|
42
|
-
|
|
43
|
-
Extract:
|
|
44
|
-
|
|
45
|
-
- format summary and source mode
|
|
46
|
-
- output dimensions, fps, and total duration
|
|
47
|
-
- source asset inventory
|
|
48
|
-
- scene or slide timeline
|
|
49
|
-
- layer decomposition
|
|
50
|
-
- deterministic caption and text surfaces
|
|
51
|
-
- HTML overlay surfaces
|
|
52
|
-
- media replacement slots
|
|
53
|
-
- audio plan
|
|
54
|
-
- safe areas and subject bounds
|
|
55
|
-
- caption positioning and wrapping rules
|
|
56
|
-
- visual rules that must survive adaptation
|
|
57
|
-
- editable controls
|
|
58
|
-
- generated asset needs, if any
|
|
59
|
-
- Lambda memory estimate
|
|
60
|
-
- production Lambda site readiness
|
|
61
|
-
- validation checklist
|
|
62
|
-
|
|
63
|
-
## Layer Classification
|
|
64
|
-
|
|
65
|
-
For every meaningful visual or audio element choose one kind:
|
|
66
|
-
|
|
67
|
-
- `video`: timed video layer or scene slice
|
|
68
|
-
- `image`: timed image/slide layer
|
|
69
|
-
- `audio`: timed audio layer
|
|
70
|
-
- `caption`: text intended as subtitle/creator caption
|
|
71
|
-
- `html`: custom deterministic HTML overlay, UI card, comment, notification, or app shell
|
|
72
|
-
- `shape`: non-text geometric layer
|
|
73
|
-
- `effect`: deterministic transform/filter/mask/highlight
|
|
74
|
-
|
|
75
|
-
For every layer choose one source of truth:
|
|
76
|
-
|
|
77
|
-
- `source_media`: the original media asset is the visual/audio content
|
|
78
|
-
- `deterministic_html`: HTML/CSS/text is the source of truth
|
|
79
|
-
- `generated_asset`: AI/generated media is the source of truth
|
|
80
|
-
- `user_asset`: caller-provided replacement asset is required
|
|
81
|
-
- `computed_effect`: derived motion, mask, crop, zoom, or highlight
|
|
82
|
-
|
|
83
|
-
## Caption Rules
|
|
84
|
-
|
|
85
|
-
Strongly identify typography:
|
|
86
|
-
|
|
87
|
-
- font family match
|
|
88
|
-
- fallback font stack
|
|
89
|
-
- font weight
|
|
90
|
-
- case
|
|
91
|
-
- color
|
|
92
|
-
- outline, stroke, radial halo, shadow
|
|
93
|
-
- background chip style
|
|
94
|
-
- line wrapping
|
|
95
|
-
- line height
|
|
96
|
-
- alignment
|
|
97
|
-
- safe area
|
|
98
|
-
- phone-size legibility
|
|
99
|
-
|
|
100
|
-
When captions have colored backgrounds, classify them as inline highlight chips unless the source clearly uses a panel. Chips must hug measured wrapped lines.
|
|
101
|
-
|
|
102
|
-
When captions are white TikTok-native captions, distinguish radial black halo/outline from a web-style directional shadow.
|
|
103
|
-
|
|
104
|
-
For multiline captions, require one shared font size and line height for the block. Do not recommend per-line rendered images.
|
|
105
|
-
|
|
106
|
-
## Lambda Memory Estimate Rules
|
|
107
|
-
|
|
108
|
-
Estimate memory from composition complexity, not vibes.
|
|
109
|
-
|
|
110
|
-
Use these defaults:
|
|
111
|
-
|
|
112
|
-
- `2048` MB for static/slideshow/simple image compositions with low DOM complexity.
|
|
113
|
-
- `3072` MB for standard 720x1280 or 1080x1920 social video with one active video stream and deterministic overlays.
|
|
114
|
-
- `4096` MB for 1080p video, multiple active videos, heavy captions, masks, filters, or long audio.
|
|
115
|
-
- `6144` MB or higher only when high resolution, many simultaneous layers, or prior failures justify it.
|
|
116
|
-
|
|
117
|
-
Return both a recommendation and a confidence. Include benchmark guidance only when the source sits near a threshold.
|
|
118
|
-
|
|
119
|
-
## Output Bias
|
|
120
|
-
|
|
121
|
-
Be concrete. A production graph should be implementable.
|
|
122
|
-
|
|
123
|
-
Bad: "Add captions around the video."
|
|
124
|
-
|
|
125
|
-
Good: "Render a 2-line white TikTok Sans Semibold caption block at x=8, y=42, width=84, height=14, fontSize=46, lineHeight=1.08, black radial halo, max 18 chars per line, timed 0.0-2.4s."
|
|
126
|
-
|
|
127
|
-
Publish correctness bias: if a source video is split into scenes, every scene must be its own timed layer or publish proxy. Deleting scene 2 must delete scene 2 from the final render.
|
|
128
|
-
|