<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0"><channel><title>framefields | Blog</title><description>Docs for framefields: a TypeScript library that renders video on the GPU, frame by frame, straight to MP4. No browser in the loop.</description><link>https://framefields.dev/</link><language>en</language><fh:complete/><atom:link rel="self" href="https://framefields.dev/blog/rss.xml"/><item><title>Add a color overlay to a person in video with TypeScript</title><link>https://framefields.dev/blog/track-person-attach-graphics/</link><guid isPermaLink="true">https://framefields.dev/blog/track-person-attach-graphics/</guid><description>Use Framefields segmentation to add a blue overlay to a moving person while leaving the background alone.</description><pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Use Framefields to segment a dancer and add a translucent blue overlay that moves with her, while keeping the background visible.&lt;/p&gt;
&lt;video controls playsinline preload=&quot;metadata&quot; poster=&quot;/docs/blog-media/tracked.jpg&quot; aria-label=&quot;A dancer in an orange dress turns as a translucent blue overlay follows her silhouette.&quot;&gt;
  &lt;source src=&quot;/docs/blog-media/tracked.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;/video&gt;
&lt;p&gt;The blue overlay follows the dancer and her dress as she turns. The video has no audio. &lt;a href=&quot;https://framefields.dev/docs/blog-media/tracked.mp4&quot;&gt;Open the MP4&lt;/a&gt; or &lt;a href=&quot;https://framefields.dev/docs/blog-media/tracked.jpg&quot;&gt;view a still frame&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;segment-the-dancer&quot;&gt;Segment the dancer&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This example uses Framefields 2.6.2 and a three-second clip at &lt;code dir=&quot;auto&quot;&gt;assets/footage/person.mp4&lt;/code&gt;. Start with a &lt;a href=&quot;https://framefields.dev/docs/getting-started/&quot;&gt;Framefields project&lt;/a&gt;, create an &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; directory, and adjust the dimensions and duration to match your clip.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Composition, Layer } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;framefields&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;comp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Composition&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width: &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;height: &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fps: &lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;durationMs: &lt;/span&gt;&lt;span&gt;3000&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;backgroundColor: &lt;/span&gt;&lt;span&gt;&quot;#000000&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Both copies need the same size and fit so the matte lines up with the footage.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;video&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; Layer.&lt;/span&gt;&lt;span&gt;video&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;assets/footage/person.mp4&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;position: &lt;/span&gt;&lt;span&gt;&quot;absolute&quot;&lt;/span&gt;&lt;span&gt;, x: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, y: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width: &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;, height: &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;, fit: &lt;/span&gt;&lt;span&gt;&quot;cover&quot;&lt;/span&gt;&lt;span&gt;, muted: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;comp.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;video&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;personMatte&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;video&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;withVision&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mode: &lt;/span&gt;&lt;span&gt;&quot;matte&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;enableSegmentation: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;classes: [&lt;/span&gt;&lt;span&gt;&quot;person&quot;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;comp.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Layer.&lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;position: &lt;/span&gt;&lt;span&gt;&quot;absolute&quot;&lt;/span&gt;&lt;span&gt;, x: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, y: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width: &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;, height: &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;background: &lt;/span&gt;&lt;span&gt;&quot;#1458ed&quot;&lt;/span&gt;&lt;span&gt;, opacity: &lt;/span&gt;&lt;span&gt;0.55&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;withMatte&lt;/span&gt;&lt;span&gt;(personMatte),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(comp.&lt;/span&gt;&lt;span&gt;lint&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; comp.&lt;/span&gt;&lt;span&gt;renderVideo&lt;/span&gt;&lt;span&gt;({ outputPath: &lt;/span&gt;&lt;span&gt;&quot;output/segmented.mp4&quot;&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The first video is the untouched footage. The second is used as a matte, so it isn’t drawn as another visible copy. It limits the blue box to the detected subject. Change the box color or opacity to try a different look.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;check-the-edges&quot;&gt;Check the edges&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Segmentation can miss hands or loose fabric, and the matte can spill onto the background. Watch the full clip, especially around fast movements and objects crossing in front of the subject. In this example, you can see some edge lag as the dress moves.&lt;/p&gt;
&lt;p&gt;Render-time vision uses the previous rendered frame, so frame 0 has no segmentation result. &lt;code dir=&quot;auto&quot;&gt;renderVideo&lt;/code&gt; processes frames in order. For stills, render at least two consecutive frames with the same renderer and inspect the last one. A frame grid jumps around and can give misleading results for vision layers. The &lt;a href=&quot;https://framefields.dev/docs/guides/vision/#timing-the-one-frame-delay&quot;&gt;vision guide&lt;/a&gt; has more on timing.&lt;/p&gt;
&lt;p&gt;Models download on first use and inference takes resources. Framefields uses WebGPU when available and can fall back to CPU. See the &lt;a href=&quot;https://framefields.dev/docs/guides/vision/&quot;&gt;vision guide&lt;/a&gt; for model options, masks and other ways to use them.&lt;/p&gt;
</content:encoded><category>vision</category><category>typescript</category><category>video</category></item><item><title>Animate text letter by letter with TypeScript</title><link>https://framefields.dev/blog/kinetic-typography-typescript/</link><guid isPermaLink="true">https://framefields.dev/blog/kinetic-typography-typescript/</guid><description>Make a kinetic title with Framefields, inspect a few frames, and export it to MP4.</description><pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Animate a title letter by letter in TypeScript, then render it to MP4 with Framefields. Change the words and the same animation works with the new text.&lt;/p&gt;
&lt;video controls playsinline preload=&quot;metadata&quot; poster=&quot;/docs/blog-media/title.jpg&quot; aria-label=&quot;A white title reading “Make something move” appears letter by letter on a dark blue background.&quot;&gt;
  &lt;source src=&quot;/docs/blog-media/title.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;/video&gt;
&lt;p&gt;The finished title, rendered from the code below. A white title reading “Make something move” appears letter by letter on a dark blue background. The video has no audio. &lt;a href=&quot;https://framefields.dev/docs/blog-media/title.mp4&quot;&gt;Open the MP4&lt;/a&gt; or &lt;a href=&quot;https://framefields.dev/docs/blog-media/title.jpg&quot;&gt;view a still frame&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;make-a-title&quot;&gt;Make a title&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Start with a &lt;a href=&quot;https://framefields.dev/docs/getting-started/&quot;&gt;Framefields project&lt;/a&gt;. The example uses Framefields 2.6.2 and a local font file at &lt;code dir=&quot;auto&quot;&gt;assets/fonts/Inter.ttf&lt;/code&gt;. Register the font before creating the text layer: Framefields doesn’t ship fonts or pick one from your system for headless rendering.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Composition, FontManager, Layer, LayerAnimation, TextAnimator } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;framefields&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; FontManager.&lt;/span&gt;&lt;span&gt;register&lt;/span&gt;&lt;span&gt;({ family: &lt;/span&gt;&lt;span&gt;&quot;Inter&quot;&lt;/span&gt;&lt;span&gt;, source: &lt;/span&gt;&lt;span&gt;&quot;assets/fonts/Inter.ttf&quot;&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;comp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Composition&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width: &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;height: &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fps: &lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;durationMs: &lt;/span&gt;&lt;span&gt;3000&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;backgroundColor: &lt;/span&gt;&lt;span&gt;&quot;#102450&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Layer.&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Make something move&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;position: &lt;/span&gt;&lt;span&gt;&quot;absolute&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x: &lt;/span&gt;&lt;span&gt;160&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;y: &lt;/span&gt;&lt;span&gt;420&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width: &lt;/span&gt;&lt;span&gt;1600&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;height: &lt;/span&gt;&lt;span&gt;240&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fontFamily: &lt;/span&gt;&lt;span&gt;&quot;Inter&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fontSize: &lt;/span&gt;&lt;span&gt;120&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fill: &lt;/span&gt;&lt;span&gt;&quot;#ffffff&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;animators: [TextAnimator.&lt;/span&gt;&lt;span&gt;waveRise&lt;/span&gt;&lt;span&gt;({ y: &lt;/span&gt;&lt;span&gt;60&lt;/span&gt;&lt;span&gt;, rotationX: &lt;/span&gt;&lt;span&gt;45&lt;/span&gt;&lt;span&gt; })],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;animate&lt;/span&gt;&lt;span&gt;(LayerAnimation.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;kineticSweep&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;comp.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(title);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(comp.&lt;/span&gt;&lt;span&gt;lint&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; comp.&lt;/span&gt;&lt;span&gt;renderVideo&lt;/span&gt;&lt;span&gt;({ outputPath: &lt;/span&gt;&lt;span&gt;&quot;output/title.mp4&quot;&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Create the &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; directory before running the script. At 30 frames per second, the sweep takes 40 frames, or about 1.3 seconds. Try a shorter sweep for a snappier entrance. If your title wraps, give it more width or reduce the font size.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;check-the-in-between-bits&quot;&gt;Check the in-between bits&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A title can look fine at the start and end but clip halfway through. Before a full export, render a contact sheet:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; comp.&lt;/span&gt;&lt;span&gt;renderFrameGrid&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;frames: [&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;60&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;columns: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;outputPath: &lt;/span&gt;&lt;span&gt;&quot;output/title-grid.png&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Look for cropped letters and awkward line breaks. If you want words or lines to move together, pass &lt;code dir=&quot;auto&quot;&gt;unit: &quot;word&quot;&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;unit: &quot;line&quot;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;waveRise&lt;/code&gt;. The default is &lt;code dir=&quot;auto&quot;&gt;&quot;character&quot;&lt;/code&gt;. There are also presets for blur, flips, color sweeps and word pops in the &lt;a href=&quot;https://framefields.dev/docs/guides/animation/#kinetic-typography&quot;&gt;animation guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is useful when the same title treatment needs to work across many names, headlines or languages. You still need to check the result: different text takes up different space, and fonts need to cover the characters you use.&lt;/p&gt;
&lt;p&gt;For font registration and text layout, see the &lt;a href=&quot;https://framefields.dev/docs/guides/layout-and-text/#text&quot;&gt;text guide&lt;/a&gt;. For more ways to inspect a composition before export, see &lt;a href=&quot;https://framefields.dev/docs/guides/rendering/&quot;&gt;rendering&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>typography</category><category>typescript</category><category>motion-graphics</category></item><item><title>Framefields is the engine behind Gatewai Studio</title><link>https://framefields.dev/blog/six-months-building-framefields/</link><guid isPermaLink="true">https://framefields.dev/blog/six-months-building-framefields/</guid><description>The engine behind Framefields has been running in production at Gatewai Studio for six months. Here&apos;s where it comes from and what you can build with it.</description><pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Framefields is the engine behind &lt;a href=&quot;https://gatewai.studio&quot;&gt;Gatewai Studio&lt;/a&gt;, and it has been running there in production for six months. That experience has made it mature enough to use for real video projects today.&lt;/p&gt;
&lt;p&gt;Gatewai Studio is a visual workspace for building media workflows and compositions. People can bring together video, images, text and audio, then render the result. Framefields comes from the engine behind that work. It isn’t a brand-new rendering experiment we put together for a launch.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;from-a-visual-studio-to-code&quot;&gt;From a visual studio to code&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With Framefields, you can build a composition in TypeScript and render it with WebGPU. That makes the engine accessible to developers and coding agents as well as people working in a visual studio.&lt;/p&gt;
&lt;p&gt;You can animate text, combine 2D graphics with 3D models, apply effects, work with audio and use vision models. If you’d like to see the output before reading the API, start with our examples: &lt;a href=&quot;https://framefields.dev/blog/kinetic-typography-typescript/&quot;&gt;animated titles&lt;/a&gt;, &lt;a href=&quot;https://framefields.dev/blog/3d-product-video-typescript/&quot;&gt;a 3D scene&lt;/a&gt; and &lt;a href=&quot;https://framefields.dev/blog/track-person-attach-graphics/&quot;&gt;a segmented video&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-practical-way-to-work&quot;&gt;A practical way to work&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We know that making a video is rarely a one-render job. A title wraps, an asset is the wrong size, or the timing just feels a little off. Framefields lets you check a composition with &lt;code dir=&quot;auto&quot;&gt;lint()&lt;/code&gt;, render a single frame or a contact sheet, and use a &lt;a href=&quot;https://framefields.dev/docs/guides/preview/&quot;&gt;live preview&lt;/a&gt; before exporting the full video. The &lt;a href=&quot;https://framefields.dev/docs/guides/rendering/&quot;&gt;rendering guide&lt;/a&gt; covers the workflow.&lt;/p&gt;
&lt;p&gt;Six months in production gives the engine a real history. It doesn’t mean every composition or machine will behave perfectly. You’ll still need to register fonts, check your assets and inspect your output. Vision masks, for example, can miss parts of a subject or lag at moving edges. We think it’s better to show those details than pretend they don’t exist.&lt;/p&gt;
&lt;p&gt;If you’re curious, the &lt;a href=&quot;https://framefields.dev/docs/getting-started/&quot;&gt;getting started guide&lt;/a&gt; will take you through your first render. The &lt;a href=&quot;https://github.com/gatewai-dev/framefields&quot;&gt;source is on GitHub&lt;/a&gt;, too.&lt;/p&gt;
</content:encoded><category>framefields</category><category>gatewai</category><category>rendering</category></item><item><title>Make a 3D product video with TypeScript</title><link>https://framefields.dev/blog/3d-product-video-typescript/</link><guid isPermaLink="true">https://framefields.dev/blog/3d-product-video-typescript/</guid><description>Put a GLB model and an animated title in the same Framefields composition, then render the result to MP4.</description><pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A spinning product and a title: a small scene, but a useful starting point for a launch video. With Framefields, you can put a 3D model and 2D text in the same composition and describe the animation in TypeScript.&lt;/p&gt;
&lt;video controls playsinline preload=&quot;metadata&quot; poster=&quot;/docs/blog-media/product.jpg&quot; aria-label=&quot;An orange faceted 3D gem turns beside the title “Made to move” on a dark blue background.&quot;&gt;
  &lt;source src=&quot;/docs/blog-media/product.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;/video&gt;
&lt;p&gt;The finished scene uses a simple faceted gem as the model. An orange faceted 3D gem turns beside the title “Made to move” on a dark blue background. The video has no audio. &lt;a href=&quot;https://framefields.dev/docs/blog-media/product.mp4&quot;&gt;Open the MP4&lt;/a&gt; or &lt;a href=&quot;https://framefields.dev/docs/blog-media/product.jpg&quot;&gt;view a still frame&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;build-the-scene&quot;&gt;Build the scene&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This example uses Framefields 2.6.2, a GLB model at &lt;code dir=&quot;auto&quot;&gt;assets/models/product.glb&lt;/code&gt;, and a font at &lt;code dir=&quot;auto&quot;&gt;assets/fonts/Inter.ttf&lt;/code&gt;. Use a model you have permission to publish. Model dimensions vary, so expect to adjust the position and scale for yours.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Composition, FontManager, Layer, LayerAnimation, Lighting } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;framefields&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; FontManager.&lt;/span&gt;&lt;span&gt;register&lt;/span&gt;&lt;span&gt;({ family: &lt;/span&gt;&lt;span&gt;&quot;Inter&quot;&lt;/span&gt;&lt;span&gt;, source: &lt;/span&gt;&lt;span&gt;&quot;assets/fonts/Inter.ttf&quot;&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;comp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Composition&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width: &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;height: &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fps: &lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;durationMs: &lt;/span&gt;&lt;span&gt;4000&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;backgroundColor: &lt;/span&gt;&lt;span&gt;&quot;#102450&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;comp.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(Lighting.&lt;/span&gt;&lt;span&gt;studio&lt;/span&gt;&lt;span&gt;({ target: [&lt;/span&gt;&lt;span&gt;960&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;540&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;] }));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;comp.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Layer.&lt;/span&gt;&lt;span&gt;glb&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;assets/models/product.glb&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x: &lt;/span&gt;&lt;span&gt;1250&lt;/span&gt;&lt;span&gt;, y: &lt;/span&gt;&lt;span&gt;540&lt;/span&gt;&lt;span&gt;, z: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, scale: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;animate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;LayerAnimation.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;fromTo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;rotateY&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;start: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, end: &lt;/span&gt;&lt;span&gt;119&lt;/span&gt;&lt;span&gt;, ease: &lt;/span&gt;&lt;span&gt;&quot;sine.inOut&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;comp.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Layer.&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Made to move&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;position: &lt;/span&gt;&lt;span&gt;&quot;absolute&quot;&lt;/span&gt;&lt;span&gt;, x: &lt;/span&gt;&lt;span&gt;120&lt;/span&gt;&lt;span&gt;, y: &lt;/span&gt;&lt;span&gt;420&lt;/span&gt;&lt;span&gt;, width: &lt;/span&gt;&lt;span&gt;700&lt;/span&gt;&lt;span&gt;, height: &lt;/span&gt;&lt;span&gt;180&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fontFamily: &lt;/span&gt;&lt;span&gt;&quot;Inter&quot;&lt;/span&gt;&lt;span&gt;, fontSize: &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;, fill: &lt;/span&gt;&lt;span&gt;&quot;#ffffff&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}).&lt;/span&gt;&lt;span&gt;animate&lt;/span&gt;&lt;span&gt;(LayerAnimation.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;fadeIn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;power2.out&quot;&lt;/span&gt;&lt;span&gt;)),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(comp.&lt;/span&gt;&lt;span&gt;lint&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; comp.&lt;/span&gt;&lt;span&gt;renderVideo&lt;/span&gt;&lt;span&gt;({ outputPath: &lt;/span&gt;&lt;span&gt;&quot;output/product.mp4&quot;&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Create the &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; directory first. The lighting rig sets up an environment and lights; the model turns while the title fades in. If the model is tiny, enormous, or facing the wrong way, adjust its scale and rotation. 3D assets have a knack for arriving with their own ideas about size.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;check-the-scene-before-exporting&quot;&gt;Check the scene before exporting&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Render a few frames first with &lt;code dir=&quot;auto&quot;&gt;comp.renderFrameGrid()&lt;/code&gt;. Check that the model stays in frame and that the title remains readable. You can also change the lighting rig or add bloom, but it’s worth getting the basic placement right first.&lt;/p&gt;
&lt;p&gt;Framefields supports several model formats, including GLB, glTF, OBJ and FBX. The &lt;a href=&quot;https://framefields.dev/docs/guides/3d/#models&quot;&gt;3D guide&lt;/a&gt; lists the loaders and documents glTF material and skeletal animation support. Shadows have a constraint: only the first shadow-casting directional or spot light casts a shadow. The same guide covers lighting, bloom and other settings.&lt;/p&gt;
&lt;p&gt;For setup and export options, start with &lt;a href=&quot;https://framefields.dev/docs/getting-started/&quot;&gt;getting started&lt;/a&gt; and &lt;a href=&quot;https://framefields.dev/docs/guides/rendering/&quot;&gt;rendering&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>3d</category><category>typescript</category><category>motion-graphics</category></item><item><title>Why framefields works well with coding agents</title><link>https://framefields.dev/blog/why-framefields-for-your-ai-agents/</link><guid isPermaLink="true">https://framefields.dev/blog/why-framefields-for-your-ai-agents/</guid><description>Framefields gives coding agents a TypeScript workflow for creating, inspecting and rendering video, with a human in the loop.</description><pubDate>Wed, 14 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A coding agent can write a video in TypeScript, render a few frames, inspect the results and adjust the composition. Framefields gives it the tools to do that without opening a desktop editor.&lt;/p&gt;
&lt;p&gt;The engine renders compositions with WebGPU in Node.js. You describe layers, animation and timing in code, then render a single frame or an MP4. The same source can be read and edited by a person or an agent.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;start-with-a-frame-not-a-full-export&quot;&gt;Start with a frame, not a full export&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A full video takes longer to render than a still. Framefields lets an agent work through smaller checks first:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Type-check the project and run &lt;code dir=&quot;auto&quot;&gt;comp.lint()&lt;/code&gt; to find common composition problems.&lt;/li&gt;
&lt;li&gt;Render a frame at a useful moment and inspect it for layout, text and color.&lt;/li&gt;
&lt;li&gt;Render a frame grid to check a sequence of moments.&lt;/li&gt;
&lt;li&gt;Open the &lt;a href=&quot;https://framefields.dev/docs/guides/preview/&quot;&gt;live preview&lt;/a&gt; for playback, scrubbing and notes.&lt;/li&gt;
&lt;li&gt;Export the video, with optional QA checks.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;a href=&quot;https://framefields.dev/docs/guides/rendering/&quot;&gt;rendering guide&lt;/a&gt; shows the commands and code for each step. Frame grids are useful for ordinary animation, but not for render-time vision: that needs consecutive frames because its results lag by one frame.&lt;/p&gt;
&lt;p&gt;A human can pause the preview and leave a note on the picture, such as “move the title up.” The note is saved locally, so an agent can read it and update the composition. You’ll still want to check the result together. A successful render doesn’t automatically mean the timing feels right.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;give-the-agent-useful-building-blocks&quot;&gt;Give the agent useful building blocks&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Framefields includes text animation, 2D layers, 3D models, effects, audio and vision. You can see the code and output in our examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://framefields.dev/blog/kinetic-typography-typescript/&quot;&gt;Animate text letter by letter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://framefields.dev/blog/3d-product-video-typescript/&quot;&gt;Combine a 3D model and a title&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://framefields.dev/blog/track-person-attach-graphics/&quot;&gt;Apply a color overlay to a segmented person&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The engine is also behind &lt;a href=&quot;https://gatewai.studio&quot;&gt;Gatewai Studio&lt;/a&gt;. Read more about &lt;a href=&quot;https://framefields.dev/blog/six-months-building-framefields/&quot;&gt;its background&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;give-your-agent-the-project-instructions&quot;&gt;Give your agent the project instructions&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For Claude Code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/plugin install framefields&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For other coding agents that support the skills installer:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;skills&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gatewai-dev/framefields&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then give the agent a specific brief, including the size, duration and moments you want to inspect. For example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Create a five-second product teaser at 1080x1920 and 30 fps.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Add an animated headline and a bar chart. Render frames at the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;start, middle and end so I can check the layout before export.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Framefields needs Node.js, project assets such as fonts, and a suitable rendering environment. CPU rendering is available on supported setups but is slower. See &lt;a href=&quot;https://framefields.dev/docs/getting-started/&quot;&gt;getting started&lt;/a&gt; for requirements and the &lt;a href=&quot;https://framefields.dev/docs/agents/&quot;&gt;agent guide&lt;/a&gt; for the workflow.&lt;/p&gt;
</content:encoded><category>agents</category><category>webgpu</category><category>video</category><category>motion-graphics</category></item></channel></rss>