<?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: zhifen zhu</title>
    <description>The latest articles on DEV Community by zhifen zhu (@zhifen_zhu_3df68293e0ddb6).</description>
    <link>https://dev.to/zhifen_zhu_3df68293e0ddb6</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%2F4157372%2F3a71799c-0939-404d-886c-e1d75fccc02b.png</url>
      <title>DEV Community: zhifen zhu</title>
      <link>https://dev.to/zhifen_zhu_3df68293e0ddb6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zhifen_zhu_3df68293e0ddb6"/>
    <language>en</language>
    <item>
      <title>Building a Focused AI Video Workflow for One or Two Portraits</title>
      <dc:creator>zhifen zhu</dc:creator>
      <pubDate>Sat, 10 Oct 2026 02:20:27 +0000</pubDate>
      <link>https://dev.to/zhifen_zhu_3df68293e0ddb6/building-a-focused-ai-video-workflow-for-one-or-two-portraits-1nj7</link>
      <guid>https://dev.to/zhifen_zhu_3df68293e0ddb6/building-a-focused-ai-video-workflow-for-one-or-two-portraits-1nj7</guid>
      <description>&lt;p&gt;When an AI video tool is built around a known reference scene, the input form is part of the product. Users should not have to write a prompt that describes a choreography the system already knows. They should only need to answer one question: which person should appear in each role?&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://airumpelstiltskin.org/" rel="noopener noreferrer"&gt;Rumpelstiltskin AI Video&lt;/a&gt; around that idea. It creates a personalized version of the Rumpelstiltskin tiptoe dance video from one or two portraits. The reference scene supplies the dance and camera direction; the uploaded portraits supply the characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Make the character mapping explicit
&lt;/h2&gt;

&lt;p&gt;The UI has two modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dancer Only&lt;/strong&gt;: one portrait replaces the tiptoe dancer, while the original maiden remains in the scene.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dancer &amp;amp; Maiden&lt;/strong&gt;: two separate portraits replace the two characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That distinction is more useful than a blank prompt box. It also gives the backend a small, predictable input model: photoMode is either one or two, and the second file is required only in the two-photo mode.&lt;/p&gt;

&lt;p&gt;The API accepts JPG, PNG, and WebP files up to 20 MB each. It also validates the original reference duration, the requested resolution, and the aspect ratio before sending work to the provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Make generation requests idempotent
&lt;/h2&gt;

&lt;p&gt;Video generation is asynchronous, and users can double-click. The browser creates an idempotency key for each attempt. The /api/generate/video route claims that key before reserving credits, so a repeated request cannot create a second paid job accidentally.&lt;/p&gt;

&lt;p&gt;The response returns a request ID and an IN_QUEUE status. The client then checks /api/generate/video/status and renders the actual state instead of pretending that the video is ready. The visible states are intentionally simple: queued, processing, completed, or failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Keep the provider workflow in stages
&lt;/h2&gt;

&lt;p&gt;The server uploads the portrait files and the silent reference video, runs image safety checks, and submits the reference-to-video task to Seedance 2.5 through KIE. The initial provider request uses generate_audio: false. When the video task completes, a separate audio step merges the original reference audio into the result.&lt;/p&gt;

&lt;p&gt;This separation makes failures easier to reason about. A video task can complete while audio finishing is still pending, and each stage has its own status and error handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Treat credits as a reservation
&lt;/h2&gt;

&lt;p&gt;A paid generation uses 100 credits at 480P or 170 credits at 720P. The server checks the user session and available balance, deducts the required amount, and records the generation request before calling the provider.&lt;/p&gt;

&lt;p&gt;If the provider fails or the audio finishing step cannot complete, the failed generation path returns the generation credits automatically. That is a credit return, not a cash refund. The UI says this directly because billing language should match the database behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Keep the product promise narrow
&lt;/h2&gt;

&lt;p&gt;The tool does not claim to generate arbitrary videos from arbitrary prompts. It does one reference-driven transformation: your portrait becomes a character in the original tiptoe dance. Users log in, buy a one-time credit pack, choose 480P or 720P, and receive an MP4 download with the original reference audio when processing succeeds.&lt;/p&gt;

&lt;p&gt;That narrow promise affects the whole implementation: the form is short, the validation is strict, the request states are visible, and the pricing copy does not suggest a free or unlimited generator.&lt;/p&gt;

&lt;p&gt;If you want to try the workflow, the product is available at &lt;a href="https://airumpelstiltskin.org/" rel="noopener noreferrer"&gt;airumpelstiltskin.org&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>nextjs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Two-photo inputs beat a blank prompt: building Hotel Lobby AI with Next.js</title>
      <dc:creator>zhifen zhu</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:10:36 +0000</pubDate>
      <link>https://dev.to/zhifen_zhu_3df68293e0ddb6/two-photo-inputs-beat-a-blank-prompt-building-hotel-lobby-ai-with-nextjs-fo9</link>
      <guid>https://dev.to/zhifen_zhu_3df68293e0ddb6/two-photo-inputs-beat-a-blank-prompt-building-hotel-lobby-ai-with-nextjs-fo9</guid>
      <description>&lt;p&gt;I built &lt;a href="https://hotel-lobby-ai.org" rel="noopener noreferrer"&gt;Hotel Lobby AI&lt;/a&gt;, a focused tool that turns two separate photos into an orange-booth rap duo video with generated audio. Here are a few implementation and interface decisions from a small Next.js, React, and TypeScript project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give each upload a meaning
&lt;/h2&gt;

&lt;p&gt;Instead of one generic image picker, the interface asks for a left performer and a right performer. The implementation keeps two separate &lt;code&gt;File&lt;/code&gt; values and two preview URLs. That makes the intended placement explicit before generation starts.&lt;/p&gt;

&lt;p&gt;The request also preserves the distinction: the multipart form has separate &lt;code&gt;person1&lt;/code&gt; and &lt;code&gt;person2&lt;/code&gt; fields, and the server validates both images. The useful idea is not the field names themselves; it is making the UI and request contract tell the same story.&lt;/p&gt;

&lt;h2&gt;
  
  
  A preview has a lifecycle
&lt;/h2&gt;

&lt;p&gt;The photo previews use &lt;code&gt;URL.createObjectURL&lt;/code&gt;. In a React component, replacing a selected file should also retire its old preview URL. Keeping preview state separate from output state helps avoid showing a generated result where the source photo is expected.&lt;/p&gt;

&lt;p&gt;For anyone building an upload-driven tool, I would check three states early: a new file selection, a replacement selection, and a missing required file. Those small transitions are easy to overlook when most attention goes to the model call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expose useful choices, keep the scene focused
&lt;/h2&gt;

&lt;p&gt;The user can choose duration, 480P or 720P quality, and portrait or landscape format. The prepared performance workflow removes the need to write a prompt or edit a timeline. This is intentionally a narrow creative tool, not an attempt to expose every possible model parameter.&lt;/p&gt;

&lt;p&gt;The output includes generated audio and can be downloaded. Faces may vary from the source photos, so clear input guidance and realistic expectations matter. People should use photos they have permission to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explain the trial before generation
&lt;/h2&gt;

&lt;p&gt;Google sign-in is required. New users receive 20 credits, enough for one 4-second 480P trial. Further generations use credits available through one-time purchases. I prefer stating those conditions directly instead of calling the entire service unlimited or completely free.&lt;/p&gt;

&lt;p&gt;You can try the workflow at &lt;a href="https://hotel-lobby-ai.org" rel="noopener noreferrer"&gt;https://hotel-lobby-ai.org&lt;/a&gt;. I would welcome feedback on the clarity of the two-photo inputs, or how you structure upload state in your own React projects.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nextjs</category>
      <category>react</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
