@studiomeyer/mcp-video 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  3. package/.github/workflows/ci.yml +34 -0
  4. package/CHANGELOG.md +24 -0
  5. package/CONTRIBUTING.md +75 -0
  6. package/LICENSE +21 -0
  7. package/README.md +198 -0
  8. package/USAGE.md +144 -0
  9. package/dist/handlers/capcut.d.ts +6 -0
  10. package/dist/handlers/capcut.js +229 -0
  11. package/dist/handlers/capcut.js.map +1 -0
  12. package/dist/handlers/editing.d.ts +6 -0
  13. package/dist/handlers/editing.js +242 -0
  14. package/dist/handlers/editing.js.map +1 -0
  15. package/dist/handlers/index.d.ts +2 -0
  16. package/dist/handlers/index.js +33 -0
  17. package/dist/handlers/index.js.map +1 -0
  18. package/dist/handlers/post-production.d.ts +5 -0
  19. package/dist/handlers/post-production.js +109 -0
  20. package/dist/handlers/post-production.js.map +1 -0
  21. package/dist/handlers/smart-screenshot.d.ts +5 -0
  22. package/dist/handlers/smart-screenshot.js +83 -0
  23. package/dist/handlers/smart-screenshot.js.map +1 -0
  24. package/dist/handlers/tts.d.ts +5 -0
  25. package/dist/handlers/tts.js +83 -0
  26. package/dist/handlers/tts.js.map +1 -0
  27. package/dist/handlers/video.d.ts +5 -0
  28. package/dist/handlers/video.js +127 -0
  29. package/dist/handlers/video.js.map +1 -0
  30. package/dist/lib/dual-transport.d.ts +42 -0
  31. package/dist/lib/dual-transport.js +208 -0
  32. package/dist/lib/dual-transport.js.map +1 -0
  33. package/dist/lib/logger.d.ts +12 -0
  34. package/dist/lib/logger.js +42 -0
  35. package/dist/lib/logger.js.map +1 -0
  36. package/dist/lib/types.d.ts +16 -0
  37. package/dist/lib/types.js +15 -0
  38. package/dist/lib/types.js.map +1 -0
  39. package/dist/schemas/capcut.d.ts +608 -0
  40. package/dist/schemas/capcut.js +411 -0
  41. package/dist/schemas/capcut.js.map +1 -0
  42. package/dist/schemas/editing.d.ts +822 -0
  43. package/dist/schemas/editing.js +466 -0
  44. package/dist/schemas/editing.js.map +1 -0
  45. package/dist/schemas/index.d.ts +2366 -0
  46. package/dist/schemas/index.js +15 -0
  47. package/dist/schemas/index.js.map +1 -0
  48. package/dist/schemas/post-production.d.ts +379 -0
  49. package/dist/schemas/post-production.js +268 -0
  50. package/dist/schemas/post-production.js.map +1 -0
  51. package/dist/schemas/smart-screenshot.d.ts +127 -0
  52. package/dist/schemas/smart-screenshot.js +122 -0
  53. package/dist/schemas/smart-screenshot.js.map +1 -0
  54. package/dist/schemas/tts.d.ts +220 -0
  55. package/dist/schemas/tts.js +194 -0
  56. package/dist/schemas/tts.js.map +1 -0
  57. package/dist/schemas/video.d.ts +236 -0
  58. package/dist/schemas/video.js +210 -0
  59. package/dist/schemas/video.js.map +1 -0
  60. package/dist/server.d.ts +11 -0
  61. package/dist/server.js +239 -0
  62. package/dist/server.js.map +1 -0
  63. package/dist/server.test.d.ts +1 -0
  64. package/dist/server.test.js +87 -0
  65. package/dist/server.test.js.map +1 -0
  66. package/dist/tools/engine/audio-mixer.d.ts +40 -0
  67. package/dist/tools/engine/audio-mixer.js +169 -0
  68. package/dist/tools/engine/audio-mixer.js.map +1 -0
  69. package/dist/tools/engine/audio.d.ts +22 -0
  70. package/dist/tools/engine/audio.js +73 -0
  71. package/dist/tools/engine/audio.js.map +1 -0
  72. package/dist/tools/engine/beat-sync.d.ts +31 -0
  73. package/dist/tools/engine/beat-sync.js +270 -0
  74. package/dist/tools/engine/beat-sync.js.map +1 -0
  75. package/dist/tools/engine/capture.d.ts +12 -0
  76. package/dist/tools/engine/capture.js +290 -0
  77. package/dist/tools/engine/capture.js.map +1 -0
  78. package/dist/tools/engine/chroma-key.d.ts +27 -0
  79. package/dist/tools/engine/chroma-key.js +154 -0
  80. package/dist/tools/engine/chroma-key.js.map +1 -0
  81. package/dist/tools/engine/concat.d.ts +49 -0
  82. package/dist/tools/engine/concat.js +149 -0
  83. package/dist/tools/engine/concat.js.map +1 -0
  84. package/dist/tools/engine/cursor.d.ts +26 -0
  85. package/dist/tools/engine/cursor.js +185 -0
  86. package/dist/tools/engine/cursor.js.map +1 -0
  87. package/dist/tools/engine/easing.d.ts +15 -0
  88. package/dist/tools/engine/easing.js +100 -0
  89. package/dist/tools/engine/easing.js.map +1 -0
  90. package/dist/tools/engine/editing.d.ts +158 -0
  91. package/dist/tools/engine/editing.js +541 -0
  92. package/dist/tools/engine/editing.js.map +1 -0
  93. package/dist/tools/engine/encoder.d.ts +31 -0
  94. package/dist/tools/engine/encoder.js +154 -0
  95. package/dist/tools/engine/encoder.js.map +1 -0
  96. package/dist/tools/engine/index.d.ts +30 -0
  97. package/dist/tools/engine/index.js +23 -0
  98. package/dist/tools/engine/index.js.map +1 -0
  99. package/dist/tools/engine/lut-presets.d.ts +25 -0
  100. package/dist/tools/engine/lut-presets.js +141 -0
  101. package/dist/tools/engine/lut-presets.js.map +1 -0
  102. package/dist/tools/engine/narrated-video.d.ts +63 -0
  103. package/dist/tools/engine/narrated-video.js +163 -0
  104. package/dist/tools/engine/narrated-video.js.map +1 -0
  105. package/dist/tools/engine/scenes.d.ts +17 -0
  106. package/dist/tools/engine/scenes.js +223 -0
  107. package/dist/tools/engine/scenes.js.map +1 -0
  108. package/dist/tools/engine/smart-screenshot.d.ts +80 -0
  109. package/dist/tools/engine/smart-screenshot.js +744 -0
  110. package/dist/tools/engine/smart-screenshot.js.map +1 -0
  111. package/dist/tools/engine/social-format.d.ts +66 -0
  112. package/dist/tools/engine/social-format.js +107 -0
  113. package/dist/tools/engine/social-format.js.map +1 -0
  114. package/dist/tools/engine/template-renderer.d.ts +45 -0
  115. package/dist/tools/engine/template-renderer.js +233 -0
  116. package/dist/tools/engine/template-renderer.js.map +1 -0
  117. package/dist/tools/engine/templates.d.ts +87 -0
  118. package/dist/tools/engine/templates.js +272 -0
  119. package/dist/tools/engine/templates.js.map +1 -0
  120. package/dist/tools/engine/text-animations.d.ts +33 -0
  121. package/dist/tools/engine/text-animations.js +192 -0
  122. package/dist/tools/engine/text-animations.js.map +1 -0
  123. package/dist/tools/engine/text-overlay.d.ts +27 -0
  124. package/dist/tools/engine/text-overlay.js +84 -0
  125. package/dist/tools/engine/text-overlay.js.map +1 -0
  126. package/dist/tools/engine/tts.d.ts +54 -0
  127. package/dist/tools/engine/tts.js +186 -0
  128. package/dist/tools/engine/tts.js.map +1 -0
  129. package/dist/tools/engine/types.d.ts +166 -0
  130. package/dist/tools/engine/types.js +13 -0
  131. package/dist/tools/engine/types.js.map +1 -0
  132. package/dist/tools/engine/voice-effects.d.ts +18 -0
  133. package/dist/tools/engine/voice-effects.js +215 -0
  134. package/dist/tools/engine/voice-effects.js.map +1 -0
  135. package/dist/tools/index.d.ts +32 -0
  136. package/dist/tools/index.js +23 -0
  137. package/dist/tools/index.js.map +1 -0
  138. package/package.json +56 -0
  139. package/scripts/check-deps.js +39 -0
  140. package/src/handlers/capcut.ts +245 -0
  141. package/src/handlers/editing.ts +260 -0
  142. package/src/handlers/index.ts +34 -0
  143. package/src/handlers/post-production.ts +136 -0
  144. package/src/handlers/smart-screenshot.ts +86 -0
  145. package/src/handlers/tts.ts +103 -0
  146. package/src/handlers/video.ts +137 -0
  147. package/src/lib/dual-transport.ts +272 -0
  148. package/src/lib/logger.ts +59 -0
  149. package/src/lib/types.ts +25 -0
  150. package/src/schemas/capcut.ts +418 -0
  151. package/src/schemas/editing.ts +476 -0
  152. package/src/schemas/index.ts +15 -0
  153. package/src/schemas/post-production.ts +273 -0
  154. package/src/schemas/smart-screenshot.ts +122 -0
  155. package/src/schemas/tts.ts +197 -0
  156. package/src/schemas/video.ts +211 -0
  157. package/src/server.test.ts +99 -0
  158. package/src/server.ts +289 -0
  159. package/src/tools/engine/audio-mixer.ts +244 -0
  160. package/src/tools/engine/audio.ts +115 -0
  161. package/src/tools/engine/beat-sync.ts +356 -0
  162. package/src/tools/engine/capture.ts +360 -0
  163. package/src/tools/engine/chroma-key.ts +202 -0
  164. package/src/tools/engine/concat.ts +242 -0
  165. package/src/tools/engine/cursor.ts +222 -0
  166. package/src/tools/engine/easing.ts +120 -0
  167. package/src/tools/engine/editing.ts +809 -0
  168. package/src/tools/engine/encoder.ts +208 -0
  169. package/src/tools/engine/index.ts +33 -0
  170. package/src/tools/engine/lut-presets.ts +235 -0
  171. package/src/tools/engine/narrated-video.ts +267 -0
  172. package/src/tools/engine/scenes.ts +309 -0
  173. package/src/tools/engine/smart-screenshot.ts +923 -0
  174. package/src/tools/engine/social-format.ts +146 -0
  175. package/src/tools/engine/template-renderer.ts +294 -0
  176. package/src/tools/engine/templates.ts +370 -0
  177. package/src/tools/engine/text-animations.ts +282 -0
  178. package/src/tools/engine/text-overlay.ts +143 -0
  179. package/src/tools/engine/tts.ts +284 -0
  180. package/src/tools/engine/types.ts +191 -0
  181. package/src/tools/engine/voice-effects.ts +258 -0
  182. package/src/tools/index.ts +67 -0
  183. package/tsconfig.json +19 -0
  184. package/vitest.config.ts +7 -0
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Video Template Engine — Pre-built video templates for common use cases.
3
+ *
4
+ * Templates define: clip slots, timing, transitions, text placeholders,
5
+ * effects, color grades, and music style.
6
+ *
7
+ * The renderer (template-renderer.ts) takes a template + user assets
8
+ * and produces a finished video using all existing engines.
9
+ */
10
+ // ─── Template Definitions ───────────────────────────────────────────
11
+ const TEMPLATES = [
12
+ // ─── Social Reel ─────────────────────────────────────────────
13
+ {
14
+ id: 'social-reel-hype',
15
+ name: 'Hype Reel',
16
+ category: 'social-reel',
17
+ description: 'Fast-paced 15-second reel with 5 quick cuts, beat-synced feel, bold text overlays. Perfect for Instagram/TikTok.',
18
+ totalDuration: 15,
19
+ aspectRatio: '9:16',
20
+ resolution: { width: 1080, height: 1920 },
21
+ slots: [
22
+ { name: 'hook-clip', duration: 3, required: true, description: 'Opening hook — attention-grabbing first 3 seconds', type: 'video' },
23
+ { name: 'clip-2', duration: 3, required: true, description: 'Second clip — show the product/action', type: 'video' },
24
+ { name: 'clip-3', duration: 3, required: true, description: 'Third clip — build momentum', type: 'video' },
25
+ { name: 'clip-4', duration: 3, required: false, description: 'Fourth clip — variety shot', type: 'video' },
26
+ { name: 'cta-clip', duration: 3, required: true, description: 'Closing CTA clip', type: 'video' },
27
+ ],
28
+ textPlaceholders: [
29
+ { name: 'hook-text', defaultText: 'WATCH THIS', animation: 'pop', startTime: 0.2, duration: 2.5, position: 'center', fontSize: 64 },
30
+ { name: 'cta-text', defaultText: 'FOLLOW FOR MORE', animation: 'slide-up', startTime: 12, duration: 3, position: 'bottom', fontSize: 48 },
31
+ ],
32
+ transition: 'fade',
33
+ colorGrade: 'high-contrast-music',
34
+ musicStyle: 'upbeat, energetic, trending audio',
35
+ tags: ['reel', 'tiktok', 'instagram', 'fast', 'hype', 'trending'],
36
+ },
37
+ {
38
+ id: 'social-reel-aesthetic',
39
+ name: 'Aesthetic Reel',
40
+ category: 'social-reel',
41
+ description: 'Slow, cinematic 30-second reel with smooth transitions and warm color grading. Great for lifestyle/travel content.',
42
+ totalDuration: 30,
43
+ aspectRatio: '9:16',
44
+ resolution: { width: 1080, height: 1920 },
45
+ slots: [
46
+ { name: 'opening', duration: 5, required: true, description: 'Slow opening shot — set the mood', type: 'video' },
47
+ { name: 'scene-2', duration: 5, required: true, description: 'Second scene — establish context', type: 'video' },
48
+ { name: 'scene-3', duration: 5, required: true, description: 'Third scene — main content', type: 'video' },
49
+ { name: 'scene-4', duration: 5, required: false, description: 'Fourth scene — detail shot', type: 'video' },
50
+ { name: 'scene-5', duration: 5, required: false, description: 'Fifth scene — variety', type: 'video' },
51
+ { name: 'closing', duration: 5, required: true, description: 'Closing scene — satisfying end', type: 'video' },
52
+ ],
53
+ textPlaceholders: [
54
+ { name: 'title', defaultText: 'Golden Hour', animation: 'fade-in', startTime: 1, duration: 4, position: 'center', fontSize: 56 },
55
+ { name: 'location', defaultText: 'Somewhere Beautiful', animation: 'fade-in-out', startTime: 6, duration: 4, position: 'bottom', fontSize: 36 },
56
+ ],
57
+ transition: 'crossfade',
58
+ colorGrade: 'warm-golden',
59
+ musicStyle: 'ambient, lo-fi, chill',
60
+ tags: ['aesthetic', 'cinematic', 'lifestyle', 'travel', 'slow'],
61
+ },
62
+ // ─── Product Demo ────────────────────────────────────────────
63
+ {
64
+ id: 'product-demo-saas',
65
+ name: 'SaaS Product Demo',
66
+ category: 'product-demo',
67
+ description: '60-second product demo: problem → solution → features → CTA. Clean look with screen recordings.',
68
+ totalDuration: 60,
69
+ aspectRatio: '16:9',
70
+ resolution: { width: 1920, height: 1080 },
71
+ slots: [
72
+ { name: 'problem', duration: 10, required: true, description: 'Show the problem your product solves', type: 'video' },
73
+ { name: 'intro-screen', duration: 5, required: true, description: 'Product name / logo reveal', type: 'video' },
74
+ { name: 'feature-1', duration: 12, required: true, description: 'Screen recording of feature 1', type: 'video' },
75
+ { name: 'feature-2', duration: 12, required: true, description: 'Screen recording of feature 2', type: 'video' },
76
+ { name: 'feature-3', duration: 12, required: false, description: 'Screen recording of feature 3', type: 'video' },
77
+ { name: 'cta', duration: 9, required: true, description: 'Closing with CTA', type: 'video' },
78
+ ],
79
+ textPlaceholders: [
80
+ { name: 'problem-text', defaultText: 'Tired of manual work?', animation: 'typewriter', startTime: 1, duration: 4, position: 'center', fontSize: 52 },
81
+ { name: 'product-name', defaultText: 'Product Name', animation: 'pop', startTime: 11, duration: 4, position: 'center', fontSize: 72 },
82
+ { name: 'feature-1-label', defaultText: 'Feature One', animation: 'slide-left', startTime: 16, duration: 3, position: 'top', fontSize: 36 },
83
+ { name: 'feature-2-label', defaultText: 'Feature Two', animation: 'slide-left', startTime: 28, duration: 3, position: 'top', fontSize: 36 },
84
+ { name: 'cta-text', defaultText: 'Try Free Today', animation: 'bounce', startTime: 52, duration: 7, position: 'center', fontSize: 64 },
85
+ ],
86
+ transition: 'fade',
87
+ colorGrade: 'cinematic-teal-orange-subtle',
88
+ musicStyle: 'corporate, uplifting, modern',
89
+ tags: ['saas', 'demo', 'product', 'screen-recording', 'corporate'],
90
+ },
91
+ // ─── Testimonial ─────────────────────────────────────────────
92
+ {
93
+ id: 'testimonial-single',
94
+ name: 'Customer Testimonial',
95
+ category: 'testimonial',
96
+ description: '30-second testimonial: quote + customer name + product shot. Warm, trustworthy feel.',
97
+ totalDuration: 30,
98
+ aspectRatio: '16:9',
99
+ resolution: { width: 1920, height: 1080 },
100
+ slots: [
101
+ { name: 'customer-video', duration: 20, required: true, description: 'Customer speaking / interview clip', type: 'video' },
102
+ { name: 'product-shot', duration: 7, required: true, description: 'Product being used', type: 'video' },
103
+ { name: 'logo-end', duration: 3, required: false, description: 'Company logo end card', type: 'image' },
104
+ ],
105
+ textPlaceholders: [
106
+ { name: 'quote', defaultText: '"This changed everything for us."', animation: 'fade-in', startTime: 2, duration: 8, position: 'bottom', fontSize: 36 },
107
+ { name: 'name', defaultText: 'Jane Doe, CEO at Company', animation: 'slide-up', startTime: 20, duration: 5, position: 'bottom', fontSize: 32 },
108
+ ],
109
+ transition: 'crossfade',
110
+ colorGrade: 'warm-golden',
111
+ musicStyle: 'soft piano, inspirational',
112
+ tags: ['testimonial', 'customer', 'review', 'trust'],
113
+ },
114
+ // ─── Before-After ────────────────────────────────────────────
115
+ {
116
+ id: 'before-after-split',
117
+ name: 'Before & After',
118
+ category: 'before-after',
119
+ description: '15-second split-screen before/after comparison. Great for transformations, renovations, edits.',
120
+ totalDuration: 15,
121
+ aspectRatio: '9:16',
122
+ resolution: { width: 1080, height: 1920 },
123
+ slots: [
124
+ { name: 'before', duration: 7, required: true, description: 'Before state', type: 'video' },
125
+ { name: 'after', duration: 7, required: true, description: 'After state (transformation)', type: 'video' },
126
+ ],
127
+ textPlaceholders: [
128
+ { name: 'before-label', defaultText: 'BEFORE', animation: 'pop', startTime: 0.5, duration: 3, position: 'top', fontSize: 56 },
129
+ { name: 'after-label', defaultText: 'AFTER', animation: 'pop', startTime: 7.5, duration: 3, position: 'top', fontSize: 56 },
130
+ ],
131
+ transition: 'wipe',
132
+ musicStyle: 'dramatic reveal, build-up',
133
+ tags: ['before-after', 'transformation', 'comparison', 'reveal'],
134
+ },
135
+ // ─── Slideshow ───────────────────────────────────────────────
136
+ {
137
+ id: 'slideshow-photo',
138
+ name: 'Photo Slideshow',
139
+ category: 'slideshow',
140
+ description: '45-second photo slideshow with Ken Burns effect (slow zoom/pan). Perfect for memories, events, portfolios.',
141
+ totalDuration: 45,
142
+ aspectRatio: '16:9',
143
+ resolution: { width: 1920, height: 1080 },
144
+ slots: [
145
+ { name: 'photo-1', duration: 5, required: true, description: 'First photo', type: 'image' },
146
+ { name: 'photo-2', duration: 5, required: true, description: 'Second photo', type: 'image' },
147
+ { name: 'photo-3', duration: 5, required: true, description: 'Third photo', type: 'image' },
148
+ { name: 'photo-4', duration: 5, required: false, description: 'Fourth photo', type: 'image' },
149
+ { name: 'photo-5', duration: 5, required: false, description: 'Fifth photo', type: 'image' },
150
+ { name: 'photo-6', duration: 5, required: false, description: 'Sixth photo', type: 'image' },
151
+ { name: 'photo-7', duration: 5, required: false, description: 'Seventh photo', type: 'image' },
152
+ { name: 'photo-8', duration: 5, required: false, description: 'Eighth photo', type: 'image' },
153
+ { name: 'photo-9', duration: 5, required: false, description: 'Ninth photo (closing)', type: 'image' },
154
+ ],
155
+ textPlaceholders: [
156
+ { name: 'title', defaultText: 'Memories', animation: 'fade-in-out', startTime: 0, duration: 5, position: 'center', fontSize: 72 },
157
+ ],
158
+ transition: 'crossfade',
159
+ colorGrade: 'vintage-film',
160
+ musicStyle: 'emotional, acoustic, nostalgic',
161
+ tags: ['slideshow', 'photos', 'memories', 'event', 'portfolio'],
162
+ },
163
+ // ─── Tutorial ────────────────────────────────────────────────
164
+ {
165
+ id: 'tutorial-howto',
166
+ name: 'How-To Tutorial',
167
+ category: 'tutorial',
168
+ description: '90-second step-by-step tutorial: intro → step 1 → step 2 → step 3 → summary. Clean and instructional.',
169
+ totalDuration: 90,
170
+ aspectRatio: '16:9',
171
+ resolution: { width: 1920, height: 1080 },
172
+ slots: [
173
+ { name: 'intro', duration: 10, required: true, description: 'What you will learn', type: 'video' },
174
+ { name: 'step-1', duration: 20, required: true, description: 'Step 1 demonstration', type: 'video' },
175
+ { name: 'step-2', duration: 20, required: true, description: 'Step 2 demonstration', type: 'video' },
176
+ { name: 'step-3', duration: 20, required: false, description: 'Step 3 demonstration', type: 'video' },
177
+ { name: 'summary', duration: 10, required: true, description: 'Summary / final result', type: 'video' },
178
+ { name: 'outro', duration: 10, required: false, description: 'Subscribe / follow CTA', type: 'video' },
179
+ ],
180
+ textPlaceholders: [
181
+ { name: 'title', defaultText: 'How to...', animation: 'typewriter', startTime: 1, duration: 5, position: 'center', fontSize: 56 },
182
+ { name: 'step-1-label', defaultText: 'Step 1', animation: 'slide-left', startTime: 10, duration: 3, position: 'top-left', fontSize: 40 },
183
+ { name: 'step-2-label', defaultText: 'Step 2', animation: 'slide-left', startTime: 30, duration: 3, position: 'top-left', fontSize: 40 },
184
+ { name: 'step-3-label', defaultText: 'Step 3', animation: 'slide-left', startTime: 50, duration: 3, position: 'top-left', fontSize: 40 },
185
+ { name: 'done-text', defaultText: "That's it!", animation: 'bounce', startTime: 70, duration: 5, position: 'center', fontSize: 64 },
186
+ ],
187
+ transition: 'fade',
188
+ musicStyle: 'lo-fi background, subtle',
189
+ tags: ['tutorial', 'howto', 'educational', 'step-by-step'],
190
+ },
191
+ // ─── Announcement ────────────────────────────────────────────
192
+ {
193
+ id: 'announcement-launch',
194
+ name: 'Product Launch',
195
+ category: 'announcement',
196
+ description: '20-second product launch announcement: dramatic reveal with bold text. High energy.',
197
+ totalDuration: 20,
198
+ aspectRatio: '1:1',
199
+ resolution: { width: 1080, height: 1080 },
200
+ slots: [
201
+ { name: 'teaser', duration: 5, required: true, description: 'Build-up / teaser shot', type: 'video' },
202
+ { name: 'reveal', duration: 8, required: true, description: 'Product reveal moment', type: 'video' },
203
+ { name: 'details', duration: 4, required: false, description: 'Key features / details', type: 'video' },
204
+ { name: 'cta', duration: 3, required: true, description: 'CTA end card', type: 'image' },
205
+ ],
206
+ textPlaceholders: [
207
+ { name: 'coming', defaultText: 'Something Big...', animation: 'fade-in', startTime: 0.5, duration: 4, position: 'center', fontSize: 56 },
208
+ { name: 'product', defaultText: 'INTRODUCING', animation: 'pop', startTime: 5, duration: 3, position: 'top', fontSize: 48 },
209
+ { name: 'name', defaultText: 'Product Name', animation: 'bounce', startTime: 6, duration: 5, position: 'center', fontSize: 72 },
210
+ { name: 'cta-text', defaultText: 'Available Now', animation: 'slide-up', startTime: 17, duration: 3, position: 'center', fontSize: 52 },
211
+ ],
212
+ transition: 'fade',
213
+ colorGrade: 'cyberpunk-neon',
214
+ musicStyle: 'dramatic, cinematic trailer, build-up + drop',
215
+ tags: ['launch', 'announcement', 'product', 'reveal', 'dramatic'],
216
+ },
217
+ // ─── Promo ───────────────────────────────────────────────────
218
+ {
219
+ id: 'promo-sale',
220
+ name: 'Sale Promo',
221
+ category: 'promo',
222
+ description: '10-second sale/discount promo: bold numbers, urgency, CTA. Perfect for stories/ads.',
223
+ totalDuration: 10,
224
+ aspectRatio: '9:16',
225
+ resolution: { width: 1080, height: 1920 },
226
+ slots: [
227
+ { name: 'product-shot', duration: 5, required: true, description: 'Product in action', type: 'video' },
228
+ { name: 'cta-shot', duration: 5, required: true, description: 'End card with CTA', type: 'image' },
229
+ ],
230
+ textPlaceholders: [
231
+ { name: 'discount', defaultText: '50% OFF', animation: 'pop', startTime: 0.3, duration: 4, position: 'center', fontSize: 96 },
232
+ { name: 'limited', defaultText: 'LIMITED TIME', animation: 'shake', startTime: 1, duration: 3, position: 'top', fontSize: 36 },
233
+ { name: 'cta', defaultText: 'SHOP NOW', animation: 'bounce', startTime: 5.5, duration: 4, position: 'center', fontSize: 64 },
234
+ ],
235
+ transition: 'fade',
236
+ colorGrade: 'blockbuster-extreme',
237
+ musicStyle: 'urgent, energetic, short',
238
+ tags: ['sale', 'promo', 'discount', 'ad', 'story'],
239
+ },
240
+ ];
241
+ // ─── Functions ──────────────────────────────────────────────────────
242
+ /** List all available templates, optionally filtered by category */
243
+ export function listTemplates(category) {
244
+ if (category) {
245
+ return TEMPLATES.filter(t => t.category === category);
246
+ }
247
+ return TEMPLATES;
248
+ }
249
+ /** Get a specific template by ID */
250
+ export function getTemplate(id) {
251
+ return TEMPLATES.find(t => t.id === id);
252
+ }
253
+ /** Get all template categories */
254
+ export function getTemplateCategories() {
255
+ return ['social-reel', 'product-demo', 'testimonial', 'before-after', 'slideshow', 'tutorial', 'announcement', 'promo'];
256
+ }
257
+ /** Get template summary for listing */
258
+ export function getTemplateSummaries(category) {
259
+ const templates = category ? listTemplates(category) : TEMPLATES;
260
+ return templates.map(t => ({
261
+ id: t.id,
262
+ name: t.name,
263
+ category: t.category,
264
+ description: t.description,
265
+ duration: `${t.totalDuration}s`,
266
+ aspectRatio: t.aspectRatio,
267
+ requiredSlots: t.slots.filter(s => s.required).length,
268
+ optionalSlots: t.slots.filter(s => !s.required).length,
269
+ tags: t.tags,
270
+ }));
271
+ }
272
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/tools/engine/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2EH,uEAAuE;AAEvE,MAAM,SAAS,GAAoB;IACjC,gEAAgE;IAChE;QACE,EAAE,EAAE,kBAAkB;QACtB,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE,kHAAkH;QAC/H,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mDAAmD,EAAE,IAAI,EAAE,OAAO,EAAE;YACnI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uCAAuC,EAAE,IAAI,EAAE,OAAO,EAAE;YACpH,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6BAA6B,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1G,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1G,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,OAAO,EAAE;SAClG;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YACnI,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SAC1I;QACD,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,qBAAqB;QACjC,UAAU,EAAE,mCAAmC;QAC/C,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;KAClE;IAED;QACE,EAAE,EAAE,uBAAuB;QAC3B,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE,oHAAoH;QACjI,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,IAAI,EAAE,OAAO,EAAE;YAChH,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,IAAI,EAAE,OAAO,EAAE;YAChH,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1G,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;YAC3G,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;YACtG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,IAAI,EAAE,OAAO,EAAE;SAC/G;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YAChI,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,qBAAqB,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SAChJ;QACD,UAAU,EAAE,WAAW;QACvB,UAAU,EAAE,aAAa;QACzB,UAAU,EAAE,uBAAuB;QACnC,IAAI,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC;KAChE;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,mBAAmB;QACvB,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,cAAc;QACxB,WAAW,EAAE,iGAAiG;QAC9G,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sCAAsC,EAAE,IAAI,EAAE,OAAO,EAAE;YACrH,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;YAC/G,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+BAA+B,EAAE,IAAI,EAAE,OAAO,EAAE;YAChH,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+BAA+B,EAAE,IAAI,EAAE,OAAO,EAAE;YAChH,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,+BAA+B,EAAE,IAAI,EAAE,OAAO,EAAE;YACjH,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,OAAO,EAAE;SAC7F;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,uBAAuB,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpJ,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YACrI,EAAE,IAAI,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC3I,EAAE,IAAI,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC3I,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SACvI;QACD,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,8BAA8B;QAC1C,UAAU,EAAE,8BAA8B;QAC1C,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,EAAE,WAAW,CAAC;KACnE;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,oBAAoB;QACxB,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE,sFAAsF;QACnG,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oCAAoC,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1H,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,IAAI,EAAE,OAAO,EAAE;YACvG,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;SACxG;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YACtJ,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SAC/I;QACD,UAAU,EAAE,WAAW;QACvB,UAAU,EAAE,aAAa;QACzB,UAAU,EAAE,2BAA2B;QACvC,IAAI,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC;KACrD;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,oBAAoB;QACxB,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,cAAc;QACxB,WAAW,EAAE,gGAAgG;QAC7G,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;YAC3F,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8BAA8B,EAAE,IAAI,EAAE,OAAO,EAAE;SAC3G;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC7H,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;SAC5H;QACD,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,2BAA2B;QACvC,IAAI,EAAE,CAAC,cAAc,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,CAAC;KACjE;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,iBAAiB;QACrB,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,4GAA4G;QACzH,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;YAC3F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;YAC5F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;YAC3F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;YAC7F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;YAC5F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;YAC5F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE;YAC9F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;YAC7F,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;SACvG;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SAClI;QACD,UAAU,EAAE,WAAW;QACvB,UAAU,EAAE,cAAc;QAC1B,UAAU,EAAE,gCAAgC;QAC5C,IAAI,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC;KAChE;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,uGAAuG;QACpH,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qBAAqB,EAAE,IAAI,EAAE,OAAO,EAAE;YAClG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE,IAAI,EAAE,OAAO,EAAE;YACpG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE,IAAI,EAAE,OAAO,EAAE;YACpG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,IAAI,EAAE,OAAO,EAAE;YACrG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wBAAwB,EAAE,IAAI,EAAE,OAAO,EAAE;YACvG,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,IAAI,EAAE,OAAO,EAAE;SACvG;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YACjI,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE;YACxI,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE;YACxI,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE;YACxI,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SACpI;QACD,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,0BAA0B;QACtC,IAAI,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,CAAC;KAC3D;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,qBAAqB;QACzB,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,cAAc;QACxB,WAAW,EAAE,qFAAqF;QAClG,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,KAAK;QAClB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wBAAwB,EAAE,IAAI,EAAE,OAAO,EAAE;YACrG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;YACpG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,IAAI,EAAE,OAAO,EAAE;YACvG,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;SACzF;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YACxI,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC3H,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC/H,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SACxI;QACD,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,gBAAgB;QAC5B,UAAU,EAAE,8CAA8C;QAC1D,IAAI,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC;KAClE;IAED,gEAAgE;IAChE;QACE,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,qFAAqF;QAClG,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,EAAE;YACtG,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,EAAE;SACnG;QACD,gBAAgB,EAAE;YAChB,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC7H,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC9H,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;SAC7H;QACD,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,qBAAqB;QACjC,UAAU,EAAE,0BAA0B;QACtC,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC;KACnD;CACF,CAAC;AAEF,uEAAuE;AAEvE,oEAAoE;AACpE,MAAM,UAAU,aAAa,CAAC,QAA2B;IACvD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AAC1H,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,oBAAoB,CAAC,QAA2B;IAW9D,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzB,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,QAAQ,EAAE,GAAG,CAAC,CAAC,aAAa,GAAG;QAC/B,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM;QACrD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM;QACtD,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Text Animation Engine — 15+ animated text effects via FFmpeg drawtext.
3
+ *
4
+ * Each animation uses drawtext's `enable` expression and alpha/position
5
+ * manipulation to create effects like typewriter, pop, slide, bounce, etc.
6
+ */
7
+ export type TextAnimation = 'typewriter' | 'pop' | 'slide-up' | 'slide-down' | 'slide-left' | 'slide-right' | 'bounce' | 'fade-in' | 'fade-out' | 'fade-in-out' | 'glitch' | 'zoom-in' | 'shake' | 'neon-glow' | 'wave';
8
+ export interface TextAnimationConfig {
9
+ inputPath: string;
10
+ outputPath: string;
11
+ /** Text to animate */
12
+ text: string;
13
+ /** Animation style */
14
+ animation: TextAnimation;
15
+ /** Start time in seconds (default: 0) */
16
+ startTime?: number;
17
+ /** Duration of the animation/text display in seconds (default: 3) */
18
+ duration?: number;
19
+ /** Font size (default: 48) */
20
+ fontSize?: number;
21
+ /** Font color as hex (e.g., 'FFFFFF'). Default: 'FFFFFF' */
22
+ fontColor?: string;
23
+ /** Position: 'center', 'top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right'. Default: 'center' */
24
+ position?: TextPosition;
25
+ /** Font family (default: 'Sans') */
26
+ fontFamily?: string;
27
+ /** Shadow/outline for readability (default: true) */
28
+ shadow?: boolean;
29
+ }
30
+ export type TextPosition = 'center' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
31
+ export declare const ALL_TEXT_ANIMATIONS: TextAnimation[];
32
+ export declare const TEXT_ANIMATION_DESCRIPTIONS: Record<TextAnimation, string>;
33
+ export declare function animateText(config: TextAnimationConfig): Promise<string>;
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Text Animation Engine — 15+ animated text effects via FFmpeg drawtext.
3
+ *
4
+ * Each animation uses drawtext's `enable` expression and alpha/position
5
+ * manipulation to create effects like typewriter, pop, slide, bounce, etc.
6
+ */
7
+ import { execFile } from 'child_process';
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ import { logger } from '../../lib/logger.js';
11
+ export const ALL_TEXT_ANIMATIONS = [
12
+ 'typewriter', 'pop', 'slide-up', 'slide-down', 'slide-left', 'slide-right',
13
+ 'bounce', 'fade-in', 'fade-out', 'fade-in-out', 'glitch', 'zoom-in',
14
+ 'shake', 'neon-glow', 'wave',
15
+ ];
16
+ export const TEXT_ANIMATION_DESCRIPTIONS = {
17
+ 'typewriter': 'Letters appear one by one like typing',
18
+ 'pop': 'Text pops in with scale effect',
19
+ 'slide-up': 'Text slides up from below',
20
+ 'slide-down': 'Text slides down from above',
21
+ 'slide-left': 'Text slides in from the right',
22
+ 'slide-right': 'Text slides in from the left',
23
+ 'bounce': 'Text bounces into position',
24
+ 'fade-in': 'Text gradually fades in',
25
+ 'fade-out': 'Text gradually fades out',
26
+ 'fade-in-out': 'Text fades in then fades out',
27
+ 'glitch': 'Text appears with digital glitch effect',
28
+ 'zoom-in': 'Text zooms in from small to normal',
29
+ 'shake': 'Text shakes/vibrates in position',
30
+ 'neon-glow': 'Text pulses with neon glow effect',
31
+ 'wave': 'Text has a wave/oscillation motion',
32
+ };
33
+ // ─── Helpers ────────────────────────────────────────────────────────
34
+ function runFfmpeg(args, timeoutMs = 300_000) {
35
+ return new Promise((resolve, reject) => {
36
+ execFile('ffmpeg', args, { maxBuffer: 100 * 1024 * 1024, timeout: timeoutMs }, (error, stdout, stderr) => {
37
+ if (error) {
38
+ logger.error(`ffmpeg failed: ${stderr}`);
39
+ reject(new Error(`ffmpeg failed: ${stderr || error.message}`));
40
+ return;
41
+ }
42
+ resolve(stdout);
43
+ });
44
+ });
45
+ }
46
+ function ensureDir(filePath) {
47
+ const dir = path.dirname(filePath);
48
+ if (!fs.existsSync(dir))
49
+ fs.mkdirSync(dir, { recursive: true });
50
+ }
51
+ function assertExists(filePath, label = 'File') {
52
+ if (!fs.existsSync(filePath))
53
+ throw new Error(`${label} not found: ${filePath}`);
54
+ }
55
+ function fileInfo(filePath) {
56
+ const stats = fs.statSync(filePath);
57
+ return `${(stats.size / 1024 / 1024).toFixed(2)} MB`;
58
+ }
59
+ /** Escape text for FFmpeg drawtext (colons, backslashes, quotes) */
60
+ function escapeDrawtext(text) {
61
+ return text
62
+ .replace(/\\/g, '\\\\\\\\')
63
+ .replace(/'/g, "'\\\\\\''")
64
+ .replace(/:/g, '\\:')
65
+ .replace(/%/g, '%%');
66
+ }
67
+ /** Get position expressions for drawtext x/y */
68
+ function getPositionExprs(position, margin = 40) {
69
+ switch (position) {
70
+ case 'center': return { x: '(w-text_w)/2', y: '(h-text_h)/2' };
71
+ case 'top': return { x: '(w-text_w)/2', y: String(margin) };
72
+ case 'bottom': return { x: '(w-text_w)/2', y: `h-text_h-${margin}` };
73
+ case 'top-left': return { x: String(margin), y: String(margin) };
74
+ case 'top-right': return { x: `w-text_w-${margin}`, y: String(margin) };
75
+ case 'bottom-left': return { x: String(margin), y: `h-text_h-${margin}` };
76
+ case 'bottom-right': return { x: `w-text_w-${margin}`, y: `h-text_h-${margin}` };
77
+ default: return { x: '(w-text_w)/2', y: '(h-text_h)/2' };
78
+ }
79
+ }
80
+ // ─── Animation Builders ─────────────────────────────────────────────
81
+ function buildAnimationFilter(config) {
82
+ const { text, animation, startTime = 0, duration = 3, fontSize = 48, fontColor = 'FFFFFF', position = 'center', fontFamily = 'Sans', shadow = true, } = config;
83
+ const escapedText = escapeDrawtext(text);
84
+ const pos = getPositionExprs(position);
85
+ const endTime = startTime + duration;
86
+ const color = fontColor.replace(/^#/, '');
87
+ // Shadow/outline for readability
88
+ const shadowOpts = shadow
89
+ ? `:shadowcolor=black@0.7:shadowx=2:shadowy=2:borderw=1:bordercolor=black@0.5`
90
+ : '';
91
+ // Enable window
92
+ const enable = `enable='between(t,${startTime},${endTime})'`;
93
+ // Relative time within animation window
94
+ const relT = `(t-${startTime})`;
95
+ const animDur = Math.min(0.8, duration * 0.3); // Animation happens in first 30% or 0.8s max
96
+ switch (animation) {
97
+ case 'typewriter': {
98
+ // Show text character by character using text expansion
99
+ const charCount = text.length;
100
+ const charsPerSec = charCount / Math.min(duration * 0.7, 2);
101
+ // Use text_shaping=0 and limit displayed text via expansion
102
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='if(lt(${relT},${duration * 0.7}),1,max(0,1-(${relT}-${duration * 0.7})/${duration * 0.3}))'${shadowOpts}`;
103
+ }
104
+ case 'pop': {
105
+ // Text appears with a quick scale effect (simulated via fontsize change)
106
+ // Can't actually animate fontsize in drawtext, so use alpha snap-in
107
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='if(lt(${relT},0.1),${relT}/0.1,1)'${shadowOpts}`;
108
+ }
109
+ case 'slide-up': {
110
+ // Text slides up from below screen
111
+ const targetY = pos.y;
112
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y='if(lt(${relT},${animDur}),h-(h-${targetY})*${relT}/${animDur},${targetY})':${enable}${shadowOpts}`;
113
+ }
114
+ case 'slide-down': {
115
+ // Text slides down from above
116
+ const targetY = pos.y;
117
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y='if(lt(${relT},${animDur}),-text_h+(${targetY}+text_h)*${relT}/${animDur},${targetY})':${enable}${shadowOpts}`;
118
+ }
119
+ case 'slide-left': {
120
+ // Text slides in from right
121
+ const targetX = pos.x;
122
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x='if(lt(${relT},${animDur}),w-(w-${targetX})*${relT}/${animDur},${targetX})':y=${pos.y}:${enable}${shadowOpts}`;
123
+ }
124
+ case 'slide-right': {
125
+ // Text slides in from left
126
+ const targetX = pos.x;
127
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x='if(lt(${relT},${animDur}),-text_w+(${targetX}+text_w)*${relT}/${animDur},${targetX})':y=${pos.y}:${enable}${shadowOpts}`;
128
+ }
129
+ case 'bounce': {
130
+ // Text bounces from top (damped oscillation)
131
+ const targetY = pos.y;
132
+ // Damped sine wave: targetY + amplitude * sin(freq*t) * exp(-decay*t)
133
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y='if(lt(${relT},${animDur * 2}),${targetY}-100*sin(${relT}*12)*exp(-${relT}*5),${targetY})':${enable}${shadowOpts}`;
134
+ }
135
+ case 'fade-in': {
136
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='min(1,${relT}/${animDur})'${shadowOpts}`;
137
+ }
138
+ case 'fade-out': {
139
+ const fadeStart = duration - animDur;
140
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='if(lt(${relT},${fadeStart}),1,max(0,1-(${relT}-${fadeStart})/${animDur}))'${shadowOpts}`;
141
+ }
142
+ case 'fade-in-out': {
143
+ const fadeInEnd = animDur;
144
+ const fadeOutStart = duration - animDur;
145
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='if(lt(${relT},${fadeInEnd}),${relT}/${fadeInEnd},if(gt(${relT},${fadeOutStart}),max(0,1-(${relT}-${fadeOutStart})/${animDur}),1))'${shadowOpts}`;
146
+ }
147
+ case 'glitch': {
148
+ // Glitch: random x/y jitter + alpha flicker
149
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x='${pos.x}+if(lt(${relT},${animDur}),(rand(0,20)-10),0)':y='${pos.y}+if(lt(${relT},${animDur}),(rand(0,10)-5),0)':${enable}:alpha='if(lt(${relT},${animDur}),if(gt(rand(0,1),0.3),1,0),1)'${shadowOpts}`;
150
+ }
151
+ case 'zoom-in': {
152
+ // Simulated zoom: larger font fading in, then normal
153
+ // We can't dynamically change fontsize in drawtext, so we fade with position shift
154
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='min(1,${relT}/${animDur})'${shadowOpts}`;
155
+ }
156
+ case 'shake': {
157
+ // Continuous shake effect
158
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x='${pos.x}+(rand(0,8)-4)*sin(t*30)':y='${pos.y}+(rand(0,6)-3)*cos(t*25)':${enable}${shadowOpts}`;
159
+ }
160
+ case 'neon-glow': {
161
+ // Pulsating alpha for neon glow effect (sine wave)
162
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y=${pos.y}:${enable}:alpha='0.6+0.4*sin(t*4)':shadowcolor=0x${color}@0.5:shadowx=0:shadowy=0:borderw=3:bordercolor=0x${color}@0.3`;
163
+ }
164
+ case 'wave': {
165
+ // Text moves in a wave pattern
166
+ const targetY = pos.y;
167
+ return `drawtext=text='${escapedText}':fontsize=${fontSize}:fontcolor=0x${color}:fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=${pos.x}:y='${targetY}+15*sin(t*3)':${enable}${shadowOpts}`;
168
+ }
169
+ default:
170
+ throw new Error(`Unknown text animation: ${animation}`);
171
+ }
172
+ }
173
+ // ─── Main Function ──────────────────────────────────────────────────
174
+ export async function animateText(config) {
175
+ const { inputPath, outputPath, animation, text } = config;
176
+ assertExists(inputPath, 'Input video');
177
+ ensureDir(outputPath);
178
+ logger.info(`Animating text: "${text.substring(0, 30)}..." with ${animation}`);
179
+ const filterStr = buildAnimationFilter(config);
180
+ const args = [
181
+ '-y', '-i', inputPath,
182
+ '-vf', filterStr,
183
+ '-c:a', 'copy',
184
+ '-c:v', 'libx264', '-crf', '18', '-preset', 'medium',
185
+ '-pix_fmt', 'yuv420p', '-movflags', '+faststart',
186
+ outputPath,
187
+ ];
188
+ await runFfmpeg(args);
189
+ logger.info(`Text animation applied: ${animation} → ${outputPath} (${fileInfo(outputPath)})`);
190
+ return outputPath;
191
+ }
192
+ //# sourceMappingURL=text-animations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-animations.js","sourceRoot":"","sources":["../../../src/tools/engine/text-animations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Text overlay engine — animated titles, subtitles, watermarks
3
+ */
4
+ export type TextPosition = 'center' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
5
+ export interface TextOverlay {
6
+ /** Text to display */
7
+ text: string;
8
+ /** Position on screen (default: center) */
9
+ position?: TextPosition;
10
+ /** Font size (default: 48) */
11
+ fontSize?: number;
12
+ /** Font color (default: white) */
13
+ fontColor?: string;
14
+ /** Start time in seconds */
15
+ startTime: number;
16
+ /** End time in seconds */
17
+ endTime: number;
18
+ /** Fade in duration (default: 0.5s) */
19
+ fadeIn?: number;
20
+ /** Fade out duration (default: 0.5s) */
21
+ fadeOut?: number;
22
+ /** Background box behind text (default: false) */
23
+ showBackground?: boolean;
24
+ /** Background color (default: black@0.6) */
25
+ backgroundColor?: string;
26
+ }
27
+ export declare function addTextOverlays(inputPath: string, outputPath: string, overlays: TextOverlay[]): Promise<string>;