<?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: Yina Lin</title>
    <description>The latest articles on DEV Community by Yina Lin (@yina_lin_a42a84dfee976777).</description>
    <link>https://dev.to/yina_lin_a42a84dfee976777</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%2F4210400%2F63d0dc1b-5c53-4ea0-823b-5c109ea5ec0a.png</url>
      <title>DEV Community: Yina Lin</title>
      <link>https://dev.to/yina_lin_a42a84dfee976777</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yina_lin_a42a84dfee976777"/>
    <language>en</language>
    <item>
      <title>Pre-flight checking photos before an image-to-video upload (a small Python script)</title>
      <dc:creator>Yina Lin</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:30:10 +0000</pubDate>
      <link>https://dev.to/yina_lin_a42a84dfee976777/pre-flight-checking-photos-before-an-image-to-video-upload-a-small-python-script-9lb</link>
      <guid>https://dev.to/yina_lin_a42a84dfee976777/pre-flight-checking-photos-before-an-image-to-video-upload-a-small-python-script-9lb</guid>
      <description>&lt;p&gt;Most image-to-video tools publish input limits, and most people ignore them until an upload fails. If you're helping friends make a short AI video from their photos, a quick local check saves a lot of "why won't it take my picture?" messages.&lt;/p&gt;

&lt;p&gt;This post walks through a small Python script that checks a folder of photos against a published set of limits, fixes the two problems you can fix automatically (orientation and file size), and flags the rest. I'll use the limits published by &lt;a href="https://gangnamstyleaivideo.org/" rel="noopener noreferrer"&gt;GangnamStyleAIVideo.org&lt;/a&gt;, a single-purpose web tool for the Gangnam Style AI trio trend, because they are documented clearly in its llms.txt. The same approach works for any tool; just change the constants.&lt;/p&gt;

&lt;h2&gt;
  
  
  The limits we're checking
&lt;/h2&gt;

&lt;p&gt;As published on the site (facts dated 2026-10-26), each video takes three photos, one person each, or one group photo of all three. Each file must be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JPG, PNG or WebP&lt;/li&gt;
&lt;li&gt;up to 4 MB&lt;/li&gt;
&lt;li&gt;300 to 5760 px per side&lt;/li&gt;
&lt;li&gt;a width-to-height ratio between 0.4 and 2.5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Photos only: no video, audio or text input. Those four rules are mechanical, so a script can check them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;You only need Pillow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;Pillow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# preflight.py: check photos against an upload spec
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ImageOps&lt;/span&gt;

&lt;span class="n"&gt;ALLOWED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WEBP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;MAX_BYTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4_000_000&lt;/span&gt;          &lt;span class="c1"&gt;# stricter reading of "4 MB"
&lt;/span&gt;&lt;span class="n"&gt;MIN_SIDE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAX_SIDE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5760&lt;/span&gt;
&lt;span class="n"&gt;MIN_RATIO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAX_RATIO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_size&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_BYTES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1e6&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB (max 4 MB)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;im&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageOps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exif_transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# size as it will display
&lt;/span&gt;        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MIN_SIDE&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_SIDE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; px is outside &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;MIN_SIDE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;MAX_SIDE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; px&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ratio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;MIN_RATIO&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;ratio&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;MAX_RATIO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ratio &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; outside &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;MIN_RATIO&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;MAX_RATIO&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Bake in orientation, cap the long side, save as JPEG.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;out_dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;im&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageOps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exif_transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;out_dir&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stem&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&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;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iterdir&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_dir&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="c1"&gt;# not an image at all
&lt;/span&gt;            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SKIP &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK   &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FIX  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;; &lt;/span&gt;&lt;span class="sh"&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="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fixed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fixed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;     -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OK&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;; &lt;/span&gt;&lt;span class="sh"&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="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it with &lt;code&gt;python3 preflight.py ./photos&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why each step is there
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;exif_transpose&lt;/code&gt;.&lt;/strong&gt; Phones often save a portrait photo as a landscape image with an orientation tag. If you measure the raw pixels, you get the ratio backwards. Applying the EXIF rotation first means you check the image the way people actually see it, and the fixed copy has the rotation baked in, so nothing downstream has to interpret the tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 4,000,000-byte limit.&lt;/strong&gt; "4 MB" can mean 4,000,000 bytes or 4 × 1024 × 1024. I don't know which one the server uses, so the script takes the stricter one. A false warning costs nothing; a rejected upload on mobile is annoying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;thumbnail((2048, 2048))&lt;/code&gt;.&lt;/strong&gt; A modern phone photo can be 4000 px or more on the long side and well over 4 MB. Capping the long side at 2048 keeps it far inside both the size and pixel limits while staying sharp enough for a face reference. &lt;code&gt;thumbnail&lt;/code&gt; keeps the aspect ratio and never upscales.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the script can't fix.&lt;/strong&gt; If an image is under 300 px on a side or has an extreme ratio (a screenshot of a chat, a panorama), resizing won't help. You need a different photo, so the script reports it and moves on rather than guessing a crop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checks a script can't do
&lt;/h2&gt;

&lt;p&gt;The mechanical rules are the easy part. For this kind of trio video, the published guidance also asks for things you have to check by eye:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;One person per photo&lt;/strong&gt;, face toward the camera; chest up is enough. If you use a single group photo instead, it should show exactly three people side by side with every face visible and nobody else in the frame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order matters.&lt;/strong&gt; The tool reads a group photo left to right, and the person in the middle holds the phone and sings first. With separate photos, each friend has their own slot (middle, left, right), so decide who goes in the middle before uploading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consent.&lt;/strong&gt; Everyone in the photos must be you or an adult who agreed to be in the video. Photos of celebrities or public figures are not allowed, and the site asks you to confirm consent before it renders.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Put those three items in the message asking friends for their photos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it before you pay
&lt;/h2&gt;

&lt;p&gt;The tool has no free tier; a 19-second Standard 480p video costs 100 credits, and the smallest pack is $9.99 for 100 credits. If a render fails, the credits go back to your balance automatically, but it's still nicer to get the inputs right the first time. The output is a 16:9 MP4 with an original beat, so plan to add the trend sound in TikTok when you post.&lt;/p&gt;

&lt;p&gt;The script is small on purpose: copy it, swap the constants for whatever tool you're using, and run it on the folder your friends' photos landed in. If you want the generator itself, it's at &lt;a href="https://gangnamstyleaivideo.org/" rel="noopener noreferrer"&gt;https://gangnamstyleaivideo.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was written with AI assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>video</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Picking the Right Photo for the ChatGPT Millionaire Meme: A Practical Walkthrough (and Its Honest Limits)</title>
      <dc:creator>Yina Lin</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:19:13 +0000</pubDate>
      <link>https://dev.to/yina_lin_a42a84dfee976777/picking-the-right-photo-for-the-chatgpt-millionaire-meme-a-practical-walkthrough-and-its-honest-3bpa</link>
      <guid>https://dev.to/yina_lin_a42a84dfee976777/picking-the-right-photo-for-the-chatgpt-millionaire-meme-a-practical-walkthrough-and-its-honest-3bpa</guid>
      <description>&lt;p&gt;If you have spent any time on short-video feeds lately, you have probably seen the ChatGPT millionaire skit. Someone types "how I become a millionaire in 30 days?" and the deadpan answer comes back: "Get a job." People now remake it with their own faces and, inevitably, their dogs and cats.&lt;/p&gt;

&lt;p&gt;This post is a walkthrough of one way to make that clip from a single photo, using an image-to-video tool built for exactly this meme. I'll focus on what actually decides the result, the photo you feed it, and be upfront about the limits.&lt;/p&gt;

&lt;p&gt;A quick disclosure first: the tool I describe, &lt;a href="https://millionaireaitrend.com/" rel="noopener noreferrer"&gt;Millionaire AI Trend&lt;/a&gt;, is an unofficial, fan-made web app. It is not affiliated with OpenAI or with the creator of the original skit. "ChatGPT" here only names the meme.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the tool works, in one paragraph
&lt;/h2&gt;

&lt;p&gt;You upload one photo. That photo is used as a face reference, not as the first frame, so the video does not literally "animate" your picture. Instead, the model (ByteDance Seedance 2.5) generates a fresh 13-second vertical 9:16 clip of that person or pet acting out the skit, with a newly generated male or female voice. There is no prompt to write and no script to edit: the scene, timing and dialogue are fixed, and the lines are always the original English ones. You only choose who plays the part. Rendering usually takes a few minutes and runs in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Decide who is going to star
&lt;/h2&gt;

&lt;p&gt;There are three allowed choices: yourself, an adult who has agreed to be in it, or your own pet. Before rendering, you confirm that everyone in the photo is you or a consenting adult, and that you won't use the clip to mislead or harass anyone.&lt;/p&gt;

&lt;p&gt;Two categories are off the table: photos of celebrities or public figures, and photos of children. That is a reasonable rule for a face-driven generator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Pick a photo that gives the model enough to work with
&lt;/h2&gt;

&lt;p&gt;Because the photo is only a reference, the model needs to "read" the face clearly. These general photo habits help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Face the camera.&lt;/strong&gt; A front-facing shot is the stated recommendation. Profiles and three-quarter turns give the model less to work with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One subject.&lt;/strong&gt; A group shot leaves the model guessing who the star is. Crop to one person or one animal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Even light.&lt;/strong&gt; Soft daylight beats a harsh flash or a dim room. Strong shadows across the face can be misread as features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No heavy filters.&lt;/strong&gt; Beauty filters and stylized edits change the face you are asking it to reproduce.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For pets, the same rules apply with a twist: you want the animal looking roughly at the lens, eyes visible, with the face not hidden by a toy or a blanket. A dog mid-sneeze is funny, but a weak reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  The technical requirements
&lt;/h3&gt;

&lt;p&gt;The upload accepts JPG, PNG or WebP, up to 4 MB, between 300 and 5760 pixels per side, with a width-to-height ratio between 0.4 and 2.5. Video, audio and text-only inputs are not accepted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Choose voice and resolution
&lt;/h2&gt;

&lt;p&gt;You pick a male or female voice that fits the face; it is generated fresh, and no real person's voice is cloned. The original skit's footage and audio are not used either.&lt;/p&gt;

&lt;p&gt;Then choose quality: &lt;strong&gt;Standard 480p&lt;/strong&gt; or &lt;strong&gt;HD 720p&lt;/strong&gt;. Both come out as 13-second vertical 9:16 MP4s with sound.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Render, wait, download
&lt;/h2&gt;

&lt;p&gt;You need a signed-in account with a verified email. It works in a phone or desktop browser, with no app to install. Hit the make button, wait a few minutes, and the clip appears in your "My videos" list, where only your account can view or download it. There is no public gallery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest limits
&lt;/h2&gt;

&lt;p&gt;Here is the full list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It is paid, with no free tier.&lt;/strong&gt; There is no free trial and no signup credit. You buy one-time credit packs; nothing renews and credits do not expire. The smallest pack is $9.90 for 100 credits, and one Standard 480p video costs 80 credits (about $7.92). HD 720p costs 180 credits per video. Bigger packs cost less per video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failed renders are refunded, nothing else is.&lt;/strong&gt; Credits are held when a video starts and only charged on delivery; a failed render returns them automatically. Otherwise, purchases are final.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One meme, one length.&lt;/strong&gt; Every clip is 13 seconds. You cannot change the question, the answer, the language of the dialogue, or add a song.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is not an editor.&lt;/strong&gt; It cannot trim, extend or restyle an existing video, and it does not produce still images.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No celebrities, public figures or children.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Photos are deleted after 30 days.&lt;/strong&gt; Uploaded photos are removed automatically 30 days after upload. Finished videos stay in your account until you delete them or the account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Is it worth it?
&lt;/h2&gt;

&lt;p&gt;If you want the joke with your face, a friend's, or your pet's, and you don't want to film anything or wrangle a general-purpose video model with prompts, a single-purpose tool like this is the shortest path. If you want something flexible, a custom script, or a longer clip, it simply isn't built for that. The pet version is arguably where the meme shines most; the dog version has its own page at &lt;a href="https://millionaireaitrend.com/chatgpt-millionaire-dog" rel="noopener noreferrer"&gt;https://millionaireaitrend.com/chatgpt-millionaire-dog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Either way, spend the extra minute on the photo. It is the one input you control.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was written with AI assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>video</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Posting a 16:9 Clip to Vertical Feeds: A Practical Workflow for Trend Videos</title>
      <dc:creator>Yina Lin</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:13:21 +0000</pubDate>
      <link>https://dev.to/yina_lin_a42a84dfee976777/posting-a-169-clip-to-vertical-feeds-a-practical-workflow-for-trend-videos-5alg</link>
      <guid>https://dev.to/yina_lin_a42a84dfee976777/posting-a-169-clip-to-vertical-feeds-a-practical-workflow-for-trend-videos-5alg</guid>
      <description>&lt;p&gt;Many AI trend videos come out in landscape, but most short-video feeds expect vertical. Getting the file is only half the job. You still have to fit a 16:9 clip into TikTok, Reels, Shorts and X, add the soundtrack, and write an honest caption. This post covers that last stretch, using a 15-second party clip from the Burning Bridges trend as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you're starting with
&lt;/h2&gt;

&lt;p&gt;The example clip comes from &lt;a href="https://burningbridgestrend.org/" rel="noopener noreferrer"&gt;Burning Bridges Trend&lt;/a&gt;, an unofficial fan tool that turns one photo into a party scene. Its output decides everything below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MP4, 15 seconds, 16:9&lt;/strong&gt;, at 480p or 720p.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The audio is not the song.&lt;/strong&gt; It's an original slow instrumental beat with party sounds (crowd, laughter, clinking glasses). There are no vocals or lyrics. If you want the trend's song, you add it yourself when you post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The person from the photo is in the middle of the frame.&lt;/strong&gt; Everyone else in the scene is AI-generated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With any tool, check the same three things: aspect ratio, what the audio is, and where the subject sits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Decide on landscape or vertical
&lt;/h2&gt;

&lt;p&gt;A 16:9 clip in a 9:16 feed has two basic options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A: keep the full landscape frame.&lt;/strong&gt; The clip plays with bands above and below (Step 2 fills them). You keep the whole scene, including the moments where the subject points at the people around them. The catch is that the video takes up less of the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option B: crop to vertical.&lt;/strong&gt; A 9:16 crop of a 16:9 frame keeps only about 32% of the width (9/16 ÷ 16/9 ≈ 0.32). A center crop usually keeps the centered subject in view, but anything toward the edges, like a gesture at someone off to the side, may get cut. Scrub through the whole clip before you commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;X is the easy one.&lt;/strong&gt; It shows landscape video well, so you can usually post the 16:9 file as it is. Rule of thumb: if the joke depends on the whole scene, keep it landscape. If it depends on the face and the final gesture, crop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Fill the bands with text, not blank space
&lt;/h2&gt;

&lt;p&gt;If you go with Option A, use the empty space. Most editors can place a 16:9 clip on a 9:16 canvas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a 1080×1920 project.&lt;/li&gt;
&lt;li&gt;Put the clip in the vertical center at full width.&lt;/li&gt;
&lt;li&gt;Use the top band for a hook line ("POV: you finally got invited").&lt;/li&gt;
&lt;li&gt;Leave the bottom mostly empty. Platforms put their own buttons and captions along the bottom and right side, which tend to cover text there.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd rather work in a terminal, ffmpeg can do the canvas step in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4 &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"scale=1080:-2,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;:a copy vertical.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a center crop instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4 &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"crop=ih*9/16:ih,scale=1080:1920"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;:a copy cropped.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scaling a 480p or 720p clip up to 1080 wide adds no detail. It just gives the platform a standard frame size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Add the song in the app, and lower the original audio
&lt;/h2&gt;

&lt;p&gt;This is where people trip up most. The built-in audio is an instrumental, so add the trend's song inside the platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload the clip, then pick the song from the app's sound library.&lt;/li&gt;
&lt;li&gt;Turn the clip's original volume way down or off, so the beat and the song don't clash. A little crowd noise underneath can make it feel more live.&lt;/li&gt;
&lt;li&gt;Line up the clip's big moment with the song's. Most apps let you choose which part of a track to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Music availability varies by platform, region and account type, and business accounts often get a smaller library. If the song isn't available, the clip's own beat works as the soundtrack. Don't bake a copyrighted song into the file before uploading. The platform's library is the usual way to stay within its music licensing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Write a caption that's honest about what it is
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name the trend&lt;/strong&gt; so people searching can find you, plus a few relevant hashtags.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say it's AI-generated.&lt;/strong&gt; Several platforms have AI-content labels. Use them where they exist, and add a "made with AI" note anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only post people who agreed.&lt;/strong&gt; If the clip shows a friend, they should have agreed to both the photo and the post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't imply any connection to the artist.&lt;/strong&gt; It's a fan recreation, so say so if you name the artist.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Post it a little differently on each platform
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TikTok / Reels / Shorts:&lt;/strong&gt; use the vertical version, add the song in the app, and get the hook on screen in the first second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X:&lt;/strong&gt; post the original 16:9 file and put the hook in the post text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Give the files clear names (&lt;code&gt;clip_16x9.mp4&lt;/code&gt;, &lt;code&gt;clip_9x16_pad.mp4&lt;/code&gt;, &lt;code&gt;clip_9x16_crop.mp4&lt;/code&gt;) so you don't upload the wrong one.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Watched the whole clip at the crop you plan to use&lt;/li&gt;
&lt;li&gt;[ ] Hook text placed above the clip, away from the platform's buttons&lt;/li&gt;
&lt;li&gt;[ ] Song added in the app, original audio lowered&lt;/li&gt;
&lt;li&gt;[ ] Caption says it's AI-generated; AI label turned on where available&lt;/li&gt;
&lt;li&gt;[ ] Everyone shown has agreed to be posted&lt;/li&gt;
&lt;li&gt;[ ] Right file for the right platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven't made the clip yet, the guide at &lt;a href="https://burningbridgestrend.org/how-to-make-burning-bridges-ai-video" rel="noopener noreferrer"&gt;https://burningbridgestrend.org/how-to-make-burning-bridges-ai-video&lt;/a&gt; covers getting from a photo to a clip.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was written with AI assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>video</category>
      <category>socialmedia</category>
      <category>tutorial</category>
      <category>ai</category>
    </item>
    <item>
      <title>Templates vs. Prompts: Turning One Photo into a Trend Video with Remix Motion</title>
      <dc:creator>Yina Lin</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:12:33 +0000</pubDate>
      <link>https://dev.to/yina_lin_a42a84dfee976777/templates-vs-prompts-turning-one-photo-into-a-trend-video-with-remix-motion-3981</link>
      <guid>https://dev.to/yina_lin_a42a84dfee976777/templates-vs-prompts-turning-one-photo-into-a-trend-video-with-remix-motion-3981</guid>
      <description>&lt;p&gt;If you have tried to copy a viral short-form video with a general AI video model, you know the loop: a long prompt describing the moves, the room and the camera, a generation where the dance is wrong, another tweak, another try. Eventually you realize you are doing prompt engineering to recreate something that already exists.&lt;/p&gt;

&lt;p&gt;This post walks through a different approach: a &lt;strong&gt;template-based workflow&lt;/strong&gt;, using &lt;a href="https://remixmotion.com/" rel="noopener noreferrer"&gt;Remix Motion&lt;/a&gt; as the example. I will cover the flow step by step, why templates fit this job, and the limits you should know before paying for anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: copying a trend is a spec problem, not a creativity problem
&lt;/h2&gt;

&lt;p&gt;When you want to join a trend, the target is already defined. The motion, the scene, the camera work and the sound are what make it recognizable. The only variable is &lt;em&gt;who is in it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A prompt-driven model treats all of that as open input, so every generation re-rolls the parts you wanted fixed. Great for original work, wrong abstraction for "this exact trend, with me in it".&lt;/p&gt;

&lt;p&gt;A template flips that: the trend is the fixed config, and your photo is the only parameter. In developer terms: calling a function with one argument instead of rewriting it every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "remix" means here
&lt;/h2&gt;

&lt;p&gt;Quick clarification: "remix" means putting yourself into a trending video. It is not a music tool, and the result is always a video.&lt;/p&gt;

&lt;p&gt;It is also not editing the original clip. Each video is a new render of the trend from your photo. The original trend video, the people in it and its song are not in the result. Remix Motion is not affiliated with TikTok, Instagram or the creators of the original trends.&lt;/p&gt;

&lt;h2&gt;
  
  
  The walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Sign in
&lt;/h3&gt;

&lt;p&gt;Making a video needs a signed-in account with a verified email address. It runs in the browser on phone or desktop; there is no app. The interface is English only.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pick a template
&lt;/h3&gt;

&lt;p&gt;There are five templates, each based on a trending TikTok or Instagram video, with motion, scene, camera and sound already set. You never write or see a prompt. Browse them at &lt;a href="https://remixmotion.com/trends:" rel="noopener noreferrer"&gt;https://remixmotion.com/trends:&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BbY WOW Guy&lt;/strong&gt;: you dance across a party, bite into sweet bread, stare at the camera and dance off. 9 seconds, 9:16, one photo. 80 credits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Burning Bridges&lt;/strong&gt;: silver cup in hand, you hype a private party under crystal chandeliers. 15 seconds, 16:9, one photo. 100 credits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulin 47&lt;/strong&gt;: you rap in a circle on a red-lit corner while a friend holds the speaker and the crowd cheers. 15 seconds, 9:16, one photo of you or your pet. 100 credits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zombie Love Story&lt;/strong&gt;: one person transforms, the other opens their arms. 15 seconds, 9:16 or 16:9, two photos (you and your partner). 100 credits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zombie Pet&lt;/strong&gt;: your pet transforms, then runs back to you. 15 seconds, 9:16 or 16:9, two photos (your pet and you). 100 credits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Prepare your photo
&lt;/h3&gt;

&lt;p&gt;This is the only input you control. The documented constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JPG, PNG or WebP&lt;/li&gt;
&lt;li&gt;up to 4 MB each&lt;/li&gt;
&lt;li&gt;300–5760 px per side&lt;/li&gt;
&lt;li&gt;width-to-height ratio between 0.4 and 2.5&lt;/li&gt;
&lt;li&gt;one photo per person in the template (plus a pet photo for Bulin 47 and Zombie Pet)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Photos only: no video, audio or text input.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Tick the consent box
&lt;/h3&gt;

&lt;p&gt;Before every video you confirm: "I own these photos and everyone in them agreed to be in the video. No minors." The server refuses a request without it. Photos of children, celebrities, politicians and other public figures are not allowed.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Check the price, then generate
&lt;/h3&gt;

&lt;p&gt;The cost (80 or 100 credits depending on the template) is shown before you generate. Credits are held when the video starts and only charged when it is delivered.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Wait a few minutes
&lt;/h3&gt;

&lt;p&gt;Rendering runs in the background with ByteDance Seedance 2.5 and usually takes a few minutes. The finished MP4, with generated sound, waits in your account's video list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Details worth knowing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Moderation on both ends.&lt;/strong&gt; Every photo is checked before any credits are held, and 5 frames of each finished video are checked before you can see it. A blocked photo costs nothing; a blocked video is refunded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machine-readable AI labeling.&lt;/strong&gt; There is no visible watermark, but each video carries an invisible "AI-generated" label in its file metadata (XMP with the IPTC digital source type &lt;code&gt;trainedAlgorithmicMedia&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private by default.&lt;/strong&gt; Only the account that made a video can view or download it, and you can delete any video and its photos at any time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The limits, honestly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paid only.&lt;/strong&gt; There is no trial tier and no signup credits. The smallest purchase is $9.90 for 100 credits, which covers one video. Packs are one-time purchases, nothing renews, and credits never expire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;480p output.&lt;/strong&gt; Not the tool if you need high resolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9 or 15 seconds.&lt;/strong&gt; No long videos, and no trimming or extending.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Five templates.&lt;/strong&gt; If your trend is not in the list, you cannot make it here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No creative control.&lt;/strong&gt; You cannot write a prompt, pick a song or upload your own video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No photos of children or public figures&lt;/strong&gt;, and only people who agreed to be in the video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purchases are final&lt;/strong&gt; (except failed or blocked videos, and duplicate or unauthorized charges).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When templates win (and when they don't)
&lt;/h2&gt;

&lt;p&gt;Use a template when the output is already specified and you just want your photo in it. You skip the prompt-and-retry loop and see the price up front.&lt;/p&gt;

&lt;p&gt;Use a prompt-driven model when you want something original, longer, sharper, or a trend no template covers.&lt;/p&gt;

&lt;p&gt;For "I want to be in that trend everyone is posting," a template is simply the better-fitting abstraction.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was written with AI assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>video</category>
      <category>tutorial</category>
      <category>generativeai</category>
    </item>
  </channel>
</rss>
