<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Louis Chi</title>
    <description>The latest articles on DEV Community by Louis Chi (@ref_vid).</description>
    <link>https://dev.to/ref_vid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4201088%2F97943aaf-ee72-4b2d-8179-71b58a101a43.png</url>
      <title>DEV Community: Louis Chi</title>
      <link>https://dev.to/ref_vid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ref_vid"/>
    <language>en</language>
    <item>
      <title>How to make a product video from your product photos, free (step by step, with screenshots)</title>
      <dc:creator>Louis Chi</dc:creator>
      <pubDate>Sun, 01 Nov 2026 15:08:35 +0000</pubDate>
      <link>https://dev.to/ref_vid/how-to-make-a-product-video-from-your-product-photos-free-step-by-step-with-screenshots-2dhg</link>
      <guid>https://dev.to/ref_vid/how-to-make-a-product-video-from-your-product-photos-free-step-by-step-with-screenshots-2dhg</guid>
      <description>&lt;p&gt;If you sell something online, you've probably been told you need video: on the listing, in the ads, on TikTok. And if you've ever priced a product shoot, you know why most small shops don't have any.&lt;/p&gt;

&lt;p&gt;I'm Louis, and I run &lt;a href="https://refvid.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-product-videos-guide" rel="noopener noreferrer"&gt;RefVid&lt;/a&gt;. We just rebuilt our free generator page so the whole thing happens on one screen: you add photos, pick a template and press Generate, and you only sign in at that last step. This post walks through it with screenshots of the real page and clips made from product photos. The full guide, kept up to date, is on &lt;a href="https://refvid.com/how-to-make-ai-product-videos?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-product-videos-guide" rel="noopener noreferrer"&gt;our site&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get for free
&lt;/h2&gt;

&lt;p&gt;Your first 5-second clip on Kling 3.0 Omni is free once you sign in with Google or email. It's 720p and silent by default, or you can spend the free credits on one clip with sound or at 1080p instead. No card, no watermark, and you can use it commercially. Five free images come with it.&lt;/p&gt;

&lt;p&gt;Here's what three photos of a shoe turn into with the Product 360 template, at exactly those free settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2m6lwgmhcwywn029nac6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2m6lwgmhcwywn029nac6.jpg" alt="One of the three reference photos of an AI-made running shoe" width="320" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://refvid.com/product-360-turntable?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-product-videos-guide" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb5yfjghnac21qy4xzosp.jpg" alt="The 5-second 360° clip made from those photos (click to play it on the template page)" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: pick a product template
&lt;/h2&gt;

&lt;p&gt;Open the &lt;a href="https://refvid.com/free-ai-video-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-product-videos-guide" rel="noopener noreferrer"&gt;free AI video generator&lt;/a&gt;. Under the heading there's a row of templates, product ones first. Press &lt;strong&gt;Use&lt;/strong&gt; on one and its prompt fills the box below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F475rb28ljzvzxem99oid.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F475rb28ljzvzxem99oid.jpg" alt="The generator's first screen: heading, template row and the input box" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pick by what the video is for: a 360° turntable or a floating product shows the item itself, a water splash or bullet time grabs attention in an ad, a hand holding the product reads like a customer's video.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: add one to five photos
&lt;/h2&gt;

&lt;p&gt;Click &lt;strong&gt;Reference&lt;/strong&gt; and add 1–5 photos. One sharp photo works; three are better: the front, a three-quarter angle, and the label up close. The model gets all of them with every prompt, which is why the label and shape come from your product rather than from a guess.&lt;/p&gt;

&lt;p&gt;Plain background, crop away big empty margins, and only use photos you have the right to. (If you're shooting them at home, I wrote up &lt;a href="https://refvid.com/how-to-shoot-product-reference-photos?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ai-product-videos-guide" rel="noopener noreferrer"&gt;how we take product photos for AI video&lt;/a&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: check the prompt
&lt;/h2&gt;

&lt;p&gt;The template's prompt already works. Five seconds hold one action and one camera move, so describe the scene, the motion and the light, and leave the product's look to the photos. This is the prompt behind a real water-splash clip on our site, with the product's name replaced by "your product":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Slow motion: your product drops into a tank of crystal-clear water against a soft blue gradient background, a burst of bubbles and droplets exploding around it, then it settles upright with the label facing the camera. Bright studio light, macro detail.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: shape, length and sound
&lt;/h2&gt;

&lt;p&gt;For the free clip, leave it on Kling 3.0 Omni, 5 seconds, 720p. Choose the shape by where it's going:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where it goes&lt;/th&gt;
&lt;th&gt;Shape&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Store listing, Instagram feed&lt;/td&gt;
&lt;td&gt;1:1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TikTok, Reels, Shorts&lt;/td&gt;
&lt;td&gt;9:16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Website banner, YouTube&lt;/td&gt;
&lt;td&gt;16:9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 5: Generate, then sign in
&lt;/h2&gt;

&lt;p&gt;Press &lt;strong&gt;Generate&lt;/strong&gt;. If you're signed out, a sign-in sheet opens over the page (Google or email). When you come back, your photos and prompt are still in the box and the video starts by itself. That was the part we cared about most: nobody should have to fill a form twice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9o7dd0q2xjkfyuaa14yx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9o7dd0q2xjkfyuaa14yx.jpg" alt="The sign-in sheet that opens on Generate, on a phone" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It usually takes 2 to 10 minutes; the clip shows up on the page and you get an email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: download and check
&lt;/h2&gt;

&lt;p&gt;Download the MP4. Then watch it full size, frame by frame: label text, product edges, hands if there are any. Models still slip sometimes, and it's much cheaper to catch it before a customer does. Label realistic AI video as AI where the platform asks.&lt;/p&gt;

&lt;p&gt;That's the whole flow. If you try it, I'd like to hear where it got in your way: what you expected to happen and didn't.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was written with AI assistance and checked against our live product.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>ecommerce</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Images to video AI, step by step: several pictures, @ tags and a picture for each shot</title>
      <dc:creator>Louis Chi</dc:creator>
      <pubDate>Sun, 01 Nov 2026 11:26:51 +0000</pubDate>
      <link>https://dev.to/ref_vid/several-pictures-one-ai-video-how-we-send-image1image7-to-kling-and-six-other-models-in-order-km0</link>
      <guid>https://dev.to/ref_vid/several-pictures-one-ai-video-how-we-send-image1image7-to-kling-and-six-other-models-in-order-km0</guid>
      <description>&lt;p&gt;&lt;em&gt;Written with AI assistance (Claude) and checked against the product. Every GIF below is a real screen recording of the RefVid studio; the clip at the end is unedited model output.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most image-to-video tools take one picture. This week we rebuilt the &lt;a href="https://refvid.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=images-to-video-ai" rel="noopener noreferrer"&gt;RefVid&lt;/a&gt; composer so one clip can use up to seven: a place, a mood, a frame from your storyboard, each placed in the shot you choose. Here is the whole flow in five steps, one recording per step.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Drop in your pictures
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2r1k81w0tyf70r0szdai.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2r1k81w0tyf70r0szdai.gif" alt="Two pictures dropped onto the composer become @Image1 and @Image2" width="740" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag pictures onto the box, paste them, or use &lt;strong&gt;+ Image&lt;/strong&gt;. Up to 7 per clip.&lt;/li&gt;
&lt;li&gt;Each one becomes a tile named &lt;code&gt;@Image1&lt;/code&gt;, &lt;code&gt;@Image2&lt;/code&gt;… in the order you add it. It gets its number at once and uploads in the background, so numbers never reshuffle.&lt;/li&gt;
&lt;li&gt;No saved character needed. Pictures work on their own, and saved characters or products (&lt;strong&gt;+ Element&lt;/strong&gt;) can join them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Type @ to put a picture in a shot
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fst4u6l1u3kr8jkp49jkp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fst4u6l1u3kr8jkp49jkp.gif" alt="Typing @ opens the picture list at the cursor; picking @Image1 makes a highlighted tag" width="740" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type &lt;code&gt;@&lt;/code&gt; anywhere in a shot: a small list of your pictures opens at the cursor. Arrow keys and Enter (or Tab) pick one; typing filters it.&lt;/li&gt;
&lt;li&gt;The pick becomes a highlighted tag such as &lt;code&gt;@Image1&lt;/code&gt;. Saved elements are tags too (&lt;code&gt;@Mia&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;A tag is one piece: Backspace removes all of it, never half.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. One shot for each beat
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9gk7fl06cqqed70lxh8l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9gk7fl06cqqed70lxh8l.gif" alt="Three shots written in the composer, 3 seconds each, 9 seconds in total" width="740" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;+ Shot&lt;/strong&gt; adds a shot (up to 3 per clip), each with its own length.&lt;/li&gt;
&lt;li&gt;In the recording: shot 1 is the courtyard in &lt;code&gt;@Image1&lt;/code&gt;, shot 2 the scene in &lt;code&gt;@Image2&lt;/code&gt;, shot 3 names no picture. Three shots of 3 seconds, 9 seconds in total.&lt;/li&gt;
&lt;li&gt;The line above the bar shows what the clip costs and what you have, and updates as you add shots.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Each shot shows its pictures
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjwk2scz446h3etio84gi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjwk2scz446h3etio84gi.gif" alt="The + on shot 3 adds @Image1 to the shot's head, and its × takes it out again" width="740" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A shot's head shows the pictures it uses, so you can check a three-shot clip at a glance.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;+&lt;/strong&gt; there offers only what the shot doesn't use yet, plus Upload a picture and Another element. The &lt;strong&gt;×&lt;/strong&gt; on a thumbnail takes it out of that shot.&lt;/li&gt;
&lt;li&gt;A picture's own menu: use in this shot, start the video on it, end the video on it (on Kling 4 and Kling 3.0 Omni), or remove it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Model, settings and sound in one row
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3c01cof472gtgl224nyr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3c01cof472gtgl224nyr.gif" alt="The settings switch 16:9 to 9:16, then the model list opens" width="740" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Settings: aspect ratio, length, quality and versions, in one small panel; the chip shows the summary (here 9:16 · 9s · 720p · 1).&lt;/li&gt;
&lt;li&gt;The model list says what each model is good at and what it costs next to Kling 4: Kling 4, Kling 3.0 Omni, Seedance 2.5, Wan 3.0, Vidu Q4, Gemini Omni Flash, PixVerse C1 and Happy Horse 1.1.&lt;/li&gt;
&lt;li&gt;Your pictures work on every one of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What happens when you press Generate
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The pictures go to the model &lt;strong&gt;in the order you added them&lt;/strong&gt;, so &lt;code&gt;@Image2&lt;/code&gt; is always your second picture. Every model names reference images differently; RefVid rewrites the tags for the model you picked, and your text stays as you wrote it.&lt;/li&gt;
&lt;li&gt;Too many pictures for a model? The studio tells you before any credits are held, instead of quietly dropping one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve&lt;/strong&gt; (the sparkle on each shot) now looks at that shot's pictures and keeps every tag you wrote. With an empty shot it writes one from the pictures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;The exact three shots from the recording, on Kling 3.0 Omni, 720p, no sound, not edited:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gcp9wuruq67xxglvoob.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gcp9wuruq67xxglvoob.jpg" alt="Frame from the 9-second, three-shot clip made from the two pictures" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One honest note: a picture is redrawn, not pasted. If a face or a product label has to stay identical across clips, save it as an element instead.&lt;/p&gt;

&lt;p&gt;Both clips (this one and a single 5-second Kling 4 move between the two pictures), the pictures and the prompts are here: &lt;a href="https://refvid.com/images-to-video-ai?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=images-to-video-ai" rel="noopener noreferrer"&gt;Images to video AI: several pictures in one clip&lt;/a&gt;. A new account's first 5-second video is free, no card, and more pictures don't change the price.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>video</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How to take product photos at home that AI video models can actually use</title>
      <dc:creator>Louis Chi</dc:creator>
      <pubDate>Sun, 25 Oct 2026 11:58:43 +0000</pubDate>
      <link>https://dev.to/ref_vid/how-to-take-product-photos-at-home-that-ai-video-models-can-actually-use-gj8</link>
      <guid>https://dev.to/ref_vid/how-to-take-product-photos-at-home-that-ai-video-models-can-actually-use-gj8</guid>
      <description>&lt;p&gt;Most "the AI ruined my product" complaints are photo problems. The logo melts, the bottle turns from teal to green, the shoe grows an extra stripe. Usually the input is one busy lifestyle shot, or five photos taken in five different lights.&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://refvid.com/how-to-shoot-product-reference-photos?utm_source=devto" rel="noopener noreferrer"&gt;RefVid&lt;/a&gt;, which turns product photos into video with reference-to-video models such as Kling Omni. We shoot many test sets for invented products (a serum called LUMEN, a shoe called AERO 1). This is what works with a phone and a kitchen table.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a reference-to-video model does with your photos
&lt;/h2&gt;

&lt;p&gt;Image-to-video animates one picture; once the camera moves past it, the model invents the rest, and products drift. Reference-to-video treats your photos as a description of the object and builds every frame of a new scene around them. The model can only keep what it can see, so it needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3 to 5 photos&lt;/strong&gt; of the same object, not 1 and not 20.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different angles&lt;/strong&gt; of it: front, three-quarter, side, back, a detail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The same light, background and color in every photo.&lt;/strong&gt; The model averages across the set. If the photos disagree, you get the average.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point causes most of the failures, so the setup below is mostly about consistency, not beauty.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup: window, sweep, phone
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Light.&lt;/strong&gt; A big window without direct sun is the best free light you have. Put the product about a meter from it and stand a sheet of white card on the other side to lift the shadows. If you shoot at night, use two identical lamps at 45 degrees on either side. Never mix a warm bulb with daylight: the color shifts between angles, and the model learns a color your product doesn't have.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backdrop.&lt;/strong&gt; Curve a sheet of white or light gray paper (or bent foam board) from the table up to the wall so there is no horizon line. Set the product well forward on the flat part so its shadow doesn't climb the wall. Use mid-gray for white products so their edges don't vanish. No wood grain, no patterned cloth, nothing with text. A background that shows up in every reference gets treated as part of the product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Light box.&lt;/strong&gt; For small things (jewelry, cosmetics, earbuds), a light box gives soft, almost shadowless light from every side. You can make one: cut windows into three sides of a cardboard box, tape baking paper over them, line the inside with a curved sheet of white paper, and put one lamp on each side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phone settings.&lt;/strong&gt; These matter more than the phone model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the main lens at 1x or 2x. The ultra-wide bends straight edges, and the model will faithfully reproduce a bent bottle.&lt;/li&gt;
&lt;li&gt;Turn off portrait mode, beauty filters and any color "look".&lt;/li&gt;
&lt;li&gt;On iPhone, tap and hold the product until AE/AF Lock appears, then drag the exposure slider down a little so white labels keep detail. The stock camera can't lock white balance, which is one more reason to keep a single light type.&lt;/li&gt;
&lt;li&gt;On Android, Pro mode lets you set white balance to a fixed value (around 5000 to 5500 K for daylight) and keep ISO low. Fix it once and leave it for the whole set.&lt;/li&gt;
&lt;li&gt;Rest the phone on books or a tripod, use the 3-second timer, and wipe the lens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The five angles (plus one)
&lt;/h2&gt;

&lt;p&gt;Shoot these in order, without moving the lights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Front&lt;/strong&gt;, straight on at the product's eye level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;45-degree three-quarter view.&lt;/strong&gt; Usually your best hero image, and the one we upload first, because the first image is treated as the main view.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Side.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Back&lt;/strong&gt;, including the label panel if there is one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detail close-up&lt;/strong&gt; of the logo or main marking, filling most of the frame and perfectly sharp.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The plus one: &lt;strong&gt;an in-use shot&lt;/strong&gt; if the product is held or worn. A hand around the bottle, the watch on a wrist. Product-only photos don't show scale, and without one you can get a perfume bottle the size of a wine bottle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii3y9matet9bv5xlwezx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii3y9matet9bv5xlwezx.jpg" alt="A reference photo of an invented serum bottle on a plain backdrop" width="240" height="240"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;One of the three plain-backdrop photos of LUMEN, a test serum. Same light, same paper, three angles.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then pick 3 to 5 of these. Front, three-quarter and logo close-up is the minimum set we'd trust; add the back and the in-use shot if you have them. The full shot list, including top-down views and turntable clips, is in our &lt;a href="https://refvid.com/how-to-shoot-product-reference-photos" rel="noopener noreferrer"&gt;guide to taking product photos at home&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jewelry and other reflective things
&lt;/h2&gt;

&lt;p&gt;Shiny surfaces mirror the room, and whatever is mirrored ends up in the video, in every scene. So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Turn off the ceiling light and use one large soft source. Stand white card around the piece so it reflects plain white, and shoot from slightly above so it reflects the card, not you.&lt;/li&gt;
&lt;li&gt;Shoot jewelry on mid-gray paper, or black for silver and diamonds. Wipe off fingerprints and dust first; a macro lens makes them huge.&lt;/li&gt;
&lt;li&gt;Stand rings upright with a small ball of putty hidden behind the band.&lt;/li&gt;
&lt;li&gt;Get as close as the phone still focuses (newer iPhone Pros switch to macro on their own) instead of using digital zoom.&lt;/li&gt;
&lt;li&gt;Clear glass disappears on white. Put a strip of black card just outside the frame on each side to draw dark edges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have a clean set, a slow turn under moving light is where jewelry looks best; our &lt;a href="https://refvid.com/jewelry-sparkle" rel="noopener noreferrer"&gt;jewelry sparkle template&lt;/a&gt; is that shot on black velvet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common failures, and the photo that fixes them
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The logo warps or the text changes.&lt;/strong&gt; Small printed text is the weakest point of every video model we've tested. You can't make it perfect, but you can stop making it worse: include one close-up where the logo fills the frame and is sharp at 100 percent zoom, and plan scenes where the logo is large and faces the camera. Fine print like ingredient lists will be redrawn whatever you do, so keep it out of focus or turned away. More on this in &lt;a href="https://refvid.com/how-to-keep-logos-and-packaging-accurate" rel="noopener noreferrer"&gt;how to keep logos and packaging accurate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The color drifts between clips.&lt;/strong&gt; Almost always mixed light or mixed sessions: two photos from Tuesday's window, two from Friday's lamp. Reshoot all of them in one session, in one light. Also, shoot each colorway as its own set. A blue bottle and a red bottle in one reference set give you a purple-ish one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shape is wrong on the back or the sides.&lt;/strong&gt; The model never saw them. Add the side and back photos. A product with a distinctive cap needs a top-down shot too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Random props show up in the scene.&lt;/strong&gt; They were in the references. Crop them out, and keep lifestyle photos out of the set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The prompt fights the photos.&lt;/strong&gt; Once the photos are attached, don't describe the product again in words ("a teal glass bottle with a gold cap"). Name it and describe the scene instead. When words and photos disagree, the model blends them.&lt;/p&gt;

&lt;h2&gt;
  
  
  From photos to clips
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftmc8yaq9ws7do5nshbvu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftmc8yaq9ws7do5nshbvu.jpg" alt="A running shoe in a gym, generated from three reference photos" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;AERO 1, an invented running shoe: three photos against one gray backdrop, then a gym scene generated from them with Kling 3.0 Omni.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once the set is right, the video part is short: save the product once, write one line about the scene, and every clip starts from the same object. Details, including what to do with only one shop photo, are in &lt;a href="https://refvid.com/product-photo-to-video" rel="noopener noreferrer"&gt;product photo to video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The clips worth making first are the ones a shop actually uses: a &lt;a href="https://refvid.com/product-360-turntable" rel="noopener noreferrer"&gt;360-degree turntable&lt;/a&gt; for the product page, a vertical clip of someone holding it for TikTok and Reels, an unboxing. Our &lt;a href="https://refvid.com/ecommerce-video" rel="noopener noreferrer"&gt;ecommerce video guide&lt;/a&gt; covers which format goes where.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One light type, no mixing.&lt;/li&gt;
&lt;li&gt;Plain curved backdrop, product well forward.&lt;/li&gt;
&lt;li&gt;Main lens, no filters, exposure locked.&lt;/li&gt;
&lt;li&gt;Front, three-quarter, side, back, logo close-up, plus one in-use shot.&lt;/li&gt;
&lt;li&gt;Colors match across the set; one set per colorway.&lt;/li&gt;
&lt;li&gt;Logo sharp at full size, checked on a big screen, not the phone.&lt;/li&gt;
&lt;li&gt;Hero angle uploaded first, 3 to 5 photos in total.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Side effect: these are the photos every shop wants anyway, so one afternoon at the window covers both the listing and the video. If your output still drifts, tell me in the comments what broke.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>video</category>
      <category>tutorial</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>How we keep one character's face the same across AI video shots (Kling reference-to-video, with code)</title>
      <dc:creator>Louis Chi</dc:creator>
      <pubDate>Sat, 24 Oct 2026 13:59:29 +0000</pubDate>
      <link>https://dev.to/ref_vid/how-we-keep-one-characters-face-the-same-across-ai-video-shots-kling-reference-to-video-with-1koi</link>
      <guid>https://dev.to/ref_vid/how-we-keep-one-characters-face-the-same-across-ai-video-shots-kling-reference-to-video-with-1koi</guid>
      <description>&lt;p&gt;If you've built anything on top of a text-to-video model, you've hit this: the first clip is great, the second has a slightly different nose, and by the fifth it's a different person. A prompt like "a woman with a copper-red bob and an olive jacket" fits millions of people, and the model picks a new one on every request.&lt;/p&gt;

&lt;p&gt;I run &lt;a href="https://refvid.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=consistency-post" rel="noopener noreferrer"&gt;RefVid&lt;/a&gt;, a small tool built around one idea: you save a character or a product once, as a few photos, and every clip after that is generated from exactly those photos. This post covers what that takes in code. We use Kling's reference-to-video endpoints through fal's queue API, and everything below comes from our production code and our own test clips.&lt;/p&gt;

&lt;h2&gt;
  
  
  Words alone drift; photos hold
&lt;/h2&gt;

&lt;p&gt;We started by measuring the problem. We took one invented character, Mia, and generated the same three scenes twice on Kling 3.0 Omni, 5 seconds each:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prompt only, with Mia described in as much detail as we could fit (hair, freckles, earrings, jacket).&lt;/li&gt;
&lt;li&gt;The same scene prompts with no appearance words at all, plus four reference photos of Mia attached.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F801jj7fw4zz2p9wc2laa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F801jj7fw4zz2p9wc2laa.jpg" alt="Prompt-only kitchen clip: the character is described in words" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Prompt only. A copper-red bob and an olive jacket, but not quite the same woman as in the other scenes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flceomei2p654fgerscur.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flceomei2p654fgerscur.jpg" alt="The same kitchen scene with four reference photos attached" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Four reference photos, no appearance words in the prompt. The same face in every scene.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The prompt-only set cost $1.26 for three clips, and each one gives you a different person who matches the description. The reference set keeps her. The full side-by-side is on our &lt;a href="https://refvid.com/consistent-character-ai-video?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=consistency-post" rel="noopener noreferrer"&gt;consistent character guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What we took from it: once you attach references, stop describing the person in the prompt. When the words and the photos disagree, the model blends them, and the blend is exactly the drift you were trying to fix.&lt;/p&gt;
&lt;h2&gt;
  
  
  The request shape: elements, not just images
&lt;/h2&gt;

&lt;p&gt;Kling's reference-to-video takes subjects as &lt;em&gt;elements&lt;/em&gt;. An element is one frontal image plus extra views of the same subject. The prompt points at it as &lt;code&gt;@Element1&lt;/code&gt;, &lt;code&gt;@Element2&lt;/code&gt;, and so on. Here is the core of how we turn a saved subject into an element (simplified from our provider):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_ELEMENT_IMAGES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// one frontal + up to three extra views per element&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;frontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageUrls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;frontal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;at least one reference image is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;views&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MAX_ELEMENT_IMAGES&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// reference_image_urls needs at least one image, so a one-photo subject repeats its frontal view&lt;/span&gt;
    &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;frontal_image_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;frontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reference_image_urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;views&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;frontal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// photos beyond four go in as general references instead of being dropped&lt;/span&gt;
    &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MAX_ELEMENT_IMAGES&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things we learned the hard way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order matters.&lt;/strong&gt; The first image is treated as the frontal view, so make it your sharpest, most evenly lit, straight-on shot. A three-quarter view in that slot gives you a slightly turned face in every clip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One photo still works, but it has to be sent twice.&lt;/strong&gt; The endpoint wants at least one extra view, so a single-image subject sends its frontal again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overflow goes to &lt;code&gt;image_urls&lt;/code&gt;.&lt;/strong&gt; If someone uploads five photos, the fifth still helps as a plain reference instead of being silently ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The prompt must name every element
&lt;/h2&gt;

&lt;p&gt;If the prompt never mentions &lt;code&gt;@Element1&lt;/code&gt;, the model is free to ignore the photos. People don't write &lt;code&gt;@Element1&lt;/code&gt;, though. They write "Mia pours coffee". So before a prompt goes out, we swap each subject's name for its token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// "Mia holds NOIR 07 and says \"Hi, I'm Mia\""&lt;/span&gt;
&lt;span class="c1"&gt;//   → "@Element1 holds @Element2 and says \"Hi, I'm Mia\""&lt;/span&gt;
&lt;span class="nf"&gt;bindSubjects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NOIR 07&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The details are where it breaks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Whole words only.&lt;/strong&gt; "Mia" must not match inside "Miami". We use Unicode-aware boundaries, &lt;code&gt;(?&amp;lt;![\p{L}\p{N}])&lt;/code&gt; before and &lt;code&gt;(?![\p{L}\p{N}])&lt;/code&gt; after. They're skipped for Chinese, Japanese and Thai, where words have no spaces around them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not inside quoted dialogue.&lt;/strong&gt; Kling 4 clips have sound, and if the swap reaches the spoken line, the voice literally says "at Element one". Text inside &lt;code&gt;"…"&lt;/code&gt;, &lt;code&gt;“…”&lt;/code&gt;, &lt;code&gt;„…“&lt;/code&gt;, &lt;code&gt;«…»&lt;/code&gt; and &lt;code&gt;「…」&lt;/code&gt; is left alone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unnamed subjects get prefixed.&lt;/strong&gt; If a subject is attached but never named, its token is put at the start of the prompt so the model still uses it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect authors who already use tokens.&lt;/strong&gt; If a prompt already contains &lt;code&gt;@Element1&lt;/code&gt;, we leave it untouched.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Long sequences: split, then chain
&lt;/h2&gt;

&lt;p&gt;Faces hold up best in short clips. Drift creeps in as the camera moves and the face turns to angles the references don't cover. So instead of one long generation, we do two things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-shot requests.&lt;/strong&gt; Kling accepts a &lt;code&gt;multi_prompt&lt;/code&gt; list, one prompt per shot, and splits the duration between them. On Kling 4, each shot's prompt is capped at 512 characters. Names and translations can push a shot over that cap, so in that case we send one prompt that lists the shots in order rather than let the request fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shotsFit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shots&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shotsFit&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;multi_prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shots&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Shot &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; s): &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Chained clips.&lt;/strong&gt; For a series, we start each clip from the last frame of the previous one (&lt;code&gt;start_image_url&lt;/code&gt;) and attach the same element every time. We made a four-shot running-shoe sequence this way: four 5-second clips at $0.42 each, plus $0.03 to pull the last frames out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flbrqr54366snch2ah4iu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flbrqr54366snch2ah4iu.jpg" alt="Shot 1 of a chained four-shot sequence" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Shot 1. Each of the next shots starts from the previous shot's last frame, with the same product element attached.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkxq33rzg9ob1vz7ybkuj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkxq33rzg9ob1vz7ybkuj.jpg" alt="Shot 4 of the same sequence" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Shot 4. Same shoe, same path, same light direction.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The start frame carries the scene and the light. The element carries the identity. You need both: with only the start frame, the identity slips once the camera moves away from what that frame showed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Products are harder than faces
&lt;/h2&gt;

&lt;p&gt;People forgive a slightly different jaw. Nobody forgives a misspelled logo. For products:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shoot three photos on a plain backdrop: the hero angle, a three-quarter view, and a close-up where the label fills the frame.&lt;/li&gt;
&lt;li&gt;Put the label in the prompt as a fact about the scene, not as a description: "the LUMEN label faces the camera and stays readable".&lt;/li&gt;
&lt;li&gt;Keep the label large in frame in at least one shot. Small text in a wide shot has too few pixels to come out right.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F64c6a888q5specp0qyep.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F64c6a888q5specp0qyep.jpg" alt="LUMEN serum bottle on a bathroom shelf, generated from three reference photos" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;LUMEN is a serum we invented for testing. Three reference photos, Kling 3.0 Omni; the label carries over into each scene.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Plumbing notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use the queue and a webhook, not a blocking call.&lt;/strong&gt; A 3-second 720p Kling 4 clip with sound took about 80 seconds to generate for us. We submit to &lt;code&gt;queue.fal.run/&amp;lt;model&amp;gt;?fal_webhook=&amp;lt;url&amp;gt;&lt;/code&gt;, verify the webhook signature, and keep a status poll as a fallback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat a 5xx on the result fetch as retryable.&lt;/strong&gt; A failed fetch of the result doesn't mean the job failed. We only mark a generation failed when fal reports an error for the job itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the webhook idempotent.&lt;/strong&gt; Record the request id before you act on it. Webhooks get delivered twice, and you don't want to refund or charge twice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd tell anyone building this
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Version the reference set. Most "the face changed" bug reports come down to clip 1 and clip 4 having been made from different photos.&lt;/li&gt;
&lt;li&gt;Strip appearance words from prompts once references are attached.&lt;/li&gt;
&lt;li&gt;Keep clips short and cut between them. Chaining 5-second clips beats one 15-second clip for identity.&lt;/li&gt;
&lt;li&gt;Test with an invented character, so you know what "the same person" means.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to try it without building any of this, &lt;a href="https://refvid.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=consistency-post" rel="noopener noreferrer"&gt;RefVid&lt;/a&gt; does all of the above behind one upload. Ask in the comments about the request shapes or the regexes. I'm happy to go into more detail.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>video</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
