@contractspec/lib.video-gen 2.7.17 → 2.7.18

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,57 +1,5 @@
1
1
  // @bun
2
- var __require = import.meta.require;
3
-
4
- // src/design/layouts.ts
5
- import { VIDEO_FORMATS } from "@contractspec/lib.contracts-integrations/integrations/providers/video";
6
- var DEFAULT_FPS = 30;
7
- var videoSafeZone = {
8
- horizontal: 120,
9
- vertical: 80,
10
- contentWidth: 1680,
11
- contentHeight: 920
12
- };
13
- function scaleSafeZone(format) {
14
- const scaleX = format.width / 1920;
15
- const scaleY = format.height / 1080;
16
- return {
17
- horizontal: Math.round(videoSafeZone.horizontal * scaleX),
18
- vertical: Math.round(videoSafeZone.vertical * scaleY),
19
- contentWidth: Math.round(videoSafeZone.contentWidth * scaleX),
20
- contentHeight: Math.round(videoSafeZone.contentHeight * scaleY)
21
- };
22
- }
23
- var videoPositions = {
24
- center: { x: 960, y: 540 },
25
- topLeft: { x: 120, y: 80 },
26
- topRight: { x: 1800, y: 80 },
27
- bottomLeft: { x: 120, y: 1000 },
28
- bottomRight: { x: 1800, y: 1000 },
29
- bottomCenter: { x: 960, y: 960 }
30
- };
31
- function getAllFormatVariants() {
32
- return [
33
- VIDEO_FORMATS.landscape,
34
- VIDEO_FORMATS.square,
35
- VIDEO_FORMATS.portrait
36
- ];
37
- }
38
-
39
- // src/i18n/catalogs/en.ts
40
- import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
41
- var enMessages = defineTranslation({
42
- meta: {
43
- key: "video-gen.messages",
44
- version: "1.0.0",
45
- domain: "video-gen",
46
- description: "All user-facing, LLM-facing, and developer-facing strings for the video-gen package",
47
- owners: ["platform"],
48
- stability: "experimental"
49
- },
50
- locale: "en",
51
- fallback: "en",
52
- messages: {
53
- "prompt.script.system": {
54
- value: `You are a video narration script writer.
2
+ var d=import.meta.require;import{VIDEO_FORMATS as W}from"@contractspec/lib.contracts-integrations/integrations/providers/video";var Q=30,J={horizontal:120,vertical:80,contentWidth:1680,contentHeight:920};function b(x){let G=x.width/1920,K=x.height/1080;return{horizontal:Math.round(J.horizontal*G),vertical:Math.round(J.vertical*K),contentWidth:Math.round(J.contentWidth*G),contentHeight:Math.round(J.contentHeight*K)}}var p={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 r(){return[W.landscape,W.square,W.portrait]}import{defineTranslation as M}from"@contractspec/lib.contracts-spec/translations";var $=M({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.
55
3
  Write a narration script for a short video (30-60 seconds).
56
4
  {styleGuide}
57
5
 
@@ -62,12 +10,7 @@ Return JSON with shape:
62
10
  }
63
11
 
64
12
  Scene IDs should be: "intro", "problems", "solutions", "metrics", "cta".
65
- Only include segments that are relevant to the brief content.`,
66
- description: "Script generator LLM system prompt",
67
- placeholders: [{ name: "styleGuide", type: "string" }]
68
- },
69
- "prompt.scenePlanner.system": {
70
- value: `You are a video scene planner for ContractSpec marketing/documentation videos.
13
+ 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.
71
14
  Given a content brief, break it into video scenes.
72
15
 
73
16
  Each scene must have:
@@ -83,125 +26,7 @@ Return a JSON object with shape:
83
26
  }
84
27
 
85
28
  Keep the total duration around {targetSeconds} seconds.
86
- Prioritize clarity and pacing. Each scene should communicate one idea.`,
87
- description: "Scene planner LLM system prompt",
88
- placeholders: [
89
- { name: "fps", type: "number" },
90
- { name: "targetSeconds", type: "number" }
91
- ]
92
- },
93
- "prompt.style.professional": {
94
- value: "Use a clear, authoritative, professional tone. Be concise and direct.",
95
- description: "Style guide for professional narration"
96
- },
97
- "prompt.style.casual": {
98
- value: "Use a friendly, conversational tone. Be approachable and relatable.",
99
- description: "Style guide for casual narration"
100
- },
101
- "prompt.style.technical": {
102
- value: "Use precise technical language. Be detailed and accurate.",
103
- description: "Style guide for technical narration"
104
- },
105
- "script.segment.challenge": {
106
- value: "The challenge: {content}",
107
- description: "Narration segment prefix for problems",
108
- placeholders: [{ name: "content", type: "string" }]
109
- },
110
- "script.segment.solution": {
111
- value: "The solution: {content}",
112
- description: "Narration segment prefix for solutions",
113
- placeholders: [{ name: "content", type: "string" }]
114
- },
115
- "script.segment.results": {
116
- value: "The results: {content}",
117
- description: "Narration segment prefix for metrics",
118
- placeholders: [{ name: "content", type: "string" }]
119
- },
120
- "scene.cta.default": {
121
- value: "Learn more",
122
- description: "Default call-to-action text for scenes"
123
- },
124
- "scene.hook.problem": {
125
- value: "The Problem",
126
- description: "Scene hook label for problem statement"
127
- },
128
- "scene.narration.problem": {
129
- value: "The problem: {content}",
130
- description: "Scene narration for problem statement",
131
- placeholders: [{ name: "content", type: "string" }]
132
- },
133
- "scene.hook.solution": {
134
- value: "The Solution",
135
- description: "Scene hook label for solution"
136
- },
137
- "scene.narration.solution": {
138
- value: "The solution: {content}",
139
- description: "Scene narration for solution",
140
- placeholders: [{ name: "content", type: "string" }]
141
- },
142
- "scene.hook.results": {
143
- value: "Results",
144
- description: "Scene hook label for results/metrics"
145
- },
146
- "composition.apiOverview.generates": {
147
- value: "Generates:",
148
- description: "ApiOverview heading for generated outputs"
149
- },
150
- "composition.apiOverview.tagline": {
151
- value: "One spec. Every surface.",
152
- description: "ApiOverview default tagline"
153
- },
154
- "composition.apiOverview.output.rest": {
155
- value: "REST Endpoint",
156
- description: "Generated output label: REST"
157
- },
158
- "composition.apiOverview.output.graphql": {
159
- value: "GraphQL Mutation",
160
- description: "Generated output label: GraphQL"
161
- },
162
- "composition.apiOverview.output.prisma": {
163
- value: "Prisma Model",
164
- description: "Generated output label: Prisma"
165
- },
166
- "composition.apiOverview.output.typescript": {
167
- value: "TypeScript SDK",
168
- description: "Generated output label: TypeScript SDK"
169
- },
170
- "composition.apiOverview.output.mcp": {
171
- value: "MCP Tool",
172
- description: "Generated output label: MCP Tool"
173
- },
174
- "composition.apiOverview.output.openapi": {
175
- value: "OpenAPI Spec",
176
- description: "Generated output label: OpenAPI"
177
- },
178
- "composition.socialClip.cta": {
179
- value: "Learn more",
180
- description: "SocialClip default CTA"
181
- },
182
- "composition.terminal.title": {
183
- value: "Terminal",
184
- description: "TerminalDemo default window title"
185
- }
186
- }
187
- });
188
-
189
- // src/i18n/catalogs/es.ts
190
- import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
191
- var esMessages = defineTranslation2({
192
- meta: {
193
- key: "video-gen.messages",
194
- version: "1.0.0",
195
- domain: "video-gen",
196
- description: "Spanish translations for the video-gen package",
197
- owners: ["platform"],
198
- stability: "experimental"
199
- },
200
- locale: "es",
201
- fallback: "en",
202
- messages: {
203
- "prompt.script.system": {
204
- value: `Eres un redactor de guiones de narraci\xF3n para v\xEDdeo.
29
+ 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 O}from"@contractspec/lib.contracts-spec/translations";var I=O({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\xF3n para v\xEDdeo.
205
30
  Escribe un gui\xF3n de narraci\xF3n para un v\xEDdeo corto (30-60 segundos).
206
31
  {styleGuide}
207
32
 
@@ -212,12 +37,7 @@ Devuelve JSON con la forma:
212
37
  }
213
38
 
214
39
  Los identificadores de escena deben ser: "intro", "problems", "solutions", "metrics", "cta".
215
- Incluye solo los segmentos relevantes para el brief.`,
216
- description: "Script generator LLM system prompt",
217
- placeholders: [{ name: "styleGuide", type: "string" }]
218
- },
219
- "prompt.scenePlanner.system": {
220
- value: `Eres un planificador de escenas de v\xEDdeo para v\xEDdeos de marketing/documentaci\xF3n de ContractSpec.
40
+ 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\xEDdeo para v\xEDdeos de marketing/documentaci\xF3n de ContractSpec.
221
41
  Dado un brief de contenido, div\xEDdelo en escenas de v\xEDdeo.
222
42
 
223
43
  Cada escena debe tener:
@@ -233,125 +53,7 @@ Devuelve un objeto JSON con la forma:
233
53
  }
234
54
 
235
55
  Mant\xE9n la duraci\xF3n total alrededor de {targetSeconds} segundos.
236
- Prioriza la claridad y el ritmo. Cada escena debe comunicar una idea.`,
237
- description: "Scene planner LLM system prompt",
238
- placeholders: [
239
- { name: "fps", type: "number" },
240
- { name: "targetSeconds", type: "number" }
241
- ]
242
- },
243
- "prompt.style.professional": {
244
- value: "Usa un tono claro, autoritario y profesional. S\xE9 conciso y directo.",
245
- description: "Style guide for professional narration"
246
- },
247
- "prompt.style.casual": {
248
- value: "Usa un tono amigable y conversacional. S\xE9 accesible y cercano.",
249
- description: "Style guide for casual narration"
250
- },
251
- "prompt.style.technical": {
252
- value: "Usa un lenguaje t\xE9cnico preciso. S\xE9 detallado y exacto.",
253
- description: "Style guide for technical narration"
254
- },
255
- "script.segment.challenge": {
256
- value: "El desaf\xEDo: {content}",
257
- description: "Narration segment prefix for problems",
258
- placeholders: [{ name: "content", type: "string" }]
259
- },
260
- "script.segment.solution": {
261
- value: "La soluci\xF3n: {content}",
262
- description: "Narration segment prefix for solutions",
263
- placeholders: [{ name: "content", type: "string" }]
264
- },
265
- "script.segment.results": {
266
- value: "Los resultados: {content}",
267
- description: "Narration segment prefix for metrics",
268
- placeholders: [{ name: "content", type: "string" }]
269
- },
270
- "scene.cta.default": {
271
- value: "M\xE1s informaci\xF3n",
272
- description: "Default call-to-action text for scenes"
273
- },
274
- "scene.hook.problem": {
275
- value: "El problema",
276
- description: "Scene hook label for problem statement"
277
- },
278
- "scene.narration.problem": {
279
- value: "El problema: {content}",
280
- description: "Scene narration for problem statement",
281
- placeholders: [{ name: "content", type: "string" }]
282
- },
283
- "scene.hook.solution": {
284
- value: "La soluci\xF3n",
285
- description: "Scene hook label for solution"
286
- },
287
- "scene.narration.solution": {
288
- value: "La soluci\xF3n: {content}",
289
- description: "Scene narration for solution",
290
- placeholders: [{ name: "content", type: "string" }]
291
- },
292
- "scene.hook.results": {
293
- value: "Resultados",
294
- description: "Scene hook label for results/metrics"
295
- },
296
- "composition.apiOverview.generates": {
297
- value: "Genera:",
298
- description: "ApiOverview heading for generated outputs"
299
- },
300
- "composition.apiOverview.tagline": {
301
- value: "Una spec. Todas las superficies.",
302
- description: "ApiOverview default tagline"
303
- },
304
- "composition.apiOverview.output.rest": {
305
- value: "Endpoint REST",
306
- description: "Generated output label: REST"
307
- },
308
- "composition.apiOverview.output.graphql": {
309
- value: "Mutaci\xF3n GraphQL",
310
- description: "Generated output label: GraphQL"
311
- },
312
- "composition.apiOverview.output.prisma": {
313
- value: "Modelo Prisma",
314
- description: "Generated output label: Prisma"
315
- },
316
- "composition.apiOverview.output.typescript": {
317
- value: "SDK TypeScript",
318
- description: "Generated output label: TypeScript SDK"
319
- },
320
- "composition.apiOverview.output.mcp": {
321
- value: "Herramienta MCP",
322
- description: "Generated output label: MCP Tool"
323
- },
324
- "composition.apiOverview.output.openapi": {
325
- value: "Spec OpenAPI",
326
- description: "Generated output label: OpenAPI"
327
- },
328
- "composition.socialClip.cta": {
329
- value: "M\xE1s informaci\xF3n",
330
- description: "SocialClip default CTA"
331
- },
332
- "composition.terminal.title": {
333
- value: "Terminal",
334
- description: "TerminalDemo default window title"
335
- }
336
- }
337
- });
338
-
339
- // src/i18n/catalogs/fr.ts
340
- import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
341
- var frMessages = defineTranslation3({
342
- meta: {
343
- key: "video-gen.messages",
344
- version: "1.0.0",
345
- domain: "video-gen",
346
- description: "French translations for the video-gen package",
347
- owners: ["platform"],
348
- stability: "experimental"
349
- },
350
- locale: "fr",
351
- fallback: "en",
352
- messages: {
353
- "prompt.script.system": {
354
- value: `Vous \xEAtes un r\xE9dacteur de scripts de narration vid\xE9o.
56
+ 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\xE9 conciso y directo.",description:"Style guide for professional narration"},"prompt.style.casual":{value:"Usa un tono amigable y conversacional. S\xE9 accesible y cercano.",description:"Style guide for casual narration"},"prompt.style.technical":{value:"Usa un lenguaje t\xE9cnico preciso. S\xE9 detallado y exacto.",description:"Style guide for technical narration"},"script.segment.challenge":{value:"El desaf\xEDo: {content}",description:"Narration segment prefix for problems",placeholders:[{name:"content",type:"string"}]},"script.segment.solution":{value:"La soluci\xF3n: {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\xE1s informaci\xF3n",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\xF3n",description:"Scene hook label for solution"},"scene.narration.solution":{value:"La soluci\xF3n: {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\xF3n 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\xE1s informaci\xF3n",description:"SocialClip default CTA"},"composition.terminal.title":{value:"Terminal",description:"TerminalDemo default window title"}}});import{defineTranslation as S}from"@contractspec/lib.contracts-spec/translations";var Y=S({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 \xEAtes un r\xE9dacteur de scripts de narration vid\xE9o.
355
57
  \xC9crivez un script de narration pour une courte vid\xE9o (30-60 secondes).
356
58
  {styleGuide}
357
59
 
@@ -362,12 +64,7 @@ Retournez du JSON avec la forme\xA0:
362
64
  }
363
65
 
364
66
  Les identifiants de sc\xE8ne doivent \xEAtre\xA0: "intro", "problems", "solutions", "metrics", "cta".
365
- N'incluez que les segments pertinents au brief.`,
366
- description: "Script generator LLM system prompt",
367
- placeholders: [{ name: "styleGuide", type: "string" }]
368
- },
369
- "prompt.scenePlanner.system": {
370
- value: `Vous \xEAtes un planificateur de sc\xE8nes vid\xE9o pour les vid\xE9os marketing/documentation de ContractSpec.
67
+ N'incluez que les segments pertinents au brief.`,description:"Script generator LLM system prompt",placeholders:[{name:"styleGuide",type:"string"}]},"prompt.scenePlanner.system":{value:`Vous \xEAtes un planificateur de sc\xE8nes vid\xE9o pour les vid\xE9os marketing/documentation de ContractSpec.
371
68
  \xC0 partir d'un brief, d\xE9composez-le en sc\xE8nes vid\xE9o.
372
69
 
373
70
  Chaque sc\xE8ne doit avoir\xA0:
@@ -383,457 +80,4 @@ Retournez un objet JSON avec la forme\xA0:
383
80
  }
384
81
 
385
82
  Gardez la dur\xE9e totale autour de {targetSeconds} secondes.
386
- Privil\xE9giez la clart\xE9 et le rythme. Chaque sc\xE8ne doit communiquer une id\xE9e.`,
387
- description: "Scene planner LLM system prompt",
388
- placeholders: [
389
- { name: "fps", type: "number" },
390
- { name: "targetSeconds", type: "number" }
391
- ]
392
- },
393
- "prompt.style.professional": {
394
- value: "Utilisez un ton clair, autoritaire et professionnel. Soyez concis et direct.",
395
- description: "Style guide for professional narration"
396
- },
397
- "prompt.style.casual": {
398
- value: "Utilisez un ton amical et conversationnel. Soyez accessible et proche.",
399
- description: "Style guide for casual narration"
400
- },
401
- "prompt.style.technical": {
402
- value: "Utilisez un langage technique pr\xE9cis. Soyez d\xE9taill\xE9 et exact.",
403
- description: "Style guide for technical narration"
404
- },
405
- "script.segment.challenge": {
406
- value: "Le d\xE9fi\xA0: {content}",
407
- description: "Narration segment prefix for problems",
408
- placeholders: [{ name: "content", type: "string" }]
409
- },
410
- "script.segment.solution": {
411
- value: "La solution\xA0: {content}",
412
- description: "Narration segment prefix for solutions",
413
- placeholders: [{ name: "content", type: "string" }]
414
- },
415
- "script.segment.results": {
416
- value: "Les r\xE9sultats\xA0: {content}",
417
- description: "Narration segment prefix for metrics",
418
- placeholders: [{ name: "content", type: "string" }]
419
- },
420
- "scene.cta.default": {
421
- value: "En savoir plus",
422
- description: "Default call-to-action text for scenes"
423
- },
424
- "scene.hook.problem": {
425
- value: "Le probl\xE8me",
426
- description: "Scene hook label for problem statement"
427
- },
428
- "scene.narration.problem": {
429
- value: "Le probl\xE8me\xA0: {content}",
430
- description: "Scene narration for problem statement",
431
- placeholders: [{ name: "content", type: "string" }]
432
- },
433
- "scene.hook.solution": {
434
- value: "La solution",
435
- description: "Scene hook label for solution"
436
- },
437
- "scene.narration.solution": {
438
- value: "La solution\xA0: {content}",
439
- description: "Scene narration for solution",
440
- placeholders: [{ name: "content", type: "string" }]
441
- },
442
- "scene.hook.results": {
443
- value: "R\xE9sultats",
444
- description: "Scene hook label for results/metrics"
445
- },
446
- "composition.apiOverview.generates": {
447
- value: "G\xE9n\xE8re\xA0:",
448
- description: "ApiOverview heading for generated outputs"
449
- },
450
- "composition.apiOverview.tagline": {
451
- value: "Un spec. Toutes les surfaces.",
452
- description: "ApiOverview default tagline"
453
- },
454
- "composition.apiOverview.output.rest": {
455
- value: "Endpoint REST",
456
- description: "Generated output label: REST"
457
- },
458
- "composition.apiOverview.output.graphql": {
459
- value: "Mutation GraphQL",
460
- description: "Generated output label: GraphQL"
461
- },
462
- "composition.apiOverview.output.prisma": {
463
- value: "Mod\xE8le Prisma",
464
- description: "Generated output label: Prisma"
465
- },
466
- "composition.apiOverview.output.typescript": {
467
- value: "SDK TypeScript",
468
- description: "Generated output label: TypeScript SDK"
469
- },
470
- "composition.apiOverview.output.mcp": {
471
- value: "Outil MCP",
472
- description: "Generated output label: MCP Tool"
473
- },
474
- "composition.apiOverview.output.openapi": {
475
- value: "Spec OpenAPI",
476
- description: "Generated output label: OpenAPI"
477
- },
478
- "composition.socialClip.cta": {
479
- value: "En savoir plus",
480
- description: "SocialClip default CTA"
481
- },
482
- "composition.terminal.title": {
483
- value: "Terminal",
484
- description: "TerminalDemo default window title"
485
- }
486
- }
487
- });
488
-
489
- // src/i18n/keys.ts
490
- var PROMPT_KEYS = {
491
- "prompt.script.system": "prompt.script.system",
492
- "prompt.scenePlanner.system": "prompt.scenePlanner.system",
493
- "prompt.style.professional": "prompt.style.professional",
494
- "prompt.style.casual": "prompt.style.casual",
495
- "prompt.style.technical": "prompt.style.technical"
496
- };
497
- var SCRIPT_KEYS = {
498
- "script.segment.challenge": "script.segment.challenge",
499
- "script.segment.solution": "script.segment.solution",
500
- "script.segment.results": "script.segment.results"
501
- };
502
- var SCENE_KEYS = {
503
- "scene.cta.default": "scene.cta.default",
504
- "scene.hook.problem": "scene.hook.problem",
505
- "scene.narration.problem": "scene.narration.problem",
506
- "scene.hook.solution": "scene.hook.solution",
507
- "scene.narration.solution": "scene.narration.solution",
508
- "scene.hook.results": "scene.hook.results"
509
- };
510
- var COMPOSITION_KEYS = {
511
- "composition.apiOverview.generates": "composition.apiOverview.generates",
512
- "composition.apiOverview.tagline": "composition.apiOverview.tagline",
513
- "composition.apiOverview.output.rest": "composition.apiOverview.output.rest",
514
- "composition.apiOverview.output.graphql": "composition.apiOverview.output.graphql",
515
- "composition.apiOverview.output.prisma": "composition.apiOverview.output.prisma",
516
- "composition.apiOverview.output.typescript": "composition.apiOverview.output.typescript",
517
- "composition.apiOverview.output.mcp": "composition.apiOverview.output.mcp",
518
- "composition.apiOverview.output.openapi": "composition.apiOverview.output.openapi",
519
- "composition.socialClip.cta": "composition.socialClip.cta",
520
- "composition.terminal.title": "composition.terminal.title"
521
- };
522
- var I18N_KEYS = {
523
- ...PROMPT_KEYS,
524
- ...SCRIPT_KEYS,
525
- ...SCENE_KEYS,
526
- ...COMPOSITION_KEYS
527
- };
528
-
529
- // src/i18n/locale.ts
530
- import {
531
- DEFAULT_LOCALE,
532
- isSupportedLocale,
533
- resolveLocale,
534
- SUPPORTED_LOCALES
535
- } from "@contractspec/lib.contracts-spec/translations";
536
-
537
- // src/i18n/messages.ts
538
- import {
539
- createI18nFactory
540
- } from "@contractspec/lib.contracts-spec/translations";
541
- var factory = createI18nFactory({
542
- specKey: "video-gen.messages",
543
- catalogs: [enMessages, frMessages, esMessages]
544
- });
545
- var createVideoGenI18n = factory.create;
546
- var getDefaultI18n = factory.getDefault;
547
- var resetI18nRegistry = factory.resetRegistry;
548
- // src/generators/scene-planner.ts
549
- class ScenePlanner {
550
- llm;
551
- model;
552
- temperature;
553
- fps;
554
- i18n;
555
- modelSelector;
556
- selectionContext;
557
- constructor(options) {
558
- this.llm = options?.llm;
559
- this.model = options?.model;
560
- this.temperature = options?.temperature ?? 0.3;
561
- this.fps = options?.fps ?? DEFAULT_FPS;
562
- this.i18n = createVideoGenI18n(options?.locale);
563
- this.modelSelector = options?.modelSelector;
564
- this.selectionContext = options?.selectionContext;
565
- }
566
- async plan(brief) {
567
- if (this.llm) {
568
- return this.planWithLlm(brief);
569
- }
570
- return this.planDeterministic(brief);
571
- }
572
- planDeterministic(brief) {
573
- const { content } = brief;
574
- const { t } = this.i18n;
575
- const scenes = [];
576
- const fps = this.fps;
577
- scenes.push({
578
- compositionId: "SocialClip",
579
- props: {
580
- hook: content.title,
581
- message: content.summary,
582
- points: content.solutions.slice(0, 3),
583
- cta: content.callToAction ?? t("scene.cta.default")
584
- },
585
- durationInFrames: 3 * fps,
586
- narrationText: `${content.title}. ${content.summary}`
587
- });
588
- if (content.problems.length > 0) {
589
- scenes.push({
590
- compositionId: "SocialClip",
591
- props: {
592
- hook: t("scene.hook.problem"),
593
- message: content.problems[0] ?? "",
594
- points: content.problems.slice(1, 4)
595
- },
596
- durationInFrames: 4 * fps,
597
- narrationText: t("scene.narration.problem", {
598
- content: content.problems.join(". ")
599
- })
600
- });
601
- }
602
- if (content.solutions.length > 0) {
603
- scenes.push({
604
- compositionId: "SocialClip",
605
- props: {
606
- hook: t("scene.hook.solution"),
607
- message: content.solutions[0] ?? "",
608
- points: content.solutions.slice(1, 4)
609
- },
610
- durationInFrames: 5 * fps,
611
- narrationText: t("scene.narration.solution", {
612
- content: content.solutions.join(". ")
613
- })
614
- });
615
- }
616
- if (content.metrics && content.metrics.length > 0) {
617
- scenes.push({
618
- compositionId: "SocialClip",
619
- props: {
620
- hook: t("scene.hook.results"),
621
- message: content.metrics[0] ?? "",
622
- points: content.metrics.slice(1, 3)
623
- },
624
- durationInFrames: 3 * fps,
625
- narrationText: content.metrics.join(". ")
626
- });
627
- }
628
- if (content.callToAction) {
629
- scenes.push({
630
- compositionId: "SocialClip",
631
- props: {
632
- hook: content.callToAction,
633
- message: "",
634
- cta: content.callToAction
635
- },
636
- durationInFrames: 2 * fps,
637
- narrationText: content.callToAction
638
- });
639
- }
640
- if (brief.targetDurationSeconds) {
641
- const targetFrames = brief.targetDurationSeconds * fps;
642
- const currentFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
643
- const ratio = targetFrames / currentFrames;
644
- for (const scene of scenes) {
645
- scene.durationInFrames = Math.round(scene.durationInFrames * ratio);
646
- }
647
- }
648
- const totalDuration = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
649
- const narrationScript = scenes.filter((s) => s.narrationText).map((s) => s.narrationText).join(" ");
650
- return {
651
- scenes,
652
- estimatedDurationSeconds: totalDuration / fps,
653
- narrationScript
654
- };
655
- }
656
- async resolveModel() {
657
- if (this.model)
658
- return this.model;
659
- if (this.modelSelector) {
660
- const ctx = this.selectionContext ?? {
661
- taskDimension: "reasoning"
662
- };
663
- const result = await this.modelSelector.select(ctx);
664
- return result.modelId;
665
- }
666
- return;
667
- }
668
- async planWithLlm(brief) {
669
- const { t } = this.i18n;
670
- const messages = [
671
- {
672
- role: "system",
673
- content: [
674
- {
675
- type: "text",
676
- text: t("prompt.scenePlanner.system", {
677
- fps: this.fps,
678
- targetSeconds: brief.targetDurationSeconds ?? 30
679
- })
680
- }
681
- ]
682
- },
683
- {
684
- role: "user",
685
- content: [
686
- {
687
- type: "text",
688
- text: JSON.stringify(brief.content)
689
- }
690
- ]
691
- }
692
- ];
693
- if (!this.llm) {
694
- return this.planDeterministic(brief);
695
- }
696
- try {
697
- const model = await this.resolveModel();
698
- const response = await this.llm.chat(messages, {
699
- model,
700
- temperature: this.temperature,
701
- responseFormat: "json"
702
- });
703
- const text = response.message.content.find((p) => p.type === "text");
704
- if (!text || text.type !== "text") {
705
- return this.planDeterministic(brief);
706
- }
707
- const parsed = JSON.parse(text.text);
708
- const totalDuration = parsed.scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
709
- return {
710
- scenes: parsed.scenes,
711
- estimatedDurationSeconds: totalDuration / this.fps,
712
- narrationScript: parsed.narrationScript
713
- };
714
- } catch {
715
- return this.planDeterministic(brief);
716
- }
717
- }
718
- }
719
-
720
- // src/generators/video-generator.ts
721
- import { VIDEO_FORMATS as VIDEO_FORMATS2 } from "@contractspec/lib.contracts-integrations/integrations/providers/video";
722
- class VideoGenerator {
723
- scenePlanner;
724
- voice;
725
- transcriber;
726
- image;
727
- fps;
728
- constructor(options) {
729
- this.fps = options?.fps ?? DEFAULT_FPS;
730
- this.voice = options?.voice;
731
- this.transcriber = options?.transcriber;
732
- this.image = options?.image;
733
- this.scenePlanner = new ScenePlanner({
734
- llm: options?.llm,
735
- model: options?.model,
736
- temperature: options?.temperature,
737
- fps: this.fps,
738
- locale: options?.locale,
739
- modelSelector: options?.modelSelector,
740
- selectionContext: options?.selectionContext
741
- });
742
- }
743
- async generate(brief) {
744
- const scenePlan = await this.scenePlanner.plan(brief);
745
- const scenes = scenePlan.scenes.map((planned, i) => ({
746
- id: `scene-${i}`,
747
- compositionId: planned.compositionId,
748
- props: planned.props,
749
- durationInFrames: planned.durationInFrames,
750
- narrationText: planned.narrationText
751
- }));
752
- let ttsProject;
753
- let narrationAudio;
754
- if (brief.narration?.enabled && this.voice) {
755
- try {
756
- ttsProject = await this.voice.synthesizeForVideo({
757
- content: brief.content,
758
- scenePlan: {
759
- scenes: scenes.map((s) => ({
760
- id: s.id,
761
- compositionId: s.compositionId,
762
- durationInFrames: s.durationInFrames,
763
- narrationText: s.narrationText
764
- })),
765
- estimatedDurationSeconds: scenePlan.estimatedDurationSeconds
766
- },
767
- voice: { voiceId: brief.narration.voiceId ?? "" },
768
- pacing: { strategy: "scene-matched" },
769
- fps: this.fps
770
- });
771
- if (ttsProject.timingMap) {
772
- for (const seg of ttsProject.timingMap.segments) {
773
- const scene = scenes.find((s) => s.id === seg.sceneId);
774
- if (scene) {
775
- scene.durationInFrames = seg.recommendedSceneDurationInFrames;
776
- }
777
- }
778
- }
779
- if (ttsProject.assembledAudio) {
780
- narrationAudio = {
781
- data: ttsProject.assembledAudio.data,
782
- format: ttsProject.assembledAudio.format === "wav" ? "wav" : "mp3",
783
- durationSeconds: (ttsProject.assembledAudio.durationMs ?? 0) / 1000,
784
- volume: 1
785
- };
786
- }
787
- } catch {}
788
- }
789
- let subtitles;
790
- if (this.transcriber && ttsProject?.assembledAudio) {
791
- try {
792
- const transcription = await this.transcriber.transcribe({
793
- audio: ttsProject.assembledAudio,
794
- subtitleFormat: "vtt"
795
- });
796
- subtitles = transcription.subtitles;
797
- } catch {}
798
- }
799
- let thumbnail;
800
- if (this.image) {
801
- try {
802
- const thumbProject = await this.image.generate({
803
- content: brief.content,
804
- purpose: "video-thumbnail",
805
- format: "png",
806
- style: "photorealistic"
807
- });
808
- const imageUrl = thumbProject.results?.images[0]?.url;
809
- thumbnail = {
810
- prompt: thumbProject.prompt.text,
811
- ...imageUrl ? { imageUrl } : {}
812
- };
813
- } catch {}
814
- }
815
- const format = brief.format ?? VIDEO_FORMATS2.landscape;
816
- const totalDurationInFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
817
- const project = {
818
- id: generateProjectId(),
819
- scenes,
820
- totalDurationInFrames,
821
- fps: this.fps,
822
- format,
823
- audio: narrationAudio ? { narration: narrationAudio } : undefined,
824
- subtitles,
825
- voiceTimingMap: ttsProject?.timingMap,
826
- thumbnail
827
- };
828
- return project;
829
- }
830
- }
831
- function generateProjectId() {
832
- const timestamp = Date.now().toString(36);
833
- const random = Math.random().toString(36).slice(2, 8);
834
- return `vp_${timestamp}_${random}`;
835
- }
836
- export {
837
- VideoGenerator,
838
- ScenePlanner
839
- };
83
+ Privil\xE9giez la clart\xE9 et le rythme. Chaque sc\xE8ne doit communiquer une id\xE9e.`,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\xE9cis. Soyez d\xE9taill\xE9 et exact.",description:"Style guide for technical narration"},"script.segment.challenge":{value:"Le d\xE9fi\xA0: {content}",description:"Narration segment prefix for problems",placeholders:[{name:"content",type:"string"}]},"script.segment.solution":{value:"La solution\xA0: {content}",description:"Narration segment prefix for solutions",placeholders:[{name:"content",type:"string"}]},"script.segment.results":{value:"Les r\xE9sultats\xA0: {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\xE8me",description:"Scene hook label for problem statement"},"scene.narration.problem":{value:"Le probl\xE8me\xA0: {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\xA0: {content}",description:"Scene narration for solution",placeholders:[{name:"content",type:"string"}]},"scene.hook.results":{value:"R\xE9sultats",description:"Scene hook label for results/metrics"},"composition.apiOverview.generates":{value:"G\xE9n\xE8re\xA0:",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\xE8le 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 X={"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"},h={"script.segment.challenge":"script.segment.challenge","script.segment.solution":"script.segment.solution","script.segment.results":"script.segment.results"},R={"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"},U={"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"},v={...X,...h,...R,...U};import{DEFAULT_LOCALE as A,isSupportedLocale as D,resolveLocale as m,SUPPORTED_LOCALES as T}from"@contractspec/lib.contracts-spec/translations";import{createI18nFactory as g}from"@contractspec/lib.contracts-spec/translations";var y=g({specKey:"video-gen.messages",catalogs:[$,Y,I]}),E=y.create,j=y.getDefault,F=y.resetRegistry;class V{llm;model;temperature;fps;i18n;modelSelector;selectionContext;constructor(x){this.llm=x?.llm,this.model=x?.model,this.temperature=x?.temperature??0.3,this.fps=x?.fps??Q,this.i18n=E(x?.locale),this.modelSelector=x?.modelSelector,this.selectionContext=x?.selectionContext}async plan(x){if(this.llm)return this.planWithLlm(x);return this.planDeterministic(x)}planDeterministic(x){let{content:G}=x,{t:K}=this.i18n,L=[],z=this.fps;if(L.push({compositionId:"SocialClip",props:{hook:G.title,message:G.summary,points:G.solutions.slice(0,3),cta:G.callToAction??K("scene.cta.default")},durationInFrames:3*z,narrationText:`${G.title}. ${G.summary}`}),G.problems.length>0)L.push({compositionId:"SocialClip",props:{hook:K("scene.hook.problem"),message:G.problems[0]??"",points:G.problems.slice(1,4)},durationInFrames:4*z,narrationText:K("scene.narration.problem",{content:G.problems.join(". ")})});if(G.solutions.length>0)L.push({compositionId:"SocialClip",props:{hook:K("scene.hook.solution"),message:G.solutions[0]??"",points:G.solutions.slice(1,4)},durationInFrames:5*z,narrationText:K("scene.narration.solution",{content:G.solutions.join(". ")})});if(G.metrics&&G.metrics.length>0)L.push({compositionId:"SocialClip",props:{hook:K("scene.hook.results"),message:G.metrics[0]??"",points:G.metrics.slice(1,3)},durationInFrames:3*z,narrationText:G.metrics.join(". ")});if(G.callToAction)L.push({compositionId:"SocialClip",props:{hook:G.callToAction,message:"",cta:G.callToAction},durationInFrames:2*z,narrationText:G.callToAction});if(x.targetDurationSeconds){let N=x.targetDurationSeconds*z,q=L.reduce((C,k)=>C+k.durationInFrames,0),H=N/q;for(let C of L)C.durationInFrames=Math.round(C.durationInFrames*H)}let w=L.reduce((N,q)=>N+q.durationInFrames,0),B=L.filter((N)=>N.narrationText).map((N)=>N.narrationText).join(" ");return{scenes:L,estimatedDurationSeconds:w/z,narrationScript:B}}async resolveModel(){if(this.model)return this.model;if(this.modelSelector){let x=this.selectionContext??{taskDimension:"reasoning"};return(await this.modelSelector.select(x)).modelId}return}async planWithLlm(x){let{t:G}=this.i18n,K=[{role:"system",content:[{type:"text",text:G("prompt.scenePlanner.system",{fps:this.fps,targetSeconds:x.targetDurationSeconds??30})}]},{role:"user",content:[{type:"text",text:JSON.stringify(x.content)}]}];if(!this.llm)return this.planDeterministic(x);try{let L=await this.resolveModel(),w=(await this.llm.chat(K,{model:L,temperature:this.temperature,responseFormat:"json"})).message.content.find((q)=>q.type==="text");if(!w||w.type!=="text")return this.planDeterministic(x);let B=JSON.parse(w.text),N=B.scenes.reduce((q,H)=>q+H.durationInFrames,0);return{scenes:B.scenes,estimatedDurationSeconds:N/this.fps,narrationScript:B.narrationScript}}catch{return this.planDeterministic(x)}}}import{VIDEO_FORMATS as P}from"@contractspec/lib.contracts-integrations/integrations/providers/video";class Z{scenePlanner;voice;transcriber;image;fps;constructor(x){this.fps=x?.fps??Q,this.voice=x?.voice,this.transcriber=x?.transcriber,this.image=x?.image,this.scenePlanner=new V({llm:x?.llm,model:x?.model,temperature:x?.temperature,fps:this.fps,locale:x?.locale,modelSelector:x?.modelSelector,selectionContext:x?.selectionContext})}async generate(x){let G=await this.scenePlanner.plan(x),K=G.scenes.map((C,k)=>({id:`scene-${k}`,compositionId:C.compositionId,props:C.props,durationInFrames:C.durationInFrames,narrationText:C.narrationText})),L,z;if(x.narration?.enabled&&this.voice)try{if(L=await this.voice.synthesizeForVideo({content:x.content,scenePlan:{scenes:K.map((C)=>({id:C.id,compositionId:C.compositionId,durationInFrames:C.durationInFrames,narrationText:C.narrationText})),estimatedDurationSeconds:G.estimatedDurationSeconds},voice:{voiceId:x.narration.voiceId??""},pacing:{strategy:"scene-matched"},fps:this.fps}),L.timingMap)for(let C of L.timingMap.segments){let k=K.find((_)=>_.id===C.sceneId);if(k)k.durationInFrames=C.recommendedSceneDurationInFrames}if(L.assembledAudio)z={data:L.assembledAudio.data,format:L.assembledAudio.format==="wav"?"wav":"mp3",durationSeconds:(L.assembledAudio.durationMs??0)/1000,volume:1}}catch{}let w;if(this.transcriber&&L?.assembledAudio)try{w=(await this.transcriber.transcribe({audio:L.assembledAudio,subtitleFormat:"vtt"})).subtitles}catch{}let B;if(this.image)try{let C=await this.image.generate({content:x.content,purpose:"video-thumbnail",format:"png",style:"photorealistic"}),k=C.results?.images[0]?.url;B={prompt:C.prompt.text,...k?{imageUrl:k}:{}}}catch{}let N=x.format??P.landscape,q=K.reduce((C,k)=>C+k.durationInFrames,0);return{id:u(),scenes:K,totalDurationInFrames:q,fps:this.fps,format:N,audio:z?{narration:z}:void 0,subtitles:w,voiceTimingMap:L?.timingMap,thumbnail:B}}}function u(){let x=Date.now().toString(36),G=Math.random().toString(36).slice(2,8);return`vp_${x}_${G}`}export{Z as VideoGenerator,V as ScenePlanner};