reframe-video 0.6.33 → 0.6.39
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/.claude-plugin/plugin.json +1 -1
- package/dist/assemble.js +138 -0
- package/dist/bin.js +248 -36
- package/dist/browserEntry.js +62 -3
- package/dist/cli.js +162 -18
- package/dist/compile-api.js +20 -0
- package/dist/compile.js +20 -0
- package/dist/diff.js +81 -3
- package/dist/frame.js +81 -3
- package/dist/index.js +1537 -1111
- package/dist/labels.js +80 -2
- package/dist/lint.js +1060 -0
- package/dist/manifest.js +1065 -0
- package/dist/types/compose.d.ts +6 -0
- package/dist/types/devicePreset.d.ts +36 -3
- package/dist/types/dsl.d.ts +4 -3
- package/dist/types/index.d.ts +4 -2
- package/dist/types/ir.d.ts +13 -5
- package/dist/types/manifest.d.ts +92 -0
- package/dist/types/titles.d.ts +71 -0
- package/dist/verifyOverlay.js +1152 -0
- package/guides/edsl-guide.md +58 -0
- package/guides/regen-contract.md +14 -0
- package/package.json +1 -1
- package/skills/reframe/SKILL.md +26 -0
package/dist/frame.js
CHANGED
|
@@ -278,11 +278,68 @@ function compileScene(ir) {
|
|
|
278
278
|
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
279
279
|
const natural = durationOf(grouping, 0);
|
|
280
280
|
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, natural) : 1);
|
|
281
|
-
const
|
|
281
|
+
const at = typeof tl.at === "number" ? tl.at : void 0;
|
|
282
|
+
const beatStart = at ?? start + (tl.gap ?? 0);
|
|
282
283
|
return beatStart + k * natural;
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
};
|
|
287
|
+
let labelClock;
|
|
288
|
+
const anyAnchor = (tl) => tl.kind === "beat" && typeof tl.at === "string" || "children" in tl && tl.children.some(anyAnchor);
|
|
289
|
+
if (ir.timeline && anyAnchor(ir.timeline)) {
|
|
290
|
+
const clock = /* @__PURE__ */ new Map();
|
|
291
|
+
const clockWalk = (tl, start) => {
|
|
292
|
+
let end = start;
|
|
293
|
+
switch (tl.kind) {
|
|
294
|
+
case "seq": {
|
|
295
|
+
let t = start;
|
|
296
|
+
for (const c of orderBeats(tl.children)) t = clockWalk(c, t);
|
|
297
|
+
end = t;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
case "par": {
|
|
301
|
+
for (const c of tl.children) end = Math.max(end, clockWalk(c, start));
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "stagger": {
|
|
305
|
+
tl.children.forEach((c, i) => {
|
|
306
|
+
end = Math.max(end, clockWalk(c, start + i * tl.interval));
|
|
307
|
+
});
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
case "wait":
|
|
311
|
+
end = start + tl.duration;
|
|
312
|
+
break;
|
|
313
|
+
case "tween":
|
|
314
|
+
end = start + (tl.duration ?? DEFAULT_TWEEN_DURATION);
|
|
315
|
+
break;
|
|
316
|
+
case "motionPath":
|
|
317
|
+
end = start + (tl.duration ?? DEFAULT_MOTIONPATH_DURATION);
|
|
318
|
+
break;
|
|
319
|
+
case "to": {
|
|
320
|
+
const override = ir.states?.[tl.state] ?? {};
|
|
321
|
+
const si = tl.stagger ?? 0;
|
|
322
|
+
const targets = nodeOrder.filter((id) => id in override && (tl.filter === void 0 || tl.filter.includes(id)));
|
|
323
|
+
end = start + (tl.duration ?? DEFAULT_TO_DURATION) + Math.max(0, targets.length - 1) * si;
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
case "beat": {
|
|
327
|
+
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
328
|
+
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, durationOf(grouping, 0)) : 1);
|
|
329
|
+
const inner = k === 1 ? grouping : scaleTimeline(grouping, k);
|
|
330
|
+
const at = typeof tl.at === "number" ? tl.at : void 0;
|
|
331
|
+
const beatStart = at ?? start + (tl.gap ?? 0);
|
|
332
|
+
end = clockWalk(inner, beatStart);
|
|
333
|
+
clock.set(tl.name, { t0: beatStart, t1: end });
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if ("label" in tl && tl.label !== void 0) clock.set(tl.label, { t0: start, t1: end });
|
|
338
|
+
return end;
|
|
339
|
+
};
|
|
340
|
+
clockWalk(ir.timeline, 0);
|
|
341
|
+
labelClock = clock;
|
|
342
|
+
}
|
|
286
343
|
const walk = (tl, start) => {
|
|
287
344
|
const end = walkInner(tl, start);
|
|
288
345
|
if ("label" in tl && tl.label !== void 0) labelTimes.set(tl.label, { t0: start, t1: end });
|
|
@@ -299,7 +356,8 @@ function compileScene(ir) {
|
|
|
299
356
|
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
300
357
|
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, durationOf(grouping, 0)) : 1);
|
|
301
358
|
const inner = k === 1 ? grouping : scaleTimeline(grouping, k);
|
|
302
|
-
const
|
|
359
|
+
const anchored = typeof tl.at === "string" ? labelClock?.get(tl.at)?.t0 : tl.at;
|
|
360
|
+
const beatStart = anchored !== void 0 ? anchored + (typeof tl.at === "string" ? tl.gap ?? 0 : 0) : start + (tl.gap ?? 0);
|
|
303
361
|
const end = walk(inner, beatStart);
|
|
304
362
|
beatTimes.set(tl.name, { t0: beatStart, t1: end });
|
|
305
363
|
labelTimes.set(tl.name, { t0: beatStart, t1: end });
|
|
@@ -500,6 +558,7 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
|
500
558
|
function validateScene(ir) {
|
|
501
559
|
const problems = [];
|
|
502
560
|
const nodeById = /* @__PURE__ */ new Map();
|
|
561
|
+
const startAnchors = [];
|
|
503
562
|
const checkPaint = (where, value) => {
|
|
504
563
|
if (typeof value !== "object" || value === null) return;
|
|
505
564
|
const g = value;
|
|
@@ -532,6 +591,7 @@ function validateScene(ir) {
|
|
|
532
591
|
if (typeof props.shadowBlur === "number" && props.shadowBlur < 0) problems.push(`node "${node.id}": shadowBlur must be >= 0`);
|
|
533
592
|
if (typeof props.blend === "string" && !BLEND_MODES.has(props.blend)) problems.push(`node "${node.id}": unknown blend "${props.blend}" \u2014 use ${[...BLEND_MODES].join(", ")}`);
|
|
534
593
|
if (typeof props.fit === "string" && !IMAGE_FITS.has(props.fit)) problems.push(`node "${node.id}": unknown fit "${props.fit}" \u2014 use ${[...IMAGE_FITS].join(", ")}`);
|
|
594
|
+
if (node.type === "video" && typeof node.props.start === "string") startAnchors.push({ id: node.id, at: node.props.start });
|
|
535
595
|
if (node.type === "group") {
|
|
536
596
|
const clip = node.props.clip;
|
|
537
597
|
if (clip) {
|
|
@@ -592,6 +652,7 @@ function validateScene(ir) {
|
|
|
592
652
|
);
|
|
593
653
|
}
|
|
594
654
|
const labels = /* @__PURE__ */ new Set();
|
|
655
|
+
const beatAnchors = [];
|
|
595
656
|
const checkEase = (path2, ease) => {
|
|
596
657
|
if (ease === void 0) return;
|
|
597
658
|
if (typeof ease === "string") {
|
|
@@ -683,6 +744,7 @@ function validateScene(ir) {
|
|
|
683
744
|
);
|
|
684
745
|
}
|
|
685
746
|
labels.add(tl.name);
|
|
747
|
+
if (typeof tl.at === "string") beatAnchors.push({ name: tl.name, at: tl.at, path: path2 });
|
|
686
748
|
if (tl.duration !== void 0 && tl.duration <= 0) {
|
|
687
749
|
problems.push(`${path2}: beat "${tl.name}" duration must be > 0`);
|
|
688
750
|
}
|
|
@@ -701,6 +763,22 @@ function validateScene(ir) {
|
|
|
701
763
|
}
|
|
702
764
|
};
|
|
703
765
|
if (ir.timeline) checkTimeline(ir.timeline, "timeline");
|
|
766
|
+
for (const a of beatAnchors) {
|
|
767
|
+
if (a.at === a.name) {
|
|
768
|
+
problems.push(`${a.path}: beat "${a.name}" at: "${a.at}" cannot anchor to itself`);
|
|
769
|
+
} else if (!labels.has(a.at)) {
|
|
770
|
+
problems.push(
|
|
771
|
+
`${a.path}: beat "${a.name}" at: "${a.at}" \u2014 unknown timeline label \u2014 known labels: ${[...labels].join(", ") || "(none)"}`
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
for (const a of startAnchors) {
|
|
776
|
+
if (!labels.has(a.at)) {
|
|
777
|
+
problems.push(
|
|
778
|
+
`video "${a.id}" start: "${a.at}" \u2014 unknown timeline label \u2014 known labels: ${[...labels].join(", ") || "(none)"}`
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
704
782
|
for (const [i, b] of (ir.behaviors ?? []).entries()) {
|
|
705
783
|
checkProps(`behaviors[${i}]`, b.target, { [b.prop]: 0 });
|
|
706
784
|
}
|
|
@@ -891,7 +969,7 @@ ${stderr.slice(-2e3)}`))
|
|
|
891
969
|
});
|
|
892
970
|
}
|
|
893
971
|
function neededSeconds(node, duration) {
|
|
894
|
-
const start = node.props.start ?? 0;
|
|
972
|
+
const start = typeof node.props.start === "string" ? 0 : node.props.start ?? 0;
|
|
895
973
|
const rate = node.props.rate ?? 1;
|
|
896
974
|
const clipStart = node.props.clipStart ?? 0;
|
|
897
975
|
return clipStart + Math.max(0, duration - start) * Math.max(0, rate) + 1 / 30;
|