<?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: rucai zhou</title>
    <description>The latest articles on DEV Community by rucai zhou (@rucai_zhou_53a3a24af095b8).</description>
    <link>https://dev.to/rucai_zhou_53a3a24af095b8</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%2F4082415%2F9186f140-7129-4603-aad2-25b5cdadadca.png</url>
      <title>DEV Community: rucai zhou</title>
      <link>https://dev.to/rucai_zhou_53a3a24af095b8</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rucai_zhou_53a3a24af095b8"/>
    <language>en</language>
    <item>
      <title>What I Learned Wiring an AI Video Model Into a Content Pipeline</title>
      <dc:creator>rucai zhou</dc:creator>
      <pubDate>Tue, 18 Aug 2026 02:12:53 +0000</pubDate>
      <link>https://dev.to/rucai_zhou_53a3a24af095b8/what-i-learned-wiring-an-ai-video-model-into-a-content-pipeline-54mp</link>
      <guid>https://dev.to/rucai_zhou_53a3a24af095b8/what-i-learned-wiring-an-ai-video-model-into-a-content-pipeline-54mp</guid>
      <description>&lt;p&gt;We needed short product videos on a schedule our two-person team could not hit by hand. The tool that ended up doing the heavy lifting was &lt;a href="https://runwayaleph.com/" rel="noopener noreferrer"&gt;Runway Aleph&lt;/a&gt;, an in-context video model — and for the headshots that go alongside them we use &lt;a href="https://beardlessfilter.com/" rel="noopener noreferrer"&gt;BeardlessAI&lt;/a&gt;, a free tool to remove beards from photos. This is a writeup of the integration, including the parts that did not work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with generate-first tools
&lt;/h2&gt;

&lt;p&gt;Our first attempt used text-to-video. Type a description, get a clip. It demoed beautifully and was useless in production for one reason: &lt;strong&gt;no continuity&lt;/strong&gt;. Every generation was independent. Two clips of "the same" product were two different products. You cannot cut that together.&lt;/p&gt;

&lt;p&gt;In-context models work differently. You pass real footage as context and describe a bounded change against it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input:  product_shot_v3.mp4
prompt: "Remove the price tag on the right side of the box.
         Keep the box, the surface, and the lighting unchanged."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The job is not invention. It is a scoped edit to something that already exists. That is what made it fit an actual pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the pipeline looks like
&lt;/h2&gt;

&lt;p&gt;Roughly four stages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;raw footage ──▶ shot manifest ──▶ edit passes ──▶ QC gate ──▶ publish
                  (JSON)          (one op each)   (human)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shot manifest was the part I underestimated. It is just a JSON file describing each shot and the operations queued against it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"shot_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hero_02"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"raw/hero_02.mp4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ops"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"price tag, right of box"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"preserve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"box, surface, lighting"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"relight"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"overcast afternoon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;"preserve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"subject position, framing"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things this bought us. First, ops are &lt;strong&gt;replayable&lt;/strong&gt; — when we changed our mind about the look, we edited the manifest and re-ran rather than reconstructing what we did from memory. Second, it forced one operation per entry, which turned out to matter a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: one operation per pass, always
&lt;/h2&gt;

&lt;p&gt;I tried batching. &lt;code&gt;"Remove the price tag, relight it as an overcast afternoon, and add a plant on the left"&lt;/code&gt; produced output where all three happened, all three badly.&lt;/p&gt;

&lt;p&gt;Split into three passes, each one was clean. More calls, more credits, better results — and crucially, when pass two looked wrong I knew it was pass two. Batched prompts are not debuggable. You get a bad frame and no idea which clause caused it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: &lt;code&gt;preserve&lt;/code&gt; is not optional
&lt;/h2&gt;

&lt;p&gt;Early prompts only said what to change. The model kept over-reaching — remove one object, and the background subtly re-renders, so the shot no longer cuts against its neighbours.&lt;/p&gt;

&lt;p&gt;Adding an explicit preserve clause fixed most of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- "Remove the car"
&lt;/span&gt;&lt;span class="gi"&gt;+ "Remove the silver car at the left edge of frame.
+  Keep the pedestrians, storefront and lighting unchanged."
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That diff is responsible for more quality improvement than every other change we made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: the QC gate has to be human, and at full res
&lt;/h2&gt;

&lt;p&gt;We tried to automate QC with a similarity check against the source. It caught gross failures and missed everything that mattered.&lt;/p&gt;

&lt;p&gt;The failures that actually hurt are semantic: a hand with the wrong number of fingers, signage that became plausible gibberish, a reflection that no longer matches the object casting it. Structural similarity scores these as fine.&lt;/p&gt;

&lt;p&gt;Failure clusters, reliably:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Region&lt;/th&gt;
&lt;th&gt;Failure rate&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hands / fingers&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Still the worst case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text &amp;amp; signage&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Degrades to convincing nonsense&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reflections, glass, chrome&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Physically inconsistent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rigid geometry&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Small warps are very visible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frame edges&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Least surrounding context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We now gate on a human reviewing those five regions &lt;strong&gt;at full resolution&lt;/strong&gt;. Preview-window review passed shots that fell apart on a large screen, which we discovered in a client review rather than in QC. Once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: cache aggressively, prompts are deterministic-ish enough
&lt;/h2&gt;

&lt;p&gt;Same source plus same prompt gets you close enough to the same output that re-running is usually waste. We key a content-addressed cache on &lt;code&gt;hash(source_file + prompt + params)&lt;/code&gt;. During a week of iteration that cut spend by more than half, because most re-runs are re-runs of a shot you already settled.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would tell someone starting
&lt;/h2&gt;

&lt;p&gt;Do not rebuild your pipeline around this. Add it at &lt;strong&gt;one&lt;/strong&gt; stage — object removal is the highest-value, lowest-risk entry point — and prove it survives QC before extending.&lt;/p&gt;

&lt;p&gt;And benchmark honestly. Compare against your existing process including review time, not just generation time. Generation is fast. Review is not, and review is where the real cost sits.&lt;/p&gt;

&lt;p&gt;The gain here is not that impossible things became possible. It is that expensive things got cheap enough to attempt, which is quieter and more useful.&lt;/p&gt;

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