@cueframe/kernel 0.2.51 → 0.2.52

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.
Files changed (50) hide show
  1. package/dist/_members/composition/validators/composition.d.ts +20 -0
  2. package/dist/_members/composition/validators/render.d.ts +2 -0
  3. package/dist/_members/composition-ops/index.d.ts +12 -0
  4. package/dist/_members/core/render/compositionAudioAndDepth.d.ts +8 -2
  5. package/dist/_members/core/render/compositionRender.d.ts +14 -0
  6. package/dist/_members/core/render/index.d.ts +1 -1
  7. package/dist/_members/core/render/types.d.ts +1 -0
  8. package/dist/authoring/build-tools.js +5 -5
  9. package/dist/authoring/context.js +4 -4
  10. package/dist/authoring/tools.js +4 -4
  11. package/dist/authoring.js +6 -6
  12. package/dist/{chunk-2LUAUF46.js → chunk-2M65KQNG.js} +7 -0
  13. package/dist/{chunk-4CNJGY7P.js → chunk-3I43W7DP.js} +107 -8
  14. package/dist/{chunk-MOUWO53S.js → chunk-3OG2674K.js} +1 -1
  15. package/dist/{chunk-NLXQ7WTH.js → chunk-5JCLZPMV.js} +1 -1
  16. package/dist/{chunk-LZEX2GAY.js → chunk-CV3QQUMK.js} +27 -1
  17. package/dist/{chunk-OVV35ZS2.js → chunk-FSEB4LSU.js} +1 -1
  18. package/dist/{chunk-M665ZQYB.js → chunk-IHXMBXXL.js} +11 -5
  19. package/dist/{chunk-FSA3UBVR.js → chunk-JWW54N24.js} +1 -1
  20. package/dist/{chunk-KY3QBG7O.js → chunk-KMDZDH5E.js} +4 -4
  21. package/dist/{chunk-LO3DH776.js → chunk-MBSQKRDF.js} +1 -1
  22. package/dist/{chunk-IHWC75AN.js → chunk-QVBUYWW6.js} +1 -1
  23. package/dist/{chunk-YKXOAGY3.js → chunk-WZ22ZYXD.js} +8 -8
  24. package/dist/compose.js +20 -20
  25. package/dist/composition/graphics-plan.js +1 -1
  26. package/dist/composition/ops.js +3 -3
  27. package/dist/composition/validators.js +6 -2
  28. package/dist/composition-ops.js +5 -5
  29. package/dist/composition.js +6 -2
  30. package/dist/{context-AIUJG7R4.js → context-2MBCDTCZ.js} +4 -4
  31. package/dist/core/render.js +3 -1
  32. package/dist/core.js +1 -1
  33. package/dist/mcp/adapter.js +2 -2
  34. package/dist/mcp/core.js +1 -1
  35. package/dist/mcp/scene-shot.js +2 -2
  36. package/dist/mcp/server.js +9 -9
  37. package/dist/mcp.js +9 -9
  38. package/dist/primitives/effects.js +2 -2
  39. package/dist/primitives/hero-text.js +2 -2
  40. package/dist/primitives/scenes.js +2 -2
  41. package/dist/primitives/text.js +2 -2
  42. package/dist/primitives/ui-blocks.js +4 -4
  43. package/dist/primitives.js +20 -20
  44. package/dist/render-harness.js +7 -7
  45. package/package.json +10 -10
  46. package/dist/{chunk-O3SJTX6S.js → chunk-4B4V3HYW.js} +4 -4
  47. package/dist/{chunk-7SXY6NFW.js → chunk-5ZQLMPDY.js} +3 -3
  48. package/dist/{chunk-RL5SO653.js → chunk-7SQOXIWR.js} +3 -3
  49. package/dist/{chunk-B3GSTQLR.js → chunk-VLJOIUHL.js} +6 -6
  50. package/dist/{chunk-RBWS5XHE.js → chunk-X34KW2SL.js} +4 -4
@@ -335,6 +335,11 @@ export declare const ClipFit: z.ZodEnum<{
335
335
  cover: "cover";
336
336
  }>;
337
337
  export type ClipFit = z.infer<typeof ClipFit>;
338
+ export declare const CaptionVisibility: z.ZodEnum<{
339
+ visible: "visible";
340
+ hidden: "hidden";
341
+ }>;
342
+ export type CaptionVisibility = z.infer<typeof CaptionVisibility>;
338
343
  export declare const PerClipEffect: z.ZodObject<{
339
344
  primitiveId: z.ZodString;
340
345
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -543,6 +548,10 @@ export declare const TimelineClip: z.ZodObject<{
543
548
  contain: "contain";
544
549
  cover: "cover";
545
550
  }>>;
551
+ captionVisibility: z.ZodOptional<z.ZodEnum<{
552
+ visible: "visible";
553
+ hidden: "hidden";
554
+ }>>;
546
555
  effects: z.ZodOptional<z.ZodArray<z.ZodObject<{
547
556
  primitiveId: z.ZodString;
548
557
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -698,6 +707,7 @@ export declare const TrackContent: z.ZodPipe<z.ZodUnknown, z.ZodTransform<{
698
707
  h: number;
699
708
  } | undefined;
700
709
  fit?: "contain" | "cover" | undefined;
710
+ captionVisibility?: "visible" | "hidden" | undefined;
701
711
  effects?: {
702
712
  primitiveId: string;
703
713
  params?: Record<string, unknown> | undefined;
@@ -857,6 +867,7 @@ export declare const Track: z.ZodObject<{
857
867
  h: number;
858
868
  } | undefined;
859
869
  fit?: "contain" | "cover" | undefined;
870
+ captionVisibility?: "visible" | "hidden" | undefined;
860
871
  effects?: {
861
872
  primitiveId: string;
862
873
  params?: Record<string, unknown> | undefined;
@@ -1148,6 +1159,13 @@ export declare function captionsAreBehindSubject(captions: {
1148
1159
  } | null | undefined): boolean;
1149
1160
  export type CompositionCaptions = z.infer<typeof CompositionCaptions>;
1150
1161
  export declare function captionWords(c: CompositionCaptions): CaptionWord[];
1162
+ /** One shared invariant for schema parsing, pure ops, and hosted writes. */
1163
+ export declare function captionVisibilityIssues(composition: {
1164
+ tracks: Track[];
1165
+ }): Array<{
1166
+ trackIndex: number;
1167
+ contentIndex: number;
1168
+ }>;
1151
1169
  export declare const Composition: z.ZodObject<{
1152
1170
  v: z.ZodLiteral<1>;
1153
1171
  format: z.ZodObject<{
@@ -1302,6 +1320,7 @@ export declare const Composition: z.ZodObject<{
1302
1320
  h: number;
1303
1321
  } | undefined;
1304
1322
  fit?: "contain" | "cover" | undefined;
1323
+ captionVisibility?: "visible" | "hidden" | undefined;
1305
1324
  effects?: {
1306
1325
  primitiveId: string;
1307
1326
  params?: Record<string, unknown> | undefined;
@@ -1698,6 +1717,7 @@ export declare const CompositionVersion: z.ZodObject<{
1698
1717
  h: number;
1699
1718
  } | undefined;
1700
1719
  fit?: "contain" | "cover" | undefined;
1720
+ captionVisibility?: "visible" | "hidden" | undefined;
1701
1721
  effects?: {
1702
1722
  primitiveId: string;
1703
1723
  params?: Record<string, unknown> | undefined;
@@ -205,6 +205,7 @@ export declare const RenderSnapshot: z.ZodObject<{
205
205
  h: number;
206
206
  } | undefined;
207
207
  fit?: "contain" | "cover" | undefined;
208
+ captionVisibility?: "visible" | "hidden" | undefined;
208
209
  effects?: {
209
210
  primitiveId: string;
210
211
  params?: Record<string, unknown> | undefined;
@@ -1049,6 +1050,7 @@ export declare const RenderJob: z.ZodObject<{
1049
1050
  h: number;
1050
1051
  } | undefined;
1051
1052
  fit?: "contain" | "cover" | undefined;
1053
+ captionVisibility?: "visible" | "hidden" | undefined;
1052
1054
  effects?: {
1053
1055
  primitiveId: string;
1054
1056
  params?: Record<string, unknown> | undefined;
@@ -170,6 +170,10 @@ export declare const CompositionOp: z.ZodDiscriminatedUnion<[z.ZodObject<{
170
170
  contain: "contain";
171
171
  cover: "cover";
172
172
  }>>;
173
+ captionVisibility: z.ZodOptional<z.ZodEnum<{
174
+ visible: "visible";
175
+ hidden: "hidden";
176
+ }>>;
173
177
  effects: z.ZodOptional<z.ZodArray<z.ZodObject<{
174
178
  primitiveId: z.ZodString;
175
179
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -363,6 +367,10 @@ export declare const CompositionOp: z.ZodDiscriminatedUnion<[z.ZodObject<{
363
367
  contain: "contain";
364
368
  cover: "cover";
365
369
  }>>>;
370
+ captionVisibility: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
371
+ visible: "visible";
372
+ hidden: "hidden";
373
+ }>>>;
366
374
  effects: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
367
375
  primitiveId: z.ZodString;
368
376
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -552,6 +560,10 @@ export declare const CompositionOp: z.ZodDiscriminatedUnion<[z.ZodObject<{
552
560
  contain: "contain";
553
561
  cover: "cover";
554
562
  }>>;
563
+ captionVisibility: z.ZodOptional<z.ZodEnum<{
564
+ visible: "visible";
565
+ hidden: "hidden";
566
+ }>>;
555
567
  effects: z.ZodOptional<z.ZodArray<z.ZodObject<{
556
568
  primitiveId: z.ZodString;
557
569
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -7,13 +7,19 @@ export declare function assertBehindSubjectCaptionCoverage(captionSegments: Rend
7
7
  width: number;
8
8
  height: number;
9
9
  }, effects?: readonly CompositionEffect[]): void;
10
+ /** The geometry needed to decide which video picture is visible, without an asset URL. */
11
+ export type VisiblePictureClip = Pick<CompositionClip, 'id' | 'trackId' | 'contentIndex' | 'layerIndex' | 'timelineStartFrames' | 'durationInFrames'> & Partial<Pick<CompositionClip, 'region' | 'fit' | 'sourceWidth' | 'sourceHeight' | 'cropTrajectory' | 'cropTrajectoryUrl' | 'captionVisibility' | 'packedUrl' | 'mediaType'>> & {
12
+ hasClipEffects?: boolean;
13
+ hasCropIntent?: boolean;
14
+ };
10
15
  /** The visible full-frame picture at each interval, following the renderer's zIndex/layer order. */
11
- export declare function visiblePackedHostWindows(clips: readonly CompositionClip[], startFrame: number, endFrame: number, output: {
16
+ export declare function visiblePackedHostWindows(clips: readonly VisiblePictureClip[], startFrame: number, endFrame: number, output: {
12
17
  width: number;
13
18
  height: number;
14
- }, effects?: readonly CompositionEffect[]): Array<{
19
+ }, effects?: readonly CompositionEffect[], hostMode?: 'packed-only' | 'all-video-candidates'): Array<{
15
20
  startFrame: number;
16
21
  endFrame: number;
17
22
  hostClipId?: string;
18
23
  candidateClipIds: string[];
24
+ captionVisible: boolean;
19
25
  }>;
@@ -2,10 +2,24 @@ import type { Composition, Format, TimelineClip as WireClip } from "../../compos
2
2
  import type { RenderInput } from "./types.js";
3
3
  import type { TrajectoryData } from "../../composition/reframe/trajectory.js";
4
4
  import { type PreparedRenderInputLeaseV1, type SceneShotPreparationDependenciesV1 } from "./sceneShotPreparation.js";
5
+ import { visiblePackedHostWindows } from "./compositionAudioAndDepth.js";
5
6
  export { validateComposition } from "./compositionValidation.js";
6
7
  export { assertBehindSubjectCaptionCoverage, visiblePackedHostWindows } from "./compositionAudioAndDepth.js";
7
8
  /** Re-exported from `trackProjection`, where the frame-lattice helpers it belongs with now live. */
8
9
  export { playableSpans, projectMediaPlaybackSpans } from "./trackProjection.js";
10
+ /**
11
+ * Project the saved video timeline into candidate visible-picture windows for fact planning.
12
+ * No source URL or matte binding is created here. A hostClipId names the uniquely visible
13
+ * video candidate; callers must still check that its exact matte exists and is ready.
14
+ */
15
+ export declare function captionVisibilityWindowsForComposition(composition: Composition, sourceDimensions: Record<string, {
16
+ width: number;
17
+ height: number;
18
+ }>): {
19
+ fps: number;
20
+ windows: ReturnType<typeof visiblePackedHostWindows>;
21
+ mediaIdByProjectedClipId: Record<string, string>;
22
+ };
9
23
  export declare function compositionFormatDimensions(format: Format): {
10
24
  width: number;
11
25
  height: number;
@@ -11,7 +11,7 @@ export type { EmphasisWord } from './emphasis.js';
11
11
  export type { DocNode, TranscriptUtterance } from './captions.js';
12
12
  export { buildEmphasisSet, isEmphasized } from './emphasis.js';
13
13
  export { extractCaptionWordsFromDoc, sliceTranscriptWords, splitIntoSentences } from './captions.js';
14
- export { compositionToRenderInput, referencedMediaIds, assembleRenderInput, assemblePreparedRenderInput, validateComposition, compositionFormatDimensions, playableSpans, projectMediaPlaybackSpans, assertBehindSubjectCaptionCoverage, visiblePackedHostWindows, } from './compositionRender.js';
14
+ export { compositionToRenderInput, referencedMediaIds, assembleRenderInput, assemblePreparedRenderInput, validateComposition, compositionFormatDimensions, captionVisibilityWindowsForComposition, playableSpans, projectMediaPlaybackSpans, assertBehindSubjectCaptionCoverage, visiblePackedHostWindows, } from './compositionRender.js';
15
15
  export { bookendFrames, resolveBookendTimeline, CARD_BOOKEND_DEFAULT_MS, VIDEO_BOOKEND_DEFAULT_MS, } from './bookends.js';
16
16
  export type { BookendTimeline } from './bookends.js';
17
17
  export { DEFAULT_FPS, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_RENDER_SETTINGS, FORMAT_PRESETS, RESOLUTION_PRESETS, bppToCrf, ensureEven, qualityToCrf, resolutionToOutputSize, } from './exportSettings.js';
@@ -69,6 +69,7 @@ export interface CompositionClip extends ProjectedVisualIdentity {
69
69
  h: number;
70
70
  };
71
71
  fit?: 'cover' | 'contain';
72
+ captionVisibility?: 'visible' | 'hidden';
72
73
  mediaType?: 'video' | 'audio' | 'image';
73
74
  kenBurns?: 'in' | 'out' | 'pan-l' | 'pan-r' | 'none';
74
75
  reframe?: Reframe;
@@ -4,13 +4,13 @@ import {
4
4
  buildPlannerTools,
5
5
  buildToolsFromSchemas,
6
6
  extractProviderError
7
- } from "../chunk-IHWC75AN.js";
8
- import "../chunk-KY3QBG7O.js";
7
+ } from "../chunk-QVBUYWW6.js";
8
+ import "../chunk-KMDZDH5E.js";
9
9
  import "../chunk-JOURGVOR.js";
10
10
  import "../chunk-7AZLFN26.js";
11
- import "../chunk-NLXQ7WTH.js";
12
- import "../chunk-LO3DH776.js";
13
- import "../chunk-LZEX2GAY.js";
11
+ import "../chunk-5JCLZPMV.js";
12
+ import "../chunk-MBSQKRDF.js";
13
+ import "../chunk-CV3QQUMK.js";
14
14
  import "../chunk-WPZKOVYF.js";
15
15
  import "../chunk-B7J5UUUV.js";
16
16
  import "../chunk-KYRDKK2D.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  buildDirectorContext
3
- } from "../chunk-OVV35ZS2.js";
4
- import "../chunk-NLXQ7WTH.js";
5
- import "../chunk-LO3DH776.js";
6
- import "../chunk-LZEX2GAY.js";
3
+ } from "../chunk-FSEB4LSU.js";
4
+ import "../chunk-5JCLZPMV.js";
5
+ import "../chunk-MBSQKRDF.js";
6
+ import "../chunk-CV3QQUMK.js";
7
7
  import "../chunk-WPZKOVYF.js";
8
8
  import "../chunk-B7J5UUUV.js";
9
9
  import "../chunk-KYRDKK2D.js";
@@ -6,12 +6,12 @@ import {
6
6
  COMPOSE_ROLE_TOOLS,
7
7
  COMPOSE_ROLE_TOOL_NAMES,
8
8
  dispatchComposeRoleTool
9
- } from "../chunk-KY3QBG7O.js";
9
+ } from "../chunk-KMDZDH5E.js";
10
10
  import "../chunk-JOURGVOR.js";
11
11
  import "../chunk-7AZLFN26.js";
12
- import "../chunk-NLXQ7WTH.js";
13
- import "../chunk-LO3DH776.js";
14
- import "../chunk-LZEX2GAY.js";
12
+ import "../chunk-5JCLZPMV.js";
13
+ import "../chunk-MBSQKRDF.js";
14
+ import "../chunk-CV3QQUMK.js";
15
15
  import "../chunk-WPZKOVYF.js";
16
16
  import "../chunk-B7J5UUUV.js";
17
17
  import "../chunk-KYRDKK2D.js";
package/dist/authoring.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  buildPlannerTools,
12
12
  buildToolsFromSchemas,
13
13
  extractProviderError
14
- } from "./chunk-IHWC75AN.js";
14
+ } from "./chunk-QVBUYWW6.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-KY3QBG7O.js";
23
+ } from "./chunk-KMDZDH5E.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-OVV35ZS2.js";
30
+ } from "./chunk-FSEB4LSU.js";
31
31
  import {
32
32
  buildFastModel,
33
33
  buildModel,
@@ -49,9 +49,9 @@ import {
49
49
  initCodeGenPrompts
50
50
  } from "./chunk-Y4HPN4BC.js";
51
51
  import "./chunk-7AZLFN26.js";
52
- import "./chunk-NLXQ7WTH.js";
53
- import "./chunk-LO3DH776.js";
54
- import "./chunk-LZEX2GAY.js";
52
+ import "./chunk-5JCLZPMV.js";
53
+ import "./chunk-MBSQKRDF.js";
54
+ import "./chunk-CV3QQUMK.js";
55
55
  import "./chunk-WPZKOVYF.js";
56
56
  import "./chunk-B7J5UUUV.js";
57
57
  import "./chunk-KYRDKK2D.js";
@@ -1436,6 +1436,7 @@ var BriefCreateRequest = zod19.strictObject({
1436
1436
  "h": zod19.number().gt(briefCreateRequestSeededGraphicsItemRegionHExclusiveMin).max(briefCreateRequestSeededGraphicsItemRegionHMax)
1437
1437
  }).optional(),
1438
1438
  "fit": zod19.enum(["cover", "contain"]).optional(),
1439
+ "captionVisibility": zod19.enum(["visible", "hidden"]).optional().describe("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."),
1439
1440
  "effects": zod19.array(zod19.strictObject({
1440
1441
  "primitiveId": zod19.string().min(1),
1441
1442
  "params": zod19.record(zod19.string(), zod19.unknown()).optional()
@@ -1697,6 +1698,7 @@ var BriefResponse = zod21.strictObject({
1697
1698
  "h": zod21.number().gt(briefResponseSeededGraphicsItemRegionHExclusiveMin).max(briefResponseSeededGraphicsItemRegionHMax)
1698
1699
  }).optional(),
1699
1700
  "fit": zod21.enum(["cover", "contain"]).optional(),
1701
+ "captionVisibility": zod21.enum(["visible", "hidden"]).optional().describe("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."),
1700
1702
  "effects": zod21.array(zod21.strictObject({
1701
1703
  "primitiveId": zod21.string().min(1),
1702
1704
  "params": zod21.record(zod21.string(), zod21.unknown()).optional()
@@ -1947,6 +1949,7 @@ var BriefPatchRequest = zod23.strictObject({
1947
1949
  "h": zod23.number().gt(briefPatchRequestSeededGraphicsItemRegionHExclusiveMin).max(briefPatchRequestSeededGraphicsItemRegionHMax)
1948
1950
  }).optional(),
1949
1951
  "fit": zod23.enum(["cover", "contain"]).optional(),
1952
+ "captionVisibility": zod23.enum(["visible", "hidden"]).optional().describe("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."),
1950
1953
  "effects": zod23.array(zod23.strictObject({
1951
1954
  "primitiveId": zod23.string().min(1),
1952
1955
  "params": zod23.record(zod23.string(), zod23.unknown()).optional()
@@ -2755,6 +2758,7 @@ var Composition = zod58.strictObject({
2755
2758
  "h": zod58.number().gt(compositionTracksItemContentsItemOneRegionHExclusiveMin).max(compositionTracksItemContentsItemOneRegionHMax)
2756
2759
  }).optional(),
2757
2760
  "fit": zod58.enum(["cover", "contain"]).optional(),
2761
+ "captionVisibility": zod58.enum(["visible", "hidden"]).optional().describe("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."),
2758
2762
  "effects": zod58.array(zod58.strictObject({
2759
2763
  "primitiveId": zod58.string().min(1),
2760
2764
  "params": zod58.record(zod58.string(), zod58.unknown()).optional()
@@ -6282,6 +6286,7 @@ var CompositionOp = zod67.union([zod67.strictObject({
6282
6286
  "h": zod67.number().gt(compositionOpThreeClipRegionHExclusiveMin).max(compositionOpThreeClipRegionHMax)
6283
6287
  }).optional(),
6284
6288
  "fit": zod67.enum(["cover", "contain"]).optional(),
6289
+ "captionVisibility": zod67.enum(["visible", "hidden"]).optional().describe("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."),
6285
6290
  "effects": zod67.array(zod67.strictObject({
6286
6291
  "primitiveId": zod67.string().min(1),
6287
6292
  "params": zod67.record(zod67.string(), zod67.unknown()).optional()
@@ -6431,6 +6436,7 @@ var CompositionOp = zod67.union([zod67.strictObject({
6431
6436
  "h": zod67.number().gt(compositionOpFivePatchRegionHExclusiveMin).max(compositionOpFivePatchRegionHMax)
6432
6437
  }).optional(),
6433
6438
  "fit": zod67.enum(["cover", "contain"]).optional(),
6439
+ "captionVisibility": zod67.enum(["visible", "hidden"]).optional().describe("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."),
6434
6440
  "effects": zod67.array(zod67.strictObject({
6435
6441
  "primitiveId": zod67.string().min(1),
6436
6442
  "params": zod67.record(zod67.string(), zod67.unknown()).optional()
@@ -6576,6 +6582,7 @@ var CompositionOp = zod67.union([zod67.strictObject({
6576
6582
  "h": zod67.number().gt(compositionOpSevenClipsItemRegionHExclusiveMin).max(compositionOpSevenClipsItemRegionHMax)
6577
6583
  }).optional(),
6578
6584
  "fit": zod67.enum(["cover", "contain"]).optional(),
6585
+ "captionVisibility": zod67.enum(["visible", "hidden"]).optional().describe("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."),
6579
6586
  "effects": zod67.array(zod67.strictObject({
6580
6587
  "primitiveId": zod67.string().min(1),
6581
6588
  "params": zod67.record(zod67.string(), zod67.unknown()).optional()
@@ -1232,6 +1232,7 @@ function assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, output,
1232
1232
  const startFrame = Math.round(word.startMs / 1e3 * fps);
1233
1233
  const endFrame = Math.max(startFrame + 1, Math.round(word.endMs / 1e3 * fps));
1234
1234
  for (const window of visiblePackedHostWindows(clips, startFrame, endFrame, output, effects)) {
1235
+ if (!window.captionVisible) continue;
1235
1236
  if (window.hostClipId) continue;
1236
1237
  const code = window.candidateClipIds.length > 1 ? "behind_subject_caption_host_ambiguous" : "behind_subject_caption_host_missing";
1237
1238
  throw renderInputError(
@@ -1245,10 +1246,10 @@ function assertBehindSubjectCaptionCoverage(captionSegments, clips, fps, output,
1245
1246
  }
1246
1247
  var FULL_RECT = { left: 0, top: 0, right: 1, bottom: 1 };
1247
1248
  function hasClipEffect(clip, effects) {
1248
- return effects.some((effect) => effect.target.kind === "clip" && effect.trackId === clip.trackId && effect.contentIndex === clip.contentIndex);
1249
+ return clip.hasClipEffects === true || effects.some((effect) => effect.target.kind === "clip" && effect.trackId === clip.trackId && effect.contentIndex === clip.contentIndex);
1249
1250
  }
1250
1251
  function pictureRect(clip, output, effects) {
1251
- if (clip.cropTrajectory || clip.cropTrajectoryUrl || hasClipEffect(clip, effects)) return void 0;
1252
+ if (clip.cropTrajectory || clip.cropTrajectoryUrl || clip.hasCropIntent || hasClipEffect(clip, effects)) return void 0;
1252
1253
  if (clip.fit !== "contain") return FULL_RECT;
1253
1254
  const sourceWidth = clip.sourceWidth;
1254
1255
  const sourceHeight = clip.sourceHeight;
@@ -1271,7 +1272,7 @@ function coversLowerPictures(upper, lower, output, effects) {
1271
1272
  return upperRect.left <= rect.left + epsilon && upperRect.top <= rect.top + epsilon && upperRect.right + epsilon >= rect.right && upperRect.bottom + epsilon >= rect.bottom;
1272
1273
  });
1273
1274
  }
1274
- function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects = []) {
1275
+ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects = [], hostMode = "packed-only") {
1275
1276
  if (endFrame <= startFrame) return [];
1276
1277
  const boundaries = /* @__PURE__ */ new Set([startFrame, endFrame]);
1277
1278
  for (const clip of clips) {
@@ -1280,6 +1281,13 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
1280
1281
  if (start > startFrame && start < endFrame) boundaries.add(start);
1281
1282
  if (end > startFrame && end < endFrame) boundaries.add(end);
1282
1283
  }
1284
+ for (const effect of effects) {
1285
+ if (effect.target.kind !== "global") continue;
1286
+ const start = effect.startFrame ?? startFrame;
1287
+ const end = start + (effect.durationInFrames ?? endFrame - start);
1288
+ if (start > startFrame && start < endFrame) boundaries.add(start);
1289
+ if (end > startFrame && end < endFrame) boundaries.add(end);
1290
+ }
1283
1291
  const points = [...boundaries].sort((a, b) => a - b);
1284
1292
  const windows = [];
1285
1293
  for (let i = 0; i < points.length - 1; i++) {
@@ -1290,6 +1298,7 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
1290
1298
  );
1291
1299
  const topLayer = Math.max(...active.map((clip) => clip.layerIndex));
1292
1300
  const top = active.filter((clip) => clip.layerIndex === topLayer);
1301
+ const globalEffectActive = effects.some((effect) => effect.target.kind === "global" && (effect.startFrame ?? startFrame) <= start && (effect.startFrame ?? startFrame) + (effect.durationInFrames ?? endFrame - startFrame) >= end);
1293
1302
  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
1303
  const provesOcclusion = top.length === 1 && fullFrame && (active.length === 1 || coversLowerPictures(
1295
1304
  top[0],
@@ -1297,18 +1306,22 @@ function visiblePackedHostWindows(clips, startFrame, endFrame, output, effects =
1297
1306
  output,
1298
1307
  effects
1299
1308
  ));
1300
- const host = provesOcclusion && top[0].packedUrl ? top[0] : void 0;
1301
- const unresolvedOverlap = top.length > 1 || top.length === 1 && !!top[0].packedUrl && active.length > 1 && !provesOcclusion;
1302
- const candidates = unresolvedOverlap ? active.filter((clip) => clip.packedUrl).map((clip) => clip.id) : top.map((clip) => clip.id);
1309
+ const suppressesCaption = provesOcclusion && !globalEffectActive && pictureRect(top[0], output, effects) !== void 0;
1310
+ const captionVisible = !(suppressesCaption && top[0].captionVisibility === "hidden");
1311
+ const candidateHost = (clip) => hostMode === "all-video-candidates" ? clip.mediaType !== "image" : !!clip.packedUrl;
1312
+ const host = provesOcclusion && candidateHost(top[0]) ? top[0] : void 0;
1313
+ const unresolvedOverlap = top.length > 1 || top.length === 1 && active.length > 1 && !provesOcclusion;
1314
+ const candidates = unresolvedOverlap ? active.filter(candidateHost).map((clip) => clip.id) : top.map((clip) => clip.id);
1303
1315
  const previous = windows[windows.length - 1];
1304
- if (previous && previous.endFrame === start && previous.hostClipId === host?.id && previous.candidateClipIds.join("\0") === candidates.join("\0")) {
1316
+ if (previous && previous.endFrame === start && previous.hostClipId === host?.id && previous.captionVisible === captionVisible && previous.candidateClipIds.join("\0") === candidates.join("\0")) {
1305
1317
  previous.endFrame = end;
1306
1318
  } else {
1307
1319
  windows.push({
1308
1320
  startFrame: start,
1309
1321
  endFrame: end,
1310
1322
  ...host ? { hostClipId: host.id } : {},
1311
- candidateClipIds: candidates
1323
+ candidateClipIds: candidates,
1324
+ captionVisible
1312
1325
  });
1313
1326
  }
1314
1327
  }
@@ -1455,6 +1468,13 @@ function projectMediaTrack(track, trackIndex, trackCount, fps, srcUrls, trajecto
1455
1468
  );
1456
1469
  }
1457
1470
  if (rendersNoFrames(c)) continue;
1471
+ if (c.captionVisibility !== void 0 && track.kind !== "video") {
1472
+ throw renderInputError(
1473
+ "invalid_composition",
1474
+ `Clip ${c.id}: captionVisibility is supported only on video media clips.`,
1475
+ { trackId: track.id, clipId: c.id, compositionPath: `composition.tracks[${track.id}].contents[${i}].captionVisibility` }
1476
+ );
1477
+ }
1458
1478
  const src = resolveSrcUrl(c.source.mediaId, srcUrls, {
1459
1479
  trackId: track.id,
1460
1480
  clipId: c.id,
@@ -1546,6 +1566,7 @@ function projectMediaTrack(track, trackIndex, trackCount, fps, srcUrls, trajecto
1546
1566
  ...c.animate !== void 0 ? { animate: c.animate } : {},
1547
1567
  ...c.region !== void 0 ? { region: c.region } : {},
1548
1568
  ...c.fit !== void 0 ? { fit: c.fit } : {},
1569
+ ...c.captionVisibility !== void 0 ? { captionVisibility: c.captionVisibility } : {},
1549
1570
  ...s === 0 && c.transitionIn ? {
1550
1571
  transitionIn: mapTransitionType(c.transitionIn.type),
1551
1572
  transitionDurationFrames: Math.max(1, Math.round(c.transitionIn.duration * fps))
@@ -1813,6 +1834,71 @@ function projectEffectTrack(track, trackIndex, trackCount, fps) {
1813
1834
  }
1814
1835
 
1815
1836
  // ../execution/core/src/render/compositionRender.ts
1837
+ function captionVisibilityWindowsForComposition(composition, sourceDimensions) {
1838
+ const { fps, width, height } = compositionFormatDimensions(composition.format);
1839
+ const clips = [];
1840
+ const mediaIdByProjectedClipId = {};
1841
+ let endFrame = 0;
1842
+ const trackCount = composition.tracks.length;
1843
+ const effects = composition.tracks.flatMap(
1844
+ (track, index) => track.enabled !== false && track.kind === "effect" ? projectEffectTrack(track, index, trackCount, fps) : []
1845
+ );
1846
+ for (const [trackIndex, track] of composition.tracks.entries()) {
1847
+ if (track.enabled === false || track.kind !== "video" && track.kind !== "image") continue;
1848
+ for (const [contentIndex, item] of track.contents.entries()) {
1849
+ if (!("source" in item)) continue;
1850
+ if (item.source.kind !== "media") {
1851
+ throw renderInputError(
1852
+ "clip_source_track_mismatch",
1853
+ `Clip ${item.id} on video track ${track.id} must use a media source.`,
1854
+ { trackId: track.id, clipId: item.id }
1855
+ );
1856
+ }
1857
+ const spans = projectMediaPlaybackSpans(track.kind === "video" ? {
1858
+ startTime: item.startTime,
1859
+ duration: item.duration,
1860
+ trim: item.source.trim,
1861
+ excludedRanges: item.source.excludedRanges,
1862
+ playbackRate: item.source.playbackRate,
1863
+ fps
1864
+ } : { startTime: item.startTime, duration: item.duration, fps });
1865
+ const dimensions = sourceDimensions[item.source.mediaId];
1866
+ const validDimensions = track.kind === "video" && dimensions && Number.isFinite(dimensions.width) && dimensions.width > 0 && Number.isFinite(dimensions.height) && dimensions.height > 0;
1867
+ for (const [spanIndex, span] of spans.entries()) {
1868
+ if (span.durationInFrames === 0) continue;
1869
+ const id = spans.length === 1 ? item.id : `${item.id}#${spanIndex}`;
1870
+ clips.push({
1871
+ id,
1872
+ trackId: track.id,
1873
+ layerIndex: trackCount - trackIndex,
1874
+ contentIndex,
1875
+ timelineStartFrames: span.timelineStartFrames,
1876
+ durationInFrames: span.durationInFrames,
1877
+ ...track.kind === "image" ? { mediaType: "image" } : {},
1878
+ ...validDimensions ? { sourceWidth: dimensions.width, sourceHeight: dimensions.height } : {},
1879
+ ...item.region ? { region: item.region } : {},
1880
+ ...item.fit ? { fit: item.fit } : {},
1881
+ ...track.kind === "video" && item.captionVisibility ? { captionVisibility: item.captionVisibility } : {},
1882
+ ...item.source.reframe?.segments.length ? { hasCropIntent: true } : {},
1883
+ ...item.effects?.length ? { hasClipEffects: true } : {}
1884
+ });
1885
+ if (track.kind === "video") mediaIdByProjectedClipId[id] = item.source.mediaId;
1886
+ endFrame = Math.max(endFrame, span.timelineStartFrames + span.durationInFrames);
1887
+ }
1888
+ }
1889
+ }
1890
+ for (const segment of composition.captions?.segments ?? []) {
1891
+ for (const word of segment.words) {
1892
+ const startFrame = Math.round(word.startMs / 1e3 * fps);
1893
+ endFrame = Math.max(endFrame, Math.max(startFrame + 1, Math.round(word.endMs / 1e3 * fps)));
1894
+ }
1895
+ }
1896
+ return {
1897
+ fps,
1898
+ windows: visiblePackedHostWindows(clips, 0, endFrame, { width, height }, effects, "all-video-candidates"),
1899
+ mediaIdByProjectedClipId
1900
+ };
1901
+ }
1816
1902
  var CAPTION_COLOR_FIELDS = [
1817
1903
  "color",
1818
1904
  "highlightColor",
@@ -1903,6 +1989,18 @@ function assertMergedCaptionFacesDrawable(composition) {
1903
1989
  function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUrls, alphaUrls, subCompositions, trajectories, options) {
1904
1990
  const flattened = hasCompoundClips(composition) ? flattenCompoundClips(composition, (id) => subCompositions?.[id]) : composition;
1905
1991
  composition = flattened;
1992
+ for (const track of composition.tracks) {
1993
+ for (const content of track.contents) {
1994
+ if (!("source" in content) || content.captionVisibility === void 0) continue;
1995
+ if (track.kind !== "video" || content.source.kind !== "media") {
1996
+ throw renderInputError(
1997
+ "invalid_composition",
1998
+ `Clip ${content.id}: captionVisibility is supported only on video media clips.`,
1999
+ { trackId: track.id, clipId: content.id, compositionPath: `composition.tracks[${track.id}].contents[${content.id}].captionVisibility` }
2000
+ );
2001
+ }
2002
+ }
2003
+ }
1906
2004
  assertMergedCaptionFacesDrawable(composition);
1907
2005
  const { width, height, fps } = compositionFormatDimensions(composition.format);
1908
2006
  const clips = [];
@@ -3086,6 +3184,7 @@ export {
3086
3184
  visiblePackedHostWindows,
3087
3185
  playableSpans,
3088
3186
  projectMediaPlaybackSpans,
3187
+ captionVisibilityWindowsForComposition,
3089
3188
  compositionFormatDimensions,
3090
3189
  referencedMediaIds,
3091
3190
  compositionToRenderInput,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  bodySchemaFor,
3
3
  opById
4
- } from "./chunk-2LUAUF46.js";
4
+ } from "./chunk-2M65KQNG.js";
5
5
 
6
6
  // ../mcp/src/generated/sceneContract.ts
7
7
  function deepFreeze(value) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Composition
3
- } from "./chunk-LZEX2GAY.js";
3
+ } from "./chunk-CV3QQUMK.js";
4
4
  import {
5
5
  expandToLinkGroup
6
6
  } from "./chunk-KYRDKK2D.js";
@@ -124,6 +124,7 @@ var CaptionRegion = Region.refine(
124
124
  "captions style.region must fit within the normalized frame"
125
125
  );
126
126
  var ClipFit = z2.enum(["cover", "contain"]);
127
+ var CaptionVisibility = z2.enum(["visible", "hidden"]);
127
128
  var PerClipEffect = z2.object({
128
129
  primitiveId: z2.string().min(1),
129
130
  params: z2.record(z2.string(), z2.unknown()).optional()
@@ -166,6 +167,9 @@ var TimelineClip = z2.object({
166
167
  position: Position.optional(),
167
168
  region: Region.optional(),
168
169
  fit: ClipFit.optional(),
170
+ captionVisibility: CaptionVisibility.optional().describe(
171
+ "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."
172
+ ),
169
173
  effects: z2.array(PerClipEffect).optional(),
170
174
  transitionIn: Transition.optional(),
171
175
  linkGroupId: z2.string().min(1).optional(),
@@ -314,6 +318,18 @@ function captionsAreBehindSubject(captions) {
314
318
  function captionWords(c) {
315
319
  return c.segments.flatMap((s) => s.words);
316
320
  }
321
+ function captionVisibilityIssues(composition) {
322
+ const issues = [];
323
+ composition.tracks.forEach((track, trackIndex) => {
324
+ track.contents.forEach((item, contentIndex) => {
325
+ if (!("source" in item) || item.captionVisibility === void 0) return;
326
+ if (track.kind !== "video" || item.source.kind !== "media") {
327
+ issues.push({ trackIndex, contentIndex });
328
+ }
329
+ });
330
+ });
331
+ return issues;
332
+ }
317
333
  var Composition = z2.object({
318
334
  v: z2.literal(1, {
319
335
  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 +348,15 @@ var Composition = z2.object({
332
348
  accessibility: CompositionAccessibility.optional(),
333
349
  ownerOrgId: z2.string().optional(),
334
350
  acl: AccessControl.optional()
335
- }).strict();
351
+ }).strict().superRefine((composition, ctx) => {
352
+ for (const issue of captionVisibilityIssues(composition)) {
353
+ ctx.addIssue({
354
+ code: "custom",
355
+ path: ["tracks", issue.trackIndex, "contents", issue.contentIndex, "captionVisibility"],
356
+ message: "captionVisibility is supported only on video media clips"
357
+ });
358
+ }
359
+ });
336
360
  var CompositionAuthorKind = z2.enum(["user", "agent", "import"]);
337
361
  var CompositionVersion = z2.object({
338
362
  id: z2.string().min(1),
@@ -502,6 +526,7 @@ export {
502
526
  Region,
503
527
  CaptionRegion,
504
528
  ClipFit,
529
+ CaptionVisibility,
505
530
  PerClipEffect,
506
531
  KeyframeEasing,
507
532
  Keyframe,
@@ -519,6 +544,7 @@ export {
519
544
  CompositionCaptions,
520
545
  captionsAreBehindSubject,
521
546
  captionWords,
547
+ captionVisibilityIssues,
522
548
  Composition,
523
549
  CompositionAuthorKind,
524
550
  CompositionVersion,
@@ -2,7 +2,7 @@ import {
2
2
  selectAllClips,
3
3
  selectAllOverlays,
4
4
  selectSceneMarkers
5
- } from "./chunk-NLXQ7WTH.js";
5
+ } from "./chunk-5JCLZPMV.js";
6
6
 
7
7
  // ../authoring/src/context/transcript.ts
8
8
  var MAX_TRANSCRIPT_CHARS = 6e4;