<?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: kemihu</title>
    <description>The latest articles on DEV Community by kemihu (@kemihu).</description>
    <link>https://dev.to/kemihu</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%2F4222471%2Fd07566f4-996f-4b46-8e0e-f70299431ce0.png</url>
      <title>DEV Community: kemihu</title>
      <link>https://dev.to/kemihu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kemihu"/>
    <language>en</language>
    <item>
      <title>Building a 5-seat Outstanding Tiny Desk AI generator: only re-render the shots you're in</title>
      <dc:creator>kemihu</dc:creator>
      <pubDate>Tue, 03 Nov 2026 02:06:02 +0000</pubDate>
      <link>https://dev.to/kemihu/building-a-5-seat-outstanding-tiny-desk-ai-generator-only-re-render-the-shots-youre-in-2e4p</link>
      <guid>https://dev.to/kemihu/building-a-5-seat-outstanding-tiny-desk-ai-generator-only-re-render-the-shots-youre-in-2e4p</guid>
      <description>&lt;p&gt;The "Outstanding" Tiny Desk AI meme puts you and your friends into Charlie Wilson's 2023 Tiny Desk performance. I built a generator for it, &lt;a href="https://tinydeskai.run/" rel="noopener noreferrer"&gt;Tiny Desk AI (tinydeskai.run)&lt;/a&gt;. This post covers the parts that weren't obvious: how the cut is split into shots, why we only re-render some of them, the prompt that keeps faces from turning back into dogs, and how the clips are stitched to frame-exact lengths.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: this is my product. Fan-made parody, not affiliated with NPR or Charlie Wilson.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Don't generate the whole video. Generate shots.
&lt;/h2&gt;

&lt;p&gt;Asking a video model to produce an 18-second, four-cut band performance with five specific faces in one go gives you drift: faces change between cuts, the sax player swaps seats, the timing slides off the song.&lt;/p&gt;

&lt;p&gt;So the template is a fixed edit of four shots, 530 frames at 30 fps:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shot&lt;/th&gt;
&lt;th&gt;Frames&lt;/th&gt;
&lt;th&gt;Seconds&lt;/th&gt;
&lt;th&gt;On screen&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The band&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;5.33&lt;/td&gt;
&lt;td&gt;keys, back left, back right&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The big laugh&lt;/td&gt;
&lt;td&gt;190&lt;/td&gt;
&lt;td&gt;6.33&lt;/td&gt;
&lt;td&gt;lead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sax solo&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;3.40&lt;/td&gt;
&lt;td&gt;sax, keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fists up&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;2.60&lt;/td&gt;
&lt;td&gt;keys, back left, back right&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each shot has a base clip — a version we generated once with fictional performers (a puppy band and a people band) and no logos. Every shot also stores a plain-English description of each seat as it appears &lt;em&gt;in that shot&lt;/em&gt;:&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="nx"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;sax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the corgi playing the saxophone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the beagle in the white cap at the lower right corner&lt;/span&gt;&lt;span class="dl"&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;The same keyboard player is "seated at the red keyboard in front" in the wide shot and "at the lower right corner" in the sax close-up. Describing the seat per shot, rather than once globally, was the biggest single fix for wrong-person swaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Only render the shots that contain a swapped seat
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shotsToRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;band&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;band&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;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;shot&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;roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;role&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;shot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;role&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;ul&gt;
&lt;li&gt;Lead only → 1 shot rendered (the big laugh); 3 shots reuse the base clip&lt;/li&gt;
&lt;li&gt;Back row only → 2 shots&lt;/li&gt;
&lt;li&gt;Whole band → all 4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why one price covers 1 to 5 people: cost tracks shots, not faces, and the worst case is bounded at four renders.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The prompt
&lt;/h2&gt;

&lt;p&gt;We use Kling 4.0 reference-to-video (via Kie). The base clip goes in as &lt;code&gt;@video_1&lt;/code&gt;, the face photos as &lt;code&gt;@image_1..N&lt;/code&gt; in the order the seats appear in that shot. The prompt is assembled per shot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use @video_1 as the exact reference and keep everything identical: camera
movement, framing, cuts, lighting, background, props, instruments, body
motion, gestures, mouth movement and timing.
Swap only these heads: the head of the corgi playing the saxophone becomes
the person in @image_1; the head of the beagle in the white cap at the lower
right corner becomes the person in @image_2.
Use each photo only for the face, hair and skin tone. Every swapped person
keeps exactly the outfit, over-ear headphones and headset microphone they
wear in @video_1, in every frame; ignore the clothes in the photos.
Each swapped head is a complete realistic human head, even when it is only
partly in frame: no dog snout, dog nose, dog ears or fur left anywhere on
them, singing with the same mouth movement and expression as the reference.
Every other band member stays exactly as in @video_1. No text, no logos.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every sentence is there because of a failure we saw:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"keep everything identical … timing"&lt;/strong&gt; — without it the model re-choreographs and the mouth stops matching the song&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"ignore the clothes in the photos"&lt;/strong&gt; — people upload selfies in hoodies; the hoodie used to replace the stage outfit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"no dog snout … even when partly in frame"&lt;/strong&gt; — in the puppy band, heads cut off by the frame edge kept a dog nose&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Every other band member stays exactly"&lt;/strong&gt; — otherwise unswapped puppies sometimes became humans too&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the prompts, for both bands → &lt;a href="https://tinydeskai.run/guides/tiny-desk-ai-prompt" rel="noopener noreferrer"&gt;Tiny Desk AI video prompts&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Stitching to frame-exact lengths
&lt;/h2&gt;

&lt;p&gt;The API takes whole seconds, so each request asks for the shot length rounded &lt;strong&gt;up&lt;/strong&gt; (6.33 s → 7 s). The stitcher then trims each clip to its exact frame count, joins the four, and lays the song under the full 17.667 s cut. The base clips carry their slice of the song so the model lip-syncs to it; the stitcher only keeps their picture.&lt;/p&gt;

&lt;p&gt;Output: 720p, 9:16, a version with the song and a silent copy for people who want to add the audio on TikTok or Reels themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Product decisions that came from the pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One price for 1–5 people&lt;/strong&gt; ($9.99 per video, no subscription) because the cost ceiling is four shots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failed renders return credits&lt;/strong&gt; automatically, since a failed shot is detectable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No free personal preview&lt;/strong&gt; — every preview would be a paid render of the hardest shot. Samples are free to watch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Five fixed seats&lt;/strong&gt; (lead, keys, back left, back right, sax) instead of free-form placement, because per-shot seat descriptions are what make swaps reliable&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it / read more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Generator: &lt;a href="https://tinydeskai.run/" rel="noopener noreferrer"&gt;https://tinydeskai.run/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Real one-photo result next to its input: &lt;a href="https://tinydeskai.run/examples/one-photo-lead" rel="noopener noreferrer"&gt;https://tinydeskai.run/examples/one-photo-lead&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Shot-by-shot template: &lt;a href="https://tinydeskai.run/outstanding-tiny-desk-ai-template" rel="noopener noreferrer"&gt;https://tinydeskai.run/outstanding-tiny-desk-ai-template&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Step-by-step guide: &lt;a href="https://tinydeskai.run/guides/how-to-make-tiny-desk-ai-video" rel="noopener noreferrer"&gt;https://tinydeskai.run/guides/how-to-make-tiny-desk-ai-video&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions about the pipeline are welcome in the comments.&lt;/p&gt;

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