1枚の明確な製品画像、Claude Code、AIHubMix APIがあれば、Seedreamでキャラクターの参照画像を生成し、それを仮想人物アセットとして登録し、Seedanceを使ってAI製品広告を作成できます。
このチュートリアルは、実際のアロエミストのキャンペーンをもとにしており、プロジェクト構成、設定、コマンド、完全な動画プロンプトを含みます。目標とする出力は、AIで生成した人物と背景を使った20秒、720p、9:16の縦型広告です。
ワークフロー全体は、Claude CodeとAIHubMixで動かします。Claude Codeはプロジェクトの概要を読み取り、プロンプトを修正し、実行を整理します。AIHubMixは単一のモデル接続先を提供するため、画像生成と動画生成を同じプロジェクト内で行えます。
モデルID、パラメータ、エラー処理は、2026年9月16日付のプロジェクトスナップショットに基づいています。再利用する前に、現在のAPIを確認してください。コマンドは、同梱のflow.pyを使用し、プロジェクトのルートディレクトリから実行してください。スターターパッケージをダウンロードする
コード、プロンプト、設定、サンプル画像をダウンロードしてください:
https://drive.google.com/uc?export=download&id=1nXcj26Fq3daHeTd0SynS7_QEXgH8z4u_
展開したら、seedance-starterディレクトリに移動してください。パッケージには、flow.py、2つのスキーマスナップショット、5つのプロンプトファイル、製品画像、3つの参照画像が含まれています。Pythonスクリプトは標準ライブラリのみを使用します。
- 動画の工程から始める場合: 付属の3つの参照画像を使用し、APIキーを設定して、ステップ4から始めてください。
- 自分の製品で始める場合: 製品画像とプロンプトの詳細を差し替え、付属の参照画像を
assets/の外に移動してから、ステップ3から始めてください。
.env.exampleを.envにコピーし、自分のAPIキーを追加してください。アカウントには関連モデルへのアクセス権、必要に応じた非同期タスクの権限、十分なクオータが必要です。API による生成には利用料金が発生します。
1. 製品画像とプロジェクトを準備する
例として使用する製品は、Nature Republic Aloe Vera Mistです。このワークフローを応用する際は、画像、製品説明、使用アクションを合わせて更新してください。
| ファイル | 用途 |
|---|---|
assets/product.png | 元の製品画像 |
prompts/prompt-a.txt | メインキャラクターのポートレート用プロンプト |
prompts/prompt-b.txt | キャラクターが製品を持つ場面のプロンプト |
prompts/prompt-c.txt | 製品を使う場面のプロンプト |
prompts/prompt-video.txt | 動画のタイムライン、カメラ、音声の要件 |
prompts.json | 解像度、長さ、参照画像の依存関係、プロンプトのパス |
flow.py | APIリクエスト、アセット登録、ポーリング、ダウンロード |
seedream.schema.json, seedance.schema.json | キャッシュされたAPIスキーマのスナップショット |
Claude Codeは、プロジェクトの概要を読み取り、設定とプロンプトの修正を支援します。実際のリクエストはflow.pyがAIHubMix経由で送信します。
このワークフローにAIHubMixが適している理由
AIを使った製品広告のワークフローでは、通常複数のモデルが必要です。画像モデルは人物と製品の参照画像を作成し、動画モデルは動きやカメラの動きを作成します。AIHubMixは主要なモデルの大半に対応しているため、提供元ごとに別々のアカウント、認証、リクエスト先を管理する代わりに、1つのAPIサービスでタスクに応じてモデルを選択できます。
AIHubMixは複数の提供元にも接続し、利用可能で低遅延の経路を自動的に選択します。画像生成、アセット処理、動画生成を順番に完了させる必要があるワークフローでは、単一の提供元が不安定になった場合の影響を抑えられます。ただし、モデルの提供状況、ルーティング、応答時間は、その時点のサービス状況に左右されます。
プロジェクトのルートに.envを作成するか、同じ変数を環境変数として設定してください:
AIHUBMIX_API_KEY=replace_with_your_api_key
プロジェクトでは、.gitignoreによって.envが除外されます。共有するのは変数名と例だけにし、実際のキーは決して共有しないでください。

ワークフロー全体は、1枚の明確な製品画像から始まります。
2. 出力の目標を設定し、画像用と動画用のパラメータを分ける
prompts.jsonの関連部分は次のようになります。実際のファイルを編集する際は、既存のstills配列やその他のフィールドを残してください。
{
"size": "1080x1920",
"aspect_ratio": "9:16",
"duration": 20,
"resolution": "720p",
"generate_audio": true,
"video_prompt_file": "prompts/prompt-video.txt"
}
sizeは画像生成用です。aspect_ratio、duration、resolution、generate_audioは動画生成用です。スクリプトは設定オブジェクト全体を両方のエンドポイントに送るのではなく、それぞれ別のリクエストを作成します。
プロジェクトでは次のモデルIDを使用します:
- Seedream:
doubao-seedream-5-0-pro-260628 - Seedance:
doubao-seedance-2-5-260628
同梱のスキーマスナップショットによると、画像エンドポイントはsizeを受け付け、動画エンドポイントはaspect_ratioを受け付けます。両者を混在させるとリクエストが拒否されます。flow.pyは、リクエストを送信する前にキャッシュされたスキーマのプロパティを確認しますが、これは完全なパラメータ検証ではありません。
3. 3つのキャラクター参照画像を順番に生成する
各画像には異なる役割があり、後の画像は前の画像に依存します:
| 参照 | 内容 | 入力 |
|---|---|---|
| A: キャラクターのポートレート | 顔、髪型、服装、部屋、照明を定める | この例ではテキストプロンプトのみ |
| B: 製品を持つ | 同じ人物が、ラベルをカメラに向けてボトルを持つ | 製品画像 + A |
| C: 製品を使う | 同じ人物がスプレーポンプを押す | 製品画像 + B |
プロンプトには、キャラクターの詳細を繰り返し記述し、製品の形状、色、ラベルのレイアウト、自然な扱い方を説明します。
実行:
python3 flow.py stills
結果はassets/frame-01.jpg、frame-02.jpg、frame-03.jpgとして保存されます。キャラクターの一貫性、パッケージの忠実度、使用動作の自然さを確認してください。
スクリプトは既存のファイルをスキップします。 プロンプトを変更した場合は、対応する出力をバックアップして移動してから再実行してください。Aを変更した場合は、BとCも再生成が必要になることがあります。

参照画像は、キャラクターの同一性、製品の見せ方、製品の使用方法を定めます。
4. 画像をホスティングし、仮想ポートレートアセットとして登録する
スターターには、作成者のアカウントに由来するアセットIDは含まれていません。参照画像は自分のアカウントに登録してください。
このプロジェクトでは、登録にパブリックな画像URLを使用します。元のワークフローでは、コミットSHAに固定したGitHubのrawURLを使用していましたが、認証なしで画像を直接返すホスティングであれば何でも使用できます。
GitHubの/blob/形式のURLはHTMLページを返すため、画像URLとしては使用できません。
このプレースホルダーのホストを、アップロードしたファイルの実際の場所に置き換えてください:
IMAGE_BASE='https://your-public-image-host.example/campaign'
python3 flow.py check "$IMAGE_BASE/frame-01.jpg" "$IMAGE_BASE/frame-02.jpg" "$IMAGE_BASE/frame-03.jpg"
python3 flow.py assets "$IMAGE_BASE/frame-01.jpg" "$IMAGE_BASE/frame-02.jpg" "$IMAGE_BASE/frame-03.jpg"
checkはHTTP 200と画像のContent-Typeを確認します。assetsはvirtual_portraitアセットグループを作成するか再利用し、各画像を登録し、activeになるまで待機して、アセットIDをstate.jsonに書き込みます。
この手順は、プロジェクトで実際に発生した失敗に基づいています。写実的なキャラクターのURLを動画エンドポイントに直接渡したところ、doubao_real_person_requiredが返されました。今回のキャンペーンの人物はAIで生成されたものだったため、virtual_portraitとして分類したのは正しい判断でした。実在の人物の写真は、対応する認証プロセスを経る必要があり、仮想として表示してはなりません。
1回の動画リクエストで使用するアセットは、すべて同じグループに属している必要があります。

参照画像は生成済みで、3つのアセットはすべてactiveでした。このスクリーンショットを撮った時点では、動画タスクはまだ実行中でした。
5. カメラの制限を含めたタイムラインとして動画プロンプトを書く
最終的なプロジェクトのプロンプトは、20秒の連続したワンショットを4つのフェーズに分けています:
| 時間 | キャラクターの動き | 製品の位置 |
|---|---|---|
| 0〜5秒 | カメラを見ながらボトルを見せる | 顔の横で、ラベルをカメラに向ける |
| 5〜10秒 | ボトルを持ち上げてポンプを押す | フレーム内にとどまる |
| 10〜15秒 | 目を閉じて、ミストが落ち着くのを感じる | フレームの下3分の1 |
| 15〜20秒 | 目を開けて、もう一度製品を見せる | 顔の横に戻り、ラベルをカメラに向ける |
以前の結果では、カメラが近づきすぎて製品が見えなくなりました。そのため最終プロンプトでは、動きをミディアムクローズアップに制限し、製品が見えたままであることを求め、最初と最後の3秒間はラベルが読めることを指定しています。
完全なprompts/prompt-video.txtは以下のとおりです。別の製品を使う場合は、ブランド、パッケージの説明、使用アクションを更新してください。これらの指示は生成の目標であり、出力の確認は依然として必要です。
One continuous 20-second vertical beauty commercial take, no cuts, in a sunlit minimalist vanity corner.
0-5s: the same 24-year-old East Asian woman in an oversized sage-green linen shirt over a white ribbed tank top stands at the vanity holding the translucent light-green Nature Republic Aloe Vera 92% Soothing Gel Mist beside her cheek, the label facing camera and fully legible. She looks to camera with a warm, easy smile and turns the bottle slightly so the label catches the morning light.
5-10s: she lifts the bottle just above eye level and presses the fine-mist pump. A soft cone of aloe mist sprays across her face and catches the light as a faint sparkle of micro-droplets.
10-15s: her eyes close and her chin lifts into a small contented smile as the mist settles, tiny droplets resting on her cheekbone and brow. The bottle stays visible in the lower third of the frame throughout this beat.
15-20s: she opens her eyes, brings the bottle back up beside her cheek with the label square to camera, and holds a final calm look at the lens.
Camera: one slow, smooth push-in from a chest-up framing to a mid-close framing ONLY. Do not push past a mid-close shot. The product must stay inside the frame for the entire take, and the label must be clearly legible in both the first three seconds and the last three seconds.
Look: soft diffused morning sunlight from camera left, photorealistic skin texture with real moisture on the skin, mist rendered as genuinely photographed spray rather than digital particles, premium K-beauty advertising. Keep the product packaging, colours, materials, label layout and label text exactly as in the reference images; do not redesign or re-letter the product. No text overlays, no captions, no watermarks.
Audio: a quiet bright room, one soft short pump-spray hiss, a gentle breath. No music, no voiceover.
音声生成は有効ですが、プロンプトでは、室内の環境音、スプレーの音1回、穏やかな呼吸音のみを求めており、音楽やナレーションは含めていません。
6. 動画を生成して保存する
アセットの登録後、asset://の参照を送信します。このコマンドは保存されたIDを読み取り、各IDを個別の引数として渡します:
python3 - <<'PYCODE'
import json
import subprocess
import sys
from pathlib import Path
state = json.loads(Path("state.json").read_text())
refs = ["asset://" + asset_id for asset_id in state["asset_ids"]]
subprocess.run([sys.executable, "flow.py", "video", *refs], check=True)
PYCODE
引数リストを使うと、元のプロジェクトで発生していたzshの問題も避けられます。複数のIDを1つの通常の文字列に格納すると、スクリプトに無効な引数として1つにまとめて渡されることがありました。
スクリプトは動画タスクIDを保存し、completedになるまでポーリングして、出力をout/video.mp4にダウンロードします。別のダウンロードでこのパスが上書きされることがあるため、比較したいバージョンはバックアップしてください。
既存のタスクを再開する、または結果を再ダウンロードするには:
python3 flow.py status
作成時のレスポンスが失われた場合は、最近のタスクを一覧表示し、該当するIDを再開してください:
python3 flow.py tasks
python3 flow.py status VIDEO_TASK_ID
別のタスクを作成する前に既存のタスクを確認しておくと、誤って同じ生成を重複して行うことを防げます。
7. 出力を確認し、反復改善する
元のプロジェクトでは、video-v1-10s.mp4と最終的なvideo.mp4を保存しています。最初のバージョンは10秒しかなく、製品の使用場面も十分に示されていなかったため、ワークフローではプロンプトを2回目に改良しました。
すべての結果を、次のチェックリストで確認してください:
- [ ] 長さ、解像度、アスペクト比が目標と一致している。
- [ ] キャラクターの顔、服装、背景が一貫している。
- [ ] 製品が見え続けており、冒頭と末尾でラベルを読むことができる。
- [ ] 扱い方とスプレーの動作が、製品の実際の使用方法と一致している。
- [ ] ボトルの形状、パッケージ、文字が目立って変化していない。
- [ ] カメラが近づきすぎておらず、音声が依頼どおりになっている。
通信時間が正しくない場合は、設定と実際のリクエストの両方を確認してください。製品がフレームから外れる場合は、カメラの制限を強めてください。使用アクションが短すぎる場合は、時間と動作をより明確に割り当ててください。prompts/prompt-video.txtだけを編集する場合は、参照画像を再生成する必要はありません。視覚的な参照を変更する必要がある場合にのみ、再生成して登録してください。
よくある質問
正しく見えるモデル名なのに404が返されるのはなぜですか?
ソースプロジェクトでは、短縮されたSeedream名でmodel_not_foundが返されました。マーケティング上の表示名がAPI識別子と同じだと想定せず、現在のエンドポイントが受け付ける完全なAPIモデルIDを使用してください。
ブラウザでは画像を開けるのに、登録に失敗するのはなぜですか?
URLがHTML、共有ページ、サインインページではなく、画像そのものを返しているか確認してください。登録の前にpython3 flow.py check URL...を使用してください。
プロンプトを変更しても参照画像が変わらなかったのはなぜですか?
stillsは既存のファイルをスキップします。再生成が必要な画像はバックアップして移動し、その後、後続の参照画像も再生成すべきかどうかを確認してください。
HTTP 200は動画の生成が完了したことを意味しますか?
いいえ。スクリプトはタスクのstatusによって処理を分岐させ、タスクがcompletedに達した後にのみダウンロードを行います。
最初のバージョンを始める
製品画像を1枚用意し、AIHubMixへのアクセスを設定して、画像モデルと動画モデルを選択してください。そのうえでClaude Codeに製品説明とプロンプトを調整させます。3つの参照画像を生成し、確認して登録した後、動画を作成してください。次の改善サイクルをどうするかは、チェックリストを使って判断してください。
今後別のプロジェクトで別のモデルが必要になった場合も、同じファイル構成とワークフローを維持し、AIHubMixのモデル選択とモデル固有のパラメータを更新してください。これが、複数のAIモデルを使うコンテンツチームにとって統合APIサービスが持つ実用的な価値です。タスクごとにモデルを変えつつ、ワークフローは再利用できる状態を保てます。



