15秒CMをGPU1枚で作りきるまで|プライスチェッカーのアニメ広告ができるまでの全工程とワークフロー配布

15秒CMをGPU1枚で作りきるまで|プライスチェッカーのアニメ広告ができるまでの全工程とワークフロー配布

こんにちは、パンゲアです。Chrome拡張「プライスチェッカー(Chrome拡張)」を作っている、大阪市在住の元 Web エンジニアです。

今回は毛色を変えて、プライスチェッカーの15秒CMを、自宅の RTX 3090 一枚で最後まで作りきった記録を書きます。2026年8月18日から28日までの10日間、外部の生成APIは一切使わず、全部ローカルで回しました。

先に完成品を置きます。

▶ 完成した15秒CM

YouTubeで見る

そして最初に言わせてください。この動画は、プライスチェッカーを使ってもらうために作りました。

Amazonの商品ページを開くだけで、他25サイトの最安値が自動で出ます。 検索も、タブの開き直しも要りません。完全無料・登録不要なので、ぜひ入れてみてください。

Chromeウェブストアでプライスチェッカーを入れる(完全無料)

——以下は、そのCMをどうやって作ったかの記録です。

これは 蒸留なし・25ステップ で回した最初の本番版で、レンダリングに 3時間09分 かかっています。この記事は、この1本を作るまでに何を測り、何で失敗し、最終的に同じ映像をどこまで速く作れるようになったかの全記録です。結論から言うと、同じ映像が最終的に 56分(−71%)になりました。

使ったワークフロー4本は記事末尾で配布しています(今すぐダウンロード)。


目次

  1. 何を作ったか(スペック)
  2. 最初に測った3つの制約
  3. ストーリーボードが全部を決める
  4. モーショングラフィックスの作法
  5. 最大の発見:シードではなく「参照動画」を編集する
  6. 完成、そしてGPUが消えた日
  7. 高速化:3時間09分をどこまで削れるか
  8. 品質のトレードオフ(比較表)
  9. 速いのに使えなかったもの
  10. 音は0.1MPで別に作る(リップシンクにも使える)
  11. BGMとCMソング、最終的にSunoで差し替えた話
  12. 配布物

1. 何を作ったか

項目内容
15.084秒(362フレーム / 24fps)
解像度1664×928(1.5MP、16:9)
構成4シーン × 107フレーム
内容10カット。日本語テロップ、価格表示、ロゴのエンドカード
効果音・ナレーションとも生成(映像と同時生成)
環境ComfyUI + MiniMax H3-Base(ローカル、API不使用)
GPURTX 3090 × 1

画面に出るコピーは「見るだけ。」「一瞬で比較。」「最安値、発見。」「検索不要。」「タイパ最強。」「完全無料。」など、短いコピーだけで構成しています。

拡張機能の広告なので、日本語の文字がちゃんと読めること¥10,980 のような価格が正しく出ることが、この案件の成否そのものでした。ここが崩れたら広告として成立しません。以降の判断は全部この一点に紐づいています。


2. 最初に測った3つの制約

作り始める前に「何ができて何ができないか」を実測しました。この3つが後の全工程を決めました。

2-1. 日本語はプロンプトからは描けない

参照画像から供給しないと、読める字になりません。 プロンプトだけで生成すると、20ステップかけてもグリフが崩れてロゴが潰れる。逆に参照画像を添えれば、たった4ステップでも長い日本語と価格が完全に読めました。

解像度も独立して効きます。

解像度日本語の状態
0.2MP(608×352)破綻。「送料無料」が読めない、「国内専用」→「圓内専朋」
0.4MP読める
1.5MP綺麗

つまり 低解像度パスは構図とテンポの確認専用で、文字の判断には一切使えない。この線引きを最初にやったのが、後でかなり効きました。

2-2. シードは解像度・ステップ数をまたいで固定されない

同じシードでも、ステップ数や解像度を変えると別の映像になります(フレーム相関0.43〜0.83)。サンプラーがノイズを違う形で消費するためです。

これは実務的にかなり重い制約で、「安い設定で当たりを探して、高画質で本番」ができないということです。出荷する設定を先に決めて、その中でシードを振るしかない。だとすれば、出荷設定そのものを安くするのが正解になります。後半の高速化の話は、全部ここから来ています。

2-3. コストはフレーム数に対して、おおよそ二次で伸びる

1.03MPでの実測で、124フレームが6〜17 s/it、362フレームが86〜102 s/it。

長い1本より、分割した方が圧倒的に安い。 15秒を1本で回さず4シーンに割ったのはこれが理由です。


3. ストーリーボードが全部を決める

絵作りは、1枚のストーリーボード・コンタクトシートから始めました。15秒・10カットを1枚のシートにして、各セルに「画/テロップ/ナレーション」を書き込んだものです。

これをH3のプロンプトに変換し、このシートを唯一の参照画像として添えて生成します。グリッドの枠線やセル番号は明示的に除外指定します。

1枚の安い画像が、アートディレクション全体を運ぶという構図です。逆に言えば、画像のクオリティ=動画のクオリティ。ここが土台なので手を抜けません。

実際のカット構成はこうなりました。

カットテロップ
1まだ自分で探してる?ノートPCでAmazonを見ている女性
2見るだけ。商品ページを見つめる横顔、光のストローク
326サイトサイトロゴが奥へ流れる
4一瞬で比較。¥12,800/¥11,900/¥10,980 が並ぶ
5最安値、発見。王冠つき ¥10,980 とチェックマーク
6検索不要。拡張のパネルが商品ページに出る
7面倒、ゼロ。「別タブで検索」等のカードが×で消える
8タイパ最強。空を見上げる女性
9完全無料。ロゴのエンドカード

ここで一度、派手に失敗しました

ストーリーボードには、最終稿のコピーを一字一句入れておく必要があります。

これを軽視して、後からプロンプト側でコピーだけ書き換えたら、書き換えた行だけが全部壊れました。

カギ      → カギジ
促進      → 促達
ここちよく → いこよく

グリフを供給しているのは参照画像であってプロンプトではないので、プロンプト側で直すと2つの情報源が矛盾するわけです。コピーを変えるならストーリーボードから作り直す。 これは鉄則になりました。


4. モーショングラフィックスの作法

H3の既定の動きは「ゆるやかに漂う」で、CMとしては明らかに鈍い。テンポはプロンプトに明示しないと出ません。

スナップ・アンド・ホールドが全てでした。 要素は1〜3フレームで所定位置にスナップし、わずかにオーバーシュートしてロックする。そしてスナップとスナップの間はフレームが静止していると書く。

緩急は「全体を速くする」ことではなく、強いアタック+長い静止から生まれます。

  • 文字は離散的なビートで組み上げる(単語ごと、文字ごと)
  • すべての着地に音を紐付ける
  • エンドカードは完全静止と明示する(「最後まで、いかなる動きもなく完全に静止」)
  • カメラは1ショットにつき3語(動き+振幅+速度。例:Push In, small amplitude, fast speed

そして単体で最も効いたのが、「文字は字幕ではなくグラフィックである」と宣言することでした。「字幕バー」「ローワーサード」「ローマ字」を名指しで否定しておかないと、H3は勝手に字幕モードに落ちます。


5. 最大の発見:シードではなく「参照動画」を編集する

ここが製作全体で一番の分岐点でした。

シード振りは収束しない

1.5MPで4テイク回した結果が 45 / 49 / 56 / 61%。しかも失敗が互いに排他的でした。「26サイトのカットが正しいテイクは、エンドカードが壊れている」「その逆」。何回引いても全カットが揃うテイクは出ません。

参照動画は「構造」を直す

そこで参照動画そのものを編集して回す方式に切り替えました。約30テイクを通じて例外なく成立した法則がこれです。

参照動画に無いものは出力に出ない。参照動画に入れたものは出力に出る。

役割分担が完全に分かれていました。

手段直せるもの
参照動画構造 — カット落ち、順序違い、カットが早く始まる(シード振りでは一度も直らなかった)
解像度可読性 — ロゴ、価格、細かい文字

低解像度で文字品質を追うのは完全に無駄な作業だと、この分離ではっきりしました。

確立した手順

0. カットごとのキービジュアル      日本語グリフの供給源。ここが土台
1. アニマティック+合成カメラワーク  GPU不要。無参照より良い(62% vs 54%)
2. 0.2MPで数テイク               1本12分。1.5MPなら2.9時間
3. 綺麗なものが無ければカット単位で参照を組み直す → 2へ
4. 綺麗なテイクが出た瞬間、それを丸ごと参照にして組み立てをやめる
5. 再現するようになったら1.5MPへ
6. 完成映像から音を作る(後述)

ステップ4で5時間溶かしました

13:52には綺麗なテイクが出ていたのに、19:30まで参照の組み立てを続けていました。理由は、組み立て参照のスコア(98%)が、綺麗なテイクのスコア(80%)より高かったから。

このスコアは自己成就的でした。 組み立てスクリプトは、採点スクリプトが測るものをそのまま作る。そして出力を予測しない。実際、アニマティックはスコア100%なのに出力は最悪でした。

自分で書いた採点スクリプトを信じすぎた、というのがこの日の教訓です。


6. 完成、そしてGPUが消えた日

4シーンが揃い、本番版が完成しました。1.5MP / 25ステップ / 蒸留LoRAなし。1シーンあたり46〜50分、全4シーンで3時間09分。これが冒頭のYouTube動画です。

その途中、8月24日の深夜2時10分にGPUがシステムから消えました。

nvidia-smi: GPU is lost. Reboot the system to recover this GPU

OSの再起動以外に復旧手段がありません。 ComfyUIの再起動では戻らない。しかもCUDAエラーもトレースバックも出ずに、ログが行の途中で止まるという分かりにくい落ち方をします。

2回とも、サンプリング中ではなくモデルのロード/アンロード中に起きました。20GBのウェイトを出し入れしていて、消費電力の変動が一番激しい瞬間です。

救いは、チェックポイントが残るので失敗したシーンから再開できること。この日はシーン1〜2を再利用して、シーン3〜4だけ作り直しました。長時間まわす前提なら、この再開の仕組みは必須だと思います。


7. 高速化:3時間09分をどこまで削れるか

映像が完成した後、同じものをもっと安く作れないかを検証しました。ここからが後半の主題です。

使ったのは PDD Acc 8-step という蒸留LoRA。H3の作者ではなく Alibaba PAI が後から公開したものです。

これが普通のLoRAではありませんでした。 中身を見ると32個の「区間ごとの最終層射影ヘッド」が本体で、LoRA部分はおまけ。標準のLoRAローダーではキーが1つもマッチせず、エラーすら出さずに無言で何も起きません。 専用ノードが必須なのは水増しではなく本質的な要件でした。

結果は劇的でした。

シーン25stepPDD 8step削減
149:3611:10−77%
246:0317:02−63%
346:5715:11−68%
447:1312:32−73%
合計3時間09分55分55秒−71%

重要なのは 1ステップあたりの時間はほぼ変わらないこと(110〜119秒 対 86〜114秒)。PDDは1ステップを軽くしているのではなく、必要な評価回数を25→8に減らしているだけです。

だから当然、すでに蒸留LoRAを使っている構成には効きません。 手元の turbo 8step と比べたら 78.35秒 対 78.24秒で完全に同速でした。「−71%」という数字は、元が非蒸留25stepだったから出た数字です。ここは正直に書いておきます。

最終的な3構成

構成全4シーン25step比
25step(当初の本番設定)3時間09分
PDD + warmup 2フェーズ1時間09分−63%
PDD 8step56分−71%

8. 品質のトレードオフ

速くなった代わりに何を失ったのか。ここが一番知りたいところだと思います。

見出しの日本語とロゴのエンドカードは、25step版と区別がつきませんでした。 崩れたのは小さい数字だけです。

¥10,980           →  ¥ と末尾の 0 がグローに飲まれる
PC画面の価格リスト  →  つぶれる
26サイトのロゴ群    →  価格.com 以外が判別不能

そこで「序盤だけ素のモデルで回して、途中からPDDに引き継ぐ」2フェーズwarmupを試しました。

sigma 1.0 ── phase 1: 素のUNET(8ステップ)── 0.8 ── phase 2: PDD(2評価)── 0.0

シーン2の ¥10,980 は完全に復活しました。 25step版と同等。コストは純PDD比 +24%。

ところが、シーン4のエンドカードが壊れました。 完全静止すべき最終カットに、架空の価格表パネルが育って「完全無料。」を画面外に押し出すという壊れ方です。

これがまた直らない。

試した設定結果
handoff 0.8 / 元シード2.7秒からパネル、最後まで居座る
handoff 0.8 / 別シード1.5〜1.9秒にUI
handoff 0.923 / warmup 4ステップ2.7秒からパネル

素のモデルの担当区間をほぼゼロまで削っても再発する。一方で純PDDと25stepは、どのタイムスタンプでも揺れの兆候すら出しません。

結論はカットごとの使い分けでした。

動きと小さい文字のあるカット → warmup 凍結したエンドカード → 純PDD

シーンごとに別ディレクトリで生成しているので、混ぜるのはタダです。最終形はシーン1〜3をwarmup、シーン4を純PDDで組んだもので、両方の問題を回避できました。


9. 速いのに使えなかったもの

Sol-Attn というスパースattentionも試しました。確かに速い。

設定時間結果
Sage(現行)8step80.0秒基準
Sol 出荷時設定 8step65.7秒(1.22倍)運動が壊れる。投げたボールがワープする
Sol 論文レシピ 8step90.0秒まだ飛ぶ。しかもSageより遅い
Sage 25step189.3秒綺麗
Sol 25step143.9秒(1.32倍)やはりボールが飛ぶ

「8ステップに畳んだせいで誤差を補正できないのでは」と仮説を立てて25stepでも検証しましたが、仮説は外れ。速度は本物で、ステップ数が多いほど利得は大きい。それでも設定に関係なく運動が壊れるので不採用にしました。

ベンチマークの数字だけ見て採用していたら、ボールが飛ぶCMが出来上がっていたところです。


10. 音は0.1MPで別に作る(リップシンクにも使える)

映像が固まってから音に入りました。ここに、たぶんこの記事で一番実用的なテクニックがあります。

なぜ映像と一緒に作らないのか

映像は4シーンに割って作ります。前シーンのフレームを引き継ぐので絵は繋がるしかし音は繋がりません。

各クリップは自分の持ち分の3.5秒しか見ていないので、ナレーションを15秒に配分することも、BGMのフレーズを跨がせることも、効果音の残響を次シーンへ伸ばすこともできない。声質もトーンも継ぎ目で変わります。 4シーンなら継ぎ目は3箇所。

解決策:絵を捨てて、音だけ1パスで作る

H3は音と映像を同時に生成するので、原理的に音だけをサンプリングすることはできません。 ただし——

音声latentは解像度に依存しません。

つまり 絵は捨てる前提の「担体」でよく、0.1MPまで潰しても音の品質は変わらない。 安くなった分を尺に回して、15秒を丸ごと1パスで通せます。

MP     = 0.1     416×224。絵は担体、捨てる
LENGTH = 362     15.083秒を1クリップで
STEPS  = 15

完成した映像を参照として渡すので、音は映像にちゃんと同期します。継ぎ目はゼロになり、モデルは全セリフを15秒全体に配分できます。

リップシンクをやるなら、この方法がそのまま使える

この0.1MPパスは、リップシンクにも有効です。 参照動画は512×288まで縮めてありますが、口の動きが読める程度の解像度があれば足ります。 音声latentが解像度に依存しない以上、口元さえ判別できれば、担体の絵は小さくて構いません。

ひとつ注意点があります。参照動画のコストは生成解像度と無関係です。内部で768短辺に正規化されるので、事前に縮小しておかないと、0.1MPで生成しても1664×928の参照に132kトークン払うことになります。 先に縮めておけば608×352で26.7kまで落ちます。ここは必ず事前縮小してください。

もうひとつのコツ:SEとVOは別パスにする

効果音(SE)とナレーション(VO)は、それぞれ別パスで作りました。セリフを撮り直しても効果音が変わらないので、後段のミックスが圧倒的に楽になります。

つまずいたところ

エンドカードで音が途切れました。 プロンプト調整だけでは1.63秒→1.28秒までしか縮まらず、最終的に ffmpeg のリバーブテール(aechoafade)で無音を0.32秒まで縮めて、映像の最終静止と合わせています。


11. BGMとCMソング、最終的にSunoで差し替えた話

BGMは MiniMax Music 3 で8パターン作り、そこからCMソング、J-POP、スキャット版と展開して、ACE-Step 1.5(turbo / base / sft)まで一通り試しました。

ここでも面白い失敗が2つありました。

CMソングに歌が入らなかった。 15秒に対してセクションタグを7つ書いたら、1ブロック約2秒になってモデルが器楽演奏として解釈し、ボーカルを完全に落としました。2ブロックに減らしたら歌い出しました。

「最安値」が読み間違えられた。 これは歌詞を全部かなで書くことで解決しました(「さいやすね」)。以降、歌わせる行はすべてかな表記にしています。日本語で歌わせるときの定石だと思います。

そして最終的に——BGMは Suno で作り直したものに差し替えました。

ローカル生成でひと通り作ってはみたものの、15秒CMの「頭サビで即入る」構成と、最後のロゴに合わせて綺麗に終わる尺感は、Suno で作ったものが一番自然でした。ここは正直、素直に良い方を採用したという話です。

映像は全部ローカルで完結させたのに音楽だけ外部、というのは一貫性がないようですが、「どこを自前でやる価値があるか」は工程ごとに違うというのがこの10日間の結論でもあります。映像は自前で回す価値が大きく(枚数を試せるので)、15秒のBGMは1曲当たれば終わりなので、こだわる理由が薄い。

なお音声ファイルは容量が大きいので、この記事では配布していません。 手法だけ書いてあるので、同じ手順で再現してもらえればと思います。


12. 配布物

記事で触れたワークフローとスクリプトを一括ダウンロードできるようにしました。

ワークフロー4本+音声生成スクリプト(zip / 約72KB)

⬇ ダウンロードする

中身: ワークフロー4本(.json) / make_audio.py / make_audio_var.py

音声ファイルと動画・比較画像は容量が大きいためzipには含めていません。 使い方と必須設定は、この記事の本文にすべて書いてあります。

ワークフロー(4本)

ファイルレシピ全4シーン25step比
1_25step_baseline.json蒸留なし・25ステップ3時間09分
2_PDD_8step.jsonPDD Acc 8step55分55秒−71%
3_PDD_warmup_2phase.json素のUNET 8step → PDD 2評価1時間09分−63%
4_audio-only_0.1MP_singlepass.api.json0.1MPで音声だけ作るパス

3本ともサンプリングのレシピだけが違う同一系譜です。記事中の速度比較は、この3本の差そのものです。

サンプル動画

  • 完成品(25step、3時間09分)
  • 同じ内容をPDD 8stepで(56分)
  • 最終形:シーン1〜3をwarmup、シーン4を純PDD
  • Sol-Attnの比較(ボールが飛ぶ様子。静止画では伝わらないので動画で)

比較画像

¥10,980 の拡大比較(25step / PDD / warmup)をはじめ、エンドカードの崩れ方、シードを振っても直らないことの証拠など11枚。

使う前に必要なもの

  • ComfyUI(MiniMax H3 ネイティブ対応版)と Contex Loop 系ノード
  • PDD版は追加で PDD-Acc ノードと蒸留モデル本体

PDD版で必ず守ることが3つあります。ここを外すとエラーにならずに壊れます。

  • BasicScheduler はグラフに置かない(sigmasはPDDノードの2番目の出力から取る)
  • sampler は euler のみ
  • CFG 1.0、他の蒸留LoRAと併用しない

まとめ

10日間やってみて、効いたのは結局この4つでした。

1. 測ってから決めた。 「日本語は参照画像から」「シードは解像度をまたがない」「コストはフレーム数の二次」——この3つを最初に実測したので、後の設計判断が全部そこから自動的に決まりました。推測で進めていたら何度もやり直していたはずです。

2. シードではなく参照を編集した。 シード振りは互いに排他的な失敗を出すだけで収束しない。参照動画を直せば、狙った欠陥を狙って直せます。

3. 安い解像度で回した。 0.2MPは1.5MPの11分の1。構造の検証は全部そこで済ませ、可読性の判断だけ1.5MPでやりました。

4. 速いものが良いとは限らない。 Sol-Attnは確実に1.2〜1.3倍速く、それでも使えませんでした。

そして、同じ映像が3時間09分から56分になりました。

CMの中身自体はシンプルで、「Amazonの商品ページを見るだけで、他の25サイトの最安値が出る」というプライスチェッカーの機能をそのまま15秒にしただけです。検索も、タブの開き直しも要らない。 作っている本人が一番その面倒くささを知っているので、そこだけは省略せずに描きました。

Chromeウェブストアで見る


著者プロフィール

パンゲア — Price Checker(Chrome拡張)開発者・USJ年パス勢パパブロガー。大阪市在住、高校生兄弟2人と妻の4人家族。Web エンジニアから独立し、ECサイト横断の価格比較拡張を運営しています。

コメント