@contractspec/lib.video-gen 2.7.17 → 2.7.19

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 (127) hide show
  1. package/dist/browser/compositions/api-overview.js +1 -645
  2. package/dist/browser/compositions/index.js +1 -1133
  3. package/dist/browser/compositions/primitives/animated-text.js +1 -144
  4. package/dist/browser/compositions/primitives/brand-frame.js +1 -181
  5. package/dist/browser/compositions/primitives/code-block.js +1 -226
  6. package/dist/browser/compositions/primitives/index.js +1 -656
  7. package/dist/browser/compositions/primitives/progress-bar.js +1 -59
  8. package/dist/browser/compositions/primitives/terminal.js +1 -265
  9. package/dist/browser/compositions/primitives/transition.js +1 -98
  10. package/dist/browser/compositions/social-clip.js +1 -500
  11. package/dist/browser/compositions/terminal-demo.js +1 -558
  12. package/dist/browser/design/index.js +1 -155
  13. package/dist/browser/design/layouts.js +1 -50
  14. package/dist/browser/design/motion.js +1 -43
  15. package/dist/browser/design/tokens.js +1 -28
  16. package/dist/browser/design/typography.js +1 -61
  17. package/dist/browser/docs/compositions.docblock.js +1 -182
  18. package/dist/browser/docs/design.docblock.js +2 -17
  19. package/dist/browser/docs/generators.docblock.js +2 -24
  20. package/dist/browser/docs/rendering.docblock.js +2 -24
  21. package/dist/browser/docs/video-gen.docblock.js +2 -17
  22. package/dist/browser/generators/index.js +7 -769
  23. package/dist/browser/generators/scene-planner.js +7 -651
  24. package/dist/browser/generators/script-generator.js +7 -599
  25. package/dist/browser/generators/video-generator.js +7 -768
  26. package/dist/browser/i18n/catalogs/en.js +3 -135
  27. package/dist/browser/i18n/catalogs/es.js +3 -135
  28. package/dist/browser/i18n/catalogs/fr.js +3 -135
  29. package/dist/browser/i18n/catalogs/index.js +7 -387
  30. package/dist/browser/i18n/index.js +7 -459
  31. package/dist/browser/i18n/keys.js +1 -54
  32. package/dist/browser/i18n/locale.js +1 -21
  33. package/dist/browser/i18n/messages.js +7 -399
  34. package/dist/browser/index.js +7 -1903
  35. package/dist/browser/player/demo-player.js +1 -1136
  36. package/dist/browser/player/index.js +1 -1136
  37. package/dist/browser/remotion/Root.js +2 -1172
  38. package/dist/browser/remotion/index.js +2 -1173
  39. package/dist/browser/renderers/config.js +1 -40
  40. package/dist/browser/renderers/index.js +1 -160
  41. package/dist/browser/renderers/local.js +1 -156
  42. package/dist/browser/types.js +1 -13
  43. package/dist/compositions/api-overview.js +1 -639
  44. package/dist/compositions/index.js +1 -1127
  45. package/dist/compositions/primitives/animated-text.js +1 -138
  46. package/dist/compositions/primitives/brand-frame.js +1 -175
  47. package/dist/compositions/primitives/code-block.js +1 -220
  48. package/dist/compositions/primitives/index.js +1 -650
  49. package/dist/compositions/primitives/progress-bar.js +1 -53
  50. package/dist/compositions/primitives/terminal.js +1 -259
  51. package/dist/compositions/primitives/transition.js +1 -92
  52. package/dist/compositions/social-clip.js +1 -494
  53. package/dist/compositions/terminal-demo.js +1 -552
  54. package/dist/design/index.js +1 -149
  55. package/dist/design/layouts.js +1 -44
  56. package/dist/design/motion.js +1 -37
  57. package/dist/design/tokens.js +1 -22
  58. package/dist/design/typography.js +1 -55
  59. package/dist/docs/compositions.docblock.js +1 -182
  60. package/dist/docs/design.docblock.js +2 -17
  61. package/dist/docs/generators.docblock.js +2 -24
  62. package/dist/docs/rendering.docblock.js +2 -24
  63. package/dist/docs/video-gen.docblock.js +2 -17
  64. package/dist/generators/index.js +7 -763
  65. package/dist/generators/scene-planner.js +7 -645
  66. package/dist/generators/script-generator.js +7 -593
  67. package/dist/generators/video-generator.js +7 -762
  68. package/dist/i18n/catalogs/en.js +3 -129
  69. package/dist/i18n/catalogs/es.js +3 -129
  70. package/dist/i18n/catalogs/fr.js +3 -129
  71. package/dist/i18n/catalogs/index.js +7 -381
  72. package/dist/i18n/index.js +7 -453
  73. package/dist/i18n/keys.js +1 -48
  74. package/dist/i18n/locale.js +1 -15
  75. package/dist/i18n/messages.js +7 -393
  76. package/dist/index.js +7 -1897
  77. package/dist/node/compositions/api-overview.js +1 -640
  78. package/dist/node/compositions/index.js +1 -1128
  79. package/dist/node/compositions/primitives/animated-text.js +1 -139
  80. package/dist/node/compositions/primitives/brand-frame.js +1 -176
  81. package/dist/node/compositions/primitives/code-block.js +1 -221
  82. package/dist/node/compositions/primitives/index.js +1 -651
  83. package/dist/node/compositions/primitives/progress-bar.js +1 -54
  84. package/dist/node/compositions/primitives/terminal.js +1 -260
  85. package/dist/node/compositions/primitives/transition.js +1 -93
  86. package/dist/node/compositions/social-clip.js +1 -495
  87. package/dist/node/compositions/terminal-demo.js +1 -553
  88. package/dist/node/design/index.js +1 -150
  89. package/dist/node/design/layouts.js +1 -45
  90. package/dist/node/design/motion.js +1 -38
  91. package/dist/node/design/tokens.js +1 -23
  92. package/dist/node/design/typography.js +1 -56
  93. package/dist/node/docs/compositions.docblock.js +1 -182
  94. package/dist/node/docs/design.docblock.js +2 -17
  95. package/dist/node/docs/generators.docblock.js +2 -24
  96. package/dist/node/docs/rendering.docblock.js +2 -24
  97. package/dist/node/docs/video-gen.docblock.js +2 -17
  98. package/dist/node/generators/index.js +7 -764
  99. package/dist/node/generators/scene-planner.js +7 -646
  100. package/dist/node/generators/script-generator.js +7 -594
  101. package/dist/node/generators/video-generator.js +7 -763
  102. package/dist/node/i18n/catalogs/en.js +3 -130
  103. package/dist/node/i18n/catalogs/es.js +3 -130
  104. package/dist/node/i18n/catalogs/fr.js +3 -130
  105. package/dist/node/i18n/catalogs/index.js +7 -382
  106. package/dist/node/i18n/index.js +7 -454
  107. package/dist/node/i18n/keys.js +1 -49
  108. package/dist/node/i18n/locale.js +1 -16
  109. package/dist/node/i18n/messages.js +7 -394
  110. package/dist/node/index.js +7 -1898
  111. package/dist/node/player/demo-player.js +1 -1131
  112. package/dist/node/player/index.js +1 -1131
  113. package/dist/node/remotion/Root.js +2 -1167
  114. package/dist/node/remotion/index.js +2 -1168
  115. package/dist/node/renderers/config.js +1 -35
  116. package/dist/node/renderers/index.js +1 -155
  117. package/dist/node/renderers/local.js +1 -151
  118. package/dist/node/types.js +1 -8
  119. package/dist/player/demo-player.js +1 -1130
  120. package/dist/player/index.js +1 -1130
  121. package/dist/remotion/Root.js +2 -1166
  122. package/dist/remotion/index.js +2 -1167
  123. package/dist/renderers/config.js +1 -34
  124. package/dist/renderers/index.js +1 -154
  125. package/dist/renderers/local.js +1 -150
  126. package/dist/types.js +1 -7
  127. package/package.json +16 -16
@@ -1,1136 +1,4 @@
1
- import { createRequire } from "node:module";
2
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
-
4
- // src/design/motion.ts
5
- import { Easing } from "remotion";
6
- var videoEasing = {
7
- entrance: Easing.out(Easing.exp),
8
- exit: Easing.in(Easing.exp),
9
- emphasis: Easing.out(Easing.back(1.4)),
10
- linear: Easing.linear,
11
- gentle: Easing.bezier(0.25, 0.1, 0.25, 1),
12
- spring: Easing.out(Easing.back(1.7))
13
- };
14
- var videoDurations = {
15
- sceneTransition: 20,
16
- textEntrance: 15,
17
- textExit: 12,
18
- codeTypingPerChar: 2,
19
- sectionPause: 30,
20
- emphasisPause: 15,
21
- brandReveal: 25,
22
- minScene: 60,
23
- shortScene: 60,
24
- mediumScene: 120,
25
- longScene: 240
26
- };
27
- var videoTransitions = {
28
- fade: { type: "fade", durationInFrames: 20 },
29
- slideLeft: { type: "slide-left", durationInFrames: 20 },
30
- slideRight: { type: "slide-right", durationInFrames: 20 },
31
- wipe: { type: "wipe", durationInFrames: 15 },
32
- none: { type: "none", durationInFrames: 0 }
33
- };
34
-
35
- // src/design/tokens.ts
36
- import { defaultTokens } from "@contractspec/lib.design-system";
37
- var defaultVideoColors = {
38
- canvasBackground: defaultTokens.colors.background,
39
- codeBackground: "#1e1e2e",
40
- terminalBackground: "#0d1117",
41
- terminalForeground: "#c9d1d9",
42
- highlight: defaultTokens.colors.accent,
43
- gradientStart: defaultTokens.colors.primary,
44
- gradientEnd: defaultTokens.colors.accent
45
- };
46
- var defaultVideoTheme = {
47
- ...defaultTokens,
48
- video: defaultVideoColors
49
- };
50
-
51
- // src/design/typography.ts
52
- var videoTypography = {
53
- title: {
54
- fontSize: 72,
55
- lineHeight: 1.1,
56
- fontWeight: 700,
57
- letterSpacing: -1
58
- },
59
- heading: {
60
- fontSize: 56,
61
- lineHeight: 1.2,
62
- fontWeight: 600,
63
- letterSpacing: -0.5
64
- },
65
- subheading: {
66
- fontSize: 40,
67
- lineHeight: 1.25,
68
- fontWeight: 500
69
- },
70
- body: {
71
- fontSize: 32,
72
- lineHeight: 1.5,
73
- fontWeight: 400
74
- },
75
- code: {
76
- fontSize: 28,
77
- lineHeight: 1.6,
78
- fontWeight: 400
79
- },
80
- caption: {
81
- fontSize: 24,
82
- lineHeight: 1.4,
83
- fontWeight: 400
84
- },
85
- label: {
86
- fontSize: 20,
87
- lineHeight: 1.3,
88
- fontWeight: 600,
89
- letterSpacing: 1
90
- }
91
- };
92
- function scaleTypography(style, targetWidth) {
93
- const scale = targetWidth / 1920;
94
- return {
95
- ...style,
96
- fontSize: Math.round(style.fontSize * scale),
97
- letterSpacing: style.letterSpacing ? Math.round(style.letterSpacing * scale * 10) / 10 : undefined
98
- };
99
- }
100
-
101
- // src/compositions/primitives/animated-text.tsx
102
- import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
103
- import { jsxDEV } from "react/jsx-dev-runtime";
104
- var AnimatedText = ({
105
- text,
106
- variant = "body",
107
- style: styleOverride,
108
- enterAt = 0,
109
- exitAt,
110
- color = "#ffffff",
111
- align = "left"
112
- }) => {
113
- const frame = useCurrentFrame();
114
- const { width } = useVideoConfig();
115
- const baseStyle = videoTypography[variant];
116
- const scaled = scaleTypography(baseStyle, width);
117
- const finalStyle = { ...scaled, ...styleOverride };
118
- const enterProgress = interpolate(frame, [enterAt, enterAt + videoDurations.textEntrance], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
119
- const enterOpacity = interpolate(enterProgress, [0, 1], [0, 1], {
120
- easing: videoEasing.entrance
121
- });
122
- const enterTranslateY = interpolate(enterProgress, [0, 1], [30, 0], {
123
- easing: videoEasing.entrance
124
- });
125
- let exitOpacity = 1;
126
- let exitTranslateY = 0;
127
- if (exitAt !== undefined) {
128
- const exitProgress = interpolate(frame, [exitAt, exitAt + videoDurations.textExit], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
129
- exitOpacity = interpolate(exitProgress, [0, 1], [1, 0], {
130
- easing: videoEasing.exit
131
- });
132
- exitTranslateY = interpolate(exitProgress, [0, 1], [0, -20], {
133
- easing: videoEasing.exit
134
- });
135
- }
136
- const opacity = enterOpacity * exitOpacity;
137
- const translateY = enterTranslateY + exitTranslateY;
138
- return /* @__PURE__ */ jsxDEV("div", {
139
- style: {
140
- fontSize: finalStyle.fontSize,
141
- lineHeight: finalStyle.lineHeight,
142
- fontWeight: finalStyle.fontWeight,
143
- letterSpacing: finalStyle.letterSpacing,
144
- color,
145
- textAlign: align,
146
- opacity,
147
- transform: `translateY(${translateY}px)`,
148
- willChange: "opacity, transform"
149
- },
150
- children: text
151
- }, undefined, false, undefined, this);
152
- };
153
-
154
- // src/design/layouts.ts
155
- import { VIDEO_FORMATS } from "@contractspec/lib.contracts-integrations/integrations/providers/video";
156
- var DEFAULT_FPS = 30;
157
- var videoSafeZone = {
158
- horizontal: 120,
159
- vertical: 80,
160
- contentWidth: 1680,
161
- contentHeight: 920
162
- };
163
- function scaleSafeZone(format) {
164
- const scaleX = format.width / 1920;
165
- const scaleY = format.height / 1080;
166
- return {
167
- horizontal: Math.round(videoSafeZone.horizontal * scaleX),
168
- vertical: Math.round(videoSafeZone.vertical * scaleY),
169
- contentWidth: Math.round(videoSafeZone.contentWidth * scaleX),
170
- contentHeight: Math.round(videoSafeZone.contentHeight * scaleY)
171
- };
172
- }
173
- var videoPositions = {
174
- center: { x: 960, y: 540 },
175
- topLeft: { x: 120, y: 80 },
176
- topRight: { x: 1800, y: 80 },
177
- bottomLeft: { x: 120, y: 1000 },
178
- bottomRight: { x: 1800, y: 1000 },
179
- bottomCenter: { x: 960, y: 960 }
180
- };
181
- function getAllFormatVariants() {
182
- return [
183
- VIDEO_FORMATS.landscape,
184
- VIDEO_FORMATS.square,
185
- VIDEO_FORMATS.portrait
186
- ];
187
- }
188
-
189
- // src/compositions/primitives/brand-frame.tsx
190
- import { interpolate as interpolate2, useCurrentFrame as useCurrentFrame2, useVideoConfig as useVideoConfig2 } from "remotion";
191
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
192
- var BrandFrame = ({
193
- styleOverrides,
194
- showBranding = true,
195
- animateEntrance = true,
196
- variant = "gradient",
197
- children
198
- }) => {
199
- const frame = useCurrentFrame2();
200
- const { width, height } = useVideoConfig2();
201
- const theme = defaultVideoTheme;
202
- const safeZone = scaleSafeZone({ type: "custom", width, height });
203
- const primaryColor = styleOverrides?.primaryColor ?? theme.colors.primary;
204
- const _accentColor = styleOverrides?.accentColor ?? theme.colors.accent;
205
- const isDark = styleOverrides?.darkMode ?? true;
206
- let background;
207
- switch (variant) {
208
- case "solid":
209
- background = isDark ? "#0a0a0a" : theme.colors.background;
210
- break;
211
- case "gradient":
212
- background = isDark ? `linear-gradient(135deg, #0a0a14 0%, #0f172a 50%, #0a0a14 100%)` : `linear-gradient(135deg, ${theme.colors.background} 0%, ${theme.colors.muted} 100%)`;
213
- break;
214
- case "dark":
215
- background = "#000000";
216
- break;
217
- }
218
- const entranceOpacity = animateEntrance ? interpolate2(frame, [0, 15], [0, 1], {
219
- extrapolateLeft: "clamp",
220
- extrapolateRight: "clamp",
221
- easing: videoEasing.entrance
222
- }) : 1;
223
- const brandOpacity = showBranding ? interpolate2(frame, [videoDurations.brandReveal, videoDurations.brandReveal + 15], [0, 0.3], {
224
- extrapolateLeft: "clamp",
225
- extrapolateRight: "clamp"
226
- }) : 0;
227
- return /* @__PURE__ */ jsxDEV2("div", {
228
- style: {
229
- width,
230
- height,
231
- background,
232
- position: "relative",
233
- overflow: "hidden",
234
- opacity: entranceOpacity
235
- },
236
- children: [
237
- variant === "gradient" && /* @__PURE__ */ jsxDEV2("div", {
238
- style: {
239
- position: "absolute",
240
- top: "-20%",
241
- right: "-10%",
242
- width: "50%",
243
- height: "50%",
244
- background: `radial-gradient(circle, ${primaryColor}15 0%, transparent 70%)`,
245
- borderRadius: "50%",
246
- pointerEvents: "none"
247
- }
248
- }, undefined, false, undefined, this),
249
- /* @__PURE__ */ jsxDEV2("div", {
250
- style: {
251
- position: "absolute",
252
- left: safeZone.horizontal,
253
- top: safeZone.vertical,
254
- width: safeZone.contentWidth,
255
- height: safeZone.contentHeight,
256
- display: "flex",
257
- flexDirection: "column"
258
- },
259
- children
260
- }, undefined, false, undefined, this),
261
- showBranding && /* @__PURE__ */ jsxDEV2("div", {
262
- style: {
263
- position: "absolute",
264
- bottom: safeZone.vertical / 2,
265
- right: safeZone.horizontal,
266
- opacity: brandOpacity,
267
- color: isDark ? "#ffffff" : "#000000",
268
- fontSize: Math.round(16 * (width / 1920)),
269
- fontWeight: 500,
270
- letterSpacing: 1
271
- },
272
- children: "ContractSpec"
273
- }, undefined, false, undefined, this)
274
- ]
275
- }, undefined, true, undefined, this);
276
- };
277
-
278
- // src/compositions/primitives/code-block.tsx
279
- import { interpolate as interpolate3, useCurrentFrame as useCurrentFrame3, useVideoConfig as useVideoConfig3 } from "remotion";
280
- import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
281
- var CodeBlock = ({
282
- code,
283
- language = "typescript",
284
- startAt = 0,
285
- typeAnimation = true,
286
- backgroundColor = defaultVideoColors.codeBackground,
287
- textColor = "#abb2bf",
288
- filename
289
- }) => {
290
- const frame = useCurrentFrame3();
291
- const { width } = useVideoConfig3();
292
- const codeStyle = scaleTypography(videoTypography.code, width);
293
- const totalChars = code.length;
294
- const typingDuration = totalChars * videoDurations.codeTypingPerChar;
295
- const charsVisible = typeAnimation ? Math.floor(interpolate3(frame, [startAt, startAt + typingDuration], [0, totalChars], {
296
- extrapolateLeft: "clamp",
297
- extrapolateRight: "clamp"
298
- })) : totalChars;
299
- const visibleCode = code.slice(0, charsVisible);
300
- const opacity = interpolate3(frame, [startAt, startAt + 10], [0, 1], {
301
- extrapolateLeft: "clamp",
302
- extrapolateRight: "clamp",
303
- easing: videoEasing.entrance
304
- });
305
- const showCursor = typeAnimation && charsVisible < totalChars && frame % 16 < 10;
306
- return /* @__PURE__ */ jsxDEV3("div", {
307
- style: {
308
- backgroundColor,
309
- borderRadius: 16,
310
- padding: 0,
311
- opacity,
312
- overflow: "hidden",
313
- boxShadow: "0 8px 32px rgba(0,0,0,0.3)"
314
- },
315
- children: [
316
- /* @__PURE__ */ jsxDEV3("div", {
317
- style: {
318
- display: "flex",
319
- alignItems: "center",
320
- padding: "12px 20px",
321
- backgroundColor: "rgba(0,0,0,0.2)",
322
- gap: 8
323
- },
324
- children: [
325
- /* @__PURE__ */ jsxDEV3("div", {
326
- style: { display: "flex", gap: 8 },
327
- children: [
328
- /* @__PURE__ */ jsxDEV3("div", {
329
- style: {
330
- width: 12,
331
- height: 12,
332
- borderRadius: "50%",
333
- backgroundColor: "#ff5f57"
334
- }
335
- }, undefined, false, undefined, this),
336
- /* @__PURE__ */ jsxDEV3("div", {
337
- style: {
338
- width: 12,
339
- height: 12,
340
- borderRadius: "50%",
341
- backgroundColor: "#febc2e"
342
- }
343
- }, undefined, false, undefined, this),
344
- /* @__PURE__ */ jsxDEV3("div", {
345
- style: {
346
- width: 12,
347
- height: 12,
348
- borderRadius: "50%",
349
- backgroundColor: "#28c840"
350
- }
351
- }, undefined, false, undefined, this)
352
- ]
353
- }, undefined, true, undefined, this),
354
- /* @__PURE__ */ jsxDEV3("div", {
355
- style: {
356
- flex: 1,
357
- textAlign: "center",
358
- color: "#666",
359
- fontSize: codeStyle.fontSize * 0.7,
360
- fontFamily: "monospace"
361
- },
362
- children: filename ?? language
363
- }, undefined, false, undefined, this)
364
- ]
365
- }, undefined, true, undefined, this),
366
- /* @__PURE__ */ jsxDEV3("div", {
367
- style: { padding: "24px 32px" },
368
- children: /* @__PURE__ */ jsxDEV3("pre", {
369
- style: {
370
- margin: 0,
371
- fontFamily: "'SF Mono', 'Fira Code', 'JetBrains Mono', monospace",
372
- fontSize: codeStyle.fontSize,
373
- lineHeight: codeStyle.lineHeight,
374
- color: textColor,
375
- whiteSpace: "pre-wrap",
376
- wordBreak: "break-word"
377
- },
378
- children: [
379
- visibleCode,
380
- showCursor && /* @__PURE__ */ jsxDEV3("span", {
381
- style: {
382
- backgroundColor: textColor,
383
- width: "2px",
384
- display: "inline-block",
385
- height: "1.2em",
386
- verticalAlign: "text-bottom"
387
- },
388
- children: " "
389
- }, undefined, false, undefined, this)
390
- ]
391
- }, undefined, true, undefined, this)
392
- }, undefined, false, undefined, this)
393
- ]
394
- }, undefined, true, undefined, this);
395
- };
396
-
397
- // src/compositions/primitives/progress-bar.tsx
398
- import { useCurrentFrame as useCurrentFrame4, useVideoConfig as useVideoConfig4 } from "remotion";
399
- import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
400
- var ProgressBar = ({
401
- height = 4,
402
- color = defaultVideoTheme.colors.primary,
403
- backgroundColor = "rgba(255,255,255,0.1)",
404
- position = "bottom"
405
- }) => {
406
- const frame = useCurrentFrame4();
407
- const { durationInFrames, width } = useVideoConfig4();
408
- const progress = frame / durationInFrames;
409
- return /* @__PURE__ */ jsxDEV4("div", {
410
- style: {
411
- position: "absolute",
412
- [position]: 0,
413
- left: 0,
414
- width,
415
- height,
416
- backgroundColor,
417
- zIndex: 100
418
- },
419
- children: /* @__PURE__ */ jsxDEV4("div", {
420
- style: {
421
- width: `${progress * 100}%`,
422
- height: "100%",
423
- backgroundColor: color,
424
- transition: "none"
425
- }
426
- }, undefined, false, undefined, this)
427
- }, undefined, false, undefined, this);
428
- };
429
-
430
- // src/compositions/api-overview.tsx
431
- import {
432
- AbsoluteFill,
433
- interpolate as interpolate4,
434
- Sequence,
435
- useCurrentFrame as useCurrentFrame5,
436
- useVideoConfig as useVideoConfig5
437
- } from "remotion";
438
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
439
- var ApiOverview = ({
440
- specName,
441
- method = "POST",
442
- endpoint = "/api/users",
443
- specCode,
444
- generatedOutputs = [
445
- "REST Endpoint",
446
- "GraphQL Mutation",
447
- "Prisma Model",
448
- "TypeScript SDK",
449
- "MCP Tool",
450
- "OpenAPI Spec"
451
- ],
452
- tagline = "One spec. Every surface."
453
- }) => {
454
- const { durationInFrames } = useVideoConfig5();
455
- const theme = defaultVideoTheme;
456
- const INTRO_END = 60;
457
- const CODE_START = 45;
458
- const CODE_END = INTRO_END + 150;
459
- const OUTPUTS_START = CODE_END - 30;
460
- const TAGLINE_START = durationInFrames - 90;
461
- return /* @__PURE__ */ jsxDEV5(AbsoluteFill, {
462
- children: [
463
- /* @__PURE__ */ jsxDEV5(BrandFrame, {
464
- variant: "gradient",
465
- showBranding: true,
466
- children: [
467
- /* @__PURE__ */ jsxDEV5(Sequence, {
468
- from: 0,
469
- durationInFrames: CODE_END,
470
- children: /* @__PURE__ */ jsxDEV5("div", {
471
- style: {
472
- flex: 1,
473
- display: "flex",
474
- flexDirection: "column",
475
- gap: 16
476
- },
477
- children: [
478
- /* @__PURE__ */ jsxDEV5("div", {
479
- style: { display: "flex", alignItems: "center", gap: 16 },
480
- children: [
481
- /* @__PURE__ */ jsxDEV5(MethodBadge, {
482
- method,
483
- enterAt: 10
484
- }, undefined, false, undefined, this),
485
- /* @__PURE__ */ jsxDEV5(AnimatedText, {
486
- text: endpoint,
487
- variant: "subheading",
488
- enterAt: 15,
489
- color: theme.colors.mutedForeground
490
- }, undefined, false, undefined, this)
491
- ]
492
- }, undefined, true, undefined, this),
493
- /* @__PURE__ */ jsxDEV5(AnimatedText, {
494
- text: specName,
495
- variant: "title",
496
- enterAt: 5,
497
- color: "#ffffff"
498
- }, undefined, false, undefined, this),
499
- /* @__PURE__ */ jsxDEV5("div", {
500
- style: { flex: 1, marginTop: 24 },
501
- children: /* @__PURE__ */ jsxDEV5(CodeBlock, {
502
- code: specCode,
503
- language: "typescript",
504
- filename: `${specName.toLowerCase()}.contract.ts`,
505
- startAt: CODE_START,
506
- typeAnimation: true
507
- }, undefined, false, undefined, this)
508
- }, undefined, false, undefined, this)
509
- ]
510
- }, undefined, true, undefined, this)
511
- }, undefined, false, undefined, this),
512
- /* @__PURE__ */ jsxDEV5(Sequence, {
513
- from: OUTPUTS_START,
514
- durationInFrames: durationInFrames - OUTPUTS_START,
515
- children: /* @__PURE__ */ jsxDEV5("div", {
516
- style: {
517
- flex: 1,
518
- display: "flex",
519
- flexDirection: "column",
520
- justifyContent: "center",
521
- alignItems: "center",
522
- gap: 24
523
- },
524
- children: [
525
- /* @__PURE__ */ jsxDEV5(AnimatedText, {
526
- text: "Generates:",
527
- variant: "heading",
528
- enterAt: 0,
529
- color: "#ffffff",
530
- align: "center"
531
- }, undefined, false, undefined, this),
532
- /* @__PURE__ */ jsxDEV5("div", {
533
- style: {
534
- display: "flex",
535
- flexWrap: "wrap",
536
- gap: 16,
537
- justifyContent: "center",
538
- maxWidth: "80%",
539
- marginTop: 32
540
- },
541
- children: generatedOutputs.map((output, i) => /* @__PURE__ */ jsxDEV5(OutputChip, {
542
- label: output,
543
- index: i,
544
- startFrame: 20 + i * 8
545
- }, output, false, undefined, this))
546
- }, undefined, false, undefined, this),
547
- /* @__PURE__ */ jsxDEV5(Sequence, {
548
- from: TAGLINE_START - OUTPUTS_START,
549
- children: /* @__PURE__ */ jsxDEV5("div", {
550
- style: { marginTop: 48 },
551
- children: /* @__PURE__ */ jsxDEV5(AnimatedText, {
552
- text: tagline,
553
- variant: "heading",
554
- enterAt: 0,
555
- color: theme.colors.accent,
556
- align: "center"
557
- }, undefined, false, undefined, this)
558
- }, undefined, false, undefined, this)
559
- }, undefined, false, undefined, this)
560
- ]
561
- }, undefined, true, undefined, this)
562
- }, undefined, false, undefined, this)
563
- ]
564
- }, undefined, true, undefined, this),
565
- /* @__PURE__ */ jsxDEV5(ProgressBar, {}, undefined, false, undefined, this)
566
- ]
567
- }, undefined, true, undefined, this);
568
- };
569
- var MethodBadge = ({
570
- method,
571
- enterAt
572
- }) => {
573
- const frame = useCurrentFrame5();
574
- const opacity = interpolate4(frame, [enterAt, enterAt + 10], [0, 1], {
575
- extrapolateLeft: "clamp",
576
- extrapolateRight: "clamp",
577
- easing: videoEasing.entrance
578
- });
579
- const scale = interpolate4(frame, [enterAt, enterAt + 12], [0.8, 1], {
580
- extrapolateLeft: "clamp",
581
- extrapolateRight: "clamp",
582
- easing: videoEasing.emphasis
583
- });
584
- const methodColors = {
585
- GET: "#61afef",
586
- POST: "#98c379",
587
- PUT: "#e5c07b",
588
- PATCH: "#d19a66",
589
- DELETE: "#e06c75"
590
- };
591
- return /* @__PURE__ */ jsxDEV5("div", {
592
- style: {
593
- opacity,
594
- transform: `scale(${scale})`,
595
- backgroundColor: methodColors[method] ?? "#61afef",
596
- color: "#000",
597
- padding: "8px 20px",
598
- borderRadius: 8,
599
- fontSize: 24,
600
- fontWeight: 700,
601
- fontFamily: "monospace",
602
- letterSpacing: 1
603
- },
604
- children: method
605
- }, undefined, false, undefined, this);
606
- };
607
- var OutputChip = ({ label, startFrame }) => {
608
- const frame = useCurrentFrame5();
609
- const opacity = interpolate4(frame, [startFrame, startFrame + 12], [0, 1], {
610
- extrapolateLeft: "clamp",
611
- extrapolateRight: "clamp"
612
- });
613
- const translateY = interpolate4(frame, [startFrame, startFrame + 15], [20, 0], {
614
- extrapolateLeft: "clamp",
615
- extrapolateRight: "clamp",
616
- easing: videoEasing.emphasis
617
- });
618
- const scale = interpolate4(frame, [startFrame, startFrame + 15], [0.9, 1], {
619
- extrapolateLeft: "clamp",
620
- extrapolateRight: "clamp",
621
- easing: videoEasing.emphasis
622
- });
623
- return /* @__PURE__ */ jsxDEV5("div", {
624
- style: {
625
- opacity,
626
- transform: `translateY(${translateY}px) scale(${scale})`,
627
- backgroundColor: "rgba(255,255,255,0.08)",
628
- border: "1px solid rgba(255,255,255,0.15)",
629
- color: "#ffffff",
630
- padding: "16px 32px",
631
- borderRadius: 12,
632
- fontSize: 28,
633
- fontWeight: 500
634
- },
635
- children: label
636
- }, undefined, false, undefined, this);
637
- };
638
-
639
- // src/compositions/primitives/terminal.tsx
640
- import { interpolate as interpolate5, useCurrentFrame as useCurrentFrame6, useVideoConfig as useVideoConfig6 } from "remotion";
641
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
642
- var LINE_TYPE_COLORS = {
643
- command: "#c9d1d9",
644
- output: "#8b949e",
645
- error: "#f85149",
646
- success: "#3fb950",
647
- comment: "#6e7681"
648
- };
649
- var Terminal = ({
650
- lines,
651
- startAt = 0,
652
- prompt = "$ ",
653
- title = "Terminal",
654
- backgroundColor = defaultVideoColors.terminalBackground,
655
- typingSpeed = videoDurations.codeTypingPerChar
656
- }) => {
657
- const frame = useCurrentFrame6();
658
- const { width } = useVideoConfig6();
659
- const codeStyle = scaleTypography(videoTypography.code, width);
660
- const lineTimings = [];
661
- let currentFrame = startAt;
662
- for (const line of lines) {
663
- const delay = line.delay ?? 10;
664
- const lineStart = currentFrame + delay;
665
- if (line.type === "command") {
666
- const typeDuration = line.text.length * typingSpeed;
667
- lineTimings.push({
668
- startFrame: lineStart,
669
- endFrame: lineStart + typeDuration
670
- });
671
- currentFrame = lineStart + typeDuration;
672
- } else {
673
- lineTimings.push({ startFrame: lineStart, endFrame: lineStart + 5 });
674
- currentFrame = lineStart + 5;
675
- }
676
- }
677
- const opacity = interpolate5(frame, [startAt, startAt + 10], [0, 1], {
678
- extrapolateLeft: "clamp",
679
- extrapolateRight: "clamp",
680
- easing: videoEasing.entrance
681
- });
682
- return /* @__PURE__ */ jsxDEV6("div", {
683
- style: {
684
- backgroundColor,
685
- borderRadius: 16,
686
- overflow: "hidden",
687
- opacity,
688
- boxShadow: "0 8px 32px rgba(0,0,0,0.3)"
689
- },
690
- children: [
691
- /* @__PURE__ */ jsxDEV6("div", {
692
- style: {
693
- display: "flex",
694
- alignItems: "center",
695
- padding: "12px 20px",
696
- backgroundColor: "rgba(255,255,255,0.05)",
697
- gap: 8
698
- },
699
- children: [
700
- /* @__PURE__ */ jsxDEV6("div", {
701
- style: { display: "flex", gap: 8 },
702
- children: [
703
- /* @__PURE__ */ jsxDEV6("div", {
704
- style: {
705
- width: 12,
706
- height: 12,
707
- borderRadius: "50%",
708
- backgroundColor: "#ff5f57"
709
- }
710
- }, undefined, false, undefined, this),
711
- /* @__PURE__ */ jsxDEV6("div", {
712
- style: {
713
- width: 12,
714
- height: 12,
715
- borderRadius: "50%",
716
- backgroundColor: "#febc2e"
717
- }
718
- }, undefined, false, undefined, this),
719
- /* @__PURE__ */ jsxDEV6("div", {
720
- style: {
721
- width: 12,
722
- height: 12,
723
- borderRadius: "50%",
724
- backgroundColor: "#28c840"
725
- }
726
- }, undefined, false, undefined, this)
727
- ]
728
- }, undefined, true, undefined, this),
729
- /* @__PURE__ */ jsxDEV6("div", {
730
- style: {
731
- flex: 1,
732
- textAlign: "center",
733
- color: "#484f58",
734
- fontSize: codeStyle.fontSize * 0.7,
735
- fontFamily: "monospace"
736
- },
737
- children: title
738
- }, undefined, false, undefined, this)
739
- ]
740
- }, undefined, true, undefined, this),
741
- /* @__PURE__ */ jsxDEV6("div", {
742
- style: { padding: "24px 32px", minHeight: 200 },
743
- children: lines.map((line, i) => {
744
- const timing = lineTimings[i];
745
- if (!timing || frame < timing.startFrame)
746
- return null;
747
- const isCommand = line.type === "command";
748
- const lineColor = LINE_TYPE_COLORS[line.type];
749
- let visibleText = line.text;
750
- if (isCommand) {
751
- const typingProgress = interpolate5(frame, [timing.startFrame, timing.endFrame], [0, line.text.length], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
752
- visibleText = line.text.slice(0, Math.floor(typingProgress));
753
- }
754
- const lineOpacity = isCommand ? 1 : interpolate5(frame, [timing.startFrame, timing.startFrame + 5], [0, 1], {
755
- extrapolateLeft: "clamp",
756
- extrapolateRight: "clamp"
757
- });
758
- const isTyping = isCommand && frame >= timing.startFrame && frame <= timing.endFrame;
759
- const showCursor = isTyping && frame % 16 < 10;
760
- return /* @__PURE__ */ jsxDEV6("div", {
761
- style: {
762
- fontFamily: "'SF Mono', 'Fira Code', 'JetBrains Mono', monospace",
763
- fontSize: codeStyle.fontSize,
764
- lineHeight: 1.8,
765
- color: lineColor,
766
- opacity: lineOpacity,
767
- whiteSpace: "pre-wrap"
768
- },
769
- children: [
770
- isCommand && /* @__PURE__ */ jsxDEV6("span", {
771
- style: { color: "#3fb950" },
772
- children: prompt
773
- }, undefined, false, undefined, this),
774
- line.type === "comment" && /* @__PURE__ */ jsxDEV6("span", {
775
- style: { color: LINE_TYPE_COLORS.comment },
776
- children: "# "
777
- }, undefined, false, undefined, this),
778
- visibleText,
779
- showCursor && /* @__PURE__ */ jsxDEV6("span", {
780
- style: {
781
- backgroundColor: "#c9d1d9",
782
- width: "2px",
783
- display: "inline-block",
784
- height: "1.2em",
785
- verticalAlign: "text-bottom"
786
- },
787
- children: " "
788
- }, undefined, false, undefined, this)
789
- ]
790
- }, `${i}-${line.text.slice(0, 20)}`, true, undefined, this);
791
- })
792
- }, undefined, false, undefined, this)
793
- ]
794
- }, undefined, true, undefined, this);
795
- };
796
-
797
- // src/compositions/primitives/transition.tsx
798
- import { interpolate as interpolate6, useCurrentFrame as useCurrentFrame7 } from "remotion";
799
- import { jsxDEV as jsxDEV7, Fragment } from "react/jsx-dev-runtime";
800
- var SceneTransitionWrapper = ({
801
- type,
802
- durationInFrames,
803
- direction,
804
- startAt = 0,
805
- children
806
- }) => {
807
- const frame = useCurrentFrame7();
808
- if (type === "none" || durationInFrames === 0) {
809
- return /* @__PURE__ */ jsxDEV7(Fragment, {
810
- children
811
- }, undefined, false, undefined, this);
812
- }
813
- const progress = interpolate6(frame, [startAt, startAt + durationInFrames], direction === "in" ? [0, 1] : [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
814
- const styles = getTransitionStyles(type, progress);
815
- return /* @__PURE__ */ jsxDEV7("div", {
816
- style: styles,
817
- children
818
- }, undefined, false, undefined, this);
819
- };
820
- function getTransitionStyles(type, progress) {
821
- const eased = videoEasing.entrance(progress);
822
- switch (type) {
823
- case "fade":
824
- return {
825
- opacity: eased,
826
- width: "100%",
827
- height: "100%"
828
- };
829
- case "slide-left":
830
- return {
831
- opacity: eased,
832
- transform: `translateX(${(1 - eased) * 100}%)`,
833
- width: "100%",
834
- height: "100%"
835
- };
836
- case "slide-right":
837
- return {
838
- opacity: eased,
839
- transform: `translateX(${(1 - eased) * -100}%)`,
840
- width: "100%",
841
- height: "100%"
842
- };
843
- case "wipe":
844
- return {
845
- clipPath: `inset(0 ${(1 - eased) * 100}% 0 0)`,
846
- width: "100%",
847
- height: "100%"
848
- };
849
- default:
850
- return { width: "100%", height: "100%" };
851
- }
852
- }
853
- // src/compositions/social-clip.tsx
854
- import {
855
- AbsoluteFill as AbsoluteFill2,
856
- interpolate as interpolate7,
857
- Sequence as Sequence2,
858
- useCurrentFrame as useCurrentFrame8,
859
- useVideoConfig as useVideoConfig7
860
- } from "remotion";
861
- import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
862
- var SocialClip = ({
863
- hook,
864
- message,
865
- points = [],
866
- cta = "Learn more",
867
- ctaUrl = "contractspec.dev",
868
- accentColor
869
- }) => {
870
- const { durationInFrames, width, height } = useVideoConfig7();
871
- const theme = defaultVideoTheme;
872
- const accent = accentColor ?? theme.colors.accent;
873
- const isPortrait = height > width;
874
- const HOOK_DURATION = 75;
875
- const MESSAGE_START = 60;
876
- const POINTS_START = MESSAGE_START + 60;
877
- const CTA_START = durationInFrames - 90;
878
- return /* @__PURE__ */ jsxDEV8(AbsoluteFill2, {
879
- children: [
880
- /* @__PURE__ */ jsxDEV8(BrandFrame, {
881
- variant: "gradient",
882
- showBranding: true,
883
- children: /* @__PURE__ */ jsxDEV8("div", {
884
- style: {
885
- flex: 1,
886
- display: "flex",
887
- flexDirection: "column",
888
- justifyContent: "center",
889
- alignItems: "center",
890
- gap: isPortrait ? 48 : 32,
891
- textAlign: "center",
892
- padding: isPortrait ? "0 20px" : 0
893
- },
894
- children: [
895
- /* @__PURE__ */ jsxDEV8(Sequence2, {
896
- from: 0,
897
- durationInFrames: HOOK_DURATION + 30,
898
- children: /* @__PURE__ */ jsxDEV8("div", {
899
- style: { width: "100%" },
900
- children: /* @__PURE__ */ jsxDEV8(AnimatedText, {
901
- text: hook,
902
- variant: "title",
903
- enterAt: 5,
904
- exitAt: HOOK_DURATION,
905
- color: "#ffffff",
906
- align: "center"
907
- }, undefined, false, undefined, this)
908
- }, undefined, false, undefined, this)
909
- }, undefined, false, undefined, this),
910
- /* @__PURE__ */ jsxDEV8(Sequence2, {
911
- from: MESSAGE_START,
912
- children: /* @__PURE__ */ jsxDEV8("div", {
913
- style: { width: "100%" },
914
- children: /* @__PURE__ */ jsxDEV8(AnimatedText, {
915
- text: message,
916
- variant: isPortrait ? "subheading" : "heading",
917
- enterAt: 0,
918
- color: "#ffffff",
919
- align: "center"
920
- }, undefined, false, undefined, this)
921
- }, undefined, false, undefined, this)
922
- }, undefined, false, undefined, this),
923
- points.length > 0 && /* @__PURE__ */ jsxDEV8(Sequence2, {
924
- from: POINTS_START,
925
- children: /* @__PURE__ */ jsxDEV8("div", {
926
- style: {
927
- display: "flex",
928
- flexDirection: "column",
929
- gap: 16,
930
- alignItems: isPortrait ? "flex-start" : "center",
931
- width: "100%",
932
- maxWidth: isPortrait ? "100%" : "80%",
933
- marginTop: 16
934
- },
935
- children: points.map((point, i) => /* @__PURE__ */ jsxDEV8(PointItem, {
936
- text: point,
937
- index: i,
938
- startFrame: i * 15,
939
- accent
940
- }, point, false, undefined, this))
941
- }, undefined, false, undefined, this)
942
- }, undefined, false, undefined, this),
943
- /* @__PURE__ */ jsxDEV8(Sequence2, {
944
- from: CTA_START,
945
- children: /* @__PURE__ */ jsxDEV8(CTABlock, {
946
- cta,
947
- url: ctaUrl,
948
- accent
949
- }, undefined, false, undefined, this)
950
- }, undefined, false, undefined, this)
951
- ]
952
- }, undefined, true, undefined, this)
953
- }, undefined, false, undefined, this),
954
- /* @__PURE__ */ jsxDEV8(ProgressBar, {
955
- color: accent
956
- }, undefined, false, undefined, this)
957
- ]
958
- }, undefined, true, undefined, this);
959
- };
960
- var PointItem = ({ text, startFrame, accent }) => {
961
- const frame = useCurrentFrame8();
962
- const opacity = interpolate7(frame, [startFrame, startFrame + 12], [0, 1], {
963
- extrapolateLeft: "clamp",
964
- extrapolateRight: "clamp"
965
- });
966
- const translateX = interpolate7(frame, [startFrame, startFrame + 15], [-30, 0], {
967
- extrapolateLeft: "clamp",
968
- extrapolateRight: "clamp",
969
- easing: videoEasing.entrance
970
- });
971
- return /* @__PURE__ */ jsxDEV8("div", {
972
- style: {
973
- opacity,
974
- transform: `translateX(${translateX}px)`,
975
- display: "flex",
976
- alignItems: "center",
977
- gap: 16,
978
- fontSize: 28,
979
- color: "#ffffff"
980
- },
981
- children: [
982
- /* @__PURE__ */ jsxDEV8("div", {
983
- style: {
984
- width: 8,
985
- height: 8,
986
- borderRadius: "50%",
987
- backgroundColor: accent,
988
- flexShrink: 0
989
- }
990
- }, undefined, false, undefined, this),
991
- text
992
- ]
993
- }, undefined, true, undefined, this);
994
- };
995
- var CTABlock = ({ cta, url, accent }) => {
996
- const frame = useCurrentFrame8();
997
- const opacity = interpolate7(frame, [0, 15], [0, 1], {
998
- extrapolateLeft: "clamp",
999
- extrapolateRight: "clamp"
1000
- });
1001
- const scale = interpolate7(frame, [0, 18], [0.9, 1], {
1002
- extrapolateLeft: "clamp",
1003
- extrapolateRight: "clamp",
1004
- easing: videoEasing.emphasis
1005
- });
1006
- return /* @__PURE__ */ jsxDEV8("div", {
1007
- style: {
1008
- opacity,
1009
- transform: `scale(${scale})`,
1010
- display: "flex",
1011
- flexDirection: "column",
1012
- alignItems: "center",
1013
- gap: 12,
1014
- marginTop: 24
1015
- },
1016
- children: [
1017
- /* @__PURE__ */ jsxDEV8("div", {
1018
- style: {
1019
- backgroundColor: accent,
1020
- color: "#ffffff",
1021
- padding: "16px 48px",
1022
- borderRadius: 12,
1023
- fontSize: 28,
1024
- fontWeight: 600
1025
- },
1026
- children: cta
1027
- }, undefined, false, undefined, this),
1028
- /* @__PURE__ */ jsxDEV8("div", {
1029
- style: { color: "rgba(255,255,255,0.5)", fontSize: 20 },
1030
- children: url
1031
- }, undefined, false, undefined, this)
1032
- ]
1033
- }, undefined, true, undefined, this);
1034
- };
1035
-
1036
- // src/compositions/terminal-demo.tsx
1037
- import { AbsoluteFill as AbsoluteFill3, Sequence as Sequence3, useVideoConfig as useVideoConfig8 } from "remotion";
1038
- import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
1039
- var TerminalDemo = ({
1040
- title,
1041
- subtitle,
1042
- lines,
1043
- terminalTitle = "Terminal",
1044
- prompt = "$ ",
1045
- summary
1046
- }) => {
1047
- const { durationInFrames } = useVideoConfig8();
1048
- const theme = defaultVideoTheme;
1049
- const TERMINAL_START = 40;
1050
- const SUMMARY_START = durationInFrames - 90;
1051
- return /* @__PURE__ */ jsxDEV9(AbsoluteFill3, {
1052
- children: [
1053
- /* @__PURE__ */ jsxDEV9(BrandFrame, {
1054
- variant: "dark",
1055
- showBranding: true,
1056
- children: /* @__PURE__ */ jsxDEV9("div", {
1057
- style: {
1058
- flex: 1,
1059
- display: "flex",
1060
- flexDirection: "column",
1061
- gap: 24
1062
- },
1063
- children: [
1064
- /* @__PURE__ */ jsxDEV9("div", {
1065
- children: [
1066
- /* @__PURE__ */ jsxDEV9(AnimatedText, {
1067
- text: title,
1068
- variant: "heading",
1069
- enterAt: 5,
1070
- color: "#ffffff"
1071
- }, undefined, false, undefined, this),
1072
- subtitle && /* @__PURE__ */ jsxDEV9("div", {
1073
- style: { marginTop: 8 },
1074
- children: /* @__PURE__ */ jsxDEV9(AnimatedText, {
1075
- text: subtitle,
1076
- variant: "body",
1077
- enterAt: 15,
1078
- color: theme.colors.mutedForeground
1079
- }, undefined, false, undefined, this)
1080
- }, undefined, false, undefined, this)
1081
- ]
1082
- }, undefined, true, undefined, this),
1083
- /* @__PURE__ */ jsxDEV9(Sequence3, {
1084
- from: TERMINAL_START,
1085
- children: /* @__PURE__ */ jsxDEV9("div", {
1086
- style: { flex: 1 },
1087
- children: /* @__PURE__ */ jsxDEV9(Terminal, {
1088
- lines,
1089
- startAt: 0,
1090
- prompt,
1091
- title: terminalTitle
1092
- }, undefined, false, undefined, this)
1093
- }, undefined, false, undefined, this)
1094
- }, undefined, false, undefined, this),
1095
- summary && /* @__PURE__ */ jsxDEV9(Sequence3, {
1096
- from: SUMMARY_START,
1097
- children: /* @__PURE__ */ jsxDEV9("div", {
1098
- style: {
1099
- marginTop: "auto",
1100
- paddingTop: 24
1101
- },
1102
- children: /* @__PURE__ */ jsxDEV9(AnimatedText, {
1103
- text: summary,
1104
- variant: "subheading",
1105
- enterAt: 0,
1106
- color: theme.colors.accent,
1107
- align: "center"
1108
- }, undefined, false, undefined, this)
1109
- }, undefined, false, undefined, this)
1110
- }, undefined, false, undefined, this)
1111
- ]
1112
- }, undefined, true, undefined, this)
1113
- }, undefined, false, undefined, this),
1114
- /* @__PURE__ */ jsxDEV9(ProgressBar, {}, undefined, false, undefined, this)
1115
- ]
1116
- }, undefined, true, undefined, this);
1117
- };
1118
- // src/i18n/catalogs/en.ts
1119
- import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
1120
- var enMessages = defineTranslation({
1121
- meta: {
1122
- key: "video-gen.messages",
1123
- version: "1.0.0",
1124
- domain: "video-gen",
1125
- description: "All user-facing, LLM-facing, and developer-facing strings for the video-gen package",
1126
- owners: ["platform"],
1127
- stability: "experimental"
1128
- },
1129
- locale: "en",
1130
- fallback: "en",
1131
- messages: {
1132
- "prompt.script.system": {
1133
- value: `You are a video narration script writer.
1
+ import{createRequire as P8}from"node:module";var Z1=P8(import.meta.url);import{Easing as w}from"remotion";var R={entrance:w.out(w.exp),exit:w.in(w.exp),emphasis:w.out(w.back(1.4)),linear:w.linear,gentle:w.bezier(0.25,0.1,0.25,1),spring:w.out(w.back(1.7))},V={sceneTransition:20,textEntrance:15,textExit:12,codeTypingPerChar:2,sectionPause:30,emphasisPause:15,brandReveal:25,minScene:60,shortScene:60,mediumScene:120,longScene:240},I1={fade:{type:"fade",durationInFrames:20},slideLeft:{type:"slide-left",durationInFrames:20},slideRight:{type:"slide-right",durationInFrames:20},wipe:{type:"wipe",durationInFrames:15},none:{type:"none",durationInFrames:0}};import{defaultTokens as b}from"@contractspec/lib.design-system";var y={canvasBackground:b.colors.background,codeBackground:"#1e1e2e",terminalBackground:"#0d1117",terminalForeground:"#c9d1d9",highlight:b.colors.accent,gradientStart:b.colors.primary,gradientEnd:b.colors.accent},P={...b,video:y};var C={title:{fontSize:72,lineHeight:1.1,fontWeight:700,letterSpacing:-1},heading:{fontSize:56,lineHeight:1.2,fontWeight:600,letterSpacing:-0.5},subheading:{fontSize:40,lineHeight:1.25,fontWeight:500},body:{fontSize:32,lineHeight:1.5,fontWeight:400},code:{fontSize:28,lineHeight:1.6,fontWeight:400},caption:{fontSize:24,lineHeight:1.4,fontWeight:400},label:{fontSize:20,lineHeight:1.3,fontWeight:600,letterSpacing:1}};function v(G,K){let L=K/1920;return{...G,fontSize:Math.round(G.fontSize*L),letterSpacing:G.letterSpacing?Math.round(G.letterSpacing*L*10)/10:void 0}}import{interpolate as A,useCurrentFrame as O8,useVideoConfig as k8}from"remotion";import{jsx as E8}from"react/jsx-runtime";var I=({text:G,variant:K="body",style:L,enterAt:z=0,exitAt:H,color:Q="#ffffff",align:$="left"})=>{let W=O8(),{width:U}=k8(),M=C[K],X={...v(M,U),...L},N=A(W,[z,z+V.textEntrance],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}),B=A(N,[0,1],[0,1],{easing:R.entrance}),Y=A(N,[0,1],[30,0],{easing:R.entrance}),Z=1,k=0;if(H!==void 0){let o=A(W,[H,H+V.textExit],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp"});Z=A(o,[0,1],[1,0],{easing:R.exit}),k=A(o,[0,1],[0,-20],{easing:R.exit})}let E=B*Z,c=Y+k;return E8("div",{style:{fontSize:X.fontSize,lineHeight:X.lineHeight,fontWeight:X.fontWeight,letterSpacing:X.letterSpacing,color:Q,textAlign:$,opacity:E,transform:`translateY(${c}px)`,willChange:"opacity, transform"},children:G})};import{VIDEO_FORMATS as r}from"@contractspec/lib.contracts-integrations/integrations/providers/video";var j=30,x={horizontal:120,vertical:80,contentWidth:1680,contentHeight:920};function J8(G){let K=G.width/1920,L=G.height/1080;return{horizontal:Math.round(x.horizontal*K),vertical:Math.round(x.vertical*L),contentWidth:Math.round(x.contentWidth*K),contentHeight:Math.round(x.contentHeight*L)}}var v1={center:{x:960,y:540},topLeft:{x:120,y:80},topRight:{x:1800,y:80},bottomLeft:{x:120,y:1000},bottomRight:{x:1800,y:1000},bottomCenter:{x:960,y:960}};function A1(){return[r.landscape,r.square,r.portrait]}import{interpolate as Q8,useCurrentFrame as S8,useVideoConfig as T8}from"remotion";import{jsx as a,jsxs as C8}from"react/jsx-runtime";var S=({styleOverrides:G,showBranding:K=!0,animateEntrance:L=!0,variant:z="gradient",children:H})=>{let Q=S8(),{width:$,height:W}=T8(),U=P,M=J8({type:"custom",width:$,height:W}),J=G?.primaryColor??U.colors.primary,X=G?.accentColor??U.colors.accent,N=G?.darkMode??!0,B;switch(z){case"solid":B=N?"#0a0a0a":U.colors.background;break;case"gradient":B=N?"linear-gradient(135deg, #0a0a14 0%, #0f172a 50%, #0a0a14 100%)":`linear-gradient(135deg, ${U.colors.background} 0%, ${U.colors.muted} 100%)`;break;case"dark":B="#000000";break}let Y=L?Q8(Q,[0,15],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.entrance}):1,Z=K?Q8(Q,[V.brandReveal,V.brandReveal+15],[0,0.3],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}):0;return C8("div",{style:{width:$,height:W,background:B,position:"relative",overflow:"hidden",opacity:Y},children:[z==="gradient"&&a("div",{style:{position:"absolute",top:"-20%",right:"-10%",width:"50%",height:"50%",background:`radial-gradient(circle, ${J}15 0%, transparent 70%)`,borderRadius:"50%",pointerEvents:"none"}}),a("div",{style:{position:"absolute",left:M.horizontal,top:M.vertical,width:M.contentWidth,height:M.contentHeight,display:"flex",flexDirection:"column"},children:H}),K&&a("div",{style:{position:"absolute",bottom:M.vertical/2,right:M.horizontal,opacity:Z,color:N?"#ffffff":"#000000",fontSize:Math.round(16*($/1920)),fontWeight:500,letterSpacing:1},children:"ContractSpec"})]})};import{interpolate as $8,useCurrentFrame as v8,useVideoConfig as A8}from"remotion";import{jsx as F,jsxs as p}from"react/jsx-runtime";var n=({code:G,language:K="typescript",startAt:L=0,typeAnimation:z=!0,backgroundColor:H=y.codeBackground,textColor:Q="#abb2bf",filename:$})=>{let W=v8(),{width:U}=A8(),M=v(C.code,U),J=G.length,X=J*V.codeTypingPerChar,N=z?Math.floor($8(W,[L,L+X],[0,J],{extrapolateLeft:"clamp",extrapolateRight:"clamp"})):J,B=G.slice(0,N),Y=$8(W,[L,L+10],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.entrance}),Z=z&&N<J&&W%16<10;return p("div",{style:{backgroundColor:H,borderRadius:16,padding:0,opacity:Y,overflow:"hidden",boxShadow:"0 8px 32px rgba(0,0,0,0.3)"},children:[p("div",{style:{display:"flex",alignItems:"center",padding:"12px 20px",backgroundColor:"rgba(0,0,0,0.2)",gap:8},children:[p("div",{style:{display:"flex",gap:8},children:[F("div",{style:{width:12,height:12,borderRadius:"50%",backgroundColor:"#ff5f57"}}),F("div",{style:{width:12,height:12,borderRadius:"50%",backgroundColor:"#febc2e"}}),F("div",{style:{width:12,height:12,borderRadius:"50%",backgroundColor:"#28c840"}})]}),F("div",{style:{flex:1,textAlign:"center",color:"#666",fontSize:M.fontSize*0.7,fontFamily:"monospace"},children:$??K})]}),F("div",{style:{padding:"24px 32px"},children:p("pre",{style:{margin:0,fontFamily:"'SF Mono', 'Fira Code', 'JetBrains Mono', monospace",fontSize:M.fontSize,lineHeight:M.lineHeight,color:Q,whiteSpace:"pre-wrap",wordBreak:"break-word"},children:[B,Z&&F("span",{style:{backgroundColor:Q,width:"2px",display:"inline-block",height:"1.2em",verticalAlign:"text-bottom"},children:" "})]})})]})};import{useCurrentFrame as F8,useVideoConfig as b8}from"remotion";import{jsx as W8}from"react/jsx-runtime";var T=({height:G=4,color:K=P.colors.primary,backgroundColor:L="rgba(255,255,255,0.1)",position:z="bottom"})=>{let H=F8(),{durationInFrames:Q,width:$}=b8(),W=H/Q;return W8("div",{style:{position:"absolute",[z]:0,left:0,width:$,height:G,backgroundColor:L,zIndex:100},children:W8("div",{style:{width:`${W*100}%`,height:"100%",backgroundColor:K,transition:"none"}})})};import{AbsoluteFill as y8,interpolate as f,Sequence as i,useCurrentFrame as X8,useVideoConfig as h8}from"remotion";import{jsx as _,jsxs as h}from"react/jsx-runtime";var f8=({specName:G,method:K="POST",endpoint:L="/api/users",specCode:z,generatedOutputs:H=["REST Endpoint","GraphQL Mutation","Prisma Model","TypeScript SDK","MCP Tool","OpenAPI Spec"],tagline:Q="One spec. Every surface."})=>{let{durationInFrames:$}=h8(),W=P,U=60,M=45,J=210,X=180,N=$-90;return h(y8,{children:[h(S,{variant:"gradient",showBranding:!0,children:[_(i,{from:0,durationInFrames:210,children:h("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:16},children:[h("div",{style:{display:"flex",alignItems:"center",gap:16},children:[_(x8,{method:K,enterAt:10}),_(I,{text:L,variant:"subheading",enterAt:15,color:W.colors.mutedForeground})]}),_(I,{text:G,variant:"title",enterAt:5,color:"#ffffff"}),_("div",{style:{flex:1,marginTop:24},children:_(n,{code:z,language:"typescript",filename:`${G.toLowerCase()}.contract.ts`,startAt:45,typeAnimation:!0})})]})}),_(i,{from:180,durationInFrames:$-180,children:h("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",gap:24},children:[_(I,{text:"Generates:",variant:"heading",enterAt:0,color:"#ffffff",align:"center"}),_("div",{style:{display:"flex",flexWrap:"wrap",gap:16,justifyContent:"center",maxWidth:"80%",marginTop:32},children:H.map((B,Y)=>_(j8,{label:B,index:Y,startFrame:20+Y*8},B))}),_(i,{from:N-180,children:_("div",{style:{marginTop:48},children:_(I,{text:Q,variant:"heading",enterAt:0,color:W.colors.accent,align:"center"})})})]})})]}),_(T,{})]})},x8=({method:G,enterAt:K})=>{let L=X8(),z=f(L,[K,K+10],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.entrance}),H=f(L,[K,K+12],[0.8,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.emphasis}),Q={GET:"#61afef",POST:"#98c379",PUT:"#e5c07b",PATCH:"#d19a66",DELETE:"#e06c75"};return _("div",{style:{opacity:z,transform:`scale(${H})`,backgroundColor:Q[G]??"#61afef",color:"#000",padding:"8px 20px",borderRadius:8,fontSize:24,fontWeight:700,fontFamily:"monospace",letterSpacing:1},children:G})},j8=({label:G,startFrame:K})=>{let L=X8(),z=f(L,[K,K+12],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}),H=f(L,[K,K+15],[20,0],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.emphasis}),Q=f(L,[K,K+15],[0.9,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.emphasis});return _("div",{style:{opacity:z,transform:`translateY(${H}px) scale(${Q})`,backgroundColor:"rgba(255,255,255,0.08)",border:"1px solid rgba(255,255,255,0.15)",color:"#ffffff",padding:"16px 32px",borderRadius:12,fontSize:28,fontWeight:500},children:G})};import{interpolate as s,useCurrentFrame as p8,useVideoConfig as g8}from"remotion";import{jsx as O,jsxs as g}from"react/jsx-runtime";var U8={command:"#c9d1d9",output:"#8b949e",error:"#f85149",success:"#3fb950",comment:"#6e7681"},t=({lines:G,startAt:K=0,prompt:L="$ ",title:z="Terminal",backgroundColor:H=y.terminalBackground,typingSpeed:Q=V.codeTypingPerChar})=>{let $=p8(),{width:W}=g8(),U=v(C.code,W),M=[],J=K;for(let N of G){let B=N.delay??10,Y=J+B;if(N.type==="command"){let Z=N.text.length*Q;M.push({startFrame:Y,endFrame:Y+Z}),J=Y+Z}else M.push({startFrame:Y,endFrame:Y+5}),J=Y+5}let X=s($,[K,K+10],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.entrance});return g("div",{style:{backgroundColor:H,borderRadius:16,overflow:"hidden",opacity:X,boxShadow:"0 8px 32px rgba(0,0,0,0.3)"},children:[g("div",{style:{display:"flex",alignItems:"center",padding:"12px 20px",backgroundColor:"rgba(255,255,255,0.05)",gap:8},children:[g("div",{style:{display:"flex",gap:8},children:[O("div",{style:{width:12,height:12,borderRadius:"50%",backgroundColor:"#ff5f57"}}),O("div",{style:{width:12,height:12,borderRadius:"50%",backgroundColor:"#febc2e"}}),O("div",{style:{width:12,height:12,borderRadius:"50%",backgroundColor:"#28c840"}})]}),O("div",{style:{flex:1,textAlign:"center",color:"#484f58",fontSize:U.fontSize*0.7,fontFamily:"monospace"},children:z})]}),O("div",{style:{padding:"24px 32px",minHeight:200},children:G.map((N,B)=>{let Y=M[B];if(!Y||$<Y.startFrame)return null;let Z=N.type==="command",k=U8[N.type],E=N.text;if(Z){let V8=s($,[Y.startFrame,Y.endFrame],[0,N.text.length],{extrapolateLeft:"clamp",extrapolateRight:"clamp"});E=N.text.slice(0,Math.floor(V8))}let c=Z?1:s($,[Y.startFrame,Y.startFrame+5],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}),w8=Z&&$>=Y.startFrame&&$<=Y.endFrame&&$%16<10;return g("div",{style:{fontFamily:"'SF Mono', 'Fira Code', 'JetBrains Mono', monospace",fontSize:U.fontSize,lineHeight:1.8,color:k,opacity:c,whiteSpace:"pre-wrap"},children:[Z&&O("span",{style:{color:"#3fb950"},children:L}),N.type==="comment"&&O("span",{style:{color:U8.comment},children:"# "}),E,w8&&O("span",{style:{backgroundColor:"#c9d1d9",width:"2px",display:"inline-block",height:"1.2em",verticalAlign:"text-bottom"},children:" "})]},`${B}-${N.text.slice(0,20)}`)})})]})};import{interpolate as u8,useCurrentFrame as m8}from"remotion";import{jsx as N8,Fragment as c8}from"react/jsx-runtime";var d8=({type:G,durationInFrames:K,direction:L,startAt:z=0,children:H})=>{let Q=m8();if(G==="none"||K===0)return N8(c8,{children:H});let $=u8(Q,[z,z+K],L==="in"?[0,1]:[1,0],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}),W=l8(G,$);return N8("div",{style:W,children:H})};function l8(G,K){let L=R.entrance(K);switch(G){case"fade":return{opacity:L,width:"100%",height:"100%"};case"slide-left":return{opacity:L,transform:`translateX(${(1-L)*100}%)`,width:"100%",height:"100%"};case"slide-right":return{opacity:L,transform:`translateX(${(1-L)*-100}%)`,width:"100%",height:"100%"};case"wipe":return{clipPath:`inset(0 ${(1-L)*100}% 0 0)`,width:"100%",height:"100%"};default:return{width:"100%",height:"100%"}}}import{AbsoluteFill as o8,interpolate as m,Sequence as u,useCurrentFrame as M8,useVideoConfig as r8}from"remotion";import{jsx as q,jsxs as d}from"react/jsx-runtime";var a8=({hook:G,message:K,points:L=[],cta:z="Learn more",ctaUrl:H="contractspec.dev",accentColor:Q})=>{let{durationInFrames:$,width:W,height:U}=r8(),J=Q??P.colors.accent,X=U>W,N=75,B=60,Y=120,Z=$-90;return d(o8,{children:[q(S,{variant:"gradient",showBranding:!0,children:d("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",gap:X?48:32,textAlign:"center",padding:X?"0 20px":0},children:[q(u,{from:0,durationInFrames:105,children:q("div",{style:{width:"100%"},children:q(I,{text:G,variant:"title",enterAt:5,exitAt:75,color:"#ffffff",align:"center"})})}),q(u,{from:60,children:q("div",{style:{width:"100%"},children:q(I,{text:K,variant:X?"subheading":"heading",enterAt:0,color:"#ffffff",align:"center"})})}),L.length>0&&q(u,{from:120,children:q("div",{style:{display:"flex",flexDirection:"column",gap:16,alignItems:X?"flex-start":"center",width:"100%",maxWidth:X?"100%":"80%",marginTop:16},children:L.map((k,E)=>q(n8,{text:k,index:E,startFrame:E*15,accent:J},k))})}),q(u,{from:Z,children:q(i8,{cta:z,url:H,accent:J})})]})}),q(T,{color:J})]})},n8=({text:G,startFrame:K,accent:L})=>{let z=M8(),H=m(z,[K,K+12],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}),Q=m(z,[K,K+15],[-30,0],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.entrance});return d("div",{style:{opacity:H,transform:`translateX(${Q}px)`,display:"flex",alignItems:"center",gap:16,fontSize:28,color:"#ffffff"},children:[q("div",{style:{width:8,height:8,borderRadius:"50%",backgroundColor:L,flexShrink:0}}),G]})},i8=({cta:G,url:K,accent:L})=>{let z=M8(),H=m(z,[0,15],[0,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp"}),Q=m(z,[0,18],[0.9,1],{extrapolateLeft:"clamp",extrapolateRight:"clamp",easing:R.emphasis});return d("div",{style:{opacity:H,transform:`scale(${Q})`,display:"flex",flexDirection:"column",alignItems:"center",gap:12,marginTop:24},children:[q("div",{style:{backgroundColor:L,color:"#ffffff",padding:"16px 48px",borderRadius:12,fontSize:28,fontWeight:600},children:G}),q("div",{style:{color:"rgba(255,255,255,0.5)",fontSize:20},children:K})]})};import{AbsoluteFill as s8,Sequence as Y8,useVideoConfig as t8}from"remotion";import{jsx as D,jsxs as e}from"react/jsx-runtime";var e8=({title:G,subtitle:K,lines:L,terminalTitle:z="Terminal",prompt:H="$ ",summary:Q})=>{let{durationInFrames:$}=t8(),W=P,U=40,M=$-90;return e(s8,{children:[D(S,{variant:"dark",showBranding:!0,children:e("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:24},children:[e("div",{children:[D(I,{text:G,variant:"heading",enterAt:5,color:"#ffffff"}),K&&D("div",{style:{marginTop:8},children:D(I,{text:K,variant:"body",enterAt:15,color:W.colors.mutedForeground})})]}),D(Y8,{from:40,children:D("div",{style:{flex:1},children:D(t,{lines:L,startAt:0,prompt:H,title:z})})}),Q&&D(Y8,{from:M,children:D("div",{style:{marginTop:"auto",paddingTop:24},children:D(I,{text:Q,variant:"subheading",enterAt:0,color:W.colors.accent,align:"center"})})})]})}),D(T,{})]})};import{defineTranslation as G1}from"@contractspec/lib.contracts-spec/translations";var G8=G1({meta:{key:"video-gen.messages",version:"1.0.0",domain:"video-gen",description:"All user-facing, LLM-facing, and developer-facing strings for the video-gen package",owners:["platform"],stability:"experimental"},locale:"en",fallback:"en",messages:{"prompt.script.system":{value:`You are a video narration script writer.
1134
2
  Write a narration script for a short video (30-60 seconds).
1135
3
  {styleGuide}
1136
4
 
@@ -1141,12 +9,7 @@ Return JSON with shape:
1141
9
  }
1142
10
 
1143
11
  Scene IDs should be: "intro", "problems", "solutions", "metrics", "cta".
1144
- Only include segments that are relevant to the brief content.`,
1145
- description: "Script generator LLM system prompt",
1146
- placeholders: [{ name: "styleGuide", type: "string" }]
1147
- },
1148
- "prompt.scenePlanner.system": {
1149
- value: `You are a video scene planner for ContractSpec marketing/documentation videos.
12
+ Only include segments that are relevant to the brief content.`,description:"Script generator LLM system prompt",placeholders:[{name:"styleGuide",type:"string"}]},"prompt.scenePlanner.system":{value:`You are a video scene planner for ContractSpec marketing/documentation videos.
1150
13
  Given a content brief, break it into video scenes.
1151
14
 
1152
15
  Each scene must have:
@@ -1162,125 +25,7 @@ Return a JSON object with shape:
1162
25
  }
1163
26
 
1164
27
  Keep the total duration around {targetSeconds} seconds.
1165
- Prioritize clarity and pacing. Each scene should communicate one idea.`,
1166
- description: "Scene planner LLM system prompt",
1167
- placeholders: [
1168
- { name: "fps", type: "number" },
1169
- { name: "targetSeconds", type: "number" }
1170
- ]
1171
- },
1172
- "prompt.style.professional": {
1173
- value: "Use a clear, authoritative, professional tone. Be concise and direct.",
1174
- description: "Style guide for professional narration"
1175
- },
1176
- "prompt.style.casual": {
1177
- value: "Use a friendly, conversational tone. Be approachable and relatable.",
1178
- description: "Style guide for casual narration"
1179
- },
1180
- "prompt.style.technical": {
1181
- value: "Use precise technical language. Be detailed and accurate.",
1182
- description: "Style guide for technical narration"
1183
- },
1184
- "script.segment.challenge": {
1185
- value: "The challenge: {content}",
1186
- description: "Narration segment prefix for problems",
1187
- placeholders: [{ name: "content", type: "string" }]
1188
- },
1189
- "script.segment.solution": {
1190
- value: "The solution: {content}",
1191
- description: "Narration segment prefix for solutions",
1192
- placeholders: [{ name: "content", type: "string" }]
1193
- },
1194
- "script.segment.results": {
1195
- value: "The results: {content}",
1196
- description: "Narration segment prefix for metrics",
1197
- placeholders: [{ name: "content", type: "string" }]
1198
- },
1199
- "scene.cta.default": {
1200
- value: "Learn more",
1201
- description: "Default call-to-action text for scenes"
1202
- },
1203
- "scene.hook.problem": {
1204
- value: "The Problem",
1205
- description: "Scene hook label for problem statement"
1206
- },
1207
- "scene.narration.problem": {
1208
- value: "The problem: {content}",
1209
- description: "Scene narration for problem statement",
1210
- placeholders: [{ name: "content", type: "string" }]
1211
- },
1212
- "scene.hook.solution": {
1213
- value: "The Solution",
1214
- description: "Scene hook label for solution"
1215
- },
1216
- "scene.narration.solution": {
1217
- value: "The solution: {content}",
1218
- description: "Scene narration for solution",
1219
- placeholders: [{ name: "content", type: "string" }]
1220
- },
1221
- "scene.hook.results": {
1222
- value: "Results",
1223
- description: "Scene hook label for results/metrics"
1224
- },
1225
- "composition.apiOverview.generates": {
1226
- value: "Generates:",
1227
- description: "ApiOverview heading for generated outputs"
1228
- },
1229
- "composition.apiOverview.tagline": {
1230
- value: "One spec. Every surface.",
1231
- description: "ApiOverview default tagline"
1232
- },
1233
- "composition.apiOverview.output.rest": {
1234
- value: "REST Endpoint",
1235
- description: "Generated output label: REST"
1236
- },
1237
- "composition.apiOverview.output.graphql": {
1238
- value: "GraphQL Mutation",
1239
- description: "Generated output label: GraphQL"
1240
- },
1241
- "composition.apiOverview.output.prisma": {
1242
- value: "Prisma Model",
1243
- description: "Generated output label: Prisma"
1244
- },
1245
- "composition.apiOverview.output.typescript": {
1246
- value: "TypeScript SDK",
1247
- description: "Generated output label: TypeScript SDK"
1248
- },
1249
- "composition.apiOverview.output.mcp": {
1250
- value: "MCP Tool",
1251
- description: "Generated output label: MCP Tool"
1252
- },
1253
- "composition.apiOverview.output.openapi": {
1254
- value: "OpenAPI Spec",
1255
- description: "Generated output label: OpenAPI"
1256
- },
1257
- "composition.socialClip.cta": {
1258
- value: "Learn more",
1259
- description: "SocialClip default CTA"
1260
- },
1261
- "composition.terminal.title": {
1262
- value: "Terminal",
1263
- description: "TerminalDemo default window title"
1264
- }
1265
- }
1266
- });
1267
-
1268
- // src/i18n/catalogs/es.ts
1269
- import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
1270
- var esMessages = defineTranslation2({
1271
- meta: {
1272
- key: "video-gen.messages",
1273
- version: "1.0.0",
1274
- domain: "video-gen",
1275
- description: "Spanish translations for the video-gen package",
1276
- owners: ["platform"],
1277
- stability: "experimental"
1278
- },
1279
- locale: "es",
1280
- fallback: "en",
1281
- messages: {
1282
- "prompt.script.system": {
1283
- value: `Eres un redactor de guiones de narración para vídeo.
28
+ Prioritize clarity and pacing. Each scene should communicate one idea.`,description:"Scene planner LLM system prompt",placeholders:[{name:"fps",type:"number"},{name:"targetSeconds",type:"number"}]},"prompt.style.professional":{value:"Use a clear, authoritative, professional tone. Be concise and direct.",description:"Style guide for professional narration"},"prompt.style.casual":{value:"Use a friendly, conversational tone. Be approachable and relatable.",description:"Style guide for casual narration"},"prompt.style.technical":{value:"Use precise technical language. Be detailed and accurate.",description:"Style guide for technical narration"},"script.segment.challenge":{value:"The challenge: {content}",description:"Narration segment prefix for problems",placeholders:[{name:"content",type:"string"}]},"script.segment.solution":{value:"The solution: {content}",description:"Narration segment prefix for solutions",placeholders:[{name:"content",type:"string"}]},"script.segment.results":{value:"The results: {content}",description:"Narration segment prefix for metrics",placeholders:[{name:"content",type:"string"}]},"scene.cta.default":{value:"Learn more",description:"Default call-to-action text for scenes"},"scene.hook.problem":{value:"The Problem",description:"Scene hook label for problem statement"},"scene.narration.problem":{value:"The problem: {content}",description:"Scene narration for problem statement",placeholders:[{name:"content",type:"string"}]},"scene.hook.solution":{value:"The Solution",description:"Scene hook label for solution"},"scene.narration.solution":{value:"The solution: {content}",description:"Scene narration for solution",placeholders:[{name:"content",type:"string"}]},"scene.hook.results":{value:"Results",description:"Scene hook label for results/metrics"},"composition.apiOverview.generates":{value:"Generates:",description:"ApiOverview heading for generated outputs"},"composition.apiOverview.tagline":{value:"One spec. Every surface.",description:"ApiOverview default tagline"},"composition.apiOverview.output.rest":{value:"REST Endpoint",description:"Generated output label: REST"},"composition.apiOverview.output.graphql":{value:"GraphQL Mutation",description:"Generated output label: GraphQL"},"composition.apiOverview.output.prisma":{value:"Prisma Model",description:"Generated output label: Prisma"},"composition.apiOverview.output.typescript":{value:"TypeScript SDK",description:"Generated output label: TypeScript SDK"},"composition.apiOverview.output.mcp":{value:"MCP Tool",description:"Generated output label: MCP Tool"},"composition.apiOverview.output.openapi":{value:"OpenAPI Spec",description:"Generated output label: OpenAPI"},"composition.socialClip.cta":{value:"Learn more",description:"SocialClip default CTA"},"composition.terminal.title":{value:"Terminal",description:"TerminalDemo default window title"}}});import{defineTranslation as K1}from"@contractspec/lib.contracts-spec/translations";var K8=K1({meta:{key:"video-gen.messages",version:"1.0.0",domain:"video-gen",description:"Spanish translations for the video-gen package",owners:["platform"],stability:"experimental"},locale:"es",fallback:"en",messages:{"prompt.script.system":{value:`Eres un redactor de guiones de narración para vídeo.
1284
29
  Escribe un guión de narración para un vídeo corto (30-60 segundos).
1285
30
  {styleGuide}
1286
31
 
@@ -1291,12 +36,7 @@ Devuelve JSON con la forma:
1291
36
  }
1292
37
 
1293
38
  Los identificadores de escena deben ser: "intro", "problems", "solutions", "metrics", "cta".
1294
- Incluye solo los segmentos relevantes para el brief.`,
1295
- description: "Script generator LLM system prompt",
1296
- placeholders: [{ name: "styleGuide", type: "string" }]
1297
- },
1298
- "prompt.scenePlanner.system": {
1299
- value: `Eres un planificador de escenas de vídeo para vídeos de marketing/documentación de ContractSpec.
39
+ Incluye solo los segmentos relevantes para el brief.`,description:"Script generator LLM system prompt",placeholders:[{name:"styleGuide",type:"string"}]},"prompt.scenePlanner.system":{value:`Eres un planificador de escenas de vídeo para vídeos de marketing/documentación de ContractSpec.
1300
40
  Dado un brief de contenido, divídelo en escenas de vídeo.
1301
41
 
1302
42
  Cada escena debe tener:
@@ -1312,125 +52,7 @@ Devuelve un objeto JSON con la forma:
1312
52
  }
1313
53
 
1314
54
  Mantén la duración total alrededor de {targetSeconds} segundos.
1315
- Prioriza la claridad y el ritmo. Cada escena debe comunicar una idea.`,
1316
- description: "Scene planner LLM system prompt",
1317
- placeholders: [
1318
- { name: "fps", type: "number" },
1319
- { name: "targetSeconds", type: "number" }
1320
- ]
1321
- },
1322
- "prompt.style.professional": {
1323
- value: "Usa un tono claro, autoritario y profesional. Sé conciso y directo.",
1324
- description: "Style guide for professional narration"
1325
- },
1326
- "prompt.style.casual": {
1327
- value: "Usa un tono amigable y conversacional. Sé accesible y cercano.",
1328
- description: "Style guide for casual narration"
1329
- },
1330
- "prompt.style.technical": {
1331
- value: "Usa un lenguaje técnico preciso. Sé detallado y exacto.",
1332
- description: "Style guide for technical narration"
1333
- },
1334
- "script.segment.challenge": {
1335
- value: "El desafío: {content}",
1336
- description: "Narration segment prefix for problems",
1337
- placeholders: [{ name: "content", type: "string" }]
1338
- },
1339
- "script.segment.solution": {
1340
- value: "La solución: {content}",
1341
- description: "Narration segment prefix for solutions",
1342
- placeholders: [{ name: "content", type: "string" }]
1343
- },
1344
- "script.segment.results": {
1345
- value: "Los resultados: {content}",
1346
- description: "Narration segment prefix for metrics",
1347
- placeholders: [{ name: "content", type: "string" }]
1348
- },
1349
- "scene.cta.default": {
1350
- value: "Más información",
1351
- description: "Default call-to-action text for scenes"
1352
- },
1353
- "scene.hook.problem": {
1354
- value: "El problema",
1355
- description: "Scene hook label for problem statement"
1356
- },
1357
- "scene.narration.problem": {
1358
- value: "El problema: {content}",
1359
- description: "Scene narration for problem statement",
1360
- placeholders: [{ name: "content", type: "string" }]
1361
- },
1362
- "scene.hook.solution": {
1363
- value: "La solución",
1364
- description: "Scene hook label for solution"
1365
- },
1366
- "scene.narration.solution": {
1367
- value: "La solución: {content}",
1368
- description: "Scene narration for solution",
1369
- placeholders: [{ name: "content", type: "string" }]
1370
- },
1371
- "scene.hook.results": {
1372
- value: "Resultados",
1373
- description: "Scene hook label for results/metrics"
1374
- },
1375
- "composition.apiOverview.generates": {
1376
- value: "Genera:",
1377
- description: "ApiOverview heading for generated outputs"
1378
- },
1379
- "composition.apiOverview.tagline": {
1380
- value: "Una spec. Todas las superficies.",
1381
- description: "ApiOverview default tagline"
1382
- },
1383
- "composition.apiOverview.output.rest": {
1384
- value: "Endpoint REST",
1385
- description: "Generated output label: REST"
1386
- },
1387
- "composition.apiOverview.output.graphql": {
1388
- value: "Mutación GraphQL",
1389
- description: "Generated output label: GraphQL"
1390
- },
1391
- "composition.apiOverview.output.prisma": {
1392
- value: "Modelo Prisma",
1393
- description: "Generated output label: Prisma"
1394
- },
1395
- "composition.apiOverview.output.typescript": {
1396
- value: "SDK TypeScript",
1397
- description: "Generated output label: TypeScript SDK"
1398
- },
1399
- "composition.apiOverview.output.mcp": {
1400
- value: "Herramienta MCP",
1401
- description: "Generated output label: MCP Tool"
1402
- },
1403
- "composition.apiOverview.output.openapi": {
1404
- value: "Spec OpenAPI",
1405
- description: "Generated output label: OpenAPI"
1406
- },
1407
- "composition.socialClip.cta": {
1408
- value: "Más información",
1409
- description: "SocialClip default CTA"
1410
- },
1411
- "composition.terminal.title": {
1412
- value: "Terminal",
1413
- description: "TerminalDemo default window title"
1414
- }
1415
- }
1416
- });
1417
-
1418
- // src/i18n/catalogs/fr.ts
1419
- import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
1420
- var frMessages = defineTranslation3({
1421
- meta: {
1422
- key: "video-gen.messages",
1423
- version: "1.0.0",
1424
- domain: "video-gen",
1425
- description: "French translations for the video-gen package",
1426
- owners: ["platform"],
1427
- stability: "experimental"
1428
- },
1429
- locale: "fr",
1430
- fallback: "en",
1431
- messages: {
1432
- "prompt.script.system": {
1433
- value: `Vous êtes un rédacteur de scripts de narration vidéo.
55
+ Prioriza la claridad y el ritmo. Cada escena debe comunicar una idea.`,description:"Scene planner LLM system prompt",placeholders:[{name:"fps",type:"number"},{name:"targetSeconds",type:"number"}]},"prompt.style.professional":{value:"Usa un tono claro, autoritario y profesional. Sé conciso y directo.",description:"Style guide for professional narration"},"prompt.style.casual":{value:"Usa un tono amigable y conversacional. Sé accesible y cercano.",description:"Style guide for casual narration"},"prompt.style.technical":{value:"Usa un lenguaje técnico preciso. Sé detallado y exacto.",description:"Style guide for technical narration"},"script.segment.challenge":{value:"El desafío: {content}",description:"Narration segment prefix for problems",placeholders:[{name:"content",type:"string"}]},"script.segment.solution":{value:"La solución: {content}",description:"Narration segment prefix for solutions",placeholders:[{name:"content",type:"string"}]},"script.segment.results":{value:"Los resultados: {content}",description:"Narration segment prefix for metrics",placeholders:[{name:"content",type:"string"}]},"scene.cta.default":{value:"Más información",description:"Default call-to-action text for scenes"},"scene.hook.problem":{value:"El problema",description:"Scene hook label for problem statement"},"scene.narration.problem":{value:"El problema: {content}",description:"Scene narration for problem statement",placeholders:[{name:"content",type:"string"}]},"scene.hook.solution":{value:"La solución",description:"Scene hook label for solution"},"scene.narration.solution":{value:"La solución: {content}",description:"Scene narration for solution",placeholders:[{name:"content",type:"string"}]},"scene.hook.results":{value:"Resultados",description:"Scene hook label for results/metrics"},"composition.apiOverview.generates":{value:"Genera:",description:"ApiOverview heading for generated outputs"},"composition.apiOverview.tagline":{value:"Una spec. Todas las superficies.",description:"ApiOverview default tagline"},"composition.apiOverview.output.rest":{value:"Endpoint REST",description:"Generated output label: REST"},"composition.apiOverview.output.graphql":{value:"Mutación GraphQL",description:"Generated output label: GraphQL"},"composition.apiOverview.output.prisma":{value:"Modelo Prisma",description:"Generated output label: Prisma"},"composition.apiOverview.output.typescript":{value:"SDK TypeScript",description:"Generated output label: TypeScript SDK"},"composition.apiOverview.output.mcp":{value:"Herramienta MCP",description:"Generated output label: MCP Tool"},"composition.apiOverview.output.openapi":{value:"Spec OpenAPI",description:"Generated output label: OpenAPI"},"composition.socialClip.cta":{value:"Más información",description:"SocialClip default CTA"},"composition.terminal.title":{value:"Terminal",description:"TerminalDemo default window title"}}});import{defineTranslation as L1}from"@contractspec/lib.contracts-spec/translations";var L8=L1({meta:{key:"video-gen.messages",version:"1.0.0",domain:"video-gen",description:"French translations for the video-gen package",owners:["platform"],stability:"experimental"},locale:"fr",fallback:"en",messages:{"prompt.script.system":{value:`Vous êtes un rédacteur de scripts de narration vidéo.
1434
56
  Écrivez un script de narration pour une courte vidéo (30-60 secondes).
1435
57
  {styleGuide}
1436
58
 
@@ -1441,12 +63,7 @@ Retournez du JSON avec la forme :
1441
63
  }
1442
64
 
1443
65
  Les identifiants de scène doivent être : "intro", "problems", "solutions", "metrics", "cta".
1444
- N'incluez que les segments pertinents au brief.`,
1445
- description: "Script generator LLM system prompt",
1446
- placeholders: [{ name: "styleGuide", type: "string" }]
1447
- },
1448
- "prompt.scenePlanner.system": {
1449
- value: `Vous êtes un planificateur de scènes vidéo pour les vidéos marketing/documentation de ContractSpec.
66
+ N'incluez que les segments pertinents au brief.`,description:"Script generator LLM system prompt",placeholders:[{name:"styleGuide",type:"string"}]},"prompt.scenePlanner.system":{value:`Vous êtes un planificateur de scènes vidéo pour les vidéos marketing/documentation de ContractSpec.
1450
67
  À partir d'un brief, décomposez-le en scènes vidéo.
1451
68
 
1452
69
  Chaque scène doit avoir :
@@ -1462,512 +79,4 @@ Retournez un objet JSON avec la forme :
1462
79
  }
1463
80
 
1464
81
  Gardez la durée totale autour de {targetSeconds} secondes.
1465
- Privilégiez la clarté et le rythme. Chaque scène doit communiquer une idée.`,
1466
- description: "Scene planner LLM system prompt",
1467
- placeholders: [
1468
- { name: "fps", type: "number" },
1469
- { name: "targetSeconds", type: "number" }
1470
- ]
1471
- },
1472
- "prompt.style.professional": {
1473
- value: "Utilisez un ton clair, autoritaire et professionnel. Soyez concis et direct.",
1474
- description: "Style guide for professional narration"
1475
- },
1476
- "prompt.style.casual": {
1477
- value: "Utilisez un ton amical et conversationnel. Soyez accessible et proche.",
1478
- description: "Style guide for casual narration"
1479
- },
1480
- "prompt.style.technical": {
1481
- value: "Utilisez un langage technique précis. Soyez détaillé et exact.",
1482
- description: "Style guide for technical narration"
1483
- },
1484
- "script.segment.challenge": {
1485
- value: "Le défi : {content}",
1486
- description: "Narration segment prefix for problems",
1487
- placeholders: [{ name: "content", type: "string" }]
1488
- },
1489
- "script.segment.solution": {
1490
- value: "La solution : {content}",
1491
- description: "Narration segment prefix for solutions",
1492
- placeholders: [{ name: "content", type: "string" }]
1493
- },
1494
- "script.segment.results": {
1495
- value: "Les résultats : {content}",
1496
- description: "Narration segment prefix for metrics",
1497
- placeholders: [{ name: "content", type: "string" }]
1498
- },
1499
- "scene.cta.default": {
1500
- value: "En savoir plus",
1501
- description: "Default call-to-action text for scenes"
1502
- },
1503
- "scene.hook.problem": {
1504
- value: "Le problème",
1505
- description: "Scene hook label for problem statement"
1506
- },
1507
- "scene.narration.problem": {
1508
- value: "Le problème : {content}",
1509
- description: "Scene narration for problem statement",
1510
- placeholders: [{ name: "content", type: "string" }]
1511
- },
1512
- "scene.hook.solution": {
1513
- value: "La solution",
1514
- description: "Scene hook label for solution"
1515
- },
1516
- "scene.narration.solution": {
1517
- value: "La solution : {content}",
1518
- description: "Scene narration for solution",
1519
- placeholders: [{ name: "content", type: "string" }]
1520
- },
1521
- "scene.hook.results": {
1522
- value: "Résultats",
1523
- description: "Scene hook label for results/metrics"
1524
- },
1525
- "composition.apiOverview.generates": {
1526
- value: "Génère :",
1527
- description: "ApiOverview heading for generated outputs"
1528
- },
1529
- "composition.apiOverview.tagline": {
1530
- value: "Un spec. Toutes les surfaces.",
1531
- description: "ApiOverview default tagline"
1532
- },
1533
- "composition.apiOverview.output.rest": {
1534
- value: "Endpoint REST",
1535
- description: "Generated output label: REST"
1536
- },
1537
- "composition.apiOverview.output.graphql": {
1538
- value: "Mutation GraphQL",
1539
- description: "Generated output label: GraphQL"
1540
- },
1541
- "composition.apiOverview.output.prisma": {
1542
- value: "Modèle Prisma",
1543
- description: "Generated output label: Prisma"
1544
- },
1545
- "composition.apiOverview.output.typescript": {
1546
- value: "SDK TypeScript",
1547
- description: "Generated output label: TypeScript SDK"
1548
- },
1549
- "composition.apiOverview.output.mcp": {
1550
- value: "Outil MCP",
1551
- description: "Generated output label: MCP Tool"
1552
- },
1553
- "composition.apiOverview.output.openapi": {
1554
- value: "Spec OpenAPI",
1555
- description: "Generated output label: OpenAPI"
1556
- },
1557
- "composition.socialClip.cta": {
1558
- value: "En savoir plus",
1559
- description: "SocialClip default CTA"
1560
- },
1561
- "composition.terminal.title": {
1562
- value: "Terminal",
1563
- description: "TerminalDemo default window title"
1564
- }
1565
- }
1566
- });
1567
-
1568
- // src/i18n/keys.ts
1569
- var PROMPT_KEYS = {
1570
- "prompt.script.system": "prompt.script.system",
1571
- "prompt.scenePlanner.system": "prompt.scenePlanner.system",
1572
- "prompt.style.professional": "prompt.style.professional",
1573
- "prompt.style.casual": "prompt.style.casual",
1574
- "prompt.style.technical": "prompt.style.technical"
1575
- };
1576
- var SCRIPT_KEYS = {
1577
- "script.segment.challenge": "script.segment.challenge",
1578
- "script.segment.solution": "script.segment.solution",
1579
- "script.segment.results": "script.segment.results"
1580
- };
1581
- var SCENE_KEYS = {
1582
- "scene.cta.default": "scene.cta.default",
1583
- "scene.hook.problem": "scene.hook.problem",
1584
- "scene.narration.problem": "scene.narration.problem",
1585
- "scene.hook.solution": "scene.hook.solution",
1586
- "scene.narration.solution": "scene.narration.solution",
1587
- "scene.hook.results": "scene.hook.results"
1588
- };
1589
- var COMPOSITION_KEYS = {
1590
- "composition.apiOverview.generates": "composition.apiOverview.generates",
1591
- "composition.apiOverview.tagline": "composition.apiOverview.tagline",
1592
- "composition.apiOverview.output.rest": "composition.apiOverview.output.rest",
1593
- "composition.apiOverview.output.graphql": "composition.apiOverview.output.graphql",
1594
- "composition.apiOverview.output.prisma": "composition.apiOverview.output.prisma",
1595
- "composition.apiOverview.output.typescript": "composition.apiOverview.output.typescript",
1596
- "composition.apiOverview.output.mcp": "composition.apiOverview.output.mcp",
1597
- "composition.apiOverview.output.openapi": "composition.apiOverview.output.openapi",
1598
- "composition.socialClip.cta": "composition.socialClip.cta",
1599
- "composition.terminal.title": "composition.terminal.title"
1600
- };
1601
- var I18N_KEYS = {
1602
- ...PROMPT_KEYS,
1603
- ...SCRIPT_KEYS,
1604
- ...SCENE_KEYS,
1605
- ...COMPOSITION_KEYS
1606
- };
1607
-
1608
- // src/i18n/locale.ts
1609
- import {
1610
- DEFAULT_LOCALE,
1611
- isSupportedLocale,
1612
- resolveLocale,
1613
- SUPPORTED_LOCALES
1614
- } from "@contractspec/lib.contracts-spec/translations";
1615
-
1616
- // src/i18n/messages.ts
1617
- import {
1618
- createI18nFactory
1619
- } from "@contractspec/lib.contracts-spec/translations";
1620
- var factory = createI18nFactory({
1621
- specKey: "video-gen.messages",
1622
- catalogs: [enMessages, frMessages, esMessages]
1623
- });
1624
- var createVideoGenI18n = factory.create;
1625
- var getDefaultI18n = factory.getDefault;
1626
- var resetI18nRegistry = factory.resetRegistry;
1627
- // src/generators/scene-planner.ts
1628
- class ScenePlanner {
1629
- llm;
1630
- model;
1631
- temperature;
1632
- fps;
1633
- i18n;
1634
- modelSelector;
1635
- selectionContext;
1636
- constructor(options) {
1637
- this.llm = options?.llm;
1638
- this.model = options?.model;
1639
- this.temperature = options?.temperature ?? 0.3;
1640
- this.fps = options?.fps ?? DEFAULT_FPS;
1641
- this.i18n = createVideoGenI18n(options?.locale);
1642
- this.modelSelector = options?.modelSelector;
1643
- this.selectionContext = options?.selectionContext;
1644
- }
1645
- async plan(brief) {
1646
- if (this.llm) {
1647
- return this.planWithLlm(brief);
1648
- }
1649
- return this.planDeterministic(brief);
1650
- }
1651
- planDeterministic(brief) {
1652
- const { content } = brief;
1653
- const { t } = this.i18n;
1654
- const scenes = [];
1655
- const fps = this.fps;
1656
- scenes.push({
1657
- compositionId: "SocialClip",
1658
- props: {
1659
- hook: content.title,
1660
- message: content.summary,
1661
- points: content.solutions.slice(0, 3),
1662
- cta: content.callToAction ?? t("scene.cta.default")
1663
- },
1664
- durationInFrames: 3 * fps,
1665
- narrationText: `${content.title}. ${content.summary}`
1666
- });
1667
- if (content.problems.length > 0) {
1668
- scenes.push({
1669
- compositionId: "SocialClip",
1670
- props: {
1671
- hook: t("scene.hook.problem"),
1672
- message: content.problems[0] ?? "",
1673
- points: content.problems.slice(1, 4)
1674
- },
1675
- durationInFrames: 4 * fps,
1676
- narrationText: t("scene.narration.problem", {
1677
- content: content.problems.join(". ")
1678
- })
1679
- });
1680
- }
1681
- if (content.solutions.length > 0) {
1682
- scenes.push({
1683
- compositionId: "SocialClip",
1684
- props: {
1685
- hook: t("scene.hook.solution"),
1686
- message: content.solutions[0] ?? "",
1687
- points: content.solutions.slice(1, 4)
1688
- },
1689
- durationInFrames: 5 * fps,
1690
- narrationText: t("scene.narration.solution", {
1691
- content: content.solutions.join(". ")
1692
- })
1693
- });
1694
- }
1695
- if (content.metrics && content.metrics.length > 0) {
1696
- scenes.push({
1697
- compositionId: "SocialClip",
1698
- props: {
1699
- hook: t("scene.hook.results"),
1700
- message: content.metrics[0] ?? "",
1701
- points: content.metrics.slice(1, 3)
1702
- },
1703
- durationInFrames: 3 * fps,
1704
- narrationText: content.metrics.join(". ")
1705
- });
1706
- }
1707
- if (content.callToAction) {
1708
- scenes.push({
1709
- compositionId: "SocialClip",
1710
- props: {
1711
- hook: content.callToAction,
1712
- message: "",
1713
- cta: content.callToAction
1714
- },
1715
- durationInFrames: 2 * fps,
1716
- narrationText: content.callToAction
1717
- });
1718
- }
1719
- if (brief.targetDurationSeconds) {
1720
- const targetFrames = brief.targetDurationSeconds * fps;
1721
- const currentFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
1722
- const ratio = targetFrames / currentFrames;
1723
- for (const scene of scenes) {
1724
- scene.durationInFrames = Math.round(scene.durationInFrames * ratio);
1725
- }
1726
- }
1727
- const totalDuration = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
1728
- const narrationScript = scenes.filter((s) => s.narrationText).map((s) => s.narrationText).join(" ");
1729
- return {
1730
- scenes,
1731
- estimatedDurationSeconds: totalDuration / fps,
1732
- narrationScript
1733
- };
1734
- }
1735
- async resolveModel() {
1736
- if (this.model)
1737
- return this.model;
1738
- if (this.modelSelector) {
1739
- const ctx = this.selectionContext ?? {
1740
- taskDimension: "reasoning"
1741
- };
1742
- const result = await this.modelSelector.select(ctx);
1743
- return result.modelId;
1744
- }
1745
- return;
1746
- }
1747
- async planWithLlm(brief) {
1748
- const { t } = this.i18n;
1749
- const messages = [
1750
- {
1751
- role: "system",
1752
- content: [
1753
- {
1754
- type: "text",
1755
- text: t("prompt.scenePlanner.system", {
1756
- fps: this.fps,
1757
- targetSeconds: brief.targetDurationSeconds ?? 30
1758
- })
1759
- }
1760
- ]
1761
- },
1762
- {
1763
- role: "user",
1764
- content: [
1765
- {
1766
- type: "text",
1767
- text: JSON.stringify(brief.content)
1768
- }
1769
- ]
1770
- }
1771
- ];
1772
- if (!this.llm) {
1773
- return this.planDeterministic(brief);
1774
- }
1775
- try {
1776
- const model = await this.resolveModel();
1777
- const response = await this.llm.chat(messages, {
1778
- model,
1779
- temperature: this.temperature,
1780
- responseFormat: "json"
1781
- });
1782
- const text = response.message.content.find((p) => p.type === "text");
1783
- if (!text || text.type !== "text") {
1784
- return this.planDeterministic(brief);
1785
- }
1786
- const parsed = JSON.parse(text.text);
1787
- const totalDuration = parsed.scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
1788
- return {
1789
- scenes: parsed.scenes,
1790
- estimatedDurationSeconds: totalDuration / this.fps,
1791
- narrationScript: parsed.narrationScript
1792
- };
1793
- } catch {
1794
- return this.planDeterministic(brief);
1795
- }
1796
- }
1797
- }
1798
-
1799
- // src/generators/video-generator.ts
1800
- import { VIDEO_FORMATS as VIDEO_FORMATS2 } from "@contractspec/lib.contracts-integrations/integrations/providers/video";
1801
- class VideoGenerator {
1802
- scenePlanner;
1803
- voice;
1804
- transcriber;
1805
- image;
1806
- fps;
1807
- constructor(options) {
1808
- this.fps = options?.fps ?? DEFAULT_FPS;
1809
- this.voice = options?.voice;
1810
- this.transcriber = options?.transcriber;
1811
- this.image = options?.image;
1812
- this.scenePlanner = new ScenePlanner({
1813
- llm: options?.llm,
1814
- model: options?.model,
1815
- temperature: options?.temperature,
1816
- fps: this.fps,
1817
- locale: options?.locale,
1818
- modelSelector: options?.modelSelector,
1819
- selectionContext: options?.selectionContext
1820
- });
1821
- }
1822
- async generate(brief) {
1823
- const scenePlan = await this.scenePlanner.plan(brief);
1824
- const scenes = scenePlan.scenes.map((planned, i) => ({
1825
- id: `scene-${i}`,
1826
- compositionId: planned.compositionId,
1827
- props: planned.props,
1828
- durationInFrames: planned.durationInFrames,
1829
- narrationText: planned.narrationText
1830
- }));
1831
- let ttsProject;
1832
- let narrationAudio;
1833
- if (brief.narration?.enabled && this.voice) {
1834
- try {
1835
- ttsProject = await this.voice.synthesizeForVideo({
1836
- content: brief.content,
1837
- scenePlan: {
1838
- scenes: scenes.map((s) => ({
1839
- id: s.id,
1840
- compositionId: s.compositionId,
1841
- durationInFrames: s.durationInFrames,
1842
- narrationText: s.narrationText
1843
- })),
1844
- estimatedDurationSeconds: scenePlan.estimatedDurationSeconds
1845
- },
1846
- voice: { voiceId: brief.narration.voiceId ?? "" },
1847
- pacing: { strategy: "scene-matched" },
1848
- fps: this.fps
1849
- });
1850
- if (ttsProject.timingMap) {
1851
- for (const seg of ttsProject.timingMap.segments) {
1852
- const scene = scenes.find((s) => s.id === seg.sceneId);
1853
- if (scene) {
1854
- scene.durationInFrames = seg.recommendedSceneDurationInFrames;
1855
- }
1856
- }
1857
- }
1858
- if (ttsProject.assembledAudio) {
1859
- narrationAudio = {
1860
- data: ttsProject.assembledAudio.data,
1861
- format: ttsProject.assembledAudio.format === "wav" ? "wav" : "mp3",
1862
- durationSeconds: (ttsProject.assembledAudio.durationMs ?? 0) / 1000,
1863
- volume: 1
1864
- };
1865
- }
1866
- } catch {}
1867
- }
1868
- let subtitles;
1869
- if (this.transcriber && ttsProject?.assembledAudio) {
1870
- try {
1871
- const transcription = await this.transcriber.transcribe({
1872
- audio: ttsProject.assembledAudio,
1873
- subtitleFormat: "vtt"
1874
- });
1875
- subtitles = transcription.subtitles;
1876
- } catch {}
1877
- }
1878
- let thumbnail;
1879
- if (this.image) {
1880
- try {
1881
- const thumbProject = await this.image.generate({
1882
- content: brief.content,
1883
- purpose: "video-thumbnail",
1884
- format: "png",
1885
- style: "photorealistic"
1886
- });
1887
- const imageUrl = thumbProject.results?.images[0]?.url;
1888
- thumbnail = {
1889
- prompt: thumbProject.prompt.text,
1890
- ...imageUrl ? { imageUrl } : {}
1891
- };
1892
- } catch {}
1893
- }
1894
- const format = brief.format ?? VIDEO_FORMATS2.landscape;
1895
- const totalDurationInFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
1896
- const project = {
1897
- id: generateProjectId(),
1898
- scenes,
1899
- totalDurationInFrames,
1900
- fps: this.fps,
1901
- format,
1902
- audio: narrationAudio ? { narration: narrationAudio } : undefined,
1903
- subtitles,
1904
- voiceTimingMap: ttsProject?.timingMap,
1905
- thumbnail
1906
- };
1907
- return project;
1908
- }
1909
- }
1910
- function generateProjectId() {
1911
- const timestamp = Date.now().toString(36);
1912
- const random = Math.random().toString(36).slice(2, 8);
1913
- return `vp_${timestamp}_${random}`;
1914
- }
1915
- // src/renderers/config.ts
1916
- var defaultRenderConfig = {
1917
- codec: "h264",
1918
- outputFormat: "mp4",
1919
- crf: 18,
1920
- pixelFormat: "yuv420p"
1921
- };
1922
- var codecFormatMap = {
1923
- h264: "mp4",
1924
- h265: "mp4",
1925
- vp8: "webm",
1926
- vp9: "webm"
1927
- };
1928
- var qualityPresets = {
1929
- draft: { crf: 28, concurrency: 1 },
1930
- standard: { crf: 18, concurrency: undefined },
1931
- high: { crf: 12, concurrency: undefined }
1932
- };
1933
- function resolveRenderConfig(userConfig, preset) {
1934
- const presetValues = preset ? qualityPresets[preset] : {};
1935
- return {
1936
- ...defaultRenderConfig,
1937
- ...presetValues,
1938
- ...userConfig
1939
- };
1940
- }
1941
-
1942
- // src/types.ts
1943
- import { VIDEO_FORMATS as VIDEO_FORMATS3 } from "@contractspec/lib.contracts-integrations/integrations/providers/video";
1944
- export {
1945
- videoTypography,
1946
- videoTransitions,
1947
- videoSafeZone,
1948
- videoPositions,
1949
- videoEasing,
1950
- videoDurations,
1951
- scaleTypography,
1952
- scaleSafeZone,
1953
- resolveRenderConfig,
1954
- qualityPresets,
1955
- getAllFormatVariants,
1956
- defaultVideoTheme,
1957
- defaultVideoColors,
1958
- defaultTokens,
1959
- defaultRenderConfig,
1960
- codecFormatMap,
1961
- VideoGenerator,
1962
- TerminalDemo,
1963
- Terminal,
1964
- SocialClip,
1965
- SceneTransitionWrapper,
1966
- ScenePlanner,
1967
- ProgressBar,
1968
- DEFAULT_FPS,
1969
- CodeBlock,
1970
- BrandFrame,
1971
- ApiOverview,
1972
- AnimatedText
1973
- };
82
+ Privilégiez la clarté et le rythme. Chaque scène doit communiquer une idée.`,description:"Scene planner LLM system prompt",placeholders:[{name:"fps",type:"number"},{name:"targetSeconds",type:"number"}]},"prompt.style.professional":{value:"Utilisez un ton clair, autoritaire et professionnel. Soyez concis et direct.",description:"Style guide for professional narration"},"prompt.style.casual":{value:"Utilisez un ton amical et conversationnel. Soyez accessible et proche.",description:"Style guide for casual narration"},"prompt.style.technical":{value:"Utilisez un langage technique précis. Soyez détaillé et exact.",description:"Style guide for technical narration"},"script.segment.challenge":{value:"Le défi : {content}",description:"Narration segment prefix for problems",placeholders:[{name:"content",type:"string"}]},"script.segment.solution":{value:"La solution : {content}",description:"Narration segment prefix for solutions",placeholders:[{name:"content",type:"string"}]},"script.segment.results":{value:"Les résultats : {content}",description:"Narration segment prefix for metrics",placeholders:[{name:"content",type:"string"}]},"scene.cta.default":{value:"En savoir plus",description:"Default call-to-action text for scenes"},"scene.hook.problem":{value:"Le problème",description:"Scene hook label for problem statement"},"scene.narration.problem":{value:"Le problème : {content}",description:"Scene narration for problem statement",placeholders:[{name:"content",type:"string"}]},"scene.hook.solution":{value:"La solution",description:"Scene hook label for solution"},"scene.narration.solution":{value:"La solution : {content}",description:"Scene narration for solution",placeholders:[{name:"content",type:"string"}]},"scene.hook.results":{value:"Résultats",description:"Scene hook label for results/metrics"},"composition.apiOverview.generates":{value:"Génère :",description:"ApiOverview heading for generated outputs"},"composition.apiOverview.tagline":{value:"Un spec. Toutes les surfaces.",description:"ApiOverview default tagline"},"composition.apiOverview.output.rest":{value:"Endpoint REST",description:"Generated output label: REST"},"composition.apiOverview.output.graphql":{value:"Mutation GraphQL",description:"Generated output label: GraphQL"},"composition.apiOverview.output.prisma":{value:"Modèle Prisma",description:"Generated output label: Prisma"},"composition.apiOverview.output.typescript":{value:"SDK TypeScript",description:"Generated output label: TypeScript SDK"},"composition.apiOverview.output.mcp":{value:"Outil MCP",description:"Generated output label: MCP Tool"},"composition.apiOverview.output.openapi":{value:"Spec OpenAPI",description:"Generated output label: OpenAPI"},"composition.socialClip.cta":{value:"En savoir plus",description:"SocialClip default CTA"},"composition.terminal.title":{value:"Terminal",description:"TerminalDemo default window title"}}});var R8={"prompt.script.system":"prompt.script.system","prompt.scenePlanner.system":"prompt.scenePlanner.system","prompt.style.professional":"prompt.style.professional","prompt.style.casual":"prompt.style.casual","prompt.style.technical":"prompt.style.technical"},B8={"script.segment.challenge":"script.segment.challenge","script.segment.solution":"script.segment.solution","script.segment.results":"script.segment.results"},Z8={"scene.cta.default":"scene.cta.default","scene.hook.problem":"scene.hook.problem","scene.narration.problem":"scene.narration.problem","scene.hook.solution":"scene.hook.solution","scene.narration.solution":"scene.narration.solution","scene.hook.results":"scene.hook.results"},_8={"composition.apiOverview.generates":"composition.apiOverview.generates","composition.apiOverview.tagline":"composition.apiOverview.tagline","composition.apiOverview.output.rest":"composition.apiOverview.output.rest","composition.apiOverview.output.graphql":"composition.apiOverview.output.graphql","composition.apiOverview.output.prisma":"composition.apiOverview.output.prisma","composition.apiOverview.output.typescript":"composition.apiOverview.output.typescript","composition.apiOverview.output.mcp":"composition.apiOverview.output.mcp","composition.apiOverview.output.openapi":"composition.apiOverview.output.openapi","composition.socialClip.cta":"composition.socialClip.cta","composition.terminal.title":"composition.terminal.title"},z1={...R8,...B8,...Z8,..._8};import{DEFAULT_LOCALE as H1,isSupportedLocale as J1,resolveLocale as Q1,SUPPORTED_LOCALES as $1}from"@contractspec/lib.contracts-spec/translations";import{createI18nFactory as W1}from"@contractspec/lib.contracts-spec/translations";var z8=W1({specKey:"video-gen.messages",catalogs:[G8,L8,K8]}),H8=z8.create,X1=z8.getDefault,U1=z8.resetRegistry;class l{llm;model;temperature;fps;i18n;modelSelector;selectionContext;constructor(G){this.llm=G?.llm,this.model=G?.model,this.temperature=G?.temperature??0.3,this.fps=G?.fps??j,this.i18n=H8(G?.locale),this.modelSelector=G?.modelSelector,this.selectionContext=G?.selectionContext}async plan(G){if(this.llm)return this.planWithLlm(G);return this.planDeterministic(G)}planDeterministic(G){let{content:K}=G,{t:L}=this.i18n,z=[],H=this.fps;if(z.push({compositionId:"SocialClip",props:{hook:K.title,message:K.summary,points:K.solutions.slice(0,3),cta:K.callToAction??L("scene.cta.default")},durationInFrames:3*H,narrationText:`${K.title}. ${K.summary}`}),K.problems.length>0)z.push({compositionId:"SocialClip",props:{hook:L("scene.hook.problem"),message:K.problems[0]??"",points:K.problems.slice(1,4)},durationInFrames:4*H,narrationText:L("scene.narration.problem",{content:K.problems.join(". ")})});if(K.solutions.length>0)z.push({compositionId:"SocialClip",props:{hook:L("scene.hook.solution"),message:K.solutions[0]??"",points:K.solutions.slice(1,4)},durationInFrames:5*H,narrationText:L("scene.narration.solution",{content:K.solutions.join(". ")})});if(K.metrics&&K.metrics.length>0)z.push({compositionId:"SocialClip",props:{hook:L("scene.hook.results"),message:K.metrics[0]??"",points:K.metrics.slice(1,3)},durationInFrames:3*H,narrationText:K.metrics.join(". ")});if(K.callToAction)z.push({compositionId:"SocialClip",props:{hook:K.callToAction,message:"",cta:K.callToAction},durationInFrames:2*H,narrationText:K.callToAction});if(G.targetDurationSeconds){let W=G.targetDurationSeconds*H,U=z.reduce((J,X)=>J+X.durationInFrames,0),M=W/U;for(let J of z)J.durationInFrames=Math.round(J.durationInFrames*M)}let Q=z.reduce((W,U)=>W+U.durationInFrames,0),$=z.filter((W)=>W.narrationText).map((W)=>W.narrationText).join(" ");return{scenes:z,estimatedDurationSeconds:Q/H,narrationScript:$}}async resolveModel(){if(this.model)return this.model;if(this.modelSelector){let G=this.selectionContext??{taskDimension:"reasoning"};return(await this.modelSelector.select(G)).modelId}return}async planWithLlm(G){let{t:K}=this.i18n,L=[{role:"system",content:[{type:"text",text:K("prompt.scenePlanner.system",{fps:this.fps,targetSeconds:G.targetDurationSeconds??30})}]},{role:"user",content:[{type:"text",text:JSON.stringify(G.content)}]}];if(!this.llm)return this.planDeterministic(G);try{let z=await this.resolveModel(),Q=(await this.llm.chat(L,{model:z,temperature:this.temperature,responseFormat:"json"})).message.content.find((U)=>U.type==="text");if(!Q||Q.type!=="text")return this.planDeterministic(G);let $=JSON.parse(Q.text),W=$.scenes.reduce((U,M)=>U+M.durationInFrames,0);return{scenes:$.scenes,estimatedDurationSeconds:W/this.fps,narrationScript:$.narrationScript}}catch{return this.planDeterministic(G)}}}import{VIDEO_FORMATS as N1}from"@contractspec/lib.contracts-integrations/integrations/providers/video";class q8{scenePlanner;voice;transcriber;image;fps;constructor(G){this.fps=G?.fps??j,this.voice=G?.voice,this.transcriber=G?.transcriber,this.image=G?.image,this.scenePlanner=new l({llm:G?.llm,model:G?.model,temperature:G?.temperature,fps:this.fps,locale:G?.locale,modelSelector:G?.modelSelector,selectionContext:G?.selectionContext})}async generate(G){let K=await this.scenePlanner.plan(G),L=K.scenes.map((J,X)=>({id:`scene-${X}`,compositionId:J.compositionId,props:J.props,durationInFrames:J.durationInFrames,narrationText:J.narrationText})),z,H;if(G.narration?.enabled&&this.voice)try{if(z=await this.voice.synthesizeForVideo({content:G.content,scenePlan:{scenes:L.map((J)=>({id:J.id,compositionId:J.compositionId,durationInFrames:J.durationInFrames,narrationText:J.narrationText})),estimatedDurationSeconds:K.estimatedDurationSeconds},voice:{voiceId:G.narration.voiceId??""},pacing:{strategy:"scene-matched"},fps:this.fps}),z.timingMap)for(let J of z.timingMap.segments){let X=L.find((N)=>N.id===J.sceneId);if(X)X.durationInFrames=J.recommendedSceneDurationInFrames}if(z.assembledAudio)H={data:z.assembledAudio.data,format:z.assembledAudio.format==="wav"?"wav":"mp3",durationSeconds:(z.assembledAudio.durationMs??0)/1000,volume:1}}catch{}let Q;if(this.transcriber&&z?.assembledAudio)try{Q=(await this.transcriber.transcribe({audio:z.assembledAudio,subtitleFormat:"vtt"})).subtitles}catch{}let $;if(this.image)try{let J=await this.image.generate({content:G.content,purpose:"video-thumbnail",format:"png",style:"photorealistic"}),X=J.results?.images[0]?.url;$={prompt:J.prompt.text,...X?{imageUrl:X}:{}}}catch{}let W=G.format??N1.landscape,U=L.reduce((J,X)=>J+X.durationInFrames,0);return{id:M1(),scenes:L,totalDurationInFrames:U,fps:this.fps,format:W,audio:H?{narration:H}:void 0,subtitles:Q,voiceTimingMap:z?.timingMap,thumbnail:$}}}function M1(){let G=Date.now().toString(36),K=Math.random().toString(36).slice(2,8);return`vp_${G}_${K}`}var I8={codec:"h264",outputFormat:"mp4",crf:18,pixelFormat:"yuv420p"},Y1={h264:"mp4",h265:"mp4",vp8:"webm",vp9:"webm"},D8={draft:{crf:28,concurrency:1},standard:{crf:18,concurrency:void 0},high:{crf:12,concurrency:void 0}};function R1(G,K){let L=K?D8[K]:{};return{...I8,...L,...G}}import{VIDEO_FORMATS as SK}from"@contractspec/lib.contracts-integrations/integrations/providers/video";export{C as videoTypography,I1 as videoTransitions,x as videoSafeZone,v1 as videoPositions,R as videoEasing,V as videoDurations,v as scaleTypography,J8 as scaleSafeZone,R1 as resolveRenderConfig,D8 as qualityPresets,A1 as getAllFormatVariants,P as defaultVideoTheme,y as defaultVideoColors,b as defaultTokens,I8 as defaultRenderConfig,Y1 as codecFormatMap,q8 as VideoGenerator,e8 as TerminalDemo,t as Terminal,a8 as SocialClip,d8 as SceneTransitionWrapper,l as ScenePlanner,T as ProgressBar,j as DEFAULT_FPS,n as CodeBlock,S as BrandFrame,f8 as ApiOverview,I as AnimatedText};