loopwind 0.9.1

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 (245) hide show
  1. package/FONTS.md +156 -0
  2. package/HELPERS_DEMO.md +134 -0
  3. package/PROJECT_STRUCTURE.md +286 -0
  4. package/PUBLISHING.md +171 -0
  5. package/README.md +1020 -0
  6. package/REGISTRY_SETUP.md +427 -0
  7. package/SHADCN_INTEGRATION.md +269 -0
  8. package/TAILWIND.md +228 -0
  9. package/TEMPLATE_SOURCES.md +363 -0
  10. package/_dsgn/templates/banner-hero/banner-hero.tsx +57 -0
  11. package/_dsgn/templates/banner-hero/meta.json +14 -0
  12. package/_dsgn/templates/composite-card/meta.json +16 -0
  13. package/_dsgn/templates/composite-card/template.tsx +44 -0
  14. package/_dsgn/templates/image/meta.json +13 -0
  15. package/_dsgn/templates/image/template.tsx +28 -0
  16. package/_dsgn/templates/kitchen-sink/meta.json +13 -0
  17. package/_dsgn/templates/kitchen-sink/template.tsx +72 -0
  18. package/_dsgn/templates/qr-card/meta.json +14 -0
  19. package/_dsgn/templates/qr-card/template.tsx +39 -0
  20. package/_dsgn/templates/test-parent/child/meta.json +11 -0
  21. package/_dsgn/templates/test-parent/child/template.tsx +27 -0
  22. package/_dsgn/templates/test-parent/meta.json +12 -0
  23. package/_dsgn/templates/test-parent/template.tsx +30 -0
  24. package/_dsgn/templates/test-sibling/meta.json +11 -0
  25. package/_dsgn/templates/test-sibling/template.tsx +20 -0
  26. package/_dsgn/templates/video/.tmp/template-1763421345296.mjs +43 -0
  27. package/_dsgn/templates/video/.tmp/template-1763421362228.mjs +43 -0
  28. package/_dsgn/templates/video/.tmp/template-1763421377706.mjs +43 -0
  29. package/_dsgn/templates/video/meta.json +17 -0
  30. package/_dsgn/templates/video/template.tsx +48 -0
  31. package/dist/cli.d.ts +3 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +70 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/commands/add.d.ts +6 -0
  36. package/dist/commands/add.d.ts.map +1 -0
  37. package/dist/commands/add.js +86 -0
  38. package/dist/commands/add.js.map +1 -0
  39. package/dist/commands/default.d.ts +2 -0
  40. package/dist/commands/default.d.ts.map +1 -0
  41. package/dist/commands/default.js +69 -0
  42. package/dist/commands/default.js.map +1 -0
  43. package/dist/commands/init.d.ts +2 -0
  44. package/dist/commands/init.d.ts.map +1 -0
  45. package/dist/commands/init.js +75 -0
  46. package/dist/commands/init.js.map +1 -0
  47. package/dist/commands/list.d.ts +2 -0
  48. package/dist/commands/list.d.ts.map +1 -0
  49. package/dist/commands/list.js +83 -0
  50. package/dist/commands/list.js.map +1 -0
  51. package/dist/commands/preview.d.ts +3 -0
  52. package/dist/commands/preview.d.ts.map +1 -0
  53. package/dist/commands/preview.js +296 -0
  54. package/dist/commands/preview.js.map +1 -0
  55. package/dist/commands/render.d.ts +10 -0
  56. package/dist/commands/render.d.ts.map +1 -0
  57. package/dist/commands/render.js +204 -0
  58. package/dist/commands/render.js.map +1 -0
  59. package/dist/commands/validate.d.ts +2 -0
  60. package/dist/commands/validate.d.ts.map +1 -0
  61. package/dist/commands/validate.js +107 -0
  62. package/dist/commands/validate.js.map +1 -0
  63. package/dist/default-templates/AGENTS.md +229 -0
  64. package/dist/default-templates/image/meta.json +13 -0
  65. package/dist/default-templates/image/template.d.ts +20 -0
  66. package/dist/default-templates/image/template.d.ts.map +1 -0
  67. package/dist/default-templates/image/template.js +18 -0
  68. package/dist/default-templates/image/template.js.map +1 -0
  69. package/dist/default-templates/image/template.tsx +20 -0
  70. package/dist/default-templates/image-template/meta.json +13 -0
  71. package/dist/default-templates/image-template/template.tsx +19 -0
  72. package/dist/default-templates/kitchen-sink/meta.json +13 -0
  73. package/dist/default-templates/kitchen-sink/template.tsx +64 -0
  74. package/dist/default-templates/page/meta.json +17 -0
  75. package/dist/default-templates/page/template.tsx +37 -0
  76. package/dist/default-templates/video/meta.json +17 -0
  77. package/dist/default-templates/video/template.d.ts +26 -0
  78. package/dist/default-templates/video/template.d.ts.map +1 -0
  79. package/dist/default-templates/video/template.js +33 -0
  80. package/dist/default-templates/video/template.js.map +1 -0
  81. package/dist/default-templates/video/template.tsx +37 -0
  82. package/dist/default-templates/video-template/meta.json +17 -0
  83. package/dist/default-templates/video-template/template.tsx +36 -0
  84. package/dist/default-templates/website/meta.json +16 -0
  85. package/dist/default-templates/website/pages/home.tsx +17 -0
  86. package/dist/default-templates/website/parts/footer.tsx +17 -0
  87. package/dist/default-templates/website/parts/header.tsx +17 -0
  88. package/dist/default-templates/website/template.tsx +17 -0
  89. package/dist/default-templates/website-template/meta.json +16 -0
  90. package/dist/default-templates/website-template/pages/home.tsx +16 -0
  91. package/dist/default-templates/website-template/parts/footer.tsx +16 -0
  92. package/dist/default-templates/website-template/parts/header.tsx +16 -0
  93. package/dist/default-templates/website-template/template.tsx +16 -0
  94. package/dist/lib/config.d.ts +34 -0
  95. package/dist/lib/config.d.ts.map +1 -0
  96. package/dist/lib/config.js +248 -0
  97. package/dist/lib/config.js.map +1 -0
  98. package/dist/lib/constants.d.ts +7 -0
  99. package/dist/lib/constants.d.ts.map +1 -0
  100. package/dist/lib/constants.js +12 -0
  101. package/dist/lib/constants.js.map +1 -0
  102. package/dist/lib/helpers.d.ts +29 -0
  103. package/dist/lib/helpers.d.ts.map +1 -0
  104. package/dist/lib/helpers.js +159 -0
  105. package/dist/lib/helpers.js.map +1 -0
  106. package/dist/lib/installer.d.ts +51 -0
  107. package/dist/lib/installer.d.ts.map +1 -0
  108. package/dist/lib/installer.js +215 -0
  109. package/dist/lib/installer.js.map +1 -0
  110. package/dist/lib/renderer.d.ts +51 -0
  111. package/dist/lib/renderer.d.ts.map +1 -0
  112. package/dist/lib/renderer.js +524 -0
  113. package/dist/lib/renderer.js.map +1 -0
  114. package/dist/lib/tailwind-config-loader.d.ts +47 -0
  115. package/dist/lib/tailwind-config-loader.d.ts.map +1 -0
  116. package/dist/lib/tailwind-config-loader.js +432 -0
  117. package/dist/lib/tailwind-config-loader.js.map +1 -0
  118. package/dist/lib/tailwind-detector.d.ts +36 -0
  119. package/dist/lib/tailwind-detector.d.ts.map +1 -0
  120. package/dist/lib/tailwind-detector.js +156 -0
  121. package/dist/lib/tailwind-detector.js.map +1 -0
  122. package/dist/lib/tailwind.d.ts +8 -0
  123. package/dist/lib/tailwind.d.ts.map +1 -0
  124. package/dist/lib/tailwind.js +994 -0
  125. package/dist/lib/tailwind.js.map +1 -0
  126. package/dist/lib/template-validator.d.ts +22 -0
  127. package/dist/lib/template-validator.d.ts.map +1 -0
  128. package/dist/lib/template-validator.js +174 -0
  129. package/dist/lib/template-validator.js.map +1 -0
  130. package/dist/lib/utils.d.ts +44 -0
  131. package/dist/lib/utils.d.ts.map +1 -0
  132. package/dist/lib/utils.js +207 -0
  133. package/dist/lib/utils.js.map +1 -0
  134. package/dist/lib/version-check.d.ts +16 -0
  135. package/dist/lib/version-check.d.ts.map +1 -0
  136. package/dist/lib/version-check.js +88 -0
  137. package/dist/lib/version-check.js.map +1 -0
  138. package/dist/lib/video-renderer.d.ts +32 -0
  139. package/dist/lib/video-renderer.d.ts.map +1 -0
  140. package/dist/lib/video-renderer.js +226 -0
  141. package/dist/lib/video-renderer.js.map +1 -0
  142. package/dist/sdk/index.d.ts +58 -0
  143. package/dist/sdk/index.d.ts.map +1 -0
  144. package/dist/sdk/index.js +119 -0
  145. package/dist/sdk/index.js.map +1 -0
  146. package/dist/sdk/template.d.ts +40 -0
  147. package/dist/sdk/template.d.ts.map +1 -0
  148. package/dist/sdk/template.js +60 -0
  149. package/dist/sdk/template.js.map +1 -0
  150. package/dist/types/config.d.ts +62 -0
  151. package/dist/types/config.d.ts.map +1 -0
  152. package/dist/types/config.js +47 -0
  153. package/dist/types/config.js.map +1 -0
  154. package/dist/types/template.d.ts +79 -0
  155. package/dist/types/template.d.ts.map +1 -0
  156. package/dist/types/template.js +2 -0
  157. package/dist/types/template.js.map +1 -0
  158. package/examples/nextjs-api/README.md +180 -0
  159. package/examples/nextjs-api/package.json +21 -0
  160. package/examples/nextjs-api/pages/api/intro-video.ts +53 -0
  161. package/examples/nextjs-api/pages/api/og-image.ts +50 -0
  162. package/netlify.toml +13 -0
  163. package/package.json +84 -0
  164. package/patches/satori+0.18.3.patch +13 -0
  165. package/test-templates/TESTS.md +63 -0
  166. package/test-templates/_dsgn/templates/absolute-spin/meta.json +7 -0
  167. package/test-templates/_dsgn/templates/absolute-spin/template.tsx +16 -0
  168. package/test-templates/_dsgn/templates/animated-intro/.tmp/template-1763468771640.mjs +7 -0
  169. package/test-templates/_dsgn/templates/animated-intro/meta.json +10 -0
  170. package/test-templates/_dsgn/templates/animated-intro/template.tsx +23 -0
  171. package/test-templates/_dsgn/templates/centered-spin/.tmp/template-1763468525386.mjs +7 -0
  172. package/test-templates/_dsgn/templates/centered-spin/meta.json +7 -0
  173. package/test-templates/_dsgn/templates/centered-spin/template.tsx +11 -0
  174. package/test-templates/_dsgn/templates/composite/.tmp/template-1763468815645.mjs +7 -0
  175. package/test-templates/_dsgn/templates/composite/meta.json +9 -0
  176. package/test-templates/_dsgn/templates/composite/template.tsx +23 -0
  177. package/test-templates/_dsgn/templates/easing-test/.tmp/template-1763468824501.mjs +7 -0
  178. package/test-templates/_dsgn/templates/easing-test/meta.json +7 -0
  179. package/test-templates/_dsgn/templates/easing-test/template.tsx +47 -0
  180. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466364336.mjs +10 -0
  181. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466584319.mjs +10 -0
  182. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466667797.mjs +10 -0
  183. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466746504.mjs +10 -0
  184. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466930225.mjs +10 -0
  185. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467004552.mjs +10 -0
  186. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467060334.mjs +10 -0
  187. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467124493.mjs +10 -0
  188. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467174690.mjs +10 -0
  189. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467359134.mjs +10 -0
  190. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467451928.mjs +10 -0
  191. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467758275.mjs +10 -0
  192. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467985201.mjs +10 -0
  193. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468020563.mjs +10 -0
  194. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468090428.mjs +10 -0
  195. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468211036.mjs +10 -0
  196. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468394057.mjs +10 -0
  197. package/test-templates/_dsgn/templates/minimal-spin/meta.json +7 -0
  198. package/test-templates/_dsgn/templates/minimal-spin/template.tsx +13 -0
  199. package/test-templates/_dsgn/templates/no-origin-spin/meta.json +7 -0
  200. package/test-templates/_dsgn/templates/no-origin-spin/template.tsx +10 -0
  201. package/test-templates/_dsgn/templates/opacity-test/meta.json +7 -0
  202. package/test-templates/_dsgn/templates/opacity-test/template.tsx +9 -0
  203. package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468758954.mjs +17 -0
  204. package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468815672.mjs +17 -0
  205. package/test-templates/_dsgn/templates/qr-code/meta.json +9 -0
  206. package/test-templates/_dsgn/templates/qr-code/template.tsx +20 -0
  207. package/test-templates/_dsgn/templates/rotation-abs-test/meta.json +7 -0
  208. package/test-templates/_dsgn/templates/rotation-abs-test/template.tsx +15 -0
  209. package/test-templates/_dsgn/templates/rotation-corner/meta.json +7 -0
  210. package/test-templates/_dsgn/templates/rotation-corner/template.tsx +12 -0
  211. package/test-templates/_dsgn/templates/rotation-test/meta.json +7 -0
  212. package/test-templates/_dsgn/templates/rotation-test/template.tsx +12 -0
  213. package/test-templates/_dsgn/templates/shake-test/meta.json +7 -0
  214. package/test-templates/_dsgn/templates/shake-test/template.tsx +12 -0
  215. package/test-templates/_dsgn/templates/static-image/.tmp/template-1763468746271.mjs +7 -0
  216. package/test-templates/_dsgn/templates/static-image/meta.json +9 -0
  217. package/test-templates/_dsgn/templates/static-image/template.tsx +19 -0
  218. package/test-templates/_dsgn/templates/translate-test/meta.json +7 -0
  219. package/test-templates/_dsgn/templates/translate-test/template.tsx +9 -0
  220. package/test-templates/_dsgn/templates/video-loops/.tmp/template-1763468793192.mjs +15 -0
  221. package/test-templates/_dsgn/templates/video-loops/meta.json +9 -0
  222. package/test-templates/_dsgn/templates/video-loops/template.tsx +39 -0
  223. package/test-templates/_dsgn/templates/wrapped-spin/meta.json +7 -0
  224. package/test-templates/_dsgn/templates/wrapped-spin/template.tsx +17 -0
  225. package/test-templates/compare-svgs.mjs +30 -0
  226. package/test-templates/convert-frames.mjs +15 -0
  227. package/test-templates/debug-rotation.mjs +25 -0
  228. package/test-templates/run-tests.sh +39 -0
  229. package/test-templates/test-sdk.mjs +115 -0
  230. package/website/.astro/settings.json +5 -0
  231. package/website/.astro/types.d.ts +1 -0
  232. package/website/README.md +112 -0
  233. package/website/astro.config.mjs +18 -0
  234. package/website/dist/_astro/fonts.DHdiHGBO.css +1 -0
  235. package/website/dist/fonts/index.html +193 -0
  236. package/website/dist/helpers/index.html +166 -0
  237. package/website/dist/images/index.html +314 -0
  238. package/website/dist/index.html +219 -0
  239. package/website/dist/llm.txt +2448 -0
  240. package/website/dist/styling/index.html +365 -0
  241. package/website/dist/templates/index.html +124 -0
  242. package/website/dist/video/index.html +636 -0
  243. package/website/package-lock.json +7606 -0
  244. package/website/package.json +23 -0
  245. package/website/public/robots.txt +5 -0
@@ -0,0 +1,636 @@
1
+ <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="description" content="dsgn - Generate beautiful images from React components"><meta name="viewport" content="width=device-width"><link rel="icon" type="image/svg+xml" href="/favicon.svg"><meta name="generator" content="Astro v4.16.19"><title></title><link rel="stylesheet" href="/_astro/fonts.DHdiHGBO.css"></head> <body class="antialiased"> <div class="min-h-screen" data-astro-cid-mw7aashj> <!-- Sidebar --> <aside class="fixed top-0 left-0 h-screen w-64 border-r border-border bg-card overflow-y-auto z-10" data-astro-cid-mw7aashj> <div class="p-6" data-astro-cid-mw7aashj> <a href="/" class="block mb-8 no-underline" data-astro-cid-mw7aashj> <h1 class="text-3xl font-bold bg-gradient-to-r from-[var(--color-brand-from)] to-[var(--color-brand-to)] bg-clip-text text-transparent" data-astro-cid-mw7aashj>
2
+ _dsgn
3
+ </h1> </a> <nav data-astro-cid-mw7aashj> <ul class="space-y-1" data-astro-cid-mw7aashj> <li data-astro-cid-mw7aashj> <a href="/" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Getting Started </a> </li><li data-astro-cid-mw7aashj> <a href="/templates" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Templates </a> </li><li data-astro-cid-mw7aashj> <a href="/images" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Images </a> </li><li data-astro-cid-mw7aashj> <a href="/video" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Video </a> </li><li data-astro-cid-mw7aashj> <a href="/helpers" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Helpers </a> </li><li data-astro-cid-mw7aashj> <a href="/styling" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Styling </a> </li><li data-astro-cid-mw7aashj> <a href="/fonts" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> Fonts </a> </li><li data-astro-cid-mw7aashj> <a href="/llm.txt" class="block px-3 py-2 rounded-md text-sm transition-colors no-underline text-muted-foreground hover:text-foreground hover:bg-accent/50" data-astro-cid-mw7aashj> LLM Docs </a> </li> </ul> </nav> </div> </aside> <!-- Main content --> <main class="ml-64" data-astro-cid-mw7aashj> <div class="p-12" data-astro-cid-mw7aashj> <article class="prose prose-invert max-w-4xl" data-astro-cid-mw7aashj> <h1 id="video-rendering">Video Rendering</h1>
4
+ <p>Create animated videos programmatically using React components. Perfect for automated video generation, social media content, and dynamic animations.</p>
5
+ <h2 id="quick-start">Quick Start</h2>
6
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Render a video template with inline props</span></span>
7
+ <span class="line"><span style="color:#B392F0">dsgn</span><span style="color:#9ECBFF"> render</span><span style="color:#9ECBFF"> video-intro</span><span style="color:#9ECBFF"> &#39;{&quot;title&quot;:&quot;Welcome!&quot;}&#39;</span><span style="color:#79B8FF"> --out</span><span style="color:#9ECBFF"> intro.mp4</span></span>
8
+ <span class="line"></span>
9
+ <span class="line"><span style="color:#6A737D"># With custom encoding</span></span>
10
+ <span class="line"><span style="color:#B392F0">dsgn</span><span style="color:#9ECBFF"> render</span><span style="color:#9ECBFF"> video-intro</span><span style="color:#9ECBFF"> &#39;{&quot;title&quot;:&quot;Welcome!&quot;}&#39;</span><span style="color:#79B8FF"> --preset</span><span style="color:#9ECBFF"> ultrafast</span></span>
11
+ <span class="line"></span>
12
+ <span class="line"><span style="color:#6A737D"># Or use a props file</span></span>
13
+ <span class="line"><span style="color:#B392F0">dsgn</span><span style="color:#9ECBFF"> render</span><span style="color:#9ECBFF"> video-intro</span><span style="color:#9ECBFF"> props.json</span><span style="color:#79B8FF"> --out</span><span style="color:#9ECBFF"> intro.mp4</span></span>
14
+ <span class="line"></span></code></pre>
15
+ <h2 id="video-template-structure">Video Template Structure</h2>
16
+ <h3 id="basic-template">Basic Template</h3>
17
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// video-intro.tsx</span></span>
18
+ <span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> VideoIntro</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">frame</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8"> }) {</span></span>
19
+ <span class="line"><span style="color:#6A737D"> // Animate opacity based on progress</span></span>
20
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> titleOpacity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0.3</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.3</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
21
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
22
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
23
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;flex items-center justify-center w-full h-full bg-gradient-to-br from-blue-600 to-purple-700&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
24
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8"> </span></span>
25
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
26
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-8xl font-bold text-white&#39;</span><span style="color:#E1E4E8">),</span></span>
27
+ <span class="line"><span style="color:#E1E4E8"> opacity: titleOpacity</span></span>
28
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
29
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
30
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
31
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
32
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
33
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Show frame counter */</span><span style="color:#E1E4E8">}</span></span>
34
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute bottom-10 right-10 text-white text-sm&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
35
+ <span class="line"><span style="color:#E1E4E8"> Frame: {frame}</span></span>
36
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
37
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
38
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
39
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
40
+ <span class="line"></span></code></pre>
41
+ <h3 id="metadata-metajson">Metadata (meta.json)</h3>
42
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
43
+ <span class="line"><span style="color:#79B8FF"> &quot;name&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;video-intro&quot;</span><span style="color:#E1E4E8">,</span></span>
44
+ <span class="line"><span style="color:#79B8FF"> &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;video&quot;</span><span style="color:#E1E4E8">,</span></span>
45
+ <span class="line"><span style="color:#79B8FF"> &quot;description&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Animated intro with fade-in title&quot;</span><span style="color:#E1E4E8">,</span></span>
46
+ <span class="line"><span style="color:#79B8FF"> &quot;size&quot;</span><span style="color:#E1E4E8">: {</span></span>
47
+ <span class="line"><span style="color:#79B8FF"> &quot;width&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1920</span><span style="color:#E1E4E8">,</span></span>
48
+ <span class="line"><span style="color:#79B8FF"> &quot;height&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1080</span></span>
49
+ <span class="line"><span style="color:#E1E4E8"> },</span></span>
50
+ <span class="line"><span style="color:#79B8FF"> &quot;video&quot;</span><span style="color:#E1E4E8">: {</span></span>
51
+ <span class="line"><span style="color:#79B8FF"> &quot;fps&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">30</span><span style="color:#E1E4E8">,</span></span>
52
+ <span class="line"><span style="color:#79B8FF"> &quot;duration&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">3</span></span>
53
+ <span class="line"><span style="color:#E1E4E8"> },</span></span>
54
+ <span class="line"><span style="color:#79B8FF"> &quot;props&quot;</span><span style="color:#E1E4E8">: {</span></span>
55
+ <span class="line"><span style="color:#79B8FF"> &quot;title&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;string&quot;</span></span>
56
+ <span class="line"><span style="color:#E1E4E8"> }</span></span>
57
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
58
+ <span class="line"></span></code></pre>
59
+ <h3 id="props-file">Props File</h3>
60
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
61
+ <span class="line"><span style="color:#79B8FF"> &quot;title&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Welcome!&quot;</span></span>
62
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
63
+ <span class="line"></span></code></pre>
64
+ <h2 id="video-specific-props">Video-Specific Props</h2>
65
+ <p>Every video template receives these additional props:</p>
66
+ <h3 id="frame"><code>frame</code></h3>
67
+ <p>Current frame number (0 to totalFrames - 1)</p>
68
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> MyVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">frame</span><span style="color:#E1E4E8"> }) {</span></span>
69
+ <span class="line"><span style="color:#6A737D"> // Frame 0, 1, 2, 3, ... 89 (for 3s @ 30fps)</span></span>
70
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;Frame: {frame}&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;;</span></span>
71
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
72
+ <span class="line"></span></code></pre>
73
+ <h3 id="progress"><code>progress</code></h3>
74
+ <p>Animation progress from 0 to 1</p>
75
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> MyVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8"> }) {</span></span>
76
+ <span class="line"><span style="color:#6A737D"> // 0.0 at start, 0.5 at middle, 1.0 at end</span></span>
77
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> x</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 100</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// Move from 0 to 100</span></span>
78
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
79
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
80
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ transform: </span><span style="color:#9ECBFF">`translateX(${</span><span style="color:#E1E4E8">x</span><span style="color:#9ECBFF">}px)`</span><span style="color:#E1E4E8"> }}&gt;</span></span>
81
+ <span class="line"><span style="color:#E1E4E8"> Moving element</span></span>
82
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
83
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
84
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
85
+ <span class="line"></span></code></pre>
86
+ <h2 id="animation-patterns">Animation Patterns</h2>
87
+ <h3 id="fade-inout">Fade In/Out</h3>
88
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> FadeVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8"> }) {</span></span>
89
+ <span class="line"><span style="color:#6A737D"> // Fade in first 20%, stay visible, fade out last 20%</span></span>
90
+ <span class="line"><span style="color:#F97583"> let</span><span style="color:#E1E4E8"> opacity </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
91
+ <span class="line"><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (progress </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0.2</span><span style="color:#E1E4E8">) {</span></span>
92
+ <span class="line"><span style="color:#E1E4E8"> opacity </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.2</span><span style="color:#E1E4E8">;</span></span>
93
+ <span class="line"><span style="color:#E1E4E8"> } </span><span style="color:#F97583">else</span><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (progress </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0.8</span><span style="color:#E1E4E8">) {</span></span>
94
+ <span class="line"><span style="color:#E1E4E8"> opacity </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">1</span><span style="color:#F97583"> -</span><span style="color:#E1E4E8"> progress) </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.2</span><span style="color:#E1E4E8">;</span></span>
95
+ <span class="line"><span style="color:#E1E4E8"> }</span></span>
96
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
97
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
98
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span><span style="color:#F97583">...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-6xl font-bold&#39;</span><span style="color:#E1E4E8">), opacity }}&gt;</span></span>
99
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
100
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
101
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
102
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
103
+ <span class="line"></span></code></pre>
104
+ <h3 id="slide-in">Slide In</h3>
105
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> SlideVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8"> }) {</span></span>
106
+ <span class="line"><span style="color:#6A737D"> // Slide in from left</span></span>
107
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> x</span><span style="color:#F97583"> =</span><span style="color:#F97583"> -</span><span style="color:#79B8FF">100</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> (progress </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 100</span><span style="color:#E1E4E8">); </span><span style="color:#6A737D">// -100 to 0</span></span>
108
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
109
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
110
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span></span>
111
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-4xl font-bold&#39;</span><span style="color:#E1E4E8">),</span></span>
112
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`translateX(${</span><span style="color:#E1E4E8">x</span><span style="color:#9ECBFF">}%)`</span></span>
113
+ <span class="line"><span style="color:#E1E4E8"> }}&gt;</span></span>
114
+ <span class="line"><span style="color:#E1E4E8"> Sliding Text</span></span>
115
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
116
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
117
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
118
+ <span class="line"></span></code></pre>
119
+ <h3 id="scale-animation">Scale Animation</h3>
120
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> ScaleVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8"> }) {</span></span>
121
+ <span class="line"><span style="color:#6A737D"> // Scale from 0 to 1</span></span>
122
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> scale</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress;</span></span>
123
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
124
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
125
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span></span>
126
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-6xl font-bold&#39;</span><span style="color:#E1E4E8">),</span></span>
127
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`scale(${</span><span style="color:#E1E4E8">scale</span><span style="color:#9ECBFF">})`</span></span>
128
+ <span class="line"><span style="color:#E1E4E8"> }}&gt;</span></span>
129
+ <span class="line"><span style="color:#E1E4E8"> Growing Text</span></span>
130
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
131
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
132
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
133
+ <span class="line"></span></code></pre>
134
+ <h3 id="rotation">Rotation</h3>
135
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> RotateVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8"> }) {</span></span>
136
+ <span class="line"><span style="color:#6A737D"> // Rotate 360 degrees</span></span>
137
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> rotation</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 360</span><span style="color:#E1E4E8">;</span></span>
138
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
139
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
140
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span></span>
141
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;w-32 h-32 bg-blue-500 rounded-lg&#39;</span><span style="color:#E1E4E8">),</span></span>
142
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`rotate(${</span><span style="color:#E1E4E8">rotation</span><span style="color:#9ECBFF">}deg)`</span></span>
143
+ <span class="line"><span style="color:#E1E4E8"> }}&gt;</span></span>
144
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
145
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
146
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
147
+ <span class="line"></span></code></pre>
148
+ <h3 id="easing-functions">Easing Functions</h3>
149
+ <p>Create smooth animations with easing:</p>
150
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> easeOutCubic</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">t</span><span style="color:#E1E4E8">) {</span></span>
151
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583"> -</span><span style="color:#E1E4E8"> Math.</span><span style="color:#B392F0">pow</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">1</span><span style="color:#F97583"> -</span><span style="color:#E1E4E8"> t, </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">);</span></span>
152
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
153
+ <span class="line"></span>
154
+ <span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> EasedVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8"> }) {</span></span>
155
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> easedProgress</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> easeOutCubic</span><span style="color:#E1E4E8">(progress);</span></span>
156
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> x</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> easedProgress </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 100</span><span style="color:#E1E4E8">;</span></span>
157
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
158
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
159
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ transform: </span><span style="color:#9ECBFF">`translateX(${</span><span style="color:#E1E4E8">x</span><span style="color:#9ECBFF">}px)`</span><span style="color:#E1E4E8"> }}&gt;</span></span>
160
+ <span class="line"><span style="color:#E1E4E8"> Smooth animation</span></span>
161
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
162
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
163
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
164
+ <span class="line"></span></code></pre>
165
+ <h2 id="embedding-videos">Embedding Videos</h2>
166
+ <p>Use the <code>video()</code> helper to embed video backgrounds that auto-sync with your animation.</p>
167
+ <h3 id="basic-usage">Basic Usage</h3>
168
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> VideoOverlay</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">video</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">background</span><span style="color:#E1E4E8"> }) {</span></span>
169
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
170
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative w-full h-full&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
171
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Background video - automatically synced to current frame */</span><span style="color:#E1E4E8">}</span></span>
172
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
173
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">video</span><span style="color:#E1E4E8">(background)} </span></span>
174
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 w-full h-full object-cover&#39;</span><span style="color:#E1E4E8">)}</span></span>
175
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
176
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
177
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Text overlay */</span><span style="color:#E1E4E8">}</span></span>
178
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative z-10 flex items-center justify-center w-full h-full&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
179
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-7xl font-bold text-white drop-shadow-lg&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
180
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
181
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
182
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
183
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
184
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
185
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
186
+ <span class="line"></span></code></pre>
187
+ <p><strong>Props:</strong></p>
188
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
189
+ <span class="line"><span style="color:#79B8FF"> &quot;title&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Amazing Video&quot;</span><span style="color:#E1E4E8">,</span></span>
190
+ <span class="line"><span style="color:#79B8FF"> &quot;background&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./footage/background.mp4&quot;</span></span>
191
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
192
+ <span class="line"></span></code></pre>
193
+ <h3 id="how-video-sync-works">How Video Sync Works</h3>
194
+ <ol>
195
+ <li><strong>First pass</strong>: Template calls <code>video()</code> to register needed videos</li>
196
+ <li><strong>Pre-processing</strong>: dsgn extracts all frames at template’s FPS</li>
197
+ <li><strong>Rendering</strong>: Each frame uses the corresponding video frame</li>
198
+ <li><strong>Caching</strong>: Frames are cached in memory for fast access</li>
199
+ </ol>
200
+ <h3 id="animated-overlay-example">Animated Overlay Example</h3>
201
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> VideoWithText</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">video</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">frame</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">clip</span><span style="color:#E1E4E8"> }) {</span></span>
202
+ <span class="line"><span style="color:#6A737D"> // Fade in title</span></span>
203
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> titleOpacity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0.2</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.2</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
204
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
205
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
206
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative w-full h-full&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
207
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Synced video background */</span><span style="color:#E1E4E8">}</span></span>
208
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
209
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">video</span><span style="color:#E1E4E8">(clip)} </span></span>
210
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 w-full h-full object-cover&#39;</span><span style="color:#E1E4E8">)}</span></span>
211
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
212
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
213
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Dark overlay */</span><span style="color:#E1E4E8">}</span></span>
214
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 bg-black/40&#39;</span><span style="color:#E1E4E8">)} /&gt;</span></span>
215
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
216
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Animated title */</span><span style="color:#E1E4E8">}</span></span>
217
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative z-10 flex items-center justify-center w-full h-full&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
218
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8"> </span></span>
219
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
220
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-8xl font-bold text-white text-center&#39;</span><span style="color:#E1E4E8">),</span></span>
221
+ <span class="line"><span style="color:#E1E4E8"> opacity: titleOpacity</span></span>
222
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
223
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
224
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
225
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
226
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
227
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
228
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Frame counter */</span><span style="color:#E1E4E8">}</span></span>
229
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute bottom-4 right-4 text-white text-sm bg-black/50 px-3 py-1 rounded&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
230
+ <span class="line"><span style="color:#E1E4E8"> {frame} / {Math.</span><span style="color:#B392F0">floor</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">3</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 30</span><span style="color:#E1E4E8">)}</span></span>
231
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
232
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
233
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
234
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
235
+ <span class="line"></span></code></pre>
236
+ <h2 id="combining-videos-and-images">Combining Videos and Images</h2>
237
+ <p>Use both <code>video()</code> and <code>image()</code> helpers together to create rich, branded video content.</p>
238
+ <h3 id="video-background-with-logo">Video Background with Logo</h3>
239
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> BrandedVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">video</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">image</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">background</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">logo</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8"> }) {</span></span>
240
+ <span class="line"><span style="color:#6A737D"> // Logo slides in from top</span></span>
241
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> logoY</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0.3</span><span style="color:#F97583"> ?</span><span style="color:#F97583"> -</span><span style="color:#79B8FF">100</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> (progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.3</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 100</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
242
+ <span class="line"><span style="color:#6A737D"> // Title fades in after logo</span></span>
243
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> titleOpacity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0.3</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> Math.</span><span style="color:#B392F0">min</span><span style="color:#E1E4E8">((progress </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 0.3</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.3</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">:</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
244
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
245
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
246
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative w-full h-full&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
247
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Video background */</span><span style="color:#E1E4E8">}</span></span>
248
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
249
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">video</span><span style="color:#E1E4E8">(background)} </span></span>
250
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 w-full h-full object-cover&#39;</span><span style="color:#E1E4E8">)}</span></span>
251
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
252
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
253
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Gradient overlay */</span><span style="color:#E1E4E8">}</span></span>
254
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 bg-gradient-to-t from-black/80 to-transparent&#39;</span><span style="color:#E1E4E8">)} /&gt;</span></span>
255
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
256
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Animated logo */</span><span style="color:#E1E4E8">}</span></span>
257
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> </span></span>
258
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
259
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute top-12 left-12&#39;</span><span style="color:#E1E4E8">),</span></span>
260
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`translateY(${</span><span style="color:#E1E4E8">logoY</span><span style="color:#9ECBFF">}px)`</span></span>
261
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
262
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
263
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
264
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">image</span><span style="color:#E1E4E8">(logo)} </span></span>
265
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;h-16 w-auto&#39;</span><span style="color:#E1E4E8">)}</span></span>
266
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
267
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
268
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
269
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Animated title */</span><span style="color:#E1E4E8">}</span></span>
270
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute bottom-20 left-12 right-12&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
271
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8"> </span></span>
272
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
273
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-7xl font-bold text-white&#39;</span><span style="color:#E1E4E8">),</span></span>
274
+ <span class="line"><span style="color:#E1E4E8"> opacity: titleOpacity</span></span>
275
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
276
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
277
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
278
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
279
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
280
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
281
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
282
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
283
+ <span class="line"></span></code></pre>
284
+ <p><strong>Props:</strong></p>
285
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
286
+ <span class="line"><span style="color:#79B8FF"> &quot;title&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Introducing Our New Product&quot;</span><span style="color:#E1E4E8">,</span></span>
287
+ <span class="line"><span style="color:#79B8FF"> &quot;background&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./footage/product-demo.mp4&quot;</span><span style="color:#E1E4E8">,</span></span>
288
+ <span class="line"><span style="color:#79B8FF"> &quot;logo&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./images/company-logo.png&quot;</span></span>
289
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
290
+ <span class="line"></span></code></pre>
291
+ <h3 id="multi-element-video-composition">Multi-Element Video Composition</h3>
292
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> ProductShowcase</span><span style="color:#E1E4E8">({ </span></span>
293
+ <span class="line"><span style="color:#FFAB70"> tw</span><span style="color:#E1E4E8">, </span></span>
294
+ <span class="line"><span style="color:#FFAB70"> video</span><span style="color:#E1E4E8">, </span></span>
295
+ <span class="line"><span style="color:#FFAB70"> image</span><span style="color:#E1E4E8">, </span></span>
296
+ <span class="line"><span style="color:#FFAB70"> progress</span><span style="color:#E1E4E8">, </span></span>
297
+ <span class="line"><span style="color:#FFAB70"> backgroundVideo</span><span style="color:#E1E4E8">,</span></span>
298
+ <span class="line"><span style="color:#FFAB70"> productImage</span><span style="color:#E1E4E8">,</span></span>
299
+ <span class="line"><span style="color:#FFAB70"> badge</span><span style="color:#E1E4E8">,</span></span>
300
+ <span class="line"><span style="color:#FFAB70"> title</span><span style="color:#E1E4E8">,</span></span>
301
+ <span class="line"><span style="color:#FFAB70"> price</span><span style="color:#E1E4E8"> </span></span>
302
+ <span class="line"><span style="color:#E1E4E8">}) {</span></span>
303
+ <span class="line"><span style="color:#6A737D"> // Product image zooms in</span></span>
304
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> scale</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 0.8</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> (Math.</span><span style="color:#B392F0">min</span><span style="color:#E1E4E8">(progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.5</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.2</span><span style="color:#E1E4E8">); </span><span style="color:#6A737D">// 0.8 to 1.0</span></span>
305
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
306
+ <span class="line"><span style="color:#6A737D"> // Badge rotates in</span></span>
307
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> badgeRotation</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0.4</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> (progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.4</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 360</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 360</span><span style="color:#E1E4E8">;</span></span>
308
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> badgeOpacity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> Math.</span><span style="color:#B392F0">min</span><span style="color:#E1E4E8">(progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.4</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">);</span></span>
309
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
310
+ <span class="line"><span style="color:#6A737D"> // Price slides up</span></span>
311
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> priceY</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0.6</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">1</span><span style="color:#F97583"> -</span><span style="color:#E1E4E8"> Math.</span><span style="color:#B392F0">min</span><span style="color:#E1E4E8">((progress </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 0.6</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.4</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">)) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 50</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 50</span><span style="color:#E1E4E8">;</span></span>
312
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
313
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
314
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative w-full h-full bg-white&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
315
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Video background (blurred) */</span><span style="color:#E1E4E8">}</span></span>
316
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 overflow-hidden&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
317
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
318
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">video</span><span style="color:#E1E4E8">(backgroundVideo)} </span></span>
319
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
320
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;w-full h-full object-cover&#39;</span><span style="color:#E1E4E8">),</span></span>
321
+ <span class="line"><span style="color:#E1E4E8"> filter: </span><span style="color:#9ECBFF">&#39;blur(20px)&#39;</span><span style="color:#E1E4E8">,</span></span>
322
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">&#39;scale(1.1)&#39;</span><span style="color:#6A737D"> // Prevent blur edge artifacts</span></span>
323
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
324
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
325
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 bg-white/50&#39;</span><span style="color:#E1E4E8">)} /&gt;</span></span>
326
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
327
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
328
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Main product image */</span><span style="color:#E1E4E8">}</span></span>
329
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative z-10 flex items-center justify-center w-full h-full p-20&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
330
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ transform: </span><span style="color:#9ECBFF">`scale(${</span><span style="color:#E1E4E8">scale</span><span style="color:#9ECBFF">})`</span><span style="color:#E1E4E8"> }}&gt;</span></span>
331
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
332
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">image</span><span style="color:#E1E4E8">(productImage)} </span></span>
333
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;w-96 h-96 object-contain drop-shadow-2xl&#39;</span><span style="color:#E1E4E8">)}</span></span>
334
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
335
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
336
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
337
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
338
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Animated badge */</span><span style="color:#E1E4E8">}</span></span>
339
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> </span></span>
340
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
341
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute top-20 right-20&#39;</span><span style="color:#E1E4E8">),</span></span>
342
+ <span class="line"><span style="color:#E1E4E8"> opacity: badgeOpacity,</span></span>
343
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`rotate(${</span><span style="color:#E1E4E8">badgeRotation</span><span style="color:#9ECBFF">}deg)`</span></span>
344
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
345
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
346
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
347
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">image</span><span style="color:#E1E4E8">(badge)} </span></span>
348
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;w-32 h-32&#39;</span><span style="color:#E1E4E8">)}</span></span>
349
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
350
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
351
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
352
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Title */</span><span style="color:#E1E4E8">}</span></span>
353
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute top-20 left-20&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
354
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-5xl font-bold text-gray-900&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
355
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
356
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">&gt;</span></span>
357
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
358
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
359
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Animated price */</span><span style="color:#E1E4E8">}</span></span>
360
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> </span></span>
361
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
362
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute bottom-20 left-20&#39;</span><span style="color:#E1E4E8">),</span></span>
363
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`translateY(${</span><span style="color:#E1E4E8">priceY</span><span style="color:#9ECBFF">}px)`</span></span>
364
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
365
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
366
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-6xl font-black text-blue-600&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
367
+ <span class="line"><span style="color:#E1E4E8"> ${price}</span></span>
368
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
369
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
370
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
371
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
372
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
373
+ <span class="line"></span></code></pre>
374
+ <p><strong>Props:</strong></p>
375
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
376
+ <span class="line"><span style="color:#79B8FF"> &quot;title&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Premium Headphones&quot;</span><span style="color:#E1E4E8">,</span></span>
377
+ <span class="line"><span style="color:#79B8FF"> &quot;price&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;299&quot;</span><span style="color:#E1E4E8">,</span></span>
378
+ <span class="line"><span style="color:#79B8FF"> &quot;backgroundVideo&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./footage/studio-background.mp4&quot;</span><span style="color:#E1E4E8">,</span></span>
379
+ <span class="line"><span style="color:#79B8FF"> &quot;productImage&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./images/headphones.png&quot;</span><span style="color:#E1E4E8">,</span></span>
380
+ <span class="line"><span style="color:#79B8FF"> &quot;badge&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./images/new-badge.png&quot;</span></span>
381
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
382
+ <span class="line"></span></code></pre>
383
+ <h3 id="video-with-multiple-image-overlays">Video with Multiple Image Overlays</h3>
384
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> TutorialVideo</span><span style="color:#E1E4E8">({ </span></span>
385
+ <span class="line"><span style="color:#FFAB70"> tw</span><span style="color:#E1E4E8">, </span></span>
386
+ <span class="line"><span style="color:#FFAB70"> video</span><span style="color:#E1E4E8">, </span></span>
387
+ <span class="line"><span style="color:#FFAB70"> image</span><span style="color:#E1E4E8">, </span></span>
388
+ <span class="line"><span style="color:#FFAB70"> progress</span><span style="color:#E1E4E8">, </span></span>
389
+ <span class="line"><span style="color:#FFAB70"> frame</span><span style="color:#E1E4E8">,</span></span>
390
+ <span class="line"><span style="color:#FFAB70"> screencast</span><span style="color:#E1E4E8">,</span></span>
391
+ <span class="line"><span style="color:#FFAB70"> avatar</span><span style="color:#E1E4E8">,</span></span>
392
+ <span class="line"><span style="color:#FFAB70"> logo</span><span style="color:#E1E4E8">,</span></span>
393
+ <span class="line"><span style="color:#FFAB70"> instructor</span><span style="color:#E1E4E8">,</span></span>
394
+ <span class="line"><span style="color:#FFAB70"> lesson</span></span>
395
+ <span class="line"><span style="color:#E1E4E8">}) {</span></span>
396
+ <span class="line"><span style="color:#6A737D"> // Avatar pulses</span></span>
397
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> avatarScale</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> Math.</span><span style="color:#B392F0">sin</span><span style="color:#E1E4E8">(frame </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.2</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.05</span><span style="color:#E1E4E8">;</span></span>
398
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
399
+ <span class="line"><span style="color:#6A737D"> // Logo stays visible</span></span>
400
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> logoOpacity</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
401
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
402
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
403
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative w-full h-full bg-gray-900&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
404
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Main screencast video */</span><span style="color:#E1E4E8">}</span></span>
405
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
406
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">video</span><span style="color:#E1E4E8">(screencast)} </span></span>
407
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute inset-0 w-full h-full object-contain&#39;</span><span style="color:#E1E4E8">)}</span></span>
408
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
409
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
410
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Company logo (top left) */</span><span style="color:#E1E4E8">}</span></span>
411
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
412
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute top-8 left-8&#39;</span><span style="color:#E1E4E8">),</span></span>
413
+ <span class="line"><span style="color:#E1E4E8"> opacity: logoOpacity</span></span>
414
+ <span class="line"><span style="color:#E1E4E8"> }}&gt;</span></span>
415
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
416
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">image</span><span style="color:#E1E4E8">(logo)} </span></span>
417
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;h-12 w-auto&#39;</span><span style="color:#E1E4E8">)}</span></span>
418
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
419
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
420
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
421
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Instructor avatar (bottom right) */</span><span style="color:#E1E4E8">}</span></span>
422
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute bottom-8 right-8&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
423
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> </span></span>
424
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
425
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;relative&#39;</span><span style="color:#E1E4E8">),</span></span>
426
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`scale(${</span><span style="color:#E1E4E8">avatarScale</span><span style="color:#9ECBFF">})`</span></span>
427
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
428
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
429
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> </span></span>
430
+ <span class="line"><span style="color:#B392F0"> src</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">image</span><span style="color:#E1E4E8">(avatar)} </span></span>
431
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;w-24 h-24 rounded-full border-4 border-blue-500&#39;</span><span style="color:#E1E4E8">)}</span></span>
432
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
433
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Red recording dot */</span><span style="color:#E1E4E8">}</span></span>
434
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute -top-1 -right-1 w-6 h-6 bg-red-500 rounded-full animate-pulse&#39;</span><span style="color:#E1E4E8">)} /&gt;</span></span>
435
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
436
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
437
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
438
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Lesson info overlay */</span><span style="color:#E1E4E8">}</span></span>
439
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;absolute bottom-8 left-8 bg-black/80 backdrop-blur px-6 py-4 rounded-lg&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
440
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-sm text-gray-400&#39;</span><span style="color:#E1E4E8">)}&gt;Instructor&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
441
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-xl font-bold text-white mb-2&#39;</span><span style="color:#E1E4E8">)}&gt;{instructor}&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
442
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-sm text-blue-400&#39;</span><span style="color:#E1E4E8">)}&gt;{lesson}&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
443
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
444
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
445
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
446
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
447
+ <span class="line"></span></code></pre>
448
+ <p><strong>Props:</strong></p>
449
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
450
+ <span class="line"><span style="color:#79B8FF"> &quot;instructor&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Sarah Johnson&quot;</span><span style="color:#E1E4E8">,</span></span>
451
+ <span class="line"><span style="color:#79B8FF"> &quot;lesson&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Lesson 3: Advanced Techniques&quot;</span><span style="color:#E1E4E8">,</span></span>
452
+ <span class="line"><span style="color:#79B8FF"> &quot;screencast&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./footage/screen-recording.mp4&quot;</span><span style="color:#E1E4E8">,</span></span>
453
+ <span class="line"><span style="color:#79B8FF"> &quot;avatar&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./images/instructor.jpg&quot;</span><span style="color:#E1E4E8">,</span></span>
454
+ <span class="line"><span style="color:#79B8FF"> &quot;logo&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./images/course-logo.png&quot;</span></span>
455
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
456
+ <span class="line"></span></code></pre>
457
+ <h3 id="supported-formats">Supported Formats</h3>
458
+ <p><strong>Video formats</strong> (via <code>video()</code> helper):</p>
459
+ <ul>
460
+ <li>✅ MP4 (<code>.mp4</code>)</li>
461
+ <li>✅ MOV (<code>.mov</code>)</li>
462
+ <li>✅ WebM (<code>.webm</code>)</li>
463
+ <li>✅ AVI (<code>.avi</code>)</li>
464
+ </ul>
465
+ <p><strong>Image formats</strong> (via <code>image()</code> helper):</p>
466
+ <ul>
467
+ <li>✅ JPEG (<code>.jpg</code>, <code>.jpeg</code>)</li>
468
+ <li>✅ PNG (<code>.png</code>) - with transparency</li>
469
+ <li>✅ GIF (<code>.gif</code>)</li>
470
+ <li>✅ WebP (<code>.webp</code>)</li>
471
+ <li>✅ SVG (<code>.svg</code>)</li>
472
+ </ul>
473
+ <h3 id="best-practices">Best Practices</h3>
474
+ <ol>
475
+ <li><strong>Pre-optimize assets</strong>: Resize images and videos to match your output resolution</li>
476
+ <li><strong>Use PNG for logos</strong>: Transparency works perfectly with video backgrounds</li>
477
+ <li><strong>Match frame rates</strong>: If possible, use videos with the same FPS as your template</li>
478
+ <li><strong>Consider file sizes</strong>: Large videos take longer to process</li>
479
+ <li><strong>Test opacity</strong>: Ensure overlays are visible against video backgrounds</li>
480
+ </ol>
481
+ <h2 id="fps-and-duration">FPS and Duration</h2>
482
+ <h3 id="common-frame-rates">Common Frame Rates</h3>
483
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
484
+ <span class="line"><span style="color:#79B8FF"> &quot;video&quot;</span><span style="color:#E1E4E8">: {</span></span>
485
+ <span class="line"><span style="color:#79B8FF"> &quot;fps&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">24</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Film standard</span></span>
486
+ <span class="line"><span style="color:#79B8FF"> &quot;duration&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">5</span></span>
487
+ <span class="line"><span style="color:#E1E4E8"> }</span></span>
488
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
489
+ <span class="line"></span></code></pre>
490
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
491
+ <span class="line"><span style="color:#79B8FF"> &quot;video&quot;</span><span style="color:#E1E4E8">: {</span></span>
492
+ <span class="line"><span style="color:#79B8FF"> &quot;fps&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">30</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// YouTube/web standard</span></span>
493
+ <span class="line"><span style="color:#79B8FF"> &quot;duration&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">3</span></span>
494
+ <span class="line"><span style="color:#E1E4E8"> }</span></span>
495
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
496
+ <span class="line"></span></code></pre>
497
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
498
+ <span class="line"><span style="color:#79B8FF"> &quot;video&quot;</span><span style="color:#E1E4E8">: {</span></span>
499
+ <span class="line"><span style="color:#79B8FF"> &quot;fps&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">60</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Smooth animations</span></span>
500
+ <span class="line"><span style="color:#79B8FF"> &quot;duration&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span></span>
501
+ <span class="line"><span style="color:#E1E4E8"> }</span></span>
502
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
503
+ <span class="line"></span></code></pre>
504
+ <p><strong>Total frames = fps × duration</strong></p>
505
+ <ul>
506
+ <li>24fps × 5s = 120 frames</li>
507
+ <li>30fps × 3s = 90 frames</li>
508
+ <li>60fps × 2s = 120 frames</li>
509
+ </ul>
510
+ <h3 id="choosing-fps">Choosing FPS</h3>
511
+ <ul>
512
+ <li><strong>24fps</strong>: Cinematic look, smaller files</li>
513
+ <li><strong>30fps</strong>: Standard web video, good balance</li>
514
+ <li><strong>60fps</strong>: Smooth animations, larger files</li>
515
+ </ul>
516
+ <h2 id="encoding-options">Encoding Options</h2>
517
+ <h3 id="default-balanced">Default (Balanced)</h3>
518
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">dsgn</span><span style="color:#9ECBFF"> render</span><span style="color:#9ECBFF"> video-intro</span><span style="color:#9ECBFF"> &#39;{&quot;title&quot;:&quot;Welcome&quot;}&#39;</span></span>
519
+ <span class="line"></span></code></pre>
520
+ <p>Uses H.264 codec with good quality/size balance.</p>
521
+ <h3 id="fast-encoding">Fast Encoding</h3>
522
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">dsgn</span><span style="color:#9ECBFF"> render</span><span style="color:#9ECBFF"> video-intro</span><span style="color:#9ECBFF"> &#39;{&quot;title&quot;:&quot;Welcome&quot;}&#39;</span><span style="color:#79B8FF"> --preset</span><span style="color:#9ECBFF"> ultrafast</span></span>
523
+ <span class="line"></span></code></pre>
524
+ <p>Faster encoding, slightly larger files. Good for previews.</p>
525
+ <h3 id="high-quality">High Quality</h3>
526
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">dsgn</span><span style="color:#9ECBFF"> render</span><span style="color:#9ECBFF"> video-intro</span><span style="color:#9ECBFF"> &#39;{&quot;title&quot;:&quot;Welcome&quot;}&#39;</span><span style="color:#79B8FF"> --preset</span><span style="color:#9ECBFF"> slow</span></span>
527
+ <span class="line"></span></code></pre>
528
+ <p>Better compression, slower encoding. Good for final output.</p>
529
+ <h2 id="performance">Performance</h2>
530
+ <h3 id="rendering-speed">Rendering Speed</h3>
531
+ <p>On an M1 Mac:</p>
532
+ <ul>
533
+ <li><strong>30fps, 3s video</strong> (90 frames): ~15-20 seconds</li>
534
+ <li><strong>60fps, 3s video</strong> (180 frames): ~30-40 seconds</li>
535
+ </ul>
536
+ <p>Speed depends on:</p>
537
+ <ul>
538
+ <li>Template complexity</li>
539
+ <li>Image/video embedding</li>
540
+ <li>CPU performance</li>
541
+ <li>Frame count</li>
542
+ </ul>
543
+ <h3 id="optimization-tips">Optimization Tips</h3>
544
+ <ol>
545
+ <li><strong>Lower FPS for previews</strong>: Test at 15fps, render final at 30fps</li>
546
+ <li><strong>Shorter duration</strong>: Preview with 1s, expand for final</li>
547
+ <li><strong>Simplify templates</strong>: Complex layouts take longer</li>
548
+ <li><strong>Pre-optimize media</strong>: Resize images/videos before embedding</li>
549
+ </ol>
550
+ <h3 id="memory-usage">Memory Usage</h3>
551
+ <p>Video frames are cached in memory during rendering:</p>
552
+ <ul>
553
+ <li><strong>1920x1080 @ 30fps for 3s</strong>: ~500MB RAM</li>
554
+ <li><strong>1920x1080 @ 60fps for 5s</strong>: ~1.7GB RAM</li>
555
+ </ul>
556
+ <p>For long videos, consider rendering in segments.</p>
557
+ <h2 id="common-video-templates">Common Video Templates</h2>
558
+ <h3 id="social-media-intro">Social Media Intro</h3>
559
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> SocialIntro</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">brand</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">tagline</span><span style="color:#E1E4E8"> }) {</span></span>
560
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> logoScale</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0.4</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.4</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
561
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> taglineOpacity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> progress </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> (progress </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 0.5</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
562
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
563
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
564
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;flex flex-col items-center justify-center w-full h-full bg-gradient-to-br from-pink-500 to-purple-600&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
565
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8"> </span></span>
566
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
567
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-9xl font-black text-white mb-8&#39;</span><span style="color:#E1E4E8">),</span></span>
568
+ <span class="line"><span style="color:#E1E4E8"> transform: </span><span style="color:#9ECBFF">`scale(${</span><span style="color:#E1E4E8">logoScale</span><span style="color:#9ECBFF">})`</span></span>
569
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
570
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
571
+ <span class="line"><span style="color:#E1E4E8"> {brand}</span></span>
572
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
573
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
574
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8"> </span></span>
575
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
576
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-3xl text-white&#39;</span><span style="color:#E1E4E8">),</span></span>
577
+ <span class="line"><span style="color:#E1E4E8"> opacity: taglineOpacity</span></span>
578
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
579
+ <span class="line"><span style="color:#E1E4E8"> &gt;</span></span>
580
+ <span class="line"><span style="color:#E1E4E8"> {tagline}</span></span>
581
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
582
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
583
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
584
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
585
+ <span class="line"></span></code></pre>
586
+ <h3 id="progress-bar-animation">Progress Bar Animation</h3>
587
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> ProgressVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">progress</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">subtitle</span><span style="color:#E1E4E8"> }) {</span></span>
588
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
589
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;flex flex-col items-center justify-center w-full h-full bg-gray-900 p-12&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
590
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-5xl font-bold text-white mb-12&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
591
+ <span class="line"><span style="color:#E1E4E8"> {title}</span></span>
592
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">&gt;</span></span>
593
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
594
+ <span class="line"><span style="color:#E1E4E8"> {</span><span style="color:#6A737D">/* Progress bar */</span><span style="color:#E1E4E8">}</span></span>
595
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;w-full max-w-2xl h-4 bg-gray-700 rounded-full overflow-hidden&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
596
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> </span></span>
597
+ <span class="line"><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{</span></span>
598
+ <span class="line"><span style="color:#F97583"> ...</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;h-full bg-gradient-to-r from-blue-500 to-green-500&#39;</span><span style="color:#E1E4E8">),</span></span>
599
+ <span class="line"><span style="color:#E1E4E8"> width: </span><span style="color:#9ECBFF">`${</span><span style="color:#E1E4E8">progress</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 100</span><span style="color:#9ECBFF">}%`</span></span>
600
+ <span class="line"><span style="color:#E1E4E8"> }}</span></span>
601
+ <span class="line"><span style="color:#E1E4E8"> /&gt;</span></span>
602
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
603
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
604
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-2xl text-gray-400 mt-8&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
605
+ <span class="line"><span style="color:#E1E4E8"> {subtitle}</span></span>
606
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
607
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
608
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
609
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
610
+ <span class="line"></span></code></pre>
611
+ <h3 id="countdown-timer">Countdown Timer</h3>
612
+ <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> CountdownVideo</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">tw</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">frame</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">message</span><span style="color:#E1E4E8"> }) {</span></span>
613
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> fps</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 30</span><span style="color:#E1E4E8">;</span></span>
614
+ <span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> secondsRemaining</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> Math.</span><span style="color:#B392F0">ceil</span><span style="color:#E1E4E8">((</span><span style="color:#79B8FF">90</span><span style="color:#F97583"> -</span><span style="color:#E1E4E8"> frame) </span><span style="color:#F97583">/</span><span style="color:#E1E4E8"> fps); </span><span style="color:#6A737D">// 3s countdown</span></span>
615
+ <span class="line"><span style="color:#E1E4E8"> </span></span>
616
+ <span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
617
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;flex flex-col items-center justify-center w-full h-full bg-black&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
618
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-[200px] font-black text-white&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
619
+ <span class="line"><span style="color:#E1E4E8"> {secondsRemaining}</span></span>
620
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
621
+ <span class="line"><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#B392F0">tw</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;text-3xl text-gray-400 mt-8&#39;</span><span style="color:#E1E4E8">)}&gt;</span></span>
622
+ <span class="line"><span style="color:#E1E4E8"> {message}</span></span>
623
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
624
+ <span class="line"><span style="color:#E1E4E8"> &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
625
+ <span class="line"><span style="color:#E1E4E8"> );</span></span>
626
+ <span class="line"><span style="color:#E1E4E8">}</span></span>
627
+ <span class="line"></span></code></pre>
628
+ <h2 id="output-format">Output Format</h2>
629
+ <p>Videos are always rendered as MP4 (H.264 codec) for maximum compatibility.</p>
630
+ <h2 id="next-steps">Next Steps</h2>
631
+ <ul>
632
+ <li><a href="/images">Learn about Image Rendering</a></li>
633
+ <li><a href="/helpers">QR Codes and Template Composition</a></li>
634
+ <li><a href="/styling">Styling with Tailwind &amp; shadcn/ui</a></li>
635
+ <li><a href="/fonts">Custom Fonts in Videos</a></li>
636
+ </ul> </article> </div> </main> </div> </body></html>