@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Composition
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UFNIB3JL.js";
|
|
4
4
|
import {
|
|
5
5
|
expandToLinkGroup
|
|
6
6
|
} from "./chunk-KYRDKK2D.js";
|
|
@@ -132,6 +132,56 @@ function pruneSelectionInDraft(draft, removedClipIds) {
|
|
|
132
132
|
draft.selectedOverlayId = patch.selectedOverlayId;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// ../composition/src/ops/captionOps.ts
|
|
136
|
+
function createCaptionOps(set) {
|
|
137
|
+
return {
|
|
138
|
+
setCaptionStyle: (style) => {
|
|
139
|
+
set((draft) => {
|
|
140
|
+
const clean = Object.fromEntries(
|
|
141
|
+
Object.entries(style).filter(([, v]) => v !== void 0)
|
|
142
|
+
);
|
|
143
|
+
if (Object.keys(clean).length === 0) return;
|
|
144
|
+
const existing = draft.composition.captions;
|
|
145
|
+
if (existing) {
|
|
146
|
+
existing.style = { ...existing.style ?? {}, ...clean };
|
|
147
|
+
} else {
|
|
148
|
+
draft.composition.captions = { source: "authored", segments: [], style: clean };
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
setCaptionLayouts: (layouts) => {
|
|
153
|
+
set((draft) => {
|
|
154
|
+
if (!draft.composition.captions) throw new Error("setCaptionLayouts requires saved transcript captions");
|
|
155
|
+
if (layouts.length === 0) delete draft.composition.captions.layouts;
|
|
156
|
+
else draft.composition.captions.layouts = layouts;
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
setCaptionDepth: (zPlane) => {
|
|
160
|
+
set((draft) => {
|
|
161
|
+
const existing = draft.composition.captions;
|
|
162
|
+
if (!existing) return;
|
|
163
|
+
if (zPlane === "front") {
|
|
164
|
+
delete existing.zPlane;
|
|
165
|
+
} else {
|
|
166
|
+
existing.zPlane = zPlane;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
setCaptions: (segments, style, derivedFrom) => {
|
|
171
|
+
set((draft) => {
|
|
172
|
+
const existing = draft.composition.captions;
|
|
173
|
+
const mergedStyle = style ? {
|
|
174
|
+
...existing?.style ?? {},
|
|
175
|
+
...Object.fromEntries(Object.entries(style).filter(([, v]) => v !== void 0))
|
|
176
|
+
} : existing?.style;
|
|
177
|
+
const styleField = mergedStyle && Object.keys(mergedStyle).length > 0 ? { style: mergedStyle } : {};
|
|
178
|
+
const depthField = existing?.zPlane ? { zPlane: existing.zPlane } : {};
|
|
179
|
+
draft.composition.captions = derivedFrom ? { source: "derived", from: derivedFrom, segments, ...styleField, ...depthField } : { source: "authored", segments, ...styleField, ...depthField };
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
135
185
|
// ../composition/src/ops/compositionOps.ts
|
|
136
186
|
function createCompositionOps(get, set) {
|
|
137
187
|
return {
|
|
@@ -447,6 +497,7 @@ function createCompositionOps(get, set) {
|
|
|
447
497
|
if (!Number.isFinite(start) || !Number.isFinite(end) || start >= end) return;
|
|
448
498
|
const span = end - start;
|
|
449
499
|
set((draft) => {
|
|
500
|
+
if (draft.composition.captions) delete draft.composition.captions.layouts;
|
|
450
501
|
for (const track of draft.composition.tracks) {
|
|
451
502
|
const next = [];
|
|
452
503
|
for (const item of track.contents) {
|
|
@@ -581,6 +632,7 @@ function createCompositionOps(get, set) {
|
|
|
581
632
|
});
|
|
582
633
|
}
|
|
583
634
|
if (draft.composition.captions) {
|
|
635
|
+
delete draft.composition.captions.layouts;
|
|
584
636
|
for (const seg of draft.composition.captions.segments) {
|
|
585
637
|
seg.words = seg.words.flatMap((w) => {
|
|
586
638
|
const r = cutTimedRange(w.startMs, w.endMs, tStart * 1e3, tEnd * 1e3);
|
|
@@ -631,6 +683,7 @@ function createCompositionOps(get, set) {
|
|
|
631
683
|
}
|
|
632
684
|
}
|
|
633
685
|
if (draft.composition.captions) {
|
|
686
|
+
delete draft.composition.captions.layouts;
|
|
634
687
|
for (const segment of draft.composition.captions.segments) {
|
|
635
688
|
for (const word of segment.words) {
|
|
636
689
|
const shifted = shiftTimedRange(word.startMs, word.endMs, insertAt * 1e3, restored * 1e3);
|
|
@@ -667,45 +720,10 @@ function createCompositionOps(get, set) {
|
|
|
667
720
|
}
|
|
668
721
|
});
|
|
669
722
|
},
|
|
670
|
-
|
|
671
|
-
set((draft) => {
|
|
672
|
-
const clean = Object.fromEntries(
|
|
673
|
-
Object.entries(style).filter(([, v]) => v !== void 0)
|
|
674
|
-
);
|
|
675
|
-
if (Object.keys(clean).length === 0) return;
|
|
676
|
-
const existing = draft.composition.captions;
|
|
677
|
-
if (existing) {
|
|
678
|
-
existing.style = { ...existing.style ?? {}, ...clean };
|
|
679
|
-
} else {
|
|
680
|
-
draft.composition.captions = { source: "authored", segments: [], style: clean };
|
|
681
|
-
}
|
|
682
|
-
});
|
|
683
|
-
},
|
|
684
|
-
setCaptionDepth: (zPlane) => {
|
|
685
|
-
set((draft) => {
|
|
686
|
-
const existing = draft.composition.captions;
|
|
687
|
-
if (!existing) return;
|
|
688
|
-
if (zPlane === "front") {
|
|
689
|
-
delete existing.zPlane;
|
|
690
|
-
} else {
|
|
691
|
-
existing.zPlane = zPlane;
|
|
692
|
-
}
|
|
693
|
-
});
|
|
694
|
-
},
|
|
695
|
-
setCaptions: (segments, style, derivedFrom) => {
|
|
696
|
-
set((draft) => {
|
|
697
|
-
const existing = draft.composition.captions;
|
|
698
|
-
const mergedStyle = style ? {
|
|
699
|
-
...existing?.style ?? {},
|
|
700
|
-
...Object.fromEntries(Object.entries(style).filter(([, v]) => v !== void 0))
|
|
701
|
-
} : existing?.style;
|
|
702
|
-
const styleField = mergedStyle && Object.keys(mergedStyle).length > 0 ? { style: mergedStyle } : {};
|
|
703
|
-
const depthField = existing?.zPlane ? { zPlane: existing.zPlane } : {};
|
|
704
|
-
draft.composition.captions = derivedFrom ? { source: "derived", from: derivedFrom, segments, ...styleField, ...depthField } : { source: "authored", segments, ...styleField, ...depthField };
|
|
705
|
-
});
|
|
706
|
-
},
|
|
723
|
+
...createCaptionOps(set),
|
|
707
724
|
ripple: (time, amount) => {
|
|
708
725
|
set((draft) => {
|
|
726
|
+
if (draft.composition.captions) delete draft.composition.captions.layouts;
|
|
709
727
|
for (const track of draft.composition.tracks) {
|
|
710
728
|
for (const item of track.contents) {
|
|
711
729
|
if (!("source" in item)) continue;
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-B7J5UUUV.js";
|
|
4
4
|
import {
|
|
5
5
|
captionFaceIssues
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7RGDRDAR.js";
|
|
7
7
|
|
|
8
8
|
// ../composition/src/validators/opaqueId.ts
|
|
9
9
|
import { z } from "zod";
|
|
@@ -11,6 +11,8 @@ var OpaqueId = z.string();
|
|
|
11
11
|
|
|
12
12
|
// ../composition/src/validators/composition.ts
|
|
13
13
|
import { z as z2 } from "zod";
|
|
14
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
15
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
14
16
|
var Format = z2.object({
|
|
15
17
|
aspectRatio: z2.enum(["16:9", "9:16", "1:1", "4:5"]),
|
|
16
18
|
fps: z2.union([z2.literal(24), z2.literal(25), z2.literal(30), z2.literal(60)]).optional(),
|
|
@@ -124,6 +126,7 @@ var CaptionRegion = Region.refine(
|
|
|
124
126
|
"captions style.region must fit within the normalized frame"
|
|
125
127
|
);
|
|
126
128
|
var ClipFit = z2.enum(["cover", "contain"]);
|
|
129
|
+
var CaptionVisibility = z2.enum(["visible", "hidden"]);
|
|
127
130
|
var PerClipEffect = z2.object({
|
|
128
131
|
primitiveId: z2.string().min(1),
|
|
129
132
|
params: z2.record(z2.string(), z2.unknown()).optional()
|
|
@@ -166,6 +169,9 @@ var TimelineClip = z2.object({
|
|
|
166
169
|
position: Position.optional(),
|
|
167
170
|
region: Region.optional(),
|
|
168
171
|
fit: ClipFit.optional(),
|
|
172
|
+
captionVisibility: CaptionVisibility.optional().describe(
|
|
173
|
+
"Video media clip only. Hide native captions while this clip is the visible full-frame picture; caption words and timings remain stored and resume when another visible clip takes over."
|
|
174
|
+
),
|
|
169
175
|
effects: z2.array(PerClipEffect).optional(),
|
|
170
176
|
transitionIn: Transition.optional(),
|
|
171
177
|
linkGroupId: z2.string().min(1).optional(),
|
|
@@ -284,6 +290,101 @@ var CaptionStyle = z2.object({
|
|
|
284
290
|
annotationColor: z2.string().optional(),
|
|
285
291
|
maxWidthPercent: z2.number().positive().max(100, "captions style.maxWidthPercent is % of composition width (max 100)").optional()
|
|
286
292
|
});
|
|
293
|
+
var CaptionLayoutStyle = CaptionStyle.pick({
|
|
294
|
+
fontFamily: true,
|
|
295
|
+
fontSize: true,
|
|
296
|
+
fontWeight: true,
|
|
297
|
+
color: true,
|
|
298
|
+
highlightColor: true,
|
|
299
|
+
backgroundColor: true,
|
|
300
|
+
plate: true,
|
|
301
|
+
textTransform: true,
|
|
302
|
+
emphasisColor: true,
|
|
303
|
+
emphasisScale: true,
|
|
304
|
+
emphasisFontFamily: true,
|
|
305
|
+
emphasisFontWeight: true,
|
|
306
|
+
emphasisTextTransform: true,
|
|
307
|
+
emphasisLetterSpacing: true,
|
|
308
|
+
emphasisFontStyle: true,
|
|
309
|
+
emphasisPlate: true,
|
|
310
|
+
emphasisPlateColor: true,
|
|
311
|
+
emphasisPlateTextColor: true,
|
|
312
|
+
emphasisPlateAltColor: true,
|
|
313
|
+
emphasisPlateAltTextColor: true,
|
|
314
|
+
emphasisPlateRadius: true,
|
|
315
|
+
emphasisPlatePadX: true,
|
|
316
|
+
emphasisPlatePadY: true,
|
|
317
|
+
annotationColor: true,
|
|
318
|
+
entrance: true,
|
|
319
|
+
entranceMs: true,
|
|
320
|
+
entranceStaggerMs: true,
|
|
321
|
+
exitMs: true
|
|
322
|
+
}).strict();
|
|
323
|
+
var CaptionLayoutInput = z2.object({
|
|
324
|
+
segmentIndex: z2.number().int().nonnegative(),
|
|
325
|
+
wordStartIndex: z2.number().int().nonnegative(),
|
|
326
|
+
wordEndIndex: z2.number().int().positive().describe("Exclusive word index in the saved caption segment."),
|
|
327
|
+
region: CaptionRegion,
|
|
328
|
+
scale: z2.number().min(0.25).max(4).optional(),
|
|
329
|
+
rotation: z2.number().min(-45).max(45).optional(),
|
|
330
|
+
style: CaptionLayoutStyle.optional(),
|
|
331
|
+
holdThroughWordIndex: z2.number().int().nonnegative().optional().describe(
|
|
332
|
+
"Inclusive saved-word index in this segment. The layout stays visible until that word ends."
|
|
333
|
+
),
|
|
334
|
+
wordMarks: z2.array(z2.object({
|
|
335
|
+
wordIndex: z2.number().int().nonnegative(),
|
|
336
|
+
emphasis: z2.boolean().optional(),
|
|
337
|
+
annotate: z2.enum(["circle", "underline"]).nullable().optional()
|
|
338
|
+
}).strict()).optional()
|
|
339
|
+
}).strict();
|
|
340
|
+
var CaptionLayout = CaptionLayoutInput.extend({
|
|
341
|
+
wordSignature: z2.string().regex(/^[a-f0-9]{64}$/)
|
|
342
|
+
});
|
|
343
|
+
function captionSegmentSignature(words) {
|
|
344
|
+
const encoded = JSON.stringify(words.map((word) => ({
|
|
345
|
+
text: word.text,
|
|
346
|
+
startMs: word.startMs,
|
|
347
|
+
endMs: word.endMs,
|
|
348
|
+
emphasis: word.emphasis ?? null,
|
|
349
|
+
annotate: word.annotate ?? null
|
|
350
|
+
})));
|
|
351
|
+
return bytesToHex(sha256(new TextEncoder().encode(encoded)));
|
|
352
|
+
}
|
|
353
|
+
function captionLayoutIssues(segments, layouts, checkSignature = false) {
|
|
354
|
+
const issues = [];
|
|
355
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
356
|
+
layouts.forEach((layout, index) => {
|
|
357
|
+
const words = segments[layout.segmentIndex]?.words;
|
|
358
|
+
if (!words) {
|
|
359
|
+
issues.push({ index, field: "segmentIndex", message: "caption layout segment does not exist" });
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (layout.wordStartIndex >= layout.wordEndIndex || layout.wordEndIndex > words.length) {
|
|
363
|
+
issues.push({ index, field: "wordEndIndex", message: "caption layout word range is outside its segment" });
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const hold = layout.holdThroughWordIndex ?? layout.wordEndIndex - 1;
|
|
367
|
+
if (hold < layout.wordEndIndex - 1 || hold >= words.length) {
|
|
368
|
+
issues.push({ index, field: "holdThroughWordIndex", message: "caption layout hold must reference this or a later word in the same segment" });
|
|
369
|
+
}
|
|
370
|
+
const marked = /* @__PURE__ */ new Set();
|
|
371
|
+
for (const mark of layout.wordMarks ?? []) {
|
|
372
|
+
if (mark.wordIndex < layout.wordStartIndex || mark.wordIndex >= layout.wordEndIndex || marked.has(mark.wordIndex)) {
|
|
373
|
+
issues.push({ index, field: "wordMarks", message: "caption layout word marks must be unique words inside the layout range" });
|
|
374
|
+
}
|
|
375
|
+
marked.add(mark.wordIndex);
|
|
376
|
+
}
|
|
377
|
+
for (let word = layout.wordStartIndex; word < layout.wordEndIndex; word++) {
|
|
378
|
+
const key = `${layout.segmentIndex}:${word}`;
|
|
379
|
+
if (occupied.has(key)) issues.push({ index, field: "wordStartIndex", message: "caption layout word ranges must not overlap" });
|
|
380
|
+
occupied.add(key);
|
|
381
|
+
}
|
|
382
|
+
if (checkSignature && "wordSignature" in layout && layout.wordSignature !== captionSegmentSignature(words)) {
|
|
383
|
+
issues.push({ index, field: "wordSignature", message: "caption layout is stale for these saved transcript words; reapply setCaptionLayouts" });
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
return issues;
|
|
387
|
+
}
|
|
287
388
|
var CaptionSegment = z2.object({
|
|
288
389
|
words: z2.array(CaptionWord)
|
|
289
390
|
});
|
|
@@ -294,18 +395,29 @@ var CompositionCaptions = z2.discriminatedUnion("source", [
|
|
|
294
395
|
from: z2.object({ clipId: z2.string() }),
|
|
295
396
|
segments: z2.array(CaptionSegment),
|
|
296
397
|
style: CaptionStyle.optional(),
|
|
398
|
+
layouts: z2.array(CaptionLayout).optional(),
|
|
297
399
|
zPlane: CaptionDepth
|
|
298
400
|
}),
|
|
299
401
|
z2.object({
|
|
300
402
|
source: z2.literal("authored"),
|
|
301
403
|
segments: z2.array(CaptionSegment),
|
|
302
404
|
style: CaptionStyle.optional(),
|
|
405
|
+
layouts: z2.array(CaptionLayout).optional(),
|
|
303
406
|
zPlane: CaptionDepth
|
|
304
407
|
})
|
|
305
408
|
]).superRefine((captions, ctx) => {
|
|
306
|
-
if (
|
|
307
|
-
|
|
308
|
-
|
|
409
|
+
if (captions.style) {
|
|
410
|
+
for (const issue of captionFaceIssues(captions.style)) {
|
|
411
|
+
ctx.addIssue({ code: "custom", path: ["style", issue.field], message: issue.message });
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
for (const issue of captionLayoutIssues(captions.segments, captions.layouts ?? [], true)) {
|
|
415
|
+
ctx.addIssue({ code: "custom", path: ["layouts", issue.index, issue.field], message: issue.message });
|
|
416
|
+
}
|
|
417
|
+
for (const [index, layout] of (captions.layouts ?? []).entries()) {
|
|
418
|
+
for (const issue of captionFaceIssues({ ...captions.style, ...layout.style })) {
|
|
419
|
+
ctx.addIssue({ code: "custom", path: ["layouts", index, "style", issue.field], message: issue.message });
|
|
420
|
+
}
|
|
309
421
|
}
|
|
310
422
|
});
|
|
311
423
|
function captionsAreBehindSubject(captions) {
|
|
@@ -314,6 +426,18 @@ function captionsAreBehindSubject(captions) {
|
|
|
314
426
|
function captionWords(c) {
|
|
315
427
|
return c.segments.flatMap((s) => s.words);
|
|
316
428
|
}
|
|
429
|
+
function captionVisibilityIssues(composition) {
|
|
430
|
+
const issues = [];
|
|
431
|
+
composition.tracks.forEach((track, trackIndex) => {
|
|
432
|
+
track.contents.forEach((item, contentIndex) => {
|
|
433
|
+
if (!("source" in item) || item.captionVisibility === void 0) return;
|
|
434
|
+
if (track.kind !== "video" || item.source.kind !== "media") {
|
|
435
|
+
issues.push({ trackIndex, contentIndex });
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
return issues;
|
|
440
|
+
}
|
|
317
441
|
var Composition = z2.object({
|
|
318
442
|
v: z2.literal(1, {
|
|
319
443
|
error: (issue) => issue.input === void 0 ? 'Missing version envelope: add top-level "v": 1 to the composition.' : `Invalid version envelope: top-level "v" must be the literal 1 (got ${JSON.stringify(issue.input)}).`
|
|
@@ -332,7 +456,15 @@ var Composition = z2.object({
|
|
|
332
456
|
accessibility: CompositionAccessibility.optional(),
|
|
333
457
|
ownerOrgId: z2.string().optional(),
|
|
334
458
|
acl: AccessControl.optional()
|
|
335
|
-
}).strict()
|
|
459
|
+
}).strict().superRefine((composition, ctx) => {
|
|
460
|
+
for (const issue of captionVisibilityIssues(composition)) {
|
|
461
|
+
ctx.addIssue({
|
|
462
|
+
code: "custom",
|
|
463
|
+
path: ["tracks", issue.trackIndex, "contents", issue.contentIndex, "captionVisibility"],
|
|
464
|
+
message: "captionVisibility is supported only on video media clips"
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
});
|
|
336
468
|
var CompositionAuthorKind = z2.enum(["user", "agent", "import"]);
|
|
337
469
|
var CompositionVersion = z2.object({
|
|
338
470
|
id: z2.string().min(1),
|
|
@@ -502,6 +634,7 @@ export {
|
|
|
502
634
|
Region,
|
|
503
635
|
CaptionRegion,
|
|
504
636
|
ClipFit,
|
|
637
|
+
CaptionVisibility,
|
|
505
638
|
PerClipEffect,
|
|
506
639
|
KeyframeEasing,
|
|
507
640
|
Keyframe,
|
|
@@ -515,10 +648,16 @@ export {
|
|
|
515
648
|
Marker,
|
|
516
649
|
CaptionWord,
|
|
517
650
|
CaptionStyle,
|
|
651
|
+
CaptionLayoutStyle,
|
|
652
|
+
CaptionLayoutInput,
|
|
653
|
+
CaptionLayout,
|
|
654
|
+
captionSegmentSignature,
|
|
655
|
+
captionLayoutIssues,
|
|
518
656
|
CaptionSegment,
|
|
519
657
|
CompositionCaptions,
|
|
520
658
|
captionsAreBehindSubject,
|
|
521
659
|
captionWords,
|
|
660
|
+
captionVisibilityIssues,
|
|
522
661
|
Composition,
|
|
523
662
|
CompositionAuthorKind,
|
|
524
663
|
CompositionVersion,
|
|
@@ -3,24 +3,29 @@ import {
|
|
|
3
3
|
projectMediaPlaybackSpans,
|
|
4
4
|
sliceTranscriptWords,
|
|
5
5
|
splitIntoSentences
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LPUQTBKU.js";
|
|
7
7
|
import {
|
|
8
8
|
createHeadlessStore,
|
|
9
9
|
findClipById,
|
|
10
10
|
findMarkerById,
|
|
11
11
|
findTrackContainingClipId
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-TPKPU4PE.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
|
-
Transition
|
|
23
|
-
|
|
24
|
+
Transition,
|
|
25
|
+
captionLayoutIssues,
|
|
26
|
+
captionSegmentSignature,
|
|
27
|
+
captionVisibilityIssues
|
|
28
|
+
} from "./chunk-UFNIB3JL.js";
|
|
24
29
|
import {
|
|
25
30
|
ReframeSegment
|
|
26
31
|
} from "./chunk-B7J5UUUV.js";
|
|
@@ -30,7 +35,7 @@ import {
|
|
|
30
35
|
} from "./chunk-CL5Y6V6K.js";
|
|
31
36
|
import {
|
|
32
37
|
introducedCaptionFaceIssues
|
|
33
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-7RGDRDAR.js";
|
|
34
39
|
|
|
35
40
|
// ../composition-ops/src/index.ts
|
|
36
41
|
import { z } from "zod";
|
|
@@ -479,6 +484,9 @@ var CompositionOp = z.discriminatedUnion("type", [
|
|
|
479
484
|
z.object({ type: z.literal("setCaptions"), segments: z.array(CaptionSegment), style: CaptionStyle.partial().optional() }).strict().describe(
|
|
480
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."
|
|
481
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
|
+
),
|
|
482
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(
|
|
483
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."
|
|
484
492
|
),
|
|
@@ -588,7 +596,12 @@ function applyCaptionOpToStore(store, op) {
|
|
|
588
596
|
function applyOp(composition, op) {
|
|
589
597
|
const store = createHeadlessStore(composition);
|
|
590
598
|
applyOpToStore(store, op);
|
|
591
|
-
|
|
599
|
+
const next = store.getState().composition;
|
|
600
|
+
const issue = captionVisibilityIssues(next)[0];
|
|
601
|
+
if (issue) {
|
|
602
|
+
throw new Error(`tracks[${issue.trackIndex}].contents[${issue.contentIndex}].captionVisibility: captionVisibility is supported only on video media clips`);
|
|
603
|
+
}
|
|
604
|
+
return next;
|
|
592
605
|
}
|
|
593
606
|
function applyOpToStore(store, op) {
|
|
594
607
|
const composition = store.getState().composition;
|
|
@@ -659,6 +672,20 @@ function applyOpToStore(store, op) {
|
|
|
659
672
|
case "setCaptions":
|
|
660
673
|
applyCaptionOpToStore(store, op);
|
|
661
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
|
+
}
|
|
662
689
|
case "applyMotionPreset":
|
|
663
690
|
throw new Error(
|
|
664
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.`
|
|
@@ -795,6 +822,11 @@ function invertOp(before, op) {
|
|
|
795
822
|
}
|
|
796
823
|
case "setCaptionDepth":
|
|
797
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
|
+
};
|
|
798
830
|
case "addTrack":
|
|
799
831
|
if (op.id === void 0) {
|
|
800
832
|
throw new Error("invertOp(addTrack): no pinned `id` \u2014 cannot target the minted track");
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
stagedBrowserLocator,
|
|
27
27
|
verifyLocalStagedBrowser,
|
|
28
28
|
vp9AlphaFfmpegOverride
|
|
29
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-AONWKKXK.js";
|
|
30
30
|
import "../chunk-WB2VFDQZ.js";
|
|
31
31
|
import "../chunk-EXY4JJPH.js";
|
|
32
32
|
import "../chunk-DAARYRNT.js";
|
|
@@ -35,7 +35,7 @@ import "../chunk-JWMWVP64.js";
|
|
|
35
35
|
import "../chunk-EC6VFQE6.js";
|
|
36
36
|
import "../chunk-CL5Y6V6K.js";
|
|
37
37
|
import "../chunk-2L7PYYJK.js";
|
|
38
|
-
import "../chunk-
|
|
38
|
+
import "../chunk-7RGDRDAR.js";
|
|
39
39
|
import "../chunk-2ESYSVXG.js";
|
|
40
40
|
export {
|
|
41
41
|
COMPONENT_BROWSER_CLEANUP_TIMEOUT_MS,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
sourceIdentityForBake,
|
|
8
8
|
startComponentAssetServer,
|
|
9
9
|
verifyComponentOutput
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2BVKNYRB.js";
|
|
11
11
|
import {
|
|
12
12
|
COMPONENT_MEDIA_HEADROOM,
|
|
13
13
|
COMPONENT_MEDIA_TIERS,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
stagedBrowserLocator,
|
|
53
53
|
verifyLocalStagedBrowser,
|
|
54
54
|
vp9AlphaFfmpegOverride
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-AONWKKXK.js";
|
|
56
56
|
import "./chunk-WB2VFDQZ.js";
|
|
57
57
|
import {
|
|
58
58
|
bundleIdentityFields,
|
|
@@ -131,7 +131,7 @@ import {
|
|
|
131
131
|
} from "./chunk-EC6VFQE6.js";
|
|
132
132
|
import "./chunk-CL5Y6V6K.js";
|
|
133
133
|
import "./chunk-2L7PYYJK.js";
|
|
134
|
-
import "./chunk-
|
|
134
|
+
import "./chunk-7RGDRDAR.js";
|
|
135
135
|
import "./chunk-2ESYSVXG.js";
|
|
136
136
|
export {
|
|
137
137
|
CANVAS2D_COMPONENT_MANIFEST_V2,
|
package/dist/compose.js
CHANGED
|
@@ -5,42 +5,42 @@ import "./chunk-GULDS3VE.js";
|
|
|
5
5
|
import {
|
|
6
6
|
isContrastCritical
|
|
7
7
|
} from "./chunk-QDBVYZSF.js";
|
|
8
|
-
import {
|
|
9
|
-
catalog
|
|
10
|
-
} from "./chunk-RBWS5XHE.js";
|
|
11
|
-
import "./chunk-DLF4WVSE.js";
|
|
12
|
-
import "./chunk-U4V4FZGE.js";
|
|
13
|
-
import {
|
|
14
|
-
catalog as catalog3
|
|
15
|
-
} from "./chunk-FVDFPJHT.js";
|
|
16
8
|
import {
|
|
17
9
|
catalog as catalog6
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import {
|
|
20
|
-
catalog as catalog5
|
|
21
|
-
} from "./chunk-RAXHCRVV.js";
|
|
10
|
+
} from "./chunk-VLJOIUHL.js";
|
|
22
11
|
import {
|
|
23
12
|
catalog as catalog2
|
|
24
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GAACUQAB.js";
|
|
25
14
|
import {
|
|
26
15
|
catalog as catalog8
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-LT4PWSR2.js";
|
|
29
|
-
import "./chunk-FWSJLHSV.js";
|
|
30
|
-
import "./chunk-ZFEXATWN.js";
|
|
16
|
+
} from "./chunk-7SQOXIWR.js";
|
|
31
17
|
import {
|
|
32
18
|
catalog as catalog4
|
|
33
|
-
} from "./chunk-
|
|
34
|
-
import "./chunk-XHGZ2E77.js";
|
|
19
|
+
} from "./chunk-CR3G2JQP.js";
|
|
35
20
|
import {
|
|
36
21
|
catalog as catalog7
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-QGAWDLYX.js";
|
|
22
|
+
} from "./chunk-C6ONUJIO.js";
|
|
39
23
|
import "./chunk-S5H6GH6M.js";
|
|
40
24
|
import "./chunk-QAGGJHAF.js";
|
|
41
25
|
import "./chunk-MFHXCHRI.js";
|
|
26
|
+
import {
|
|
27
|
+
catalog
|
|
28
|
+
} from "./chunk-X34KW2SL.js";
|
|
29
|
+
import "./chunk-DLF4WVSE.js";
|
|
30
|
+
import "./chunk-U4V4FZGE.js";
|
|
31
|
+
import "./chunk-LT4PWSR2.js";
|
|
32
|
+
import "./chunk-FWSJLHSV.js";
|
|
33
|
+
import {
|
|
34
|
+
catalog as catalog3
|
|
35
|
+
} from "./chunk-FVDFPJHT.js";
|
|
36
|
+
import "./chunk-QGAWDLYX.js";
|
|
37
|
+
import {
|
|
38
|
+
catalog as catalog5
|
|
39
|
+
} from "./chunk-RAXHCRVV.js";
|
|
40
|
+
import "./chunk-XHGZ2E77.js";
|
|
41
|
+
import "./chunk-ZFEXATWN.js";
|
|
42
42
|
import "./chunk-W2245F6G.js";
|
|
43
|
-
import "./chunk-
|
|
43
|
+
import "./chunk-D5E5XFHK.js";
|
|
44
44
|
import "./chunk-XV2K3AQT.js";
|
|
45
45
|
import {
|
|
46
46
|
getPrimitiveSubtextParam,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
} from "./chunk-VG2ND6PX.js";
|
|
59
59
|
import "./chunk-CL5Y6V6K.js";
|
|
60
60
|
import "./chunk-2L7PYYJK.js";
|
|
61
|
-
import "./chunk-
|
|
61
|
+
import "./chunk-7RGDRDAR.js";
|
|
62
62
|
import "./chunk-2ESYSVXG.js";
|
|
63
63
|
|
|
64
64
|
// ../execution/compose/src/primitiveRegistry.ts
|
|
@@ -20,17 +20,17 @@ import {
|
|
|
20
20
|
PlanRect,
|
|
21
21
|
StyleRole,
|
|
22
22
|
ZPlane
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-UFNIB3JL.js";
|
|
24
24
|
import "../chunk-WPZKOVYF.js";
|
|
25
25
|
import "../chunk-B7J5UUUV.js";
|
|
26
26
|
import {
|
|
27
27
|
placeInLegalArea,
|
|
28
28
|
resolveBrandRefsDeep
|
|
29
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-RMLGMYEJ.js";
|
|
30
30
|
import "../chunk-WREYUH2E.js";
|
|
31
31
|
import "../chunk-ILO4NEZ3.js";
|
|
32
32
|
import "../chunk-VG2ND6PX.js";
|
|
33
|
-
import "../chunk-
|
|
33
|
+
import "../chunk-7RGDRDAR.js";
|
|
34
34
|
import "../chunk-2ESYSVXG.js";
|
|
35
35
|
|
|
36
36
|
// ../composition/src/graphics-plan/solve.ts
|
package/dist/composition/ops.js
CHANGED
|
@@ -20,14 +20,14 @@ import {
|
|
|
20
20
|
selectMediaClipAt,
|
|
21
21
|
selectSceneMarkers,
|
|
22
22
|
selectTracksByKind
|
|
23
|
-
} from "../chunk-
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
23
|
+
} from "../chunk-TPKPU4PE.js";
|
|
24
|
+
import "../chunk-CJMUTCJW.js";
|
|
25
|
+
import "../chunk-UFNIB3JL.js";
|
|
26
26
|
import "../chunk-WPZKOVYF.js";
|
|
27
27
|
import "../chunk-B7J5UUUV.js";
|
|
28
28
|
import "../chunk-KYRDKK2D.js";
|
|
29
29
|
import "../chunk-WREYUH2E.js";
|
|
30
|
-
import "../chunk-
|
|
30
|
+
import "../chunk-7RGDRDAR.js";
|
|
31
31
|
import "../chunk-2ESYSVXG.js";
|
|
32
32
|
export {
|
|
33
33
|
compositionWithSourceClip,
|