@clipwright/core 0.33.0 → 0.34.0

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 (119) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/dist/api-failure.js +2 -1
  3. package/dist/api-failure.js.map +1 -1
  4. package/dist/asset-identity.d.ts +6 -0
  5. package/dist/asset-identity.js +7 -0
  6. package/dist/asset-identity.js.map +1 -0
  7. package/dist/assets.d.ts +386 -7
  8. package/dist/assets.js +114 -21
  9. package/dist/assets.js.map +1 -1
  10. package/dist/caption-language.d.ts +2 -0
  11. package/dist/caption-language.js +17 -0
  12. package/dist/caption-language.js.map +1 -0
  13. package/dist/contract-dispositions.d.ts +1133 -8
  14. package/dist/contract-dispositions.js +51 -11
  15. package/dist/contract-dispositions.js.map +1 -1
  16. package/dist/contracts/v1/workflow-brief.d.ts +1670 -2
  17. package/dist/contracts/v1/workflow-catalog.d.ts +1670 -2
  18. package/dist/contracts/v1/workflow-client.d.ts +835 -1
  19. package/dist/contracts/v1/workflow-execution.d.ts +2 -0
  20. package/dist/contracts/v1/workflow-plan.d.ts +2533 -31
  21. package/dist/endpoints.js +2 -0
  22. package/dist/endpoints.js.map +1 -1
  23. package/dist/errors.d.ts +1 -1
  24. package/dist/errors.js +1 -0
  25. package/dist/errors.js.map +1 -1
  26. package/dist/generations.d.ts +32 -6
  27. package/dist/generations.js +83 -27
  28. package/dist/generations.js.map +1 -1
  29. package/dist/index.d.ts +4 -0
  30. package/dist/index.js +4 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/public-endpoints.d.ts +2 -0
  33. package/dist/public-endpoints.js +2 -0
  34. package/dist/public-endpoints.js.map +1 -1
  35. package/dist/resolved-timeline.d.ts +153 -0
  36. package/dist/resolved-timeline.js +46 -0
  37. package/dist/resolved-timeline.js.map +1 -1
  38. package/dist/run-static-warnings.js +5 -2
  39. package/dist/run-static-warnings.js.map +1 -1
  40. package/dist/semantic-inserts.d.ts +7 -0
  41. package/dist/semantic-inserts.js +19 -9
  42. package/dist/semantic-inserts.js.map +1 -1
  43. package/dist/skills.d.ts +4112 -77
  44. package/dist/skills.js +261 -16
  45. package/dist/skills.js.map +1 -1
  46. package/dist/templates/callout.d.ts +34 -0
  47. package/dist/templates/callout.js +51 -0
  48. package/dist/templates/callout.js.map +1 -0
  49. package/dist/templates/checklist.d.ts +42 -0
  50. package/dist/templates/checklist.js +47 -0
  51. package/dist/templates/checklist.js.map +1 -0
  52. package/dist/templates/compare.d.ts +26 -0
  53. package/dist/templates/compare.js +35 -0
  54. package/dist/templates/compare.js.map +1 -0
  55. package/dist/templates/end-card.d.ts +16 -0
  56. package/dist/templates/end-card.js +25 -0
  57. package/dist/templates/end-card.js.map +1 -0
  58. package/dist/templates/index.d.ts +164 -0
  59. package/dist/templates/index.js +382 -0
  60. package/dist/templates/index.js.map +1 -0
  61. package/dist/templates/lower-third.d.ts +18 -0
  62. package/dist/templates/lower-third.js +26 -0
  63. package/dist/templates/lower-third.js.map +1 -0
  64. package/dist/templates/notification.d.ts +30 -0
  65. package/dist/templates/notification.js +32 -0
  66. package/dist/templates/notification.js.map +1 -0
  67. package/dist/templates/phone-call.d.ts +24 -0
  68. package/dist/templates/phone-call.js +36 -0
  69. package/dist/templates/phone-call.js.map +1 -0
  70. package/dist/templates/progress.d.ts +22 -0
  71. package/dist/templates/progress.js +42 -0
  72. package/dist/templates/progress.js.map +1 -0
  73. package/dist/templates/quote.d.ts +21 -0
  74. package/dist/templates/quote.js +29 -0
  75. package/dist/templates/quote.js.map +1 -0
  76. package/dist/templates/rating.d.ts +22 -0
  77. package/dist/templates/rating.js +29 -0
  78. package/dist/templates/rating.js.map +1 -0
  79. package/dist/templates/size.d.ts +13 -0
  80. package/dist/templates/size.js +10 -0
  81. package/dist/templates/size.js.map +1 -0
  82. package/dist/templates/slot.d.ts +10 -0
  83. package/dist/templates/slot.js +5 -0
  84. package/dist/templates/slot.js.map +1 -0
  85. package/dist/templates/sounds.d.ts +351 -0
  86. package/dist/templates/sounds.js +67 -0
  87. package/dist/templates/sounds.js.map +1 -0
  88. package/dist/templates/stat.d.ts +20 -0
  89. package/dist/templates/stat.js +33 -0
  90. package/dist/templates/stat.js.map +1 -0
  91. package/dist/templates/tag.d.ts +23 -0
  92. package/dist/templates/tag.js +31 -0
  93. package/dist/templates/tag.js.map +1 -0
  94. package/dist/templates/theme.d.ts +29 -0
  95. package/dist/templates/theme.js +47 -0
  96. package/dist/templates/theme.js.map +1 -0
  97. package/dist/templates/title-card.d.ts +21 -0
  98. package/dist/templates/title-card.js +30 -0
  99. package/dist/templates/title-card.js.map +1 -0
  100. package/dist/tts-backend.d.ts +9 -0
  101. package/dist/tts-backend.js +21 -0
  102. package/dist/tts-backend.js.map +1 -1
  103. package/dist/ugc-layers.d.ts +84 -0
  104. package/dist/ugc-layers.js +137 -0
  105. package/dist/ugc-layers.js.map +1 -0
  106. package/dist/ugc-video-media.d.ts +12 -0
  107. package/dist/ugc-video-media.js +39 -0
  108. package/dist/ugc-video-media.js.map +1 -0
  109. package/dist/voice-admission.d.ts +835 -1
  110. package/dist/workflows/methods/faceless-explainer.d.ts +329 -2
  111. package/dist/workflows/methods/kinetic-launch.d.ts +329 -2
  112. package/dist/workflows/methods/product-image-story.d.ts +329 -2
  113. package/dist/workflows/methods/shared.d.ts +329 -2
  114. package/dist/workflows/methods/ugc-faq-answer.d.ts +329 -2
  115. package/dist/workflows/methods/ugc-product-intro.d.ts +329 -2
  116. package/dist/workflows/methods/website-proof-demo.d.ts +329 -2
  117. package/dist/workflows/validate.js +14 -9
  118. package/dist/workflows/validate.js.map +1 -1
  119. package/package.json +2 -2
@@ -0,0 +1,67 @@
1
+ import { z } from "zod";
2
+ // Template sounds (#778 S3c): the owner's library of 23.10, one list of names per beat, with his default first in each.
3
+ export const TEMPLATE_SOUND_BEATS = ["click", "toggle", "ring", "answer", "notify", "step", "whoosh", "flash"];
4
+ /** Each beat's names, its default and where it plays; the composition bundles `<beat>__<name>.mp3` for each, and a test keeps the two equal. */
5
+ export const TEMPLATE_SOUNDS = {
6
+ click: { default: "click_mouse", names: ["click_mouse", "click_soft", "click_crisp", "click_light"],
7
+ plays: "a checklist's cursor clicks a row, on each click" },
8
+ toggle: { default: "switch_flip", names: ["switch_flip", "toggle_snap", "switch_heavy", "switch_light"],
9
+ plays: "a checklist row's switch or check box lands, just after each click" },
10
+ ring: { default: "ring_classic", names: ["ring_classic", "ring_marimba", "ring_digital"],
11
+ plays: "a phone_call rings from its pop, repeating, until it is answered" },
12
+ answer: { default: "answer_confirm", names: ["answer_confirm", "answer_open", "answer_pop", "answer_select"],
13
+ plays: "a phone_call is answered, on answer_at" },
14
+ notify: { default: "chime", names: ["chime", "glass_ping", "glass_soft", "bong", "question_ping"], plays: "a notification drops in" },
15
+ step: { default: "drop", names: ["drop", "drop_high", "tick", "pluck", "pluck_bright"], plays: "a progress step fills, and each rating star" },
16
+ whoosh: { default: "whoosh", names: ["whoosh", "whip", "paper_swipe", "sweep"],
17
+ plays: "a full-frame template's wipe or zoom, in and out, and a compare's reveal" },
18
+ flash: { default: "shutter", names: ["shutter", "glitch"], plays: "a full-frame template's flash, on each of its cuts" },
19
+ };
20
+ /** The beats each kind plays over the presenter; a full-frame template adds its transition's beat (see `templateSoundBeats`). */
21
+ export const TEMPLATE_KIND_SOUNDS = {
22
+ checklist: ["click", "toggle"], phone_call: ["ring", "answer"], notification: ["notify"], progress: ["step"], rating: ["step"], compare: ["whoosh"],
23
+ };
24
+ export const DEFAULT_TEMPLATE_SOUNDS = Object.freeze(Object.fromEntries(TEMPLATE_SOUND_BEATS.map(beat => [beat, TEMPLATE_SOUNDS[beat].default])));
25
+ const name = (beat) => z.enum(TEMPLATE_SOUNDS[beat].names, {
26
+ error: issue => `${JSON.stringify(issue.input)} is not a ${beat} sound: use ${TEMPLATE_SOUNDS[beat].names.join(", ")}`,
27
+ }).optional();
28
+ const overrides = z.strictObject({ click: name("click"), toggle: name("toggle"), ring: name("ring"), answer: name("answer"), notify: name("notify"),
29
+ step: name("step"), whoosh: name("whoosh"), flash: name("flash") }, {
30
+ error: issue => (issue.code === "unrecognized_keys" ? `template_sounds has no beat ${issue.keys.join(", ")}: the beats are ${TEMPLATE_SOUND_BEATS.join(", ")}` : undefined),
31
+ });
32
+ /** Why a value cannot be the field, with the beat's path; a union names no branch on its own, so the message does. */
33
+ function soundsRefusal(input) {
34
+ if (input === null || typeof input !== "object" || Array.isArray(input))
35
+ return "template_sounds is false (no sounds) or { beat: name }";
36
+ const issue = overrides.safeParse(input).error?.issues[0];
37
+ // zod 4.6 may surface the unknown-beat issue past the union, so that message carries its own path.
38
+ if (issue?.code === "unrecognized_keys")
39
+ return issue.message;
40
+ return `${["template_sounds", ...(issue?.path ?? []).map(String)].join(".")} ${issue?.message ?? "is invalid"}`;
41
+ }
42
+ export const templateSounds = z.union([z.literal(false), overrides], { error: issue => soundsRefusal(issue.input) })
43
+ .describe("Template sounds: false for none, or { beat: name } over the defaults; list_template_sounds names them.");
44
+ /** The slim MCP field, which keeps tools/list small: any beat and name pass here, and the server checks them strictly (S3 D3). */
45
+ export const mcpTemplateSounds = z.union([z.literal(false), z.record(z.string(), z.string())]).describe(templateSounds.description);
46
+ /** A run's sounds: the defaults with its overrides, or none for `false` (S3c C2, C4). */
47
+ export function templateSoundMap(sounds) {
48
+ return sounds === false ? undefined : { ...DEFAULT_TEMPLATE_SOUNDS, ...sounds };
49
+ }
50
+ /** The beats one template plays: its kind's, and on a full frame its wipe or zoom (whoosh) or flash. */
51
+ export function templateSoundBeats(item) {
52
+ const transition = item.placement !== "full" ? [] : item.transition === "wipe" || item.transition === "zoom" ? ["whoosh"]
53
+ : item.transition === "flash" ? ["flash"] : [];
54
+ return [...new Set([...(TEMPLATE_KIND_SOUNDS[item.kind] ?? []), ...transition])];
55
+ }
56
+ export const TEMPLATE_SOUNDS_PATH = "/v1/template-sounds";
57
+ /** The catalog `GET /v1/template-sounds` and `list_template_sounds` return. */
58
+ export const templateSoundsList = z.strictObject({
59
+ beats: z.array(z.strictObject({ beat: z.enum(TEMPLATE_SOUND_BEATS), default: z.string().min(1), names: z.array(z.string().min(1)).min(1),
60
+ plays: z.string().min(1) })),
61
+ contract_version: z.string().min(1),
62
+ });
63
+ export function listTemplateSounds() {
64
+ return TEMPLATE_SOUND_BEATS.map(beat => ({ beat, default: TEMPLATE_SOUNDS[beat].default, names: [...TEMPLATE_SOUNDS[beat].names],
65
+ plays: TEMPLATE_SOUNDS[beat].plays }));
66
+ }
67
+ //# sourceMappingURL=sounds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sounds.js","sourceRoot":"","sources":["../../src/templates/sounds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import type { TemplateKind } from "./index.js";
3
+ /** The number at medium on a 1080 short side over the presenter; on a full frame it draws 1.6 times larger. */
4
+ export declare const STAT_FONT_PX = 120;
5
+ /** The drawn area is this many number sizes high: the number and its label; the composition reads the size back. */
6
+ export declare const STAT_RECT_EMS = 1.9;
7
+ declare const data: z.ZodObject<{
8
+ value: z.ZodNumber;
9
+ prefix: z.ZodOptional<z.ZodString>;
10
+ suffix: z.ZodOptional<z.ZodString>;
11
+ label: z.ZodOptional<z.ZodString>;
12
+ size: z.ZodOptional<z.ZodEnum<{
13
+ large: "large";
14
+ medium: "medium";
15
+ small: "small";
16
+ }>>;
17
+ }, z.core.$strict>;
18
+ /** A number that counts up from zero to `value`, with an optional prefix, suffix and label under it. */
19
+ export declare const stat: TemplateKind<typeof data>;
20
+ export {};
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import { frameCanvasOf } from "../ugc-layers.js";
3
+ import { sizedScale, templateSize } from "./size.js";
4
+ /** The number at medium on a 1080 short side over the presenter; on a full frame it draws 1.6 times larger. */
5
+ export const STAT_FONT_PX = 120;
6
+ const FULL_SCALE = 1.6;
7
+ /** The drawn area is this many number sizes high: the number and its label; the composition reads the size back. */
8
+ export const STAT_RECT_EMS = 1.9;
9
+ const data = z.object({ value: z.number().min(0).max(999_999_999).multipleOf(0.01), prefix: z.string().min(1).max(6).optional(),
10
+ suffix: z.string().min(1).max(6).optional(), label: z.string().min(1).max(32).optional(), size: templateSize }).strict();
11
+ /** A number that counts up from zero to `value`, with an optional prefix, suffix and label under it. */
12
+ export const stat = {
13
+ kind: "stat",
14
+ kindVersion: 1,
15
+ description: "a number counting up from 0 to value (up to 2 decimals), with prefix and suffix around it and a label under it; " +
16
+ "full fills the frame, over sits at chest level on a card",
17
+ placements: ["full", "over"],
18
+ data,
19
+ text: { prefix: 6, suffix: 6, label: 32 },
20
+ slots: {},
21
+ hidesCaptions: () => false,
22
+ onInserts: false,
23
+ rect: (value, aspectRatio, placement) => {
24
+ const canvas = frameCanvasOf(aspectRatio), { width: w, height: h } = canvas, short = Math.min(w, h);
25
+ const scale = sizedScale(value.size, canvas) * (placement === "full" ? FULL_SCALE : 1);
26
+ const width = Math.round(Math.min(0.9 * w, 1.1 * short * Math.min(scale, 1))), height = Math.round(STAT_RECT_EMS * STAT_FONT_PX * scale);
27
+ // Over the presenter it sits at chest level, as the reference's toggle card (62–80% of the height), off the face.
28
+ const centre = placement === "full" ? 0.5 : 0.71;
29
+ return { left: Math.round((w - width) / 2) / w, top: Math.round(centre * h - height / 2) / h, width: width / w, height: height / h };
30
+ },
31
+ sample: { value: 17, prefix: "$", suffix: "M", label: "raised this year" },
32
+ };
33
+ //# sourceMappingURL=stat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.js","sourceRoot":"","sources":["../../src/templates/stat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import type { TemplateKind } from "./index.js";
3
+ export declare const TAG_POSITIONS: readonly ["top", "center", "bottom"];
4
+ /** The pill's text at medium on a 1080 short side: the reference pill's cap height, about 3.5% of a 9:16 frame. */
5
+ export declare const TAG_FONT_PX = 92;
6
+ /** The footprint is this many font sizes high: the pill and its glow; the composition reads the font back from it. */
7
+ export declare const TAG_RECT_EMS = 1.6;
8
+ declare const data: z.ZodObject<{
9
+ text: z.ZodString;
10
+ position: z.ZodOptional<z.ZodEnum<{
11
+ bottom: "bottom";
12
+ center: "center";
13
+ top: "top";
14
+ }>>;
15
+ size: z.ZodOptional<z.ZodEnum<{
16
+ large: "large";
17
+ medium: "medium";
18
+ small: "small";
19
+ }>>;
20
+ }, z.core.$strict>;
21
+ /** A short gradient pill over the presenter, centred on a caption line or in the caption spot; it may sit on insert frames. */
22
+ export declare const tag: TemplateKind<typeof data>;
23
+ export {};
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { frameCanvasOf } from "../ugc-layers.js";
3
+ import { sizedScale, templateSize } from "./size.js";
4
+ export const TAG_POSITIONS = ["top", "center", "bottom"];
5
+ /** Absent position is the reference's: two thirds down, at chest level, in the caption spot. */
6
+ const CENTRES = { top: 0.22, center: 0.5, bottom: 0.78, caption: 0.66 };
7
+ /** The pill's text at medium on a 1080 short side: the reference pill's cap height, about 3.5% of a 9:16 frame. */
8
+ export const TAG_FONT_PX = 92;
9
+ /** The footprint is this many font sizes high: the pill and its glow; the composition reads the font back from it. */
10
+ export const TAG_RECT_EMS = 1.6;
11
+ const data = z.object({ text: z.string().min(1).max(32), position: z.enum(TAG_POSITIONS).optional(), size: templateSize }).strict();
12
+ /** A short gradient pill over the presenter, centred on a caption line or in the caption spot; it may sit on insert frames. */
13
+ export const tag = {
14
+ kind: "tag",
15
+ kindVersion: 1,
16
+ description: "a short gradient pill over the presenter or an insert; without position it sits in the caption spot and hides captions while it shows",
17
+ placements: ["over"],
18
+ data,
19
+ text: { text: 32 },
20
+ slots: {},
21
+ hidesCaptions: value => value.position === undefined,
22
+ onInserts: true,
23
+ rect: (value, aspectRatio) => {
24
+ const canvas = frameCanvasOf(aspectRatio), { width: w, height: h } = canvas, short = Math.min(w, h), scale = sizedScale(value.size, canvas);
25
+ const width = Math.round(Math.min(0.9 * w, 1.25 * short * scale)), height = Math.round(TAG_RECT_EMS * TAG_FONT_PX * scale);
26
+ return { left: Math.round((w - width) / 2) / w, top: Math.round(CENTRES[value.position ?? "caption"] * h - height / 2) / h, width: width / w,
27
+ height: height / h };
28
+ },
29
+ sample: { text: "sounds natural", position: "center" },
30
+ };
31
+ //# sourceMappingURL=tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/templates/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAClE,gGAAgG;AAChG,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAW,CAAC;AACjF,mHAAmH;AACnH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,sHAAsH;AACtH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAEpI,+HAA+H;AAC/H,MAAM,CAAC,MAAM,GAAG,GAA8B;IAC5C,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,uIAAuI;IACpJ,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,IAAI;IACJ,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IAClB,KAAK,EAAE,EAAE;IACT,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;IACpD,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5I,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,WAAW,GAAG,KAAK,CAAC,CAAC;QAC3H,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC;YAC1I,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE;CACvD,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ /** Looks the composition draws templates in (#778 S3, D8); presets are judged by eye on sheets, only a customer's colour is checked. */
3
+ export declare const TEMPLATE_PRESETS: readonly ["clean_light", "bold_dark", "neon", "paper", "mono"];
4
+ export type TemplatePreset = (typeof TEMPLATE_PRESETS)[number];
5
+ /** The look of a run whose `template_theme` names none; the schema has no default (A8). */
6
+ export declare const DEFAULT_TEMPLATE_PRESET: TemplatePreset;
7
+ /** The colours an accent meets in each look: the text drawn on it, and the grounds it is drawn on as ink. The composition's themes
8
+ * hold the same values; a test keeps them equal. */
9
+ export declare const TEMPLATE_PRESET_SURFACES: Readonly<Record<TemplatePreset, {
10
+ onAccent: string;
11
+ grounds: readonly string[];
12
+ }>>;
13
+ /** Large text needs 3:1 (WCAG 1.4.3); every template text is large. */
14
+ export declare const TEMPLATE_MIN_CONTRAST = 3;
15
+ export declare const templateTheme: z.ZodObject<{
16
+ preset: z.ZodOptional<z.ZodEnum<{
17
+ bold_dark: "bold_dark";
18
+ clean_light: "clean_light";
19
+ mono: "mono";
20
+ neon: "neon";
21
+ paper: "paper";
22
+ }>>;
23
+ accent: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strict>;
25
+ export type TemplateTheme = z.infer<typeof templateTheme>;
26
+ /** The WCAG contrast ratio of two `#RRGGBB` colours. */
27
+ export declare function contrastRatio(a: string, b: string): number;
28
+ /** Why a customer accent cannot be drawn in a look, or nothing: it is refused, never shifted (D8). */
29
+ export declare function templateAccentRefusal(preset: TemplatePreset, accent: string): string | undefined;
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ /** Looks the composition draws templates in (#778 S3, D8); presets are judged by eye on sheets, only a customer's colour is checked. */
3
+ export const TEMPLATE_PRESETS = ["clean_light", "bold_dark", "neon", "paper", "mono"];
4
+ /** The look of a run whose `template_theme` names none; the schema has no default (A8). */
5
+ export const DEFAULT_TEMPLATE_PRESET = "clean_light";
6
+ /** The colours an accent meets in each look: the text drawn on it, and the grounds it is drawn on as ink. The composition's themes
7
+ * hold the same values; a test keeps them equal. */
8
+ export const TEMPLATE_PRESET_SURFACES = {
9
+ clean_light: { onAccent: "#FFFFFF", grounds: ["#FFFFFF", "#EAF1FC", "#D9E7FB"] },
10
+ bold_dark: { onAccent: "#0B0F19", grounds: ["#1F2937", "#0B0F17", "#1C222C"] },
11
+ neon: { onAccent: "#FFFFFF", grounds: ["#0A0E16", "#05070D", "#0A1428"] },
12
+ paper: { onAccent: "#FFFFFF", grounds: ["#FDF8EF", "#F6EFE3", "#EADCC8"] },
13
+ mono: { onAccent: "#FFFFFF", grounds: ["#FFFFFF", "#F4F4F4", "#E2E2E2"] },
14
+ };
15
+ /** Large text needs 3:1 (WCAG 1.4.3); every template text is large. */
16
+ export const TEMPLATE_MIN_CONTRAST = 3;
17
+ export const templateTheme = z.object({
18
+ preset: z.enum(TEMPLATE_PRESETS).optional().describe("clean_light (light cards on our blue gradient), bold_dark (dark cards, a yellow accent), neon (black, " +
19
+ "cyan to blue), paper (warm cream, terracotta) or mono (black and white); omitted is clean_light."),
20
+ accent: z.string().regex(/^#[0-9A-Fa-f]{6}$/, "must be a #RRGGBB hex colour").optional()
21
+ .describe("#RRGGBB in place of the preset's accent: the pills' fill and the accent text. Refused below 3:1 against the colours it meets."),
22
+ }).strict();
23
+ const luminance = (hex) => {
24
+ const [r, g, b] = [1, 3, 5].map(at => Number.parseInt(hex.slice(at, at + 2), 16) / 255)
25
+ .map(channel => (channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4));
26
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
27
+ };
28
+ /** The WCAG contrast ratio of two `#RRGGBB` colours. */
29
+ export function contrastRatio(a, b) {
30
+ const [light, dark] = [luminance(a), luminance(b)].sort((x, y) => y - x);
31
+ return (light + 0.05) / (dark + 0.05);
32
+ }
33
+ /** Why a customer accent cannot be drawn in a look, or nothing: it is refused, never shifted (D8). */
34
+ export function templateAccentRefusal(preset, accent) {
35
+ const { onAccent, grounds } = TEMPLATE_PRESET_SURFACES[preset];
36
+ const worst = [{ against: onAccent, role: `the ${onAccent} text drawn on it` },
37
+ ...grounds.map(ground => ({ against: ground, role: `the ${ground} card or ground it is drawn on` }))]
38
+ .map(entry => ({ ...entry, ratio: contrastRatio(accent, entry.against) })).sort((a, b) => a.ratio - b.ratio)[0];
39
+ if (worst.ratio >= TEMPLATE_MIN_CONTRAST)
40
+ return undefined;
41
+ // Towards the nearest luminance that clears them all: in neon the white text and the dark grounds sit on opposite sides of it.
42
+ const own = luminance(accent), levels = [onAccent, ...grounds].map(luminance);
43
+ const nearest = Array.from({ length: 1001 }, (_, step) => step / 1000).filter(level => levels.every(other => (Math.max(level, other) + 0.05) / (Math.min(level, other) + 0.05) >= TEMPLATE_MIN_CONTRAST)).sort((a, b) => Math.abs(a - own) - Math.abs(b - own))[0];
44
+ return `${accent} reaches ${worst.ratio.toFixed(2)}:1 against ${worst.role} in ${preset}, under the ${TEMPLATE_MIN_CONTRAST}:1 large text needs: ` +
45
+ (nearest === undefined ? "pick another preset" : `pick a ${nearest < own ? "darker" : "lighter"} accent or another preset`);
46
+ }
47
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/templates/theme.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import type { TemplateKind } from "./index.js";
3
+ /** The title at medium on a 1080 short side, as reference frames 1–2 draw the brand on the card. */
4
+ export declare const TITLE_CARD_FONT_PX = 96;
5
+ /** The drawn area is this many title sizes high: the card with two title lines, the gap and the chip; the composition reads the size back. */
6
+ export declare const TITLE_CARD_RECT_EMS = 5;
7
+ declare const data: z.ZodObject<{
8
+ title: z.ZodString;
9
+ chip: z.ZodOptional<z.ZodString>;
10
+ logo: z.ZodOptional<z.ZodObject<{
11
+ asset_id: z.ZodString;
12
+ }, z.core.$strict>>;
13
+ size: z.ZodOptional<z.ZodEnum<{
14
+ large: "large";
15
+ medium: "medium";
16
+ small: "small";
17
+ }>>;
18
+ }, z.core.$strict>;
19
+ /** The hook card of reference frames 1–2: the title on a white card beside an optional logo, a gradient chip under it, on a full frame. */
20
+ export declare const titleCard: TemplateKind<typeof data>;
21
+ export {};
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import { frameCanvasOf } from "../ugc-layers.js";
3
+ import { sizedScale, templateSize } from "./size.js";
4
+ import { templateMedia } from "./slot.js";
5
+ /** The title at medium on a 1080 short side, as reference frames 1–2 draw the brand on the card. */
6
+ export const TITLE_CARD_FONT_PX = 96;
7
+ /** The drawn area is this many title sizes high: the card with two title lines, the gap and the chip; the composition reads the size back. */
8
+ export const TITLE_CARD_RECT_EMS = 5;
9
+ const data = z.object({ title: z.string().min(1).max(48), chip: z.string().min(1).max(32).optional(), logo: templateMedia.optional(),
10
+ size: templateSize }).strict();
11
+ /** The hook card of reference frames 1–2: the title on a white card beside an optional logo, a gradient chip under it, on a full frame. */
12
+ export const titleCard = {
13
+ kind: "title_card",
14
+ kindVersion: 1,
15
+ description: "a full-frame hook card: the title (up to two lines) on a white card beside an optional logo image, and an optional chip under it",
16
+ placements: ["full"],
17
+ data,
18
+ text: { title: 48, chip: 32 },
19
+ slots: { logo: { type: "image" } },
20
+ hidesCaptions: () => true,
21
+ onInserts: false,
22
+ rect: (value, aspectRatio) => {
23
+ const canvas = frameCanvasOf(aspectRatio), { width: w, height: h } = canvas, scale = sizedScale(value.size, canvas);
24
+ // The reference card is 89% of a 1080 width; the drawn area adds a 3% margin on each side.
25
+ const width = Math.round(Math.min(0.95 * w, 1022 * scale)), height = Math.round(TITLE_CARD_RECT_EMS * TITLE_CARD_FONT_PX * scale);
26
+ return { left: Math.round((w - width) / 2) / w, top: Math.round((h > w ? 0.38 : 0.5) * h - height / 2) / h, width: width / w, height: height / h };
27
+ },
28
+ sample: { title: "fonio.ai", chip: "raised $17 million" },
29
+ };
30
+ //# sourceMappingURL=title-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-card.js","sourceRoot":"","sources":["../../src/templates/title-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,oGAAoG;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,8IAA8I;AAC9I,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,QAAQ,EAAE;IAClI,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAEjC,2IAA2I;AAC3I,MAAM,CAAC,MAAM,SAAS,GAA8B;IAClD,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,kIAAkI;IAC/I,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,IAAI;IACJ,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAClC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;IACzB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpH,2FAA2F;QAC3F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,kBAAkB,GAAG,KAAK,CAAC,CAAC;QAClI,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IACrJ,CAAC;IACD,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,oBAAoB,EAAE;CAC1D,CAAC"}
@@ -45,3 +45,12 @@ export interface TtsBackend {
45
45
  /** Joins per-character timings into words, shared by vendors with that format. Whitespace */
46
46
  /** ends a word without joining it; empty words are never produced. */
47
47
  export declare function charTimingsToWords(characters: readonly string[], startTimes: readonly number[], endTimes: readonly number[]): WordTiming[];
48
+ /** One speech model's alignment ends 80 ms past its decoded audio on every measured take (#779), */
49
+ /** fresh and recovered alike; a tail up to this long is the model's, not a timing error. */
50
+ export declare const ALIGNMENT_TAIL_TOLERANCE_SEC = 0.1;
51
+ /** Word ends past the decoded audio pulled back to its end, or null when a word starts at */
52
+ /** or after it or overshoots by more than the tolerance. `clippedSec` is the largest pull. */
53
+ export declare function clampAlignmentTail(words: readonly WordTiming[], durationSec: number): {
54
+ words: WordTiming[];
55
+ clippedSec: number;
56
+ } | null;
@@ -30,4 +30,25 @@ export function charTimingsToWords(characters, startTimes, endTimes) {
30
30
  flush();
31
31
  return words;
32
32
  }
33
+ /** One speech model's alignment ends 80 ms past its decoded audio on every measured take (#779), */
34
+ /** fresh and recovered alike; a tail up to this long is the model's, not a timing error. */
35
+ export const ALIGNMENT_TAIL_TOLERANCE_SEC = 0.1;
36
+ /** Word ends past the decoded audio pulled back to its end, or null when a word starts at */
37
+ /** or after it or overshoots by more than the tolerance. `clippedSec` is the largest pull. */
38
+ export function clampAlignmentTail(words, durationSec) {
39
+ let clippedSec = 0;
40
+ const clamped = [];
41
+ for (const word of words) {
42
+ if (word.endSec <= durationSec) {
43
+ clamped.push({ ...word });
44
+ continue;
45
+ }
46
+ const overshoot = word.endSec - durationSec;
47
+ if (!(word.startSec < durationSec) || overshoot > ALIGNMENT_TAIL_TOLERANCE_SEC + 1e-9)
48
+ return null;
49
+ clippedSec = Math.max(clippedSec, overshoot);
50
+ clamped.push({ ...word, endSec: durationSec });
51
+ }
52
+ return { words: clamped, clippedSec };
53
+ }
33
54
  //# sourceMappingURL=tts-backend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tts-backend.js","sourceRoot":"","sources":["../src/tts-backend.ts"],"names":[],"mappings":"AAsDA,6FAA6F;AAC7F,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAChC,UAA6B,EAC7B,UAA6B,EAC7B,QAA2B;IAE3B,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,qCAAqC,UAAU,CAAC,MAAM,UAAU;YAC9D,GAAG,UAAU,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,OAAO,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACxD,GAAG,GAAG,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAClB,KAAK,EAAE,CAAC;YACR,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,KAAK,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QAClC,CAAC;QACD,GAAG,IAAI,EAAE,CAAC;QACV,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAW,CAAC;IAC9B,CAAC;IACD,KAAK,EAAE,CAAC;IAER,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"tts-backend.js","sourceRoot":"","sources":["../src/tts-backend.ts"],"names":[],"mappings":"AAsDA,6FAA6F;AAC7F,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAChC,UAA6B,EAC7B,UAA6B,EAC7B,QAA2B;IAE3B,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,qCAAqC,UAAU,CAAC,MAAM,UAAU;YAC9D,GAAG,UAAU,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,OAAO,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACxD,GAAG,GAAG,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAClB,KAAK,EAAE,CAAC;YACR,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,KAAK,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QAClC,CAAC;QACD,GAAG,IAAI,EAAE,CAAC;QACV,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAW,CAAC;IAC9B,CAAC;IACD,KAAK,EAAE,CAAC;IAER,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oGAAoG;AACpG,4FAA4F;AAC5F,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD,6FAA6F;AAC7F,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,KAA4B,EAAE,WAAmB;IAElF,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,SAAS,GAAG,4BAA4B,GAAG,IAAI;YAAE,OAAO,IAAI,CAAC;QACnG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,84 @@
1
+ import type { WordTiming } from "./tts-backend.js";
2
+ export declare const OVERLAY_POSITIONS: readonly ["top_left", "top_right", "bottom_left", "bottom_right", "top", "bottom"];
3
+ export type OverlayPosition = (typeof OVERLAY_POSITIONS)[number];
4
+ export declare const LAYER_ENTERS: readonly ["cut", "fade", "slide", "tilt_in"];
5
+ export type LayerEnter = (typeof LAYER_ENTERS)[number];
6
+ export declare const LAYOUT_WINDOW_KINDS: readonly ["split", "card"];
7
+ export type LayoutWindowKind = (typeof LAYOUT_WINDOW_KINDS)[number];
8
+ export declare const INSERT_TRANSITIONS: readonly ["cut", "wipe", "flash", "zoom"];
9
+ export type InsertTransition = (typeof INSERT_TRANSITIONS)[number];
10
+ export declare const MAX_OVERLAYS = 10;
11
+ export declare const MAX_LAYOUT_WINDOWS = 5;
12
+ export declare const MAX_OVERLAYS_AT_ONCE = 2;
13
+ /** A footprint on the frame, in shares of its width and height (#778 S3 D5). */
14
+ export interface LayerRect {
15
+ left: number;
16
+ top: number;
17
+ width: number;
18
+ height: number;
19
+ }
20
+ /** The frame of a `W:H` format in pixels, as the composition's `canvasForRatio` derives it: the short side 1080, both sides even. */
21
+ export declare function frameCanvasOf(aspectRatio: string): {
22
+ width: number;
23
+ height: number;
24
+ };
25
+ /** The most an overlay at `position` takes, as `overlayBox` draws it: a corner 42% wide, a band the width less margins, 30% high. */
26
+ export declare function overlayRect(position: OverlayPosition, canvas: {
27
+ width: number;
28
+ height: number;
29
+ }): LayerRect;
30
+ /** Two footprints collide when they share an area; touching edges do not. */
31
+ export declare function rectsOverlap(a: LayerRect, b: LayerRect): boolean;
32
+ /** Where the presenter's face sits: 12–48% of the height and the middle 60% of a 9:16 clip, which other formats fit whole and centre (#778 S3). */
33
+ export declare function faceZone(aspectRatio: string): LayerRect;
34
+ type WordAnchor = {
35
+ startWord: number;
36
+ endWord: number;
37
+ } | {
38
+ quote: string;
39
+ occurrence?: number | undefined;
40
+ };
41
+ export interface AnchoredItem {
42
+ id: string;
43
+ anchor: WordAnchor;
44
+ cover_words?: number | undefined;
45
+ }
46
+ export interface WordRange {
47
+ startWord: number;
48
+ coverWord: number;
49
+ }
50
+ /** The words an item covers, `[startWord, coverWord)`, as an insert anchor resolves; a string names why it does not resolve. */
51
+ export declare function layerWordRange(tokens: readonly string[], item: AnchoredItem): WordRange | string;
52
+ export interface LayerRefusal {
53
+ path: (string | number)[];
54
+ message: string;
55
+ }
56
+ export interface LayerCheckInput {
57
+ script: string;
58
+ aspect_ratio?: string | undefined;
59
+ inserts?: readonly AnchoredItem[] | undefined;
60
+ overlays?: readonly (AnchoredItem & {
61
+ position: OverlayPosition;
62
+ })[] | undefined;
63
+ layout_windows?: readonly (AnchoredItem & {
64
+ layout: LayoutWindowKind;
65
+ })[] | undefined;
66
+ }
67
+ /** Every refusal of overlays and layout windows against the script, named by path; empty when they render. */
68
+ export declare function layerRefusals(input: LayerCheckInput): LayerRefusal[];
69
+ export interface LayerFrames {
70
+ id: string;
71
+ startFrame: number;
72
+ endFrame: number;
73
+ }
74
+ /** Frames of each word range on the run's narration, by the rule inserts follow: a range ends where its first uncovered word starts. */
75
+ export declare function resolveLayerFrames(input: {
76
+ tokens: readonly string[];
77
+ words: readonly WordTiming[];
78
+ totalFrames: number;
79
+ fps: number;
80
+ layers: readonly (WordRange & {
81
+ id: string;
82
+ })[];
83
+ }): LayerFrames[];
84
+ export {};