@cueframe/kernel 0.2.52 → 0.2.54
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/dist/_members/composition/fonts/bundledFaces.d.ts +9 -15
- package/dist/_members/composition/fonts/captionFaces.d.ts +2 -3
- package/dist/_members/composition/ops/captionOps.d.ts +11 -0
- package/dist/_members/composition/ops/compositionOps.d.ts +20 -19
- package/dist/_members/composition/ops/compositionOps.shared.d.ts +1 -0
- package/dist/_members/composition/validators/composition.d.ts +724 -0
- package/dist/_members/composition/validators/registry.d.ts +1 -1
- package/dist/_members/composition/validators/render.d.ts +332 -0
- package/dist/_members/composition-ops/index.d.ts +89 -0
- package/dist/_members/core/render/compositionAudioAndDepth.d.ts +3 -2
- package/dist/_members/core/render/index.d.ts +1 -1
- package/dist/_members/core/render/types.d.ts +3 -1
- package/dist/_members/plane/contract.d.ts +1 -1
- package/dist/_members/primitives/captions/Captions.d.ts +18 -1
- package/dist/_members/primitives/captions/index.d.ts +1 -1
- package/dist/_members/primitives/lib/text/spec.d.ts +1 -0
- package/dist/animate.js +2 -2
- package/dist/authoring/build-tools.js +6 -6
- package/dist/authoring/context.js +5 -5
- package/dist/authoring/tools.js +5 -5
- package/dist/authoring.js +9 -9
- package/dist/{chunk-MYBK6DKF.js → chunk-2BVKNYRB.js} +1 -1
- package/dist/{chunk-AVTEPAWI.js → chunk-7RGDRDAR.js} +17 -13
- package/dist/{chunk-7XZW26U2.js → chunk-AONWKKXK.js} +1 -1
- package/dist/{chunk-WZ22ZYXD.js → chunk-C3ARYFN6.js} +4 -4
- package/dist/{chunk-4B4V3HYW.js → chunk-C6ONUJIO.js} +1 -1
- package/dist/{chunk-CZOVEX2D.js → chunk-CR3G2JQP.js} +1 -1
- package/dist/{chunk-2PU2TSUG.js → chunk-D5E5XFHK.js} +1 -1
- package/dist/{chunk-D2EG7J7X.js → chunk-DFB7UFZD.js} +1 -1
- package/dist/{chunk-FSEB4LSU.js → chunk-FYMXVYWS.js} +1 -1
- package/dist/{chunk-6WQHVYJD.js → chunk-G7ZSFSQG.js} +1 -1
- package/dist/{chunk-5ZQLMPDY.js → chunk-GAACUQAB.js} +1 -1
- package/dist/{chunk-3I43W7DP.js → chunk-GZMKTLO3.js} +52 -21
- package/dist/{chunk-QVBUYWW6.js → chunk-Q2FWFTDZ.js} +1 -1
- package/dist/{chunk-MBSQKRDF.js → chunk-QCGT3M7M.js} +2 -2
- package/dist/{chunk-KMDZDH5E.js → chunk-QCJUGKRC.js} +4 -4
- package/dist/{chunk-Z6NY6MCL.js → chunk-RMLGMYEJ.js} +1 -1
- package/dist/{chunk-IHXMBXXL.js → chunk-SIGKJOSF.js} +30 -4
- package/dist/{chunk-5JCLZPMV.js → chunk-T7WKIMTB.js} +63 -44
- package/dist/{chunk-ACURZCPN.js → chunk-UKKY7HWN.js} +1 -1
- package/dist/{chunk-2M65KQNG.js → chunk-V6GL37RZ.js} +394 -54
- package/dist/{chunk-CV3QQUMK.js → chunk-VKZTGD5Z.js} +128 -5
- package/dist/{chunk-JWW54N24.js → chunk-VYSBZUXZ.js} +1 -1
- package/dist/{chunk-3OG2674K.js → chunk-ZDE5S3DE.js} +1 -1
- package/dist/component-runtime/render.js +2 -2
- package/dist/component-runtime.js +3 -3
- package/dist/compose.js +5 -5
- package/dist/composition/fonts.js +1 -1
- package/dist/composition/graphics-plan.js +3 -3
- package/dist/composition/ops.js +4 -4
- package/dist/composition/projection.js +3 -3
- package/dist/composition/validators.js +13 -3
- package/dist/composition-ops.js +8 -8
- package/dist/composition.js +15 -5
- package/dist/{context-2MBCDTCZ.js → context-I7SPXR2Z.js} +5 -5
- package/dist/core/render.js +4 -4
- package/dist/core.js +4 -4
- package/dist/mcp/adapter.js +2 -2
- package/dist/mcp/core.js +1 -1
- package/dist/mcp/scene-shot.js +2 -2
- package/dist/mcp/server.js +12 -12
- package/dist/mcp.js +12 -12
- package/dist/primitives/captions.js +276 -44
- package/dist/primitives/effects.js +3 -3
- package/dist/primitives/layouts.js +3 -3
- package/dist/primitives/lib/text/marker.js +1 -1
- package/dist/primitives/scenes.js +3 -3
- package/dist/primitives.js +5 -5
- package/dist/render-harness/cardFonts.js +2 -2
- package/dist/render-harness.js +7 -7
- package/package.json +10 -10
|
@@ -4,19 +4,19 @@ import {
|
|
|
4
4
|
buildPlannerTools,
|
|
5
5
|
buildToolsFromSchemas,
|
|
6
6
|
extractProviderError
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-Q2FWFTDZ.js";
|
|
8
|
+
import "../chunk-QCJUGKRC.js";
|
|
9
9
|
import "../chunk-JOURGVOR.js";
|
|
10
10
|
import "../chunk-7AZLFN26.js";
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-T7WKIMTB.js";
|
|
12
|
+
import "../chunk-QCGT3M7M.js";
|
|
13
|
+
import "../chunk-VKZTGD5Z.js";
|
|
14
14
|
import "../chunk-WPZKOVYF.js";
|
|
15
15
|
import "../chunk-B7J5UUUV.js";
|
|
16
16
|
import "../chunk-KYRDKK2D.js";
|
|
17
17
|
import "../chunk-WREYUH2E.js";
|
|
18
18
|
import "../chunk-7PA7FGLD.js";
|
|
19
|
-
import "../chunk-
|
|
19
|
+
import "../chunk-7RGDRDAR.js";
|
|
20
20
|
import "../chunk-2ESYSVXG.js";
|
|
21
21
|
export {
|
|
22
22
|
ZERO_USAGE,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildDirectorContext
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-FYMXVYWS.js";
|
|
4
|
+
import "../chunk-T7WKIMTB.js";
|
|
5
|
+
import "../chunk-QCGT3M7M.js";
|
|
6
|
+
import "../chunk-VKZTGD5Z.js";
|
|
7
7
|
import "../chunk-WPZKOVYF.js";
|
|
8
8
|
import "../chunk-B7J5UUUV.js";
|
|
9
9
|
import "../chunk-KYRDKK2D.js";
|
|
10
10
|
import "../chunk-WREYUH2E.js";
|
|
11
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-7RGDRDAR.js";
|
|
12
12
|
import "../chunk-2ESYSVXG.js";
|
|
13
13
|
export {
|
|
14
14
|
buildDirectorContext
|
package/dist/authoring/tools.js
CHANGED
|
@@ -6,18 +6,18 @@ import {
|
|
|
6
6
|
COMPOSE_ROLE_TOOLS,
|
|
7
7
|
COMPOSE_ROLE_TOOL_NAMES,
|
|
8
8
|
dispatchComposeRoleTool
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-QCJUGKRC.js";
|
|
10
10
|
import "../chunk-JOURGVOR.js";
|
|
11
11
|
import "../chunk-7AZLFN26.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-T7WKIMTB.js";
|
|
13
|
+
import "../chunk-QCGT3M7M.js";
|
|
14
|
+
import "../chunk-VKZTGD5Z.js";
|
|
15
15
|
import "../chunk-WPZKOVYF.js";
|
|
16
16
|
import "../chunk-B7J5UUUV.js";
|
|
17
17
|
import "../chunk-KYRDKK2D.js";
|
|
18
18
|
import "../chunk-WREYUH2E.js";
|
|
19
19
|
import "../chunk-7PA7FGLD.js";
|
|
20
|
-
import "../chunk-
|
|
20
|
+
import "../chunk-7RGDRDAR.js";
|
|
21
21
|
import "../chunk-2ESYSVXG.js";
|
|
22
22
|
export {
|
|
23
23
|
COMPOSE_MOTION_TOOLS,
|
package/dist/authoring.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
buildPlannerTools,
|
|
12
12
|
buildToolsFromSchemas,
|
|
13
13
|
extractProviderError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-Q2FWFTDZ.js";
|
|
15
15
|
import {
|
|
16
16
|
COMPOSE_MOTION_TOOLS,
|
|
17
17
|
COMPOSE_MOTION_VERIFY_TOOLS,
|
|
@@ -20,14 +20,14 @@ import {
|
|
|
20
20
|
COMPOSE_ROLE_TOOLS,
|
|
21
21
|
COMPOSE_ROLE_TOOL_NAMES,
|
|
22
22
|
dispatchComposeRoleTool
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QCJUGKRC.js";
|
|
24
24
|
import {
|
|
25
25
|
AgentFixableCaptureError,
|
|
26
26
|
getExcludedTools
|
|
27
27
|
} from "./chunk-JOURGVOR.js";
|
|
28
28
|
import {
|
|
29
29
|
buildDirectorContext
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-FYMXVYWS.js";
|
|
31
31
|
import {
|
|
32
32
|
buildFastModel,
|
|
33
33
|
buildModel,
|
|
@@ -49,16 +49,16 @@ import {
|
|
|
49
49
|
initCodeGenPrompts
|
|
50
50
|
} from "./chunk-Y4HPN4BC.js";
|
|
51
51
|
import "./chunk-7AZLFN26.js";
|
|
52
|
-
import "./chunk-
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
52
|
+
import "./chunk-T7WKIMTB.js";
|
|
53
|
+
import "./chunk-QCGT3M7M.js";
|
|
54
|
+
import "./chunk-VKZTGD5Z.js";
|
|
55
55
|
import "./chunk-WPZKOVYF.js";
|
|
56
56
|
import "./chunk-B7J5UUUV.js";
|
|
57
57
|
import "./chunk-KYRDKK2D.js";
|
|
58
|
-
import "./chunk-
|
|
58
|
+
import "./chunk-G7ZSFSQG.js";
|
|
59
59
|
import {
|
|
60
60
|
cssLayoutVars
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-RMLGMYEJ.js";
|
|
62
62
|
import "./chunk-WREYUH2E.js";
|
|
63
63
|
import "./chunk-ILO4NEZ3.js";
|
|
64
64
|
import "./chunk-E63UEO5C.js";
|
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
isSceneShotClip
|
|
70
70
|
} from "./chunk-CL5Y6V6K.js";
|
|
71
71
|
import "./chunk-2L7PYYJK.js";
|
|
72
|
-
import "./chunk-
|
|
72
|
+
import "./chunk-7RGDRDAR.js";
|
|
73
73
|
import "./chunk-2ESYSVXG.js";
|
|
74
74
|
|
|
75
75
|
// ../authoring/src/agent.ts
|
|
@@ -75,7 +75,7 @@ var BUNDLED_FONT_FACES = Object.freeze({
|
|
|
75
75
|
},
|
|
76
76
|
"Instrument Serif": {
|
|
77
77
|
slug: "instrument-serif",
|
|
78
|
-
faces: [{ weight: "400", file: "400" }],
|
|
78
|
+
faces: [{ weight: "400", file: "400" }, { weight: "400", file: "400-italic", style: "italic" }],
|
|
79
79
|
captionDefaults: { base: 400, emphasis: 400 }
|
|
80
80
|
},
|
|
81
81
|
"National Park": {
|
|
@@ -102,19 +102,19 @@ function bundledFaceCoversWeight(face, weight) {
|
|
|
102
102
|
return weight >= lo && weight <= hi;
|
|
103
103
|
}
|
|
104
104
|
function bundledFontFaceExists(family, weight, style) {
|
|
105
|
-
if (style !== BUNDLED_FONT_STYLE) return false;
|
|
106
105
|
const bundled = bundledFontFamilyFaces(family);
|
|
107
106
|
if (!bundled) return false;
|
|
108
|
-
return bundled.faces.some((face) => bundledFaceCoversWeight(face, weight));
|
|
107
|
+
return bundled.faces.some((face) => (face.style ?? BUNDLED_FONT_STYLE) === style && bundledFaceCoversWeight(face, weight));
|
|
109
108
|
}
|
|
110
109
|
function describeBundledFontWeights(family) {
|
|
111
110
|
const bundled = bundledFontFamilyFaces(family);
|
|
112
111
|
if (!bundled) return "";
|
|
113
|
-
return bundled.faces.map((face) => face.weight.split(/\s+/).join("-")).join(", ");
|
|
112
|
+
return [...new Set(bundled.faces.map((face) => face.weight.split(/\s+/).join("-")))].join(", ");
|
|
114
113
|
}
|
|
115
114
|
function unrenderableFaceField(family, weight, style, sealed) {
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
const bundled = bundledFontFamilyFaces(family);
|
|
116
|
+
if (bundled) {
|
|
117
|
+
return bundled.faces.some((face) => (face.style ?? BUNDLED_FONT_STYLE) === style) ? "fontWeight" : "fontStyle";
|
|
118
118
|
}
|
|
119
119
|
if (sealed.hasFamily(family)) {
|
|
120
120
|
return sealed.hasWeight(family, weight) ? "fontStyle" : "fontWeight";
|
|
@@ -165,7 +165,7 @@ function admissibleFamilyForStack(stack) {
|
|
|
165
165
|
return resolved.kind === "bundled" ? resolved.family : stack;
|
|
166
166
|
}
|
|
167
167
|
function weightRanges(faces) {
|
|
168
|
-
return faces.map((face) => {
|
|
168
|
+
return [...new Map(faces.map((face) => [face.weight, face])).values()].map((face) => {
|
|
169
169
|
const parts = face.weight.split(/\s+/).map(Number);
|
|
170
170
|
const min = parts[0];
|
|
171
171
|
const max = parts.length > 1 ? parts[1] : min;
|
|
@@ -188,7 +188,7 @@ function vendoredFontCatalog() {
|
|
|
188
188
|
return {
|
|
189
189
|
family,
|
|
190
190
|
weights: weightRanges(entry.faces),
|
|
191
|
-
styles: [BUNDLED_FONT_STYLE],
|
|
191
|
+
styles: [...new Set(entry.faces.map((face) => face.style ?? BUNDLED_FONT_STYLE))],
|
|
192
192
|
captionDefaults: entry.captionDefaults,
|
|
193
193
|
origin: aliased.has(family) ? "aliased" : "bundled"
|
|
194
194
|
};
|
|
@@ -261,12 +261,12 @@ function faceIssue(use) {
|
|
|
261
261
|
return {
|
|
262
262
|
field: use.field,
|
|
263
263
|
face: { family: use.stack, weight: use.weight, style: use.style },
|
|
264
|
-
message: `font_not_reproducible \u2014 ${because(use)}: "${use.stack}" names no font file the render bundle carries,
|
|
264
|
+
message: `font_not_reproducible \u2014 ${because(use)}: "${use.stack}" names no font file the render bundle carries, so this stack ships no italic binary to select and the browser would slant whatever upright face it matched and the render refuses it before capture. Emphasise with emphasisFontWeight, emphasisColor or emphasisScale, or name an uploaded brand font that is sealed in italic.`
|
|
265
265
|
};
|
|
266
266
|
}
|
|
267
267
|
if (use.resolved.kind !== "bundled") return null;
|
|
268
268
|
const face = { family: use.resolved.family, weight: use.weight, style: use.style };
|
|
269
|
-
if (use.style === "italic") {
|
|
269
|
+
if (use.style === "italic" && !bundledFontFamilyFaces(use.resolved.family).faces.some((face2) => face2.style === "italic")) {
|
|
270
270
|
return {
|
|
271
271
|
field: use.field,
|
|
272
272
|
face,
|
|
@@ -274,10 +274,11 @@ function faceIssue(use) {
|
|
|
274
274
|
};
|
|
275
275
|
}
|
|
276
276
|
if (bundledFontFaceExists(use.resolved.family, use.weight, use.style)) return null;
|
|
277
|
+
const weightField = use.role === "emphasis" ? "emphasisFontWeight" : "fontWeight";
|
|
277
278
|
return {
|
|
278
|
-
field:
|
|
279
|
+
field: weightField,
|
|
279
280
|
face,
|
|
280
|
-
message: `font_not_reproducible \u2014 ${
|
|
281
|
+
message: `font_not_reproducible \u2014 ${weightField} ${use.weight} (${use.style}) has no file behind it: ${use.resolved.family} ships ${describeBundledFontWeights(use.resolved.family)}. The render refuses a weight outside that range before capture rather than let the browser substitute a nearby file, so set ${weightField} to a weight the family covers, or pick a family whose files do.`
|
|
281
282
|
};
|
|
282
283
|
}
|
|
283
284
|
function captionFaceIssues(style) {
|
|
@@ -377,7 +378,10 @@ function captionWeightChoices(stack) {
|
|
|
377
378
|
);
|
|
378
379
|
}
|
|
379
380
|
function captionStyleChoices(stack) {
|
|
380
|
-
|
|
381
|
+
const resolved = captionStackFamily(stack);
|
|
382
|
+
if (resolved.kind === "unknown") return ["normal", "italic"];
|
|
383
|
+
if (resolved.kind !== "bundled") return ["normal"];
|
|
384
|
+
return [...new Set(bundledFontFamilyFaces(resolved.family).faces.map((face) => face.style ?? BUNDLED_FONT_STYLE))];
|
|
381
385
|
}
|
|
382
386
|
|
|
383
387
|
// ../composition/src/fonts.ts
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
SCENE_SHOT_RESOURCE_DESCRIPTION,
|
|
3
3
|
SCENE_SHOT_RESOURCE_URI,
|
|
4
4
|
sceneShotContract
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZDE5S3DE.js";
|
|
6
6
|
import {
|
|
7
7
|
querySchemaShape,
|
|
8
8
|
serializeQuery,
|
|
9
9
|
waitForJob
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VYSBZUXZ.js";
|
|
11
11
|
import {
|
|
12
12
|
CURATED_TOOLS
|
|
13
13
|
} from "./chunk-4WBSXHQA.js";
|
|
@@ -28,10 +28,10 @@ import {
|
|
|
28
28
|
text,
|
|
29
29
|
textWithData,
|
|
30
30
|
withMedia
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-V6GL37RZ.js";
|
|
32
32
|
import {
|
|
33
33
|
CompositionOp
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-SIGKJOSF.js";
|
|
35
35
|
|
|
36
36
|
// ../mcp/src/prompts.ts
|
|
37
37
|
var skillListCache = null;
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from "./chunk-W2245F6G.js";
|
|
25
25
|
import {
|
|
26
26
|
FlexLayout
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-D5E5XFHK.js";
|
|
28
28
|
|
|
29
29
|
// ../execution/primitives/src/layouts/chat-to-preview-layout/index.tsx
|
|
30
30
|
import { Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
} from "./chunk-VZ7TYX6Z.js";
|
|
32
32
|
import {
|
|
33
33
|
resolveBrandRef
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-RMLGMYEJ.js";
|
|
35
35
|
import {
|
|
36
36
|
SHOT_SCALE_TARGET,
|
|
37
37
|
shotScaleZoom
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
bundledFontFaceExists,
|
|
65
65
|
mergedCaptionFaceIssues,
|
|
66
66
|
unrenderableFaceField
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-7RGDRDAR.js";
|
|
68
68
|
|
|
69
69
|
// ../execution/core/src/render/sceneCaptureIdentity.ts
|
|
70
70
|
var INTENT_FIELDS = [
|
|
@@ -1226,22 +1226,33 @@ function bindBehindSubjectHosts(overlays, clips) {
|
|
|
1226
1226
|
);
|
|
1227
1227
|
}
|
|
1228
1228
|
}
|
|
1229
|
-
function assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, output, effects = []) {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
{ candidateClipIds: window.candidateClipIds, startFrame: window.startFrame, endFrame: window.endFrame }
|
|
1242
|
-
);
|
|
1243
|
-
}
|
|
1229
|
+
function assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, output, effects = [], captionLayouts = []) {
|
|
1230
|
+
const requireCoverage = (label, startMs, endMs) => {
|
|
1231
|
+
const startFrame = Math.round(startMs / 1e3 * fps);
|
|
1232
|
+
const endFrame = Math.max(startFrame + 1, Math.round(endMs / 1e3 * fps));
|
|
1233
|
+
for (const window of visiblePackedHostWindows(clips, startFrame, endFrame, output, effects)) {
|
|
1234
|
+
if (!window.captionVisible || window.hostClipId) continue;
|
|
1235
|
+
const code = window.candidateClipIds.length > 1 ? "behind_subject_caption_host_ambiguous" : "behind_subject_caption_host_missing";
|
|
1236
|
+
throw renderInputError(
|
|
1237
|
+
code,
|
|
1238
|
+
`Behind-subject caption ${label} is not fully covered by a unique visible packed host during frames [${window.startFrame}, ${window.endFrame}); an exact matte is required for the visible picture.`,
|
|
1239
|
+
{ candidateClipIds: window.candidateClipIds, startFrame: window.startFrame, endFrame: window.endFrame }
|
|
1240
|
+
);
|
|
1244
1241
|
}
|
|
1242
|
+
};
|
|
1243
|
+
for (const segment of captionSegments ?? []) {
|
|
1244
|
+
for (const word of segment) requireCoverage(`word '${word.text}'`, word.startMs, word.endMs);
|
|
1245
|
+
}
|
|
1246
|
+
for (const layout of captionLayouts ?? []) {
|
|
1247
|
+
const segment = captionSegments?.[layout.segmentIndex];
|
|
1248
|
+
const first = segment?.[layout.wordStartIndex];
|
|
1249
|
+
const last = segment?.[layout.holdThroughWordIndex ?? layout.wordEndIndex - 1];
|
|
1250
|
+
if (!first || !last) throw new Error("Behind-subject caption layout references missing saved transcript words");
|
|
1251
|
+
requireCoverage(
|
|
1252
|
+
`layout segment ${layout.segmentIndex} words ${layout.wordStartIndex}..${layout.wordEndIndex - 1}`,
|
|
1253
|
+
first.startMs,
|
|
1254
|
+
last.endMs
|
|
1255
|
+
);
|
|
1245
1256
|
}
|
|
1246
1257
|
}
|
|
1247
1258
|
var FULL_RECT = { left: 0, top: 0, right: 1, bottom: 1 };
|
|
@@ -1272,6 +1283,11 @@ function coversLowerPictures(upper, lower, output, effects) {
|
|
|
1272
1283
|
return upperRect.left <= rect.left + epsilon && upperRect.top <= rect.top + epsilon && upperRect.right + epsilon >= rect.right && upperRect.bottom + epsilon >= rect.bottom;
|
|
1273
1284
|
});
|
|
1274
1285
|
}
|
|
1286
|
+
function explicitlyHidesCaptions(clip, effects) {
|
|
1287
|
+
if (!clip || clip.captionVisibility !== "hidden" || clip.mediaType === "image") return false;
|
|
1288
|
+
const region = clip.region;
|
|
1289
|
+
return !!region && region.x === 0 && region.y === 0 && region.w === 1 && region.h === 1 && (clip.opacity ?? 1) === 1 && (clip.scale ?? 1) === 1 && (clip.rotation ?? 0) === 0 && !clip.animate && !clip.cropTrajectory && !clip.cropTrajectoryUrl && !clip.hasCropIntent && !hasClipEffect(clip, effects) && !clip.hasTransition && (!clip.transitionIn || clip.transitionIn === "none");
|
|
1290
|
+
}
|
|
1275
1291
|
function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects = [], hostMode = "packed-only") {
|
|
1276
1292
|
if (endFrame <= startFrame) return [];
|
|
1277
1293
|
const boundaries = /* @__PURE__ */ new Set([startFrame, endFrame]);
|
|
@@ -1307,7 +1323,7 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
|
|
|
1307
1323
|
effects
|
|
1308
1324
|
));
|
|
1309
1325
|
const suppressesCaption = provesOcclusion && !globalEffectActive && pictureRect(top[0], output, effects) !== void 0;
|
|
1310
|
-
const captionVisible = !(suppressesCaption && top[0].captionVisibility === "hidden");
|
|
1326
|
+
const captionVisible = !(top.length === 1 && !globalEffectActive && (suppressesCaption && top[0].captionVisibility === "hidden" || explicitlyHidesCaptions(top[0], effects)));
|
|
1311
1327
|
const candidateHost = (clip) => hostMode === "all-video-candidates" ? clip.mediaType !== "image" : !!clip.packedUrl;
|
|
1312
1328
|
const host = provesOcclusion && candidateHost(top[0]) ? top[0] : void 0;
|
|
1313
1329
|
const unresolvedOverlap = top.length > 1 || top.length === 1 && active.length > 1 && !provesOcclusion;
|
|
@@ -1879,6 +1895,11 @@ function captionVisibilityWindowsForComposition(composition, sourceDimensions) {
|
|
|
1879
1895
|
...item.region ? { region: item.region } : {},
|
|
1880
1896
|
...item.fit ? { fit: item.fit } : {},
|
|
1881
1897
|
...track.kind === "video" && item.captionVisibility ? { captionVisibility: item.captionVisibility } : {},
|
|
1898
|
+
...item.opacity !== void 0 ? { opacity: item.opacity } : {},
|
|
1899
|
+
...item.scale !== void 0 ? { scale: item.scale } : {},
|
|
1900
|
+
...item.rotation !== void 0 ? { rotation: item.rotation } : {},
|
|
1901
|
+
...item.animate !== void 0 ? { animate: item.animate } : {},
|
|
1902
|
+
...spanIndex === 0 && item.transitionIn?.type !== void 0 && item.transitionIn.type !== "cut" && item.transitionIn.type !== "none" ? { hasTransition: true } : {},
|
|
1882
1903
|
...item.source.reframe?.segments.length ? { hasCropIntent: true } : {},
|
|
1883
1904
|
...item.effects?.length ? { hasClipEffects: true } : {}
|
|
1884
1905
|
});
|
|
@@ -1976,6 +1997,11 @@ function assertMergedCaptionFacesDrawable(composition) {
|
|
|
1976
1997
|
if (!captions?.segments.some((segment) => segment.words.length > 0)) return;
|
|
1977
1998
|
const brandCaption = composition.brandKit?.caption;
|
|
1978
1999
|
const issues = mergedCaptionFaceIssues(captions.style, brandCaption);
|
|
2000
|
+
for (const [index, layout] of (captions.layouts ?? []).entries()) {
|
|
2001
|
+
for (const issue of mergedCaptionFaceIssues({ ...captions.style, ...layout.style }, brandCaption)) {
|
|
2002
|
+
issues.push({ ...issue, path: `captions.layouts[${index}].style.${issue.path.split(".").at(-1)}` });
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
1979
2005
|
if (issues.length === 0) return;
|
|
1980
2006
|
throw renderInputError(
|
|
1981
2007
|
"font_not_reproducible",
|
|
@@ -2078,9 +2104,9 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2078
2104
|
if (end > maxBackgroundEndFrames) maxBackgroundEndFrames = end;
|
|
2079
2105
|
}
|
|
2080
2106
|
const bodyDurationInFrames = maxBackgroundEndFrames > 0 ? Math.min(maxEndFrames, maxBackgroundEndFrames) : maxEndFrames;
|
|
2081
|
-
const captionSegments = composition.captions?.segments.map((seg) => seg.words)
|
|
2107
|
+
const captionSegments = composition.captions?.segments.map((seg) => seg.words);
|
|
2082
2108
|
if (composition.captions?.zPlane === "behind-subject") {
|
|
2083
|
-
assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, { width, height }, effects);
|
|
2109
|
+
assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, { width, height }, effects, composition.captions.layouts);
|
|
2084
2110
|
}
|
|
2085
2111
|
const brandKit = composition.brandKit;
|
|
2086
2112
|
const { totalFrames: durationInFrames } = resolveBookendTimeline(
|
|
@@ -2102,7 +2128,7 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2102
2128
|
...mot.exitMs != null ? { exitMs: mot.exitMs } : {}
|
|
2103
2129
|
} : void 0;
|
|
2104
2130
|
const baseStyle = composition.captions?.style;
|
|
2105
|
-
const hasCaptions = captionSegments
|
|
2131
|
+
const hasCaptions = captionSegments?.some((words) => words.length > 0) ?? false;
|
|
2106
2132
|
const captionStyle = hasCaptions && (cap || baseStyle || captionMotion) ? {
|
|
2107
2133
|
...baseStyle ?? {},
|
|
2108
2134
|
...cap?.fontFamily ? { fontFamily: cap.fontFamily } : {},
|
|
@@ -2127,6 +2153,10 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2127
2153
|
...cap?.exitMs != null ? { exitMs: cap.exitMs } : {}
|
|
2128
2154
|
} : void 0;
|
|
2129
2155
|
const resolvedCaptionStyle = captionStyle ? resolveCaptionColorRefs(captionStyle, brandKit) : void 0;
|
|
2156
|
+
const captionLayouts = composition.captions?.layouts?.map((layout) => ({
|
|
2157
|
+
...layout,
|
|
2158
|
+
...layout.style ? { style: resolveCaptionColorRefs(layout.style, brandKit) } : {}
|
|
2159
|
+
}));
|
|
2130
2160
|
return {
|
|
2131
2161
|
clips,
|
|
2132
2162
|
overlays,
|
|
@@ -2138,6 +2168,7 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2138
2168
|
...audioTracks.length > 0 ? { audioTracks } : {},
|
|
2139
2169
|
...effects.length > 0 ? { effects } : {},
|
|
2140
2170
|
...hasCaptions ? { captionSegments } : {},
|
|
2171
|
+
...hasCaptions && captionLayouts?.length ? { captionLayouts } : {},
|
|
2141
2172
|
...hasCaptions && composition.captions?.zPlane === "behind-subject" ? { captionsBehind: true } : {},
|
|
2142
2173
|
...resolvedCaptionStyle ? { captionStyle: resolvedCaptionStyle } : {},
|
|
2143
2174
|
...brandKit ? { brandKit } : {}
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
Format,
|
|
5
5
|
GraphicRole,
|
|
6
6
|
OpaqueId
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VKZTGD5Z.js";
|
|
8
8
|
import {
|
|
9
9
|
brandKitCaptionFaceIssues
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7RGDRDAR.js";
|
|
11
11
|
|
|
12
12
|
// ../composition/src/validators/composePlan.ts
|
|
13
13
|
import { z } from "zod";
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
} from "./chunk-7AZLFN26.js";
|
|
8
8
|
import {
|
|
9
9
|
selectAllOverlays
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-T7WKIMTB.js";
|
|
11
11
|
import {
|
|
12
12
|
ComposePlan
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-QCGT3M7M.js";
|
|
14
14
|
import {
|
|
15
15
|
OverlayClipSource
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VKZTGD5Z.js";
|
|
17
17
|
|
|
18
18
|
// ../authoring/src/tools/toolSets.ts
|
|
19
19
|
var COMPOSE_PLANNER_TOOLS = [
|
|
@@ -63,7 +63,7 @@ var COMPOSE_ROLE_TOOLS = Object.freeze({
|
|
|
63
63
|
schema: z.object({}),
|
|
64
64
|
metadata: { label: "Get Context" },
|
|
65
65
|
handler: async (_args, capabilities) => {
|
|
66
|
-
const { buildDirectorContext } = await import("./context-
|
|
66
|
+
const { buildDirectorContext } = await import("./context-I7SPXR2Z.js");
|
|
67
67
|
return buildDirectorContext(capabilities);
|
|
68
68
|
}
|
|
69
69
|
},
|
|
@@ -3,25 +3,29 @@ import {
|
|
|
3
3
|
projectMediaPlaybackSpans,
|
|
4
4
|
sliceTranscriptWords,
|
|
5
5
|
splitIntoSentences
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GZMKTLO3.js";
|
|
7
7
|
import {
|
|
8
8
|
createHeadlessStore,
|
|
9
9
|
findClipById,
|
|
10
10
|
findMarkerById,
|
|
11
11
|
findTrackContainingClipId
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-T7WKIMTB.js";
|
|
13
13
|
import {
|
|
14
|
+
CaptionLayoutInput,
|
|
14
15
|
CaptionSegment,
|
|
15
16
|
CaptionStyle,
|
|
16
17
|
Composition,
|
|
18
|
+
CompositionCaptions,
|
|
17
19
|
Format,
|
|
18
20
|
Marker,
|
|
19
21
|
PerClipEffect,
|
|
20
22
|
TimelineClip,
|
|
21
23
|
Track,
|
|
22
24
|
Transition,
|
|
25
|
+
captionLayoutIssues,
|
|
26
|
+
captionSegmentSignature,
|
|
23
27
|
captionVisibilityIssues
|
|
24
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-VKZTGD5Z.js";
|
|
25
29
|
import {
|
|
26
30
|
ReframeSegment
|
|
27
31
|
} from "./chunk-B7J5UUUV.js";
|
|
@@ -31,7 +35,7 @@ import {
|
|
|
31
35
|
} from "./chunk-CL5Y6V6K.js";
|
|
32
36
|
import {
|
|
33
37
|
introducedCaptionFaceIssues
|
|
34
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-7RGDRDAR.js";
|
|
35
39
|
|
|
36
40
|
// ../composition-ops/src/index.ts
|
|
37
41
|
import { z } from "zod";
|
|
@@ -480,6 +484,9 @@ var CompositionOp = z.discriminatedUnion("type", [
|
|
|
480
484
|
z.object({ type: z.literal("setCaptions"), segments: z.array(CaptionSegment), style: CaptionStyle.partial().optional() }).strict().describe(
|
|
481
485
|
"Replace the caption SEGMENTS wholesale \u2014 author the word-timed caption layer directly (each segment = one sentence/page of `words` with timeline-ms `startMs`/`endMs`, optional `emphasis`). This is how a client with its OWN word timings (e.g. a generated VO take) gets word-synced captions without a source transcript; the compose lane's transcript slice writes the same layer. `style`, when given, merges with setCaptionStyle semantics; an omitted style keeps the existing one. Renderer paginates within a segment and never pools words across two \u2014 keep segments sentence-bounded."
|
|
482
486
|
),
|
|
487
|
+
z.object({ type: z.literal("setCaptionLayouts"), layouts: z.array(CaptionLayoutInput) }).strict().describe(
|
|
488
|
+
"Replace native caption placements without changing transcript words or timings. Each layout references a half-open word-index range in one saved segment; a one-word range is valid. region places that group independently, optional bounded scale/rotation/style changes its look, and holdThroughWordIndex keeps it visible through a later saved word in the same segment. All words in a placed range occupy one page; rendering refuses a range that cannot fit its box, so enlarge region or split the range. The box reserves horizontal space of 1.6 font sizes and vertical space of 0.8 font sizes for padding, with at most three lines. Unreferenced words keep the default caption layout. Word ranges must not overlap. Reapply after caption regeneration or timeline cuts."
|
|
489
|
+
),
|
|
483
490
|
z.object({ type: z.literal("applyMotionPreset"), clipId: z.string(), preset: z.string(), params: z.object({ enterMs: z.number().optional(), exitMs: z.number().optional(), staggerMs: z.number().optional() }).strict().optional() }).strict().describe(
|
|
484
491
|
"Shell a STATIC `card` clip with a frame-driven MOTION preset \u2014 the public card-shelling op (the layout renders VERBATIM; only the container animates in/out). The server wraps the card in the chosen `preset` (fade-up / slide-in-left / slide-in-right / scale-pop / stagger-reveal), transpiles it, mints it as a LIVE component, and swaps the clip source to that component (the bakeless live lane \u2014 no box). `params` tunes timing (`enterMs`/`exitMs`, `staggerMs` for stagger-reveal). The target must be a static card (components already carry motion; library overlays already move); re-run overwrites idempotently ONLY while the target is still a card (an uncompilable shell); once shelled, the clip is a COMPONENT \u2014 to change its motion, remove and re-add the card, then re-shell. Honored under `dry_run` (validates preset + target without transpiling or persisting). ORDERING: the preset resolves its target against the PERSISTED composition \u2014 a card added in the SAME batch is not yet visible to it. Persist the clip.add batch first, then shell in a following call."
|
|
485
492
|
),
|
|
@@ -665,6 +672,20 @@ function applyOpToStore(store, op) {
|
|
|
665
672
|
case "setCaptions":
|
|
666
673
|
applyCaptionOpToStore(store, op);
|
|
667
674
|
break;
|
|
675
|
+
case "setCaptionLayouts": {
|
|
676
|
+
const captions = composition.captions;
|
|
677
|
+
if (!captions) throw new Error("setCaptionLayouts requires saved transcript captions");
|
|
678
|
+
const issue = captionLayoutIssues(captions.segments, op.layouts)[0];
|
|
679
|
+
if (issue) throw new Error(`setCaptionLayouts.layouts[${issue.index}].${issue.field}: ${issue.message}`);
|
|
680
|
+
const layouts = op.layouts.map((layout) => ({
|
|
681
|
+
...layout,
|
|
682
|
+
wordSignature: captionSegmentSignature(captions.segments[layout.segmentIndex].words)
|
|
683
|
+
}));
|
|
684
|
+
const parsed = CompositionCaptions.safeParse({ ...captions, layouts });
|
|
685
|
+
if (!parsed.success) throw new Error(`setCaptionLayouts: ${parsed.error.issues[0]?.message}`);
|
|
686
|
+
store.setCaptionLayouts(layouts);
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
668
689
|
case "applyMotionPreset":
|
|
669
690
|
throw new Error(
|
|
670
691
|
`applyOp: 'applyMotionPreset' is route-materialized \u2014 it needs a director transpile of the generated motion shell and is rewritten to a clip.update at /composition/apply before reaching the pure engine.`
|
|
@@ -801,6 +822,11 @@ function invertOp(before, op) {
|
|
|
801
822
|
}
|
|
802
823
|
case "setCaptionDepth":
|
|
803
824
|
return { type: "setCaptionDepth", zPlane: before.captions?.zPlane ?? "front" };
|
|
825
|
+
case "setCaptionLayouts":
|
|
826
|
+
return {
|
|
827
|
+
type: "setCaptionLayouts",
|
|
828
|
+
layouts: (before.captions?.layouts ?? []).map(({ wordSignature: _signature, ...layout }) => layout)
|
|
829
|
+
};
|
|
804
830
|
case "addTrack":
|
|
805
831
|
if (op.id === void 0) {
|
|
806
832
|
throw new Error("invertOp(addTrack): no pinned `id` \u2014 cannot target the minted track");
|