@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.
- package/dist/_members/composition/validators/composition.d.ts +20 -0
- package/dist/_members/composition/validators/render.d.ts +2 -0
- package/dist/_members/composition-ops/index.d.ts +12 -0
- package/dist/_members/core/render/compositionAudioAndDepth.d.ts +8 -2
- package/dist/_members/core/render/compositionRender.d.ts +14 -0
- package/dist/_members/core/render/index.d.ts +1 -1
- package/dist/_members/core/render/types.d.ts +1 -0
- package/dist/authoring/build-tools.js +5 -5
- package/dist/authoring/context.js +4 -4
- package/dist/authoring/tools.js +4 -4
- package/dist/authoring.js +6 -6
- package/dist/{chunk-2LUAUF46.js → chunk-2M65KQNG.js} +7 -0
- package/dist/{chunk-4CNJGY7P.js → chunk-3I43W7DP.js} +107 -8
- package/dist/{chunk-MOUWO53S.js → chunk-3OG2674K.js} +1 -1
- package/dist/{chunk-NLXQ7WTH.js → chunk-5JCLZPMV.js} +1 -1
- package/dist/{chunk-LZEX2GAY.js → chunk-CV3QQUMK.js} +27 -1
- package/dist/{chunk-OVV35ZS2.js → chunk-FSEB4LSU.js} +1 -1
- package/dist/{chunk-M665ZQYB.js → chunk-IHXMBXXL.js} +11 -5
- package/dist/{chunk-FSA3UBVR.js → chunk-JWW54N24.js} +1 -1
- package/dist/{chunk-KY3QBG7O.js → chunk-KMDZDH5E.js} +4 -4
- package/dist/{chunk-LO3DH776.js → chunk-MBSQKRDF.js} +1 -1
- package/dist/{chunk-IHWC75AN.js → chunk-QVBUYWW6.js} +1 -1
- package/dist/{chunk-YKXOAGY3.js → chunk-WZ22ZYXD.js} +8 -8
- package/dist/compose.js +20 -20
- package/dist/composition/graphics-plan.js +1 -1
- package/dist/composition/ops.js +3 -3
- package/dist/composition/validators.js +6 -2
- package/dist/composition-ops.js +5 -5
- package/dist/composition.js +6 -2
- package/dist/{context-AIUJG7R4.js → context-2MBCDTCZ.js} +4 -4
- package/dist/core/render.js +3 -1
- package/dist/core.js +1 -1
- 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 +9 -9
- package/dist/mcp.js +9 -9
- package/dist/primitives/effects.js +2 -2
- package/dist/primitives/hero-text.js +2 -2
- package/dist/primitives/scenes.js +2 -2
- package/dist/primitives/text.js +2 -2
- package/dist/primitives/ui-blocks.js +4 -4
- package/dist/primitives.js +20 -20
- package/dist/render-harness.js +7 -7
- package/package.json +10 -10
- package/dist/{chunk-O3SJTX6S.js → chunk-4B4V3HYW.js} +4 -4
- package/dist/{chunk-7SXY6NFW.js → chunk-5ZQLMPDY.js} +3 -3
- 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
|
@@ -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
|
|
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-
|
|
8
|
-
import "../chunk-
|
|
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-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
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-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
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";
|
package/dist/authoring/tools.js
CHANGED
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
COMPOSE_ROLE_TOOLS,
|
|
7
7
|
COMPOSE_ROLE_TOOL_NAMES,
|
|
8
8
|
dispatchComposeRoleTool
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-KMDZDH5E.js";
|
|
10
10
|
import "../chunk-JOURGVOR.js";
|
|
11
11
|
import "../chunk-7AZLFN26.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-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-
|
|
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-
|
|
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-
|
|
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-
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
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
|
|
1301
|
-
const
|
|
1302
|
-
const
|
|
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,
|
|
@@ -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,
|