@contractspec/lib.video-gen 2.7.6 → 2.7.7

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 (75) hide show
  1. package/README.md +67 -25
  2. package/dist/browser/compositions/api-overview.js +114 -114
  3. package/dist/browser/compositions/index.js +115 -115
  4. package/dist/browser/compositions/primitives/index.js +113 -113
  5. package/dist/browser/compositions/social-clip.js +114 -114
  6. package/dist/browser/compositions/terminal-demo.js +113 -113
  7. package/dist/browser/design/index.js +35 -35
  8. package/dist/browser/generators/index.js +94 -94
  9. package/dist/browser/generators/scene-planner.js +94 -94
  10. package/dist/browser/generators/script-generator.js +94 -94
  11. package/dist/browser/generators/video-generator.js +94 -94
  12. package/dist/browser/i18n/catalogs/index.js +74 -74
  13. package/dist/browser/i18n/index.js +94 -94
  14. package/dist/browser/i18n/locale.js +2 -2
  15. package/dist/browser/i18n/messages.js +74 -74
  16. package/dist/browser/index.js +212 -212
  17. package/dist/browser/player/demo-player.js +116 -116
  18. package/dist/browser/player/index.js +116 -116
  19. package/dist/browser/remotion/Root.js +115 -115
  20. package/dist/browser/remotion/index.js +115 -115
  21. package/dist/compositions/api-overview.js +114 -114
  22. package/dist/compositions/index.d.ts +4 -4
  23. package/dist/compositions/index.js +115 -115
  24. package/dist/compositions/primitives/animated-text.d.ts +1 -1
  25. package/dist/compositions/primitives/brand-frame.d.ts +1 -1
  26. package/dist/compositions/primitives/index.d.ts +8 -8
  27. package/dist/compositions/primitives/index.js +113 -113
  28. package/dist/compositions/primitives/transition.d.ts +1 -1
  29. package/dist/compositions/social-clip.js +114 -114
  30. package/dist/compositions/terminal-demo.js +113 -113
  31. package/dist/design/index.d.ts +2 -2
  32. package/dist/design/index.js +35 -35
  33. package/dist/generators/index.d.ts +2 -2
  34. package/dist/generators/index.js +94 -94
  35. package/dist/generators/scene-planner.d.ts +1 -1
  36. package/dist/generators/scene-planner.js +94 -94
  37. package/dist/generators/script-generator.d.ts +2 -2
  38. package/dist/generators/script-generator.js +94 -94
  39. package/dist/generators/video-generator.js +94 -94
  40. package/dist/i18n/catalogs/index.d.ts +1 -1
  41. package/dist/i18n/catalogs/index.js +74 -74
  42. package/dist/i18n/index.d.ts +7 -7
  43. package/dist/i18n/index.js +94 -94
  44. package/dist/i18n/locale.d.ts +1 -1
  45. package/dist/i18n/locale.js +2 -2
  46. package/dist/i18n/messages.js +74 -74
  47. package/dist/index.d.ts +3 -3
  48. package/dist/index.js +212 -212
  49. package/dist/node/compositions/api-overview.js +114 -114
  50. package/dist/node/compositions/index.js +115 -115
  51. package/dist/node/compositions/primitives/index.js +113 -113
  52. package/dist/node/compositions/social-clip.js +114 -114
  53. package/dist/node/compositions/terminal-demo.js +113 -113
  54. package/dist/node/design/index.js +35 -35
  55. package/dist/node/generators/index.js +94 -94
  56. package/dist/node/generators/scene-planner.js +94 -94
  57. package/dist/node/generators/script-generator.js +94 -94
  58. package/dist/node/generators/video-generator.js +94 -94
  59. package/dist/node/i18n/catalogs/index.js +74 -74
  60. package/dist/node/i18n/index.js +94 -94
  61. package/dist/node/i18n/locale.js +2 -2
  62. package/dist/node/i18n/messages.js +74 -74
  63. package/dist/node/index.js +212 -212
  64. package/dist/node/player/demo-player.js +116 -116
  65. package/dist/node/player/index.js +116 -116
  66. package/dist/node/remotion/Root.js +115 -115
  67. package/dist/node/remotion/index.js +115 -115
  68. package/dist/player/demo-player.js +116 -116
  69. package/dist/player/index.d.ts +1 -1
  70. package/dist/player/index.js +116 -116
  71. package/dist/remotion/Root.js +115 -115
  72. package/dist/remotion/index.js +115 -115
  73. package/dist/renderers/index.d.ts +2 -2
  74. package/dist/types.d.ts +6 -6
  75. package/package.json +15 -15
package/README.md CHANGED
@@ -1,37 +1,79 @@
1
1
  # @contractspec/lib.video-gen
2
2
 
3
- Website: https://contractspec.io/
3
+ **AI-powered video generation with Remotion: compositions, rendering, and design integration.**
4
4
 
5
- Programmatic video generation using Remotion. Follows the same generator pattern as `@contractspec/lib.content-gen` and consumes contracts from video provider integrations. All generators work deterministically by default -- LLM integration is optional and enhances output when available.
5
+ ## What It Provides
6
6
 
7
- ## Modules
7
+ - **Layer**: lib.
8
+ - **Consumers**: bundles, video-studio app.
9
+ - `src/docs/` contains docblocks and documentation-facing exports.
10
+ - Related ContractSpec packages include `@contractspec/lib.ai-providers`, `@contractspec/lib.content-gen`, `@contractspec/lib.contracts-integrations`, `@contractspec/lib.contracts-spec`, `@contractspec/lib.design-system`, `@contractspec/lib.image-gen`, ...
11
+ - `src/docs/` contains docblocks and documentation-facing exports.
8
12
 
9
- - **Types** -- `VideoBrief`, `VideoGeneratorOptions`, `GeneratedVideo`, `ScenePlan`, `PlannedScene`, plus re-exported contract types (`VideoProject`, `RenderConfig`, `VideoFormat`)
10
- - **Design** -- Video-specific design tokens extending the design system: color tokens, motion/easing curves, typography scale (1920x1080), and layout safe zones with format variants (landscape/square/portrait)
11
- - **Compositions** -- Remotion compositions for rendering video scenes:
12
- - **Primitives**: `AnimatedText`, `BrandFrame`, `CodeBlock`, `ProgressBar`, `Terminal`, `SceneTransitionWrapper`
13
- - **Full**: `ApiOverview` (spec to API surface visualization), `SocialClip` (marketing content, adaptive formats), `TerminalDemo` (CLI walkthrough)
14
- - **Generators** -- `VideoGenerator` (main orchestrator), `ScenePlanner` (breaks briefs into scenes), `ScriptGenerator` (narration with professional/casual/technical styles)
15
- - **Renderers** -- `LocalRenderer` wrapping `@remotion/renderer` with quality presets (draft/standard/high)
16
- - **Player** -- `DemoPlayer` component for embedding in React apps via `@remotion/player`
13
+ ## Installation
17
14
 
18
- Deterministic by default: every generator produces consistent output without an LLM. When an LLM is provided via the constructor, generators produce richer, more varied content. On LLM failure, the system falls back to deterministic output automatically.
15
+ `npm install @contractspec/lib.video-gen`
19
16
 
20
- ## Quickstart
17
+ or
21
18
 
22
- ```typescript
23
- import { VideoGenerator } from "@contractspec/lib.video-gen/generators";
24
- import type { VideoBrief } from "@contractspec/lib.video-gen/types";
19
+ `bun add @contractspec/lib.video-gen`
25
20
 
26
- const generator = new VideoGenerator(); // no LLM needed
21
+ ## Usage
27
22
 
28
- const brief: VideoBrief = {
29
- title: "Ship APIs 10x Faster",
30
- summary: "See how ContractSpec generates production-ready APIs from specs.",
31
- format: "landscape",
32
- };
23
+ Import the root entrypoint from `@contractspec/lib.video-gen`, or choose a documented subpath when you only need one part of the package surface.
33
24
 
34
- const project = await generator.generate(brief);
35
- ```
25
+ ## Architecture
36
26
 
37
- Compositions are pure React components -- same props always produce the same visual output, with frame-based timing and no side effects.
27
+ - `src/compositions` is part of the package's public or composition surface.
28
+ - `src/design` is part of the package's public or composition surface.
29
+ - `src/docs/` contains docblocks and documentation-facing exports.
30
+ - `src/generators` is part of the package's public or composition surface.
31
+ - `src/i18n` is part of the package's public or composition surface.
32
+ - `src/index.ts` is the root public barrel and package entrypoint.
33
+ - `src/player` is part of the package's public or composition surface.
34
+ - `src/types.ts` is shared public type definitions.
35
+
36
+ ## Public Entry Points
37
+
38
+ - Export `.` resolves through `./src/index.ts`.
39
+ - Export `./compositions` resolves through `./src/compositions/index.ts`.
40
+ - Export `./compositions/api-overview` resolves through `./src/compositions/api-overview.tsx`.
41
+ - Export `./compositions/primitives` resolves through `./src/compositions/primitives/index.ts`.
42
+ - Export `./compositions/primitives/animated-text` resolves through `./src/compositions/primitives/animated-text.tsx`.
43
+ - Export `./compositions/primitives/brand-frame` resolves through `./src/compositions/primitives/brand-frame.tsx`.
44
+ - Export `./compositions/primitives/code-block` resolves through `./src/compositions/primitives/code-block.tsx`.
45
+ - Export `./compositions/primitives/progress-bar` resolves through `./src/compositions/primitives/progress-bar.tsx`.
46
+ - Export `./compositions/primitives/terminal` resolves through `./src/compositions/primitives/terminal.tsx`.
47
+ - Export `./compositions/primitives/transition` resolves through `./src/compositions/primitives/transition.tsx`.
48
+ - The package publishes 42 total export subpaths; keep docs aligned with `package.json`.
49
+
50
+ ## Local Commands
51
+
52
+ - `bun run dev` — contractspec-bun-build dev
53
+ - `bun run build` — bun run prebuild && bun run build:bundle && bun run build:types
54
+ - `bun run test` — bun test --pass-with-no-tests
55
+ - `bun run lint` — bun lint:fix
56
+ - `bun run lint:check` — biome check .
57
+ - `bun run lint:fix` — biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .
58
+ - `bun run typecheck` — tsc --noEmit
59
+ - `bun run publish:pkg` — bun publish --tolerate-republish --ignore-scripts --verbose
60
+ - `bun run publish:pkg:canary` — bun publish:pkg --tag canary
61
+ - `bun run clean` — rimraf dist .turbo
62
+ - `bun run build:bundle` — contractspec-bun-build transpile
63
+ - `bun run build:types` — contractspec-bun-build types
64
+ - `bun run prebuild` — contractspec-bun-build prebuild
65
+
66
+ ## Recent Updates
67
+
68
+ - Replace eslint+prettier by biomejs to optimize speed.
69
+ - Resolve lint, build, and type errors across nine packages.
70
+ - Add first-class transport, auth, versioning, and BYOK support across all integrations.
71
+ - Add AI provider ranking system with ranking-driven model selection.
72
+ - Resolve lint/test regressions after voice capability updates.
73
+ - Add @contractspec/lib.voice package for TTS, STT, and conversational voice.
74
+
75
+ ## Notes
76
+
77
+ - Remotion composition API is version-sensitive — pin and test upgrades carefully.
78
+ - Renderer interface is the adapter boundary — do not leak Remotion internals.
79
+ - Depends on voice, content-gen, image-gen, design-system — coordinate cross-lib changes.
@@ -53,6 +53,109 @@ var defaultVideoTheme = {
53
53
  video: defaultVideoColors
54
54
  };
55
55
 
56
+ // src/design/typography.ts
57
+ var videoTypography = {
58
+ title: {
59
+ fontSize: 72,
60
+ lineHeight: 1.1,
61
+ fontWeight: 700,
62
+ letterSpacing: -1
63
+ },
64
+ heading: {
65
+ fontSize: 56,
66
+ lineHeight: 1.2,
67
+ fontWeight: 600,
68
+ letterSpacing: -0.5
69
+ },
70
+ subheading: {
71
+ fontSize: 40,
72
+ lineHeight: 1.25,
73
+ fontWeight: 500
74
+ },
75
+ body: {
76
+ fontSize: 32,
77
+ lineHeight: 1.5,
78
+ fontWeight: 400
79
+ },
80
+ code: {
81
+ fontSize: 28,
82
+ lineHeight: 1.6,
83
+ fontWeight: 400
84
+ },
85
+ caption: {
86
+ fontSize: 24,
87
+ lineHeight: 1.4,
88
+ fontWeight: 400
89
+ },
90
+ label: {
91
+ fontSize: 20,
92
+ lineHeight: 1.3,
93
+ fontWeight: 600,
94
+ letterSpacing: 1
95
+ }
96
+ };
97
+ function scaleTypography(style, targetWidth) {
98
+ const scale = targetWidth / 1920;
99
+ return {
100
+ ...style,
101
+ fontSize: Math.round(style.fontSize * scale),
102
+ letterSpacing: style.letterSpacing ? Math.round(style.letterSpacing * scale * 10) / 10 : undefined
103
+ };
104
+ }
105
+
106
+ // src/compositions/primitives/animated-text.tsx
107
+ import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
108
+ import { jsxDEV } from "react/jsx-dev-runtime";
109
+ var AnimatedText = ({
110
+ text,
111
+ variant = "body",
112
+ style: styleOverride,
113
+ enterAt = 0,
114
+ exitAt,
115
+ color = "#ffffff",
116
+ align = "left"
117
+ }) => {
118
+ const frame = useCurrentFrame();
119
+ const { width } = useVideoConfig();
120
+ const baseStyle = videoTypography[variant];
121
+ const scaled = scaleTypography(baseStyle, width);
122
+ const finalStyle = { ...scaled, ...styleOverride };
123
+ const enterProgress = interpolate(frame, [enterAt, enterAt + videoDurations.textEntrance], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
124
+ const enterOpacity = interpolate(enterProgress, [0, 1], [0, 1], {
125
+ easing: videoEasing.entrance
126
+ });
127
+ const enterTranslateY = interpolate(enterProgress, [0, 1], [30, 0], {
128
+ easing: videoEasing.entrance
129
+ });
130
+ let exitOpacity = 1;
131
+ let exitTranslateY = 0;
132
+ if (exitAt !== undefined) {
133
+ const exitProgress = interpolate(frame, [exitAt, exitAt + videoDurations.textExit], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
134
+ exitOpacity = interpolate(exitProgress, [0, 1], [1, 0], {
135
+ easing: videoEasing.exit
136
+ });
137
+ exitTranslateY = interpolate(exitProgress, [0, 1], [0, -20], {
138
+ easing: videoEasing.exit
139
+ });
140
+ }
141
+ const opacity = enterOpacity * exitOpacity;
142
+ const translateY = enterTranslateY + exitTranslateY;
143
+ return /* @__PURE__ */ jsxDEV("div", {
144
+ style: {
145
+ fontSize: finalStyle.fontSize,
146
+ lineHeight: finalStyle.lineHeight,
147
+ fontWeight: finalStyle.fontWeight,
148
+ letterSpacing: finalStyle.letterSpacing,
149
+ color,
150
+ textAlign: align,
151
+ opacity,
152
+ transform: `translateY(${translateY}px)`,
153
+ willChange: "opacity, transform"
154
+ },
155
+ children: text
156
+ }, undefined, false, undefined, this);
157
+ };
158
+
56
159
  // src/design/layouts.ts
57
160
  import { VIDEO_FORMATS } from "@contractspec/lib.contracts-integrations/integrations/providers/video";
58
161
  var DEFAULT_FPS = 30;
@@ -89,8 +192,8 @@ function getAllFormatVariants() {
89
192
  }
90
193
 
91
194
  // src/compositions/primitives/brand-frame.tsx
92
- import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
93
- import { jsxDEV } from "react/jsx-dev-runtime";
195
+ import { interpolate as interpolate2, useCurrentFrame as useCurrentFrame2, useVideoConfig as useVideoConfig2 } from "remotion";
196
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
94
197
  var BrandFrame = ({
95
198
  styleOverrides,
96
199
  showBranding = true,
@@ -98,8 +201,8 @@ var BrandFrame = ({
98
201
  variant = "gradient",
99
202
  children
100
203
  }) => {
101
- const frame = useCurrentFrame();
102
- const { width, height } = useVideoConfig();
204
+ const frame = useCurrentFrame2();
205
+ const { width, height } = useVideoConfig2();
103
206
  const theme = defaultVideoTheme;
104
207
  const safeZone = scaleSafeZone({ type: "custom", width, height });
105
208
  const primaryColor = styleOverrides?.primaryColor ?? theme.colors.primary;
@@ -117,16 +220,16 @@ var BrandFrame = ({
117
220
  background = "#000000";
118
221
  break;
119
222
  }
120
- const entranceOpacity = animateEntrance ? interpolate(frame, [0, 15], [0, 1], {
223
+ const entranceOpacity = animateEntrance ? interpolate2(frame, [0, 15], [0, 1], {
121
224
  extrapolateLeft: "clamp",
122
225
  extrapolateRight: "clamp",
123
226
  easing: videoEasing.entrance
124
227
  }) : 1;
125
- const brandOpacity = showBranding ? interpolate(frame, [videoDurations.brandReveal, videoDurations.brandReveal + 15], [0, 0.3], {
228
+ const brandOpacity = showBranding ? interpolate2(frame, [videoDurations.brandReveal, videoDurations.brandReveal + 15], [0, 0.3], {
126
229
  extrapolateLeft: "clamp",
127
230
  extrapolateRight: "clamp"
128
231
  }) : 0;
129
- return /* @__PURE__ */ jsxDEV("div", {
232
+ return /* @__PURE__ */ jsxDEV2("div", {
130
233
  style: {
131
234
  width,
132
235
  height,
@@ -136,7 +239,7 @@ var BrandFrame = ({
136
239
  opacity: entranceOpacity
137
240
  },
138
241
  children: [
139
- variant === "gradient" && /* @__PURE__ */ jsxDEV("div", {
242
+ variant === "gradient" && /* @__PURE__ */ jsxDEV2("div", {
140
243
  style: {
141
244
  position: "absolute",
142
245
  top: "-20%",
@@ -148,7 +251,7 @@ var BrandFrame = ({
148
251
  pointerEvents: "none"
149
252
  }
150
253
  }, undefined, false, undefined, this),
151
- /* @__PURE__ */ jsxDEV("div", {
254
+ /* @__PURE__ */ jsxDEV2("div", {
152
255
  style: {
153
256
  position: "absolute",
154
257
  left: safeZone.horizontal,
@@ -160,7 +263,7 @@ var BrandFrame = ({
160
263
  },
161
264
  children
162
265
  }, undefined, false, undefined, this),
163
- showBranding && /* @__PURE__ */ jsxDEV("div", {
266
+ showBranding && /* @__PURE__ */ jsxDEV2("div", {
164
267
  style: {
165
268
  position: "absolute",
166
269
  bottom: safeZone.vertical / 2,
@@ -177,109 +280,6 @@ var BrandFrame = ({
177
280
  }, undefined, true, undefined, this);
178
281
  };
179
282
 
180
- // src/design/typography.ts
181
- var videoTypography = {
182
- title: {
183
- fontSize: 72,
184
- lineHeight: 1.1,
185
- fontWeight: 700,
186
- letterSpacing: -1
187
- },
188
- heading: {
189
- fontSize: 56,
190
- lineHeight: 1.2,
191
- fontWeight: 600,
192
- letterSpacing: -0.5
193
- },
194
- subheading: {
195
- fontSize: 40,
196
- lineHeight: 1.25,
197
- fontWeight: 500
198
- },
199
- body: {
200
- fontSize: 32,
201
- lineHeight: 1.5,
202
- fontWeight: 400
203
- },
204
- code: {
205
- fontSize: 28,
206
- lineHeight: 1.6,
207
- fontWeight: 400
208
- },
209
- caption: {
210
- fontSize: 24,
211
- lineHeight: 1.4,
212
- fontWeight: 400
213
- },
214
- label: {
215
- fontSize: 20,
216
- lineHeight: 1.3,
217
- fontWeight: 600,
218
- letterSpacing: 1
219
- }
220
- };
221
- function scaleTypography(style, targetWidth) {
222
- const scale = targetWidth / 1920;
223
- return {
224
- ...style,
225
- fontSize: Math.round(style.fontSize * scale),
226
- letterSpacing: style.letterSpacing ? Math.round(style.letterSpacing * scale * 10) / 10 : undefined
227
- };
228
- }
229
-
230
- // src/compositions/primitives/animated-text.tsx
231
- import { interpolate as interpolate2, useCurrentFrame as useCurrentFrame2, useVideoConfig as useVideoConfig2 } from "remotion";
232
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
233
- var AnimatedText = ({
234
- text,
235
- variant = "body",
236
- style: styleOverride,
237
- enterAt = 0,
238
- exitAt,
239
- color = "#ffffff",
240
- align = "left"
241
- }) => {
242
- const frame = useCurrentFrame2();
243
- const { width } = useVideoConfig2();
244
- const baseStyle = videoTypography[variant];
245
- const scaled = scaleTypography(baseStyle, width);
246
- const finalStyle = { ...scaled, ...styleOverride };
247
- const enterProgress = interpolate2(frame, [enterAt, enterAt + videoDurations.textEntrance], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
248
- const enterOpacity = interpolate2(enterProgress, [0, 1], [0, 1], {
249
- easing: videoEasing.entrance
250
- });
251
- const enterTranslateY = interpolate2(enterProgress, [0, 1], [30, 0], {
252
- easing: videoEasing.entrance
253
- });
254
- let exitOpacity = 1;
255
- let exitTranslateY = 0;
256
- if (exitAt !== undefined) {
257
- const exitProgress = interpolate2(frame, [exitAt, exitAt + videoDurations.textExit], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
258
- exitOpacity = interpolate2(exitProgress, [0, 1], [1, 0], {
259
- easing: videoEasing.exit
260
- });
261
- exitTranslateY = interpolate2(exitProgress, [0, 1], [0, -20], {
262
- easing: videoEasing.exit
263
- });
264
- }
265
- const opacity = enterOpacity * exitOpacity;
266
- const translateY = enterTranslateY + exitTranslateY;
267
- return /* @__PURE__ */ jsxDEV2("div", {
268
- style: {
269
- fontSize: finalStyle.fontSize,
270
- lineHeight: finalStyle.lineHeight,
271
- fontWeight: finalStyle.fontWeight,
272
- letterSpacing: finalStyle.letterSpacing,
273
- color,
274
- textAlign: align,
275
- opacity,
276
- transform: `translateY(${translateY}px)`,
277
- willChange: "opacity, transform"
278
- },
279
- children: text
280
- }, undefined, false, undefined, this);
281
- };
282
-
283
283
  // src/compositions/primitives/code-block.tsx
284
284
  import { interpolate as interpolate3, useCurrentFrame as useCurrentFrame3, useVideoConfig as useVideoConfig3 } from "remotion";
285
285
  import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
@@ -435,8 +435,8 @@ var ProgressBar = ({
435
435
  // src/compositions/api-overview.tsx
436
436
  import {
437
437
  AbsoluteFill,
438
- Sequence,
439
438
  interpolate as interpolate4,
439
+ Sequence,
440
440
  useCurrentFrame as useCurrentFrame5,
441
441
  useVideoConfig as useVideoConfig5
442
442
  } from "remotion";