@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,137 @@
1
+ import { lexicalTokens, quoteOccurrences } from "./semantic-inserts.js";
2
+ // Overlays and layout windows of a long-form `make_ugc` run (#778 S2b): drawn over the actor slots, never planned as inserts.
3
+ export const OVERLAY_POSITIONS = ["top_left", "top_right", "bottom_left", "bottom_right", "top", "bottom"];
4
+ export const LAYER_ENTERS = ["cut", "fade", "slide", "tilt_in"];
5
+ export const LAYOUT_WINDOW_KINDS = ["split", "card"];
6
+ export const INSERT_TRANSITIONS = ["cut", "wipe", "flash", "zoom"];
7
+ export const MAX_OVERLAYS = 10;
8
+ export const MAX_LAYOUT_WINDOWS = 5;
9
+ export const MAX_OVERLAYS_AT_ONCE = 2;
10
+ /** The frame of a `W:H` format in pixels, as the composition's `canvasForRatio` derives it: the short side 1080, both sides even. */
11
+ export function frameCanvasOf(aspectRatio) {
12
+ const [w, h] = aspectRatio.split(":").map(Number);
13
+ const even = (value) => { const rounded = Math.round(value); return rounded % 2 === 0 ? rounded : rounded + 1; };
14
+ return w >= h ? { width: even((1080 * w) / h), height: 1080 } : { width: 1080, height: even((1080 * h) / w) };
15
+ }
16
+ /** The most an overlay at `position` takes, as `overlayBox` draws it: a corner 42% wide, a band the width less margins, 30% high. */
17
+ export function overlayRect(position, canvas) {
18
+ const margin = Math.round(0.04 * Math.min(canvas.width, canvas.height));
19
+ const band = position === "top" || position === "bottom";
20
+ const width = band ? canvas.width - 2 * margin : Math.round(0.42 * canvas.width), height = Math.round(0.3 * canvas.height);
21
+ const left = band || position.endsWith("left") ? margin : canvas.width - margin - width;
22
+ const top = position.startsWith("top") ? margin : canvas.height - margin - height;
23
+ return { left: left / canvas.width, top: top / canvas.height, width: width / canvas.width, height: height / canvas.height };
24
+ }
25
+ /** Two footprints collide when they share an area; touching edges do not. */
26
+ export function rectsOverlap(a, b) {
27
+ return a.left < b.left + b.width && b.left < a.left + a.width && a.top < b.top + b.height && b.top < a.top + a.height;
28
+ }
29
+ /** 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). */
30
+ export function faceZone(aspectRatio) {
31
+ const { width, height } = frameCanvasOf(aspectRatio);
32
+ const share = 0.6 * Math.min(1, (9 / 16) / (width / height));
33
+ return { left: (1 - share) / 2, top: 0.12, width: share, height: 0.36 };
34
+ }
35
+ /** The words an item covers, `[startWord, coverWord)`, as an insert anchor resolves; a string names why it does not resolve. */
36
+ export function layerWordRange(tokens, item) {
37
+ let range;
38
+ if ("startWord" in item.anchor) {
39
+ range = { startWord: item.anchor.startWord, endWord: item.anchor.endWord };
40
+ if (range.endWord > tokens.length)
41
+ return `anchor ends at word ${range.endWord}, past the script's ${tokens.length} words`;
42
+ }
43
+ else {
44
+ const matches = quoteOccurrences(tokens, item.anchor.quote);
45
+ if (matches.length === 0)
46
+ return `anchor quote "${item.anchor.quote}" does not occur in script`;
47
+ if (item.anchor.occurrence === undefined && matches.length > 1) {
48
+ return `anchor quote "${item.anchor.quote}" occurs ${matches.length} times in script: pass occurrence`;
49
+ }
50
+ const picked = matches[item.anchor.occurrence ?? 0];
51
+ if (!picked)
52
+ return `anchor quote "${item.anchor.quote}" has no occurrence ${item.anchor.occurrence}`;
53
+ range = picked;
54
+ }
55
+ const coverWord = item.cover_words === undefined ? range.endWord : range.startWord + item.cover_words;
56
+ if (coverWord < range.endWord)
57
+ return `cover_words ${item.cover_words} is fewer than the ${range.endWord - range.startWord} words the anchor names`;
58
+ if (coverWord > tokens.length)
59
+ return `cover_words runs past the script's ${tokens.length} words`;
60
+ return { startWord: range.startWord, coverWord };
61
+ }
62
+ const overlaps = (a, b) => a.startWord < b.coverWord && b.startWord < a.coverWord;
63
+ const coveredBy = (range, cover) => Array.from({ length: range.coverWord - range.startWord }, (_, offset) => range.startWord + offset).every(word => cover.some(other => word >= other.startWord && word < other.coverWord));
64
+ /** Every refusal of overlays and layout windows against the script, named by path; empty when they render. */
65
+ export function layerRefusals(input) {
66
+ const refusals = [];
67
+ const tokens = lexicalTokens(input.script);
68
+ const canvas = frameCanvasOf(input.aspect_ratio ?? "9:16");
69
+ const seen = new Map();
70
+ for (const field of ["inserts", "overlays", "layout_windows"]) {
71
+ for (const [index, item] of (input[field] ?? []).entries()) {
72
+ const owner = seen.get(item.id);
73
+ if (owner !== undefined && field !== "inserts") {
74
+ refusals.push({ path: [field, index, "id"], message: `id "${item.id}" is already used in ${owner}: ids are unique across inserts, overlays and layout_windows` });
75
+ }
76
+ seen.set(item.id, owner ?? field);
77
+ }
78
+ }
79
+ const ranged = (field, items) => (items ?? []).flatMap((item, index) => {
80
+ const range = layerWordRange(tokens, item);
81
+ if (typeof range === "string") {
82
+ refusals.push({ path: [field, index, "anchor"], message: `${field === "overlays" ? "overlay" : "layout window"} "${item.id}": ${range}` });
83
+ return [];
84
+ }
85
+ return [{ item, index, range }];
86
+ });
87
+ const overlays = ranged("overlays", input.overlays);
88
+ const windows = ranged("layout_windows", input.layout_windows);
89
+ const inserts = (input.inserts ?? []).flatMap(item => { const range = layerWordRange(tokens, item); return typeof range === "string" ? [] : [{ item, range }]; });
90
+ for (const [at, layout] of windows.entries()) {
91
+ if (layout.item.layout === "split" && input.aspect_ratio !== undefined && input.aspect_ratio !== "9:16") {
92
+ refusals.push({ path: ["layout_windows", layout.index, "layout"], message: `layout window "${layout.item.id}": split works in 9:16 only, and aspect_ratio is ${input.aspect_ratio}` });
93
+ }
94
+ const earlier = windows.slice(0, at).find(other => overlaps(other.range, layout.range));
95
+ if (earlier) {
96
+ refusals.push({ path: ["layout_windows", layout.index], message: `layout window "${layout.item.id}" overlaps layout window "${earlier.item.id}": windows take the frame one at a time` });
97
+ }
98
+ const insert = inserts.find(other => overlaps(other.range, layout.range));
99
+ if (insert) {
100
+ refusals.push({ path: ["layout_windows", layout.index], message: `layout window "${layout.item.id}" overlaps insert "${insert.item.id}": a window reframes the presenter, who is not on screen during a full-frame insert` });
101
+ }
102
+ }
103
+ for (const [at, overlay] of overlays.entries()) {
104
+ const under = inserts.filter(other => overlaps(other.range, overlay.range));
105
+ if (under.length && coveredBy(overlay.range, under.map(other => other.range))) {
106
+ refusals.push({ path: ["overlays", overlay.index], message: `overlay "${overlay.item.id}" lies wholly under insert "${under[0].item.id}": an overlay draws over the presenter, who is not on screen during a full-frame insert` });
107
+ }
108
+ const together = overlays.slice(0, at).filter(other => overlaps(other.range, overlay.range));
109
+ const clash = together.find(other => rectsOverlap(overlayRect(other.item.position, canvas), overlayRect(overlay.item.position, canvas)));
110
+ if (clash) {
111
+ refusals.push({ path: ["overlays", overlay.index, "position"], message: `overlay "${overlay.item.id}" (${overlay.item.position}) shares the screen with overlay "${clash.item.id}" (${clash.item.position}) at the same time: overlays on screen together need different positions` });
112
+ continue;
113
+ }
114
+ const crowd = together.flatMap((a, i) => together.slice(i + 1).filter(b => Math.max(a.range.startWord, b.range.startWord, overlay.range.startWord) <
115
+ Math.min(a.range.coverWord, b.range.coverWord, overlay.range.coverWord)).map(b => [a, b]))[0];
116
+ if (crowd) {
117
+ refusals.push({ path: ["overlays", overlay.index], message: `overlay "${overlay.item.id}" would be on screen together with "${crowd[0].item.id}" and "${crowd[1].item.id}": at most ${MAX_OVERLAYS_AT_ONCE} overlays show at once` });
118
+ }
119
+ }
120
+ return refusals;
121
+ }
122
+ /** Frames of each word range on the run's narration, by the rule inserts follow: a range ends where its first uncovered word starts. */
123
+ export function resolveLayerFrames(input) {
124
+ const lexical = input.words.filter(word => !/^\p{P}+$/u.test(word.word));
125
+ if (lexical.length !== input.tokens.length || lexical.some((word, index) => lexicalTokens(word.word)[0] !== input.tokens[index])) {
126
+ throw new Error("layer word timings do not follow the script's words");
127
+ }
128
+ return input.layers.map(layer => {
129
+ const startFrame = layer.startWord === 0 ? 0 : Math.round(lexical[layer.startWord].startSec * input.fps);
130
+ const endFrame = layer.coverWord >= lexical.length ? input.totalFrames : Math.round(lexical[layer.coverWord].startSec * input.fps);
131
+ if (!Number.isSafeInteger(startFrame) || endFrame <= startFrame || endFrame > input.totalFrames) {
132
+ throw new Error(`layer ${layer.id} has no frames on the narration`);
133
+ }
134
+ return { id: layer.id, startFrame, endFrame };
135
+ });
136
+ }
137
+ //# sourceMappingURL=ugc-layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ugc-layers.js","sourceRoot":"","sources":["../src/ugc-layers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { MakeUgcInput, PinnedInsertAsset } from "./skills.js";
2
+ /** Codecs Remotion's OffthreadVideo decodes with its bundled FFmpeg, locally and on Lambda; asset ingest takes the same two. */
3
+ export declare const MEDIA_VIDEO_CODECS: readonly ["h264", "hevc"];
4
+ export interface VideoSourceFacts {
5
+ codec?: string | null | undefined;
6
+ pixFmt?: string | null | undefined;
7
+ colorTransfer?: string | null | undefined;
8
+ }
9
+ /** Why a video source cannot be drawn, or `null`. A fact that is not known is not refused here; the worker measures it. */
10
+ export declare function videoMediaRefusal(facts: VideoSourceFacts): string | null;
11
+ /** The quote's warning for a pinned video asset the narration may outlast; the slow speech edge gives the longest its words can take. */
12
+ export declare function videoHoldWarnings(input: Pick<MakeUgcInput, "script" | "inserts" | "overlays" | "layout_windows">, pinned: readonly PinnedInsertAsset[] | undefined): string[];
@@ -0,0 +1,39 @@
1
+ import { WORDS_PER_SECOND_MIN } from "./pacing.js";
2
+ import { lexicalTokens } from "./semantic-inserts.js";
3
+ import { layerWordRange } from "./ugc-layers.js";
4
+ // Video media in inserts, overlays and layout windows of a long-form `make_ugc` run (#778 S2c): muted, held on its last frame when short.
5
+ /** Codecs Remotion's OffthreadVideo decodes with its bundled FFmpeg, locally and on Lambda; asset ingest takes the same two. */
6
+ export const MEDIA_VIDEO_CODECS = ["h264", "hevc"];
7
+ const HDR_TRANSFERS = { smpte2084: "PQ", "arib-std-b67": "HLG" };
8
+ /** Why a video source cannot be drawn, or `null`. A fact that is not known is not refused here; the worker measures it. */
9
+ export function videoMediaRefusal(facts) {
10
+ if (facts.codec && !MEDIA_VIDEO_CODECS.includes(facts.codec)) {
11
+ return `is ${facts.codec} video: video media takes H.264 or HEVC; re-encode it as H.264`;
12
+ }
13
+ const depth = facts.pixFmt ? /(9|1[0-6])(le|be)$/.exec(facts.pixFmt)?.[1] : undefined;
14
+ if (depth)
15
+ return `is ${depth}-bit video (${facts.pixFmt}): video media takes 8-bit video; re-encode it as 8-bit H.264 (yuv420p)`;
16
+ const hdr = facts.colorTransfer ? HDR_TRANSFERS[facts.colorTransfer] : undefined;
17
+ if (hdr)
18
+ return `is HDR video (${hdr}, transfer ${facts.colorTransfer}): video media takes SDR video; re-encode it as SDR BT.709`;
19
+ return null;
20
+ }
21
+ const LISTS = [["inserts", "insert"], ["overlays", "overlay"], ["layout_windows", "layout window"]];
22
+ /** The quote's warning for a pinned video asset the narration may outlast; the slow speech edge gives the longest its words can take. */
23
+ export function videoHoldWarnings(input, pinned) {
24
+ if (!pinned?.length || typeof input.script !== "string")
25
+ return [];
26
+ const tokens = lexicalTokens(input.script);
27
+ return LISTS.flatMap(([list, noun]) => (input[list] ?? []).flatMap((item, index) => {
28
+ const asset = pinned.find(one => one.insert_id === item.id);
29
+ if (item.media_type !== "video" || asset?.kind !== "video" || !asset.duration_frames || !asset.fps)
30
+ return [];
31
+ const range = layerWordRange(tokens, item);
32
+ if (typeof range === "string")
33
+ return [];
34
+ const words = range.coverWord - range.startWord, clipSec = asset.duration_frames / asset.fps, longestSec = words / WORDS_PER_SECOND_MIN;
35
+ return clipSec < longestSec ? [`${list}[${index}] ${noun} ${item.id}: its video asset runs ${clipSec.toFixed(1)} s, and the ${words} words ` +
36
+ `it covers can take up to ${longestSec.toFixed(1)} s; if the narration outlasts the clip, its last frame holds to the end`] : [];
37
+ }));
38
+ }
39
+ //# sourceMappingURL=ugc-video-media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ugc-video-media.js","sourceRoot":"","sources":["../src/ugc-video-media.ts"],"names":[],"mappings":"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"}