@cueframe/kernel 0.2.51 → 0.2.53
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/validators/composition.d.ts +664 -0
- package/dist/_members/composition/validators/registry.d.ts +1 -1
- package/dist/_members/composition/validators/render.d.ts +294 -0
- package/dist/_members/composition-ops/index.d.ts +86 -0
- package/dist/_members/core/render/compositionAudioAndDepth.d.ts +9 -3
- package/dist/_members/core/render/compositionRender.d.ts +14 -0
- package/dist/_members/core/render/index.d.ts +2 -2
- package/dist/_members/core/render/types.d.ts +4 -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/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-2LUAUF46.js → chunk-46DGDPXR.js} +303 -47
- package/dist/{chunk-KY3QBG7O.js → chunk-4DM63RTI.js} +4 -4
- package/dist/{chunk-IHWC75AN.js → chunk-5E4YP44R.js} +1 -1
- package/dist/{chunk-MOUWO53S.js → chunk-7AUHC2X7.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-O3SJTX6S.js → chunk-C6ONUJIO.js} +5 -5
- package/dist/{chunk-LO3DH776.js → chunk-CJMUTCJW.js} +2 -2
- package/dist/{chunk-CZOVEX2D.js → chunk-CR3G2JQP.js} +1 -1
- package/dist/{chunk-2PU2TSUG.js → chunk-D5E5XFHK.js} +1 -1
- package/dist/{chunk-6WQHVYJD.js → chunk-G7ZSFSQG.js} +1 -1
- package/dist/{chunk-7SXY6NFW.js → chunk-GAACUQAB.js} +4 -4
- package/dist/{chunk-4CNJGY7P.js → chunk-LPUQTBKU.js} +147 -27
- package/dist/{chunk-YKXOAGY3.js → chunk-P3DYA5NA.js} +8 -8
- package/dist/{chunk-Z6NY6MCL.js → chunk-RMLGMYEJ.js} +1 -1
- package/dist/{chunk-NLXQ7WTH.js → chunk-TPKPU4PE.js} +56 -38
- package/dist/{chunk-LZEX2GAY.js → chunk-UFNIB3JL.js} +144 -5
- package/dist/{chunk-ACURZCPN.js → chunk-UKKY7HWN.js} +1 -1
- package/dist/{chunk-M665ZQYB.js → chunk-VTM7NEJC.js} +38 -6
- package/dist/{chunk-FSA3UBVR.js → chunk-ZFW35DLG.js} +1 -1
- package/dist/{chunk-OVV35ZS2.js → chunk-ZIPGDGBR.js} +1 -1
- package/dist/component-runtime/render.js +2 -2
- package/dist/component-runtime.js +3 -3
- package/dist/compose.js +23 -23
- 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 +17 -3
- package/dist/composition-ops.js +8 -8
- package/dist/composition.js +19 -5
- package/dist/{context-AIUJG7R4.js → context-UAS5WJRB.js} +5 -5
- package/dist/core/render.js +6 -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 +195 -32
- package/dist/primitives/effects.js +4 -4
- package/dist/primitives/hero-text.js +2 -2
- package/dist/primitives/layouts.js +3 -3
- package/dist/primitives/scenes.js +4 -4
- package/dist/primitives/text.js +2 -2
- package/dist/primitives/ui-blocks.js +4 -4
- package/dist/primitives.js +23 -23
- package/dist/render-harness/cardFonts.js +2 -2
- package/dist/render-harness.js +12 -12
- package/package.json +12 -12
- package/dist/{chunk-RL5SO653.js → chunk-7SQOXIWR.js} +3 -3
- package/dist/{chunk-B3GSTQLR.js → chunk-VLJOIUHL.js} +6 -6
- package/dist/{chunk-RBWS5XHE.js → chunk-X34KW2SL.js} +4 -4
|
@@ -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
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
frostedGlassWipe,
|
|
3
|
-
spatialPush
|
|
4
|
-
} from "./chunk-QGAWDLYX.js";
|
|
5
1
|
import {
|
|
6
2
|
DashboardPopulate
|
|
7
3
|
} from "./chunk-S5H6GH6M.js";
|
|
@@ -11,6 +7,10 @@ import {
|
|
|
11
7
|
import {
|
|
12
8
|
EASING_BY_INTENT
|
|
13
9
|
} from "./chunk-MFHXCHRI.js";
|
|
10
|
+
import {
|
|
11
|
+
frostedGlassWipe,
|
|
12
|
+
spatialPush
|
|
13
|
+
} from "./chunk-QGAWDLYX.js";
|
|
14
14
|
import {
|
|
15
15
|
ACCENT,
|
|
16
16
|
ACCENT_SOFT,
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
makeDefaultScreenTexture,
|
|
44
44
|
resolveCamera,
|
|
45
45
|
useImageTexture
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-D5E5XFHK.js";
|
|
47
47
|
import {
|
|
48
48
|
DEVICE_GLASS_OPACITY_ENCODED,
|
|
49
49
|
DeviceMesh,
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
Format,
|
|
5
5
|
GraphicRole,
|
|
6
6
|
OpaqueId
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UFNIB3JL.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";
|
|
@@ -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";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FitText
|
|
3
|
-
} from "./chunk-XHGZ2E77.js";
|
|
4
1
|
import {
|
|
5
2
|
EASING_BY_INTENT
|
|
6
3
|
} from "./chunk-MFHXCHRI.js";
|
|
4
|
+
import {
|
|
5
|
+
FitText
|
|
6
|
+
} from "./chunk-XHGZ2E77.js";
|
|
7
7
|
import {
|
|
8
8
|
ACCENT,
|
|
9
9
|
ACCENT_STRONG,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
perspectiveFor,
|
|
27
27
|
resolveCamera,
|
|
28
28
|
useStage
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-D5E5XFHK.js";
|
|
30
30
|
|
|
31
31
|
// ../execution/primitives/src/effects/blur/index.tsx
|
|
32
32
|
import React2 from "react";
|
|
@@ -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,29 +1226,41 @@ 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
|
-
);
|
|
1242
|
-
}
|
|
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
|
+
);
|
|
1243
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
|
+
);
|
|
1244
1256
|
}
|
|
1245
1257
|
}
|
|
1246
1258
|
var FULL_RECT = { left: 0, top: 0, right: 1, bottom: 1 };
|
|
1247
1259
|
function hasClipEffect(clip, effects) {
|
|
1248
|
-
return effects.some((effect) => effect.target.kind === "clip" && effect.trackId === clip.trackId && effect.contentIndex === clip.contentIndex);
|
|
1260
|
+
return clip.hasClipEffects === true || effects.some((effect) => effect.target.kind === "clip" && effect.trackId === clip.trackId && effect.contentIndex === clip.contentIndex);
|
|
1249
1261
|
}
|
|
1250
1262
|
function pictureRect(clip, output, effects) {
|
|
1251
|
-
if (clip.cropTrajectory || clip.cropTrajectoryUrl || hasClipEffect(clip, effects)) return void 0;
|
|
1263
|
+
if (clip.cropTrajectory || clip.cropTrajectoryUrl || clip.hasCropIntent || hasClipEffect(clip, effects)) return void 0;
|
|
1252
1264
|
if (clip.fit !== "contain") return FULL_RECT;
|
|
1253
1265
|
const sourceWidth = clip.sourceWidth;
|
|
1254
1266
|
const sourceHeight = clip.sourceHeight;
|
|
@@ -1271,7 +1283,7 @@ function coversLowerPictures(upper, lower, output, effects) {
|
|
|
1271
1283
|
return upperRect.left <= rect.left + epsilon && upperRect.top <= rect.top + epsilon && upperRect.right + epsilon >= rect.right && upperRect.bottom + epsilon >= rect.bottom;
|
|
1272
1284
|
});
|
|
1273
1285
|
}
|
|
1274
|
-
function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects = []) {
|
|
1286
|
+
function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects = [], hostMode = "packed-only") {
|
|
1275
1287
|
if (endFrame <= startFrame) return [];
|
|
1276
1288
|
const boundaries = /* @__PURE__ */ new Set([startFrame, endFrame]);
|
|
1277
1289
|
for (const clip of clips) {
|
|
@@ -1280,6 +1292,13 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
|
|
|
1280
1292
|
if (start > startFrame && start < endFrame) boundaries.add(start);
|
|
1281
1293
|
if (end > startFrame && end < endFrame) boundaries.add(end);
|
|
1282
1294
|
}
|
|
1295
|
+
for (const effect of effects) {
|
|
1296
|
+
if (effect.target.kind !== "global") continue;
|
|
1297
|
+
const start = effect.startFrame ?? startFrame;
|
|
1298
|
+
const end = start + (effect.durationInFrames ?? endFrame - start);
|
|
1299
|
+
if (start > startFrame && start < endFrame) boundaries.add(start);
|
|
1300
|
+
if (end > startFrame && end < endFrame) boundaries.add(end);
|
|
1301
|
+
}
|
|
1283
1302
|
const points = [...boundaries].sort((a, b) => a - b);
|
|
1284
1303
|
const windows = [];
|
|
1285
1304
|
for (let i = 0; i < points.length - 1; i++) {
|
|
@@ -1290,6 +1309,7 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
|
|
|
1290
1309
|
);
|
|
1291
1310
|
const topLayer = Math.max(...active.map((clip) => clip.layerIndex));
|
|
1292
1311
|
const top = active.filter((clip) => clip.layerIndex === topLayer);
|
|
1312
|
+
const globalEffectActive = effects.some((effect) => effect.target.kind === "global" && (effect.startFrame ?? startFrame) <= start && (effect.startFrame ?? startFrame) + (effect.durationInFrames ?? endFrame - startFrame) >= end);
|
|
1293
1313
|
const fullFrame = top[0]?.region === void 0 || top[0].region.x === 0 && top[0].region.y === 0 && top[0].region.w === 1 && top[0].region.h === 1;
|
|
1294
1314
|
const provesOcclusion = top.length === 1 && fullFrame && (active.length === 1 || coversLowerPictures(
|
|
1295
1315
|
top[0],
|
|
@@ -1297,18 +1317,22 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
|
|
|
1297
1317
|
output,
|
|
1298
1318
|
effects
|
|
1299
1319
|
));
|
|
1300
|
-
const
|
|
1301
|
-
const
|
|
1302
|
-
const
|
|
1320
|
+
const suppressesCaption = provesOcclusion && !globalEffectActive && pictureRect(top[0], output, effects) !== void 0;
|
|
1321
|
+
const captionVisible = !(suppressesCaption && top[0].captionVisibility === "hidden");
|
|
1322
|
+
const candidateHost = (clip) => hostMode === "all-video-candidates" ? clip.mediaType !== "image" : !!clip.packedUrl;
|
|
1323
|
+
const host = provesOcclusion && candidateHost(top[0]) ? top[0] : void 0;
|
|
1324
|
+
const unresolvedOverlap = top.length > 1 || top.length === 1 && active.length > 1 && !provesOcclusion;
|
|
1325
|
+
const candidates = unresolvedOverlap ? active.filter(candidateHost).map((clip) => clip.id) : top.map((clip) => clip.id);
|
|
1303
1326
|
const previous = windows[windows.length - 1];
|
|
1304
|
-
if (previous && previous.endFrame === start && previous.hostClipId === host?.id && previous.candidateClipIds.join("\0") === candidates.join("\0")) {
|
|
1327
|
+
if (previous && previous.endFrame === start && previous.hostClipId === host?.id && previous.captionVisible === captionVisible && previous.candidateClipIds.join("\0") === candidates.join("\0")) {
|
|
1305
1328
|
previous.endFrame = end;
|
|
1306
1329
|
} else {
|
|
1307
1330
|
windows.push({
|
|
1308
1331
|
startFrame: start,
|
|
1309
1332
|
endFrame: end,
|
|
1310
1333
|
...host ? { hostClipId: host.id } : {},
|
|
1311
|
-
candidateClipIds: candidates
|
|
1334
|
+
candidateClipIds: candidates,
|
|
1335
|
+
captionVisible
|
|
1312
1336
|
});
|
|
1313
1337
|
}
|
|
1314
1338
|
}
|
|
@@ -1455,6 +1479,13 @@ function projectMediaTrack(track, trackIndex, trackCount, fps, srcUrls, trajecto
|
|
|
1455
1479
|
);
|
|
1456
1480
|
}
|
|
1457
1481
|
if (rendersNoFrames(c)) continue;
|
|
1482
|
+
if (c.captionVisibility !== void 0 && track.kind !== "video") {
|
|
1483
|
+
throw renderInputError(
|
|
1484
|
+
"invalid_composition",
|
|
1485
|
+
`Clip ${c.id}: captionVisibility is supported only on video media clips.`,
|
|
1486
|
+
{ trackId: track.id, clipId: c.id, compositionPath: `composition.tracks[${track.id}].contents[${i}].captionVisibility` }
|
|
1487
|
+
);
|
|
1488
|
+
}
|
|
1458
1489
|
const src = resolveSrcUrl(c.source.mediaId, srcUrls, {
|
|
1459
1490
|
trackId: track.id,
|
|
1460
1491
|
clipId: c.id,
|
|
@@ -1546,6 +1577,7 @@ function projectMediaTrack(track, trackIndex, trackCount, fps, srcUrls, trajecto
|
|
|
1546
1577
|
...c.animate !== void 0 ? { animate: c.animate } : {},
|
|
1547
1578
|
...c.region !== void 0 ? { region: c.region } : {},
|
|
1548
1579
|
...c.fit !== void 0 ? { fit: c.fit } : {},
|
|
1580
|
+
...c.captionVisibility !== void 0 ? { captionVisibility: c.captionVisibility } : {},
|
|
1549
1581
|
...s === 0 && c.transitionIn ? {
|
|
1550
1582
|
transitionIn: mapTransitionType(c.transitionIn.type),
|
|
1551
1583
|
transitionDurationFrames: Math.max(1, Math.round(c.transitionIn.duration * fps))
|
|
@@ -1813,6 +1845,71 @@ function projectEffectTrack(track, trackIndex, trackCount, fps) {
|
|
|
1813
1845
|
}
|
|
1814
1846
|
|
|
1815
1847
|
// ../execution/core/src/render/compositionRender.ts
|
|
1848
|
+
function captionVisibilityWindowsForComposition(composition, sourceDimensions) {
|
|
1849
|
+
const { fps, width, height } = compositionFormatDimensions(composition.format);
|
|
1850
|
+
const clips = [];
|
|
1851
|
+
const mediaIdByProjectedClipId = {};
|
|
1852
|
+
let endFrame = 0;
|
|
1853
|
+
const trackCount = composition.tracks.length;
|
|
1854
|
+
const effects = composition.tracks.flatMap(
|
|
1855
|
+
(track, index) => track.enabled !== false && track.kind === "effect" ? projectEffectTrack(track, index, trackCount, fps) : []
|
|
1856
|
+
);
|
|
1857
|
+
for (const [trackIndex, track] of composition.tracks.entries()) {
|
|
1858
|
+
if (track.enabled === false || track.kind !== "video" && track.kind !== "image") continue;
|
|
1859
|
+
for (const [contentIndex, item] of track.contents.entries()) {
|
|
1860
|
+
if (!("source" in item)) continue;
|
|
1861
|
+
if (item.source.kind !== "media") {
|
|
1862
|
+
throw renderInputError(
|
|
1863
|
+
"clip_source_track_mismatch",
|
|
1864
|
+
`Clip ${item.id} on video track ${track.id} must use a media source.`,
|
|
1865
|
+
{ trackId: track.id, clipId: item.id }
|
|
1866
|
+
);
|
|
1867
|
+
}
|
|
1868
|
+
const spans = projectMediaPlaybackSpans(track.kind === "video" ? {
|
|
1869
|
+
startTime: item.startTime,
|
|
1870
|
+
duration: item.duration,
|
|
1871
|
+
trim: item.source.trim,
|
|
1872
|
+
excludedRanges: item.source.excludedRanges,
|
|
1873
|
+
playbackRate: item.source.playbackRate,
|
|
1874
|
+
fps
|
|
1875
|
+
} : { startTime: item.startTime, duration: item.duration, fps });
|
|
1876
|
+
const dimensions = sourceDimensions[item.source.mediaId];
|
|
1877
|
+
const validDimensions = track.kind === "video" && dimensions && Number.isFinite(dimensions.width) && dimensions.width > 0 && Number.isFinite(dimensions.height) && dimensions.height > 0;
|
|
1878
|
+
for (const [spanIndex, span] of spans.entries()) {
|
|
1879
|
+
if (span.durationInFrames === 0) continue;
|
|
1880
|
+
const id = spans.length === 1 ? item.id : `${item.id}#${spanIndex}`;
|
|
1881
|
+
clips.push({
|
|
1882
|
+
id,
|
|
1883
|
+
trackId: track.id,
|
|
1884
|
+
layerIndex: trackCount - trackIndex,
|
|
1885
|
+
contentIndex,
|
|
1886
|
+
timelineStartFrames: span.timelineStartFrames,
|
|
1887
|
+
durationInFrames: span.durationInFrames,
|
|
1888
|
+
...track.kind === "image" ? { mediaType: "image" } : {},
|
|
1889
|
+
...validDimensions ? { sourceWidth: dimensions.width, sourceHeight: dimensions.height } : {},
|
|
1890
|
+
...item.region ? { region: item.region } : {},
|
|
1891
|
+
...item.fit ? { fit: item.fit } : {},
|
|
1892
|
+
...track.kind === "video" && item.captionVisibility ? { captionVisibility: item.captionVisibility } : {},
|
|
1893
|
+
...item.source.reframe?.segments.length ? { hasCropIntent: true } : {},
|
|
1894
|
+
...item.effects?.length ? { hasClipEffects: true } : {}
|
|
1895
|
+
});
|
|
1896
|
+
if (track.kind === "video") mediaIdByProjectedClipId[id] = item.source.mediaId;
|
|
1897
|
+
endFrame = Math.max(endFrame, span.timelineStartFrames + span.durationInFrames);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
for (const segment of composition.captions?.segments ?? []) {
|
|
1902
|
+
for (const word of segment.words) {
|
|
1903
|
+
const startFrame = Math.round(word.startMs / 1e3 * fps);
|
|
1904
|
+
endFrame = Math.max(endFrame, Math.max(startFrame + 1, Math.round(word.endMs / 1e3 * fps)));
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
return {
|
|
1908
|
+
fps,
|
|
1909
|
+
windows: visiblePackedHostWindows(clips, 0, endFrame, { width, height }, effects, "all-video-candidates"),
|
|
1910
|
+
mediaIdByProjectedClipId
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1816
1913
|
var CAPTION_COLOR_FIELDS = [
|
|
1817
1914
|
"color",
|
|
1818
1915
|
"highlightColor",
|
|
@@ -1890,6 +1987,11 @@ function assertMergedCaptionFacesDrawable(composition) {
|
|
|
1890
1987
|
if (!captions?.segments.some((segment) => segment.words.length > 0)) return;
|
|
1891
1988
|
const brandCaption = composition.brandKit?.caption;
|
|
1892
1989
|
const issues = mergedCaptionFaceIssues(captions.style, brandCaption);
|
|
1990
|
+
for (const [index, layout] of (captions.layouts ?? []).entries()) {
|
|
1991
|
+
for (const issue of mergedCaptionFaceIssues({ ...captions.style, ...layout.style }, brandCaption)) {
|
|
1992
|
+
issues.push({ ...issue, path: `captions.layouts[${index}].style.${issue.path.split(".").at(-1)}` });
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1893
1995
|
if (issues.length === 0) return;
|
|
1894
1996
|
throw renderInputError(
|
|
1895
1997
|
"font_not_reproducible",
|
|
@@ -1903,6 +2005,18 @@ function assertMergedCaptionFacesDrawable(composition) {
|
|
|
1903
2005
|
function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUrls, alphaUrls, subCompositions, trajectories, options) {
|
|
1904
2006
|
const flattened = hasCompoundClips(composition) ? flattenCompoundClips(composition, (id) => subCompositions?.[id]) : composition;
|
|
1905
2007
|
composition = flattened;
|
|
2008
|
+
for (const track of composition.tracks) {
|
|
2009
|
+
for (const content of track.contents) {
|
|
2010
|
+
if (!("source" in content) || content.captionVisibility === void 0) continue;
|
|
2011
|
+
if (track.kind !== "video" || content.source.kind !== "media") {
|
|
2012
|
+
throw renderInputError(
|
|
2013
|
+
"invalid_composition",
|
|
2014
|
+
`Clip ${content.id}: captionVisibility is supported only on video media clips.`,
|
|
2015
|
+
{ trackId: track.id, clipId: content.id, compositionPath: `composition.tracks[${track.id}].contents[${content.id}].captionVisibility` }
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
1906
2020
|
assertMergedCaptionFacesDrawable(composition);
|
|
1907
2021
|
const { width, height, fps } = compositionFormatDimensions(composition.format);
|
|
1908
2022
|
const clips = [];
|
|
@@ -1980,9 +2094,9 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
1980
2094
|
if (end > maxBackgroundEndFrames) maxBackgroundEndFrames = end;
|
|
1981
2095
|
}
|
|
1982
2096
|
const bodyDurationInFrames = maxBackgroundEndFrames > 0 ? Math.min(maxEndFrames, maxBackgroundEndFrames) : maxEndFrames;
|
|
1983
|
-
const captionSegments = composition.captions?.segments.map((seg) => seg.words)
|
|
2097
|
+
const captionSegments = composition.captions?.segments.map((seg) => seg.words);
|
|
1984
2098
|
if (composition.captions?.zPlane === "behind-subject") {
|
|
1985
|
-
assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, { width, height }, effects);
|
|
2099
|
+
assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, { width, height }, effects, composition.captions.layouts);
|
|
1986
2100
|
}
|
|
1987
2101
|
const brandKit = composition.brandKit;
|
|
1988
2102
|
const { totalFrames: durationInFrames } = resolveBookendTimeline(
|
|
@@ -2004,7 +2118,7 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2004
2118
|
...mot.exitMs != null ? { exitMs: mot.exitMs } : {}
|
|
2005
2119
|
} : void 0;
|
|
2006
2120
|
const baseStyle = composition.captions?.style;
|
|
2007
|
-
const hasCaptions = captionSegments
|
|
2121
|
+
const hasCaptions = captionSegments?.some((words) => words.length > 0) ?? false;
|
|
2008
2122
|
const captionStyle = hasCaptions && (cap || baseStyle || captionMotion) ? {
|
|
2009
2123
|
...baseStyle ?? {},
|
|
2010
2124
|
...cap?.fontFamily ? { fontFamily: cap.fontFamily } : {},
|
|
@@ -2029,6 +2143,10 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2029
2143
|
...cap?.exitMs != null ? { exitMs: cap.exitMs } : {}
|
|
2030
2144
|
} : void 0;
|
|
2031
2145
|
const resolvedCaptionStyle = captionStyle ? resolveCaptionColorRefs(captionStyle, brandKit) : void 0;
|
|
2146
|
+
const captionLayouts = composition.captions?.layouts?.map((layout) => ({
|
|
2147
|
+
...layout,
|
|
2148
|
+
...layout.style ? { style: resolveCaptionColorRefs(layout.style, brandKit) } : {}
|
|
2149
|
+
}));
|
|
2032
2150
|
return {
|
|
2033
2151
|
clips,
|
|
2034
2152
|
overlays,
|
|
@@ -2040,6 +2158,7 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
|
|
|
2040
2158
|
...audioTracks.length > 0 ? { audioTracks } : {},
|
|
2041
2159
|
...effects.length > 0 ? { effects } : {},
|
|
2042
2160
|
...hasCaptions ? { captionSegments } : {},
|
|
2161
|
+
...hasCaptions && captionLayouts?.length ? { captionLayouts } : {},
|
|
2043
2162
|
...hasCaptions && composition.captions?.zPlane === "behind-subject" ? { captionsBehind: true } : {},
|
|
2044
2163
|
...resolvedCaptionStyle ? { captionStyle: resolvedCaptionStyle } : {},
|
|
2045
2164
|
...brandKit ? { brandKit } : {}
|
|
@@ -3086,6 +3205,7 @@ export {
|
|
|
3086
3205
|
visiblePackedHostWindows,
|
|
3087
3206
|
playableSpans,
|
|
3088
3207
|
projectMediaPlaybackSpans,
|
|
3208
|
+
captionVisibilityWindowsForComposition,
|
|
3089
3209
|
compositionFormatDimensions,
|
|
3090
3210
|
referencedMediaIds,
|
|
3091
3211
|
compositionToRenderInput,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SCENE_SHOT_RESOURCE_DESCRIPTION,
|
|
3
|
+
SCENE_SHOT_RESOURCE_URI,
|
|
4
|
+
sceneShotContract
|
|
5
|
+
} from "./chunk-7AUHC2X7.js";
|
|
1
6
|
import {
|
|
2
7
|
querySchemaShape,
|
|
3
8
|
serializeQuery,
|
|
4
9
|
waitForJob
|
|
5
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZFW35DLG.js";
|
|
6
11
|
import {
|
|
7
12
|
CURATED_TOOLS
|
|
8
13
|
} from "./chunk-4WBSXHQA.js";
|
|
9
|
-
import {
|
|
10
|
-
SCENE_SHOT_RESOURCE_DESCRIPTION,
|
|
11
|
-
SCENE_SHOT_RESOURCE_URI,
|
|
12
|
-
sceneShotContract
|
|
13
|
-
} from "./chunk-MOUWO53S.js";
|
|
14
14
|
import {
|
|
15
15
|
GENERATED_OPERATIONS,
|
|
16
16
|
apiErrorFrom,
|
|
@@ -28,10 +28,10 @@ import {
|
|
|
28
28
|
text,
|
|
29
29
|
textWithData,
|
|
30
30
|
withMedia
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-46DGDPXR.js";
|
|
32
32
|
import {
|
|
33
33
|
CompositionOp
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-VTM7NEJC.js";
|
|
35
35
|
|
|
36
36
|
// ../mcp/src/prompts.ts
|
|
37
37
|
var skillListCache = null;
|