Qwen Image 2.1 + MiniMax H3:ローカル首尾フレーム動画パイプライン
完全ローカル768pを選ぶ条件、ハイブリッド2Kへ進む条件、Qwenでの首尾フレーム作成、H3-Baseのローカル実行、同一入力でのホスト版比較、失敗の切り分けを説明します。
目次

Qwenで最初と最後のフレームを作れても、本当に難しいのはH3がその間を一つの連続ショットとしてつなげられるかです。人物を変えず、不要なカットを入れず、API依存の2K経路を「ローカル」と誤認しない必要があります。まず完全ローカル768pを成立させ、納品要件で2Kが必要な場合だけハイブリッド2Kへ進み、同じ入力でローカル版とホスト版を比較する手順を示します。
先に結論:本当に2Kが必要でなければローカル768pから始める
首尾フレームの受け渡し確認、素材のローカル保持、不要なカットの原因調査が目的なら、完全ローカル768pを先に選びます。最終納品で2Kが必須で、H3-Context-IRとH3-Regenerate-2KのリモートAPIを許容できる場合だけ、ハイブリッド2Kを選びます。
| 目的 | 最初に選ぶ構成 | 理由 | 推奨が変わる条件 |
|---|---|---|---|
| エンドツーエンドで動くことを確認したい | 完全ローカル768p | 変数が少なく、QwenとH3の問題を分離しやすい | 768pが安定し、納品に本当に2Kが必要になったとき |
| 素材を手元のマシンから出したくない | 完全ローカル768p | QwenのフレームとH3-Baseをローカルに保てる | 2K必須かつリモートAPI不可なら、文書化された完全2K経路は条件を満たさないため、別のローカル2K手段が必要 |
| 最終動画を2Kで納品したい | ハイブリッド2K | 公式の完全2K経路は二つのホスト型モジュールに依存する | 素材を遠隔送信できない場合は768pか別方式へ戻す |
| ローカル版とホスト版のどちらが合うか決めたい | まずローカル768pを成立させ、その後ペア比較 | そうしないと導入エラーとモデル品質が混ざる | 複数のショット種類で繰り返してから長期構成を固定する |
GPU名だけで動作を約束しないでください。MiniMaxのSGLang例は4 GPU、公開事例はDGX Sparkですが、どちらも最小VRAMを示さず、一般的なコンシューマーGPUでの動作を証明していません。
手元のマシンだけで完結できる範囲
Qwenのフレーム生成とH3-Baseの768pはローカルで完結できますが、公式の完全2K経路は完結しません。
| 段階 | ローカル実行 | 文書化された境界 |
|---|---|---|
| Qwen Image 2.1で首尾フレームを生成・編集 | 可能 | 公式リポジトリはQwenImage21Pipeline、ローカルDiffusers例、ネイティブ2Kサイズ、最大10枚の参照画像を公開 |
| MiniMax H3-Baseで首尾フレームから音声付き動画を生成 | 可能 | 公開FL2VAチェックポイントは0、1、2枚の画像を受け付け、2枚で首尾フレームモードになる。ローカル検証は768p |
| H3-Context-IR | 公式の完全実装はローカル不可 | MiniMaxはホスト型の前処理・オーケストレーションと説明し、今回のオープンリリースには含めていない。APIを使うか、Prompting Guidanceを基に独自前処理を作る |
| H3-Regenerate-2K | 現在の公開部品だけでは不可 | モジュールは未公開で、公式2KワークフローはAPI経由で呼び出す |
| ホスト版H3との比較 | 不可 | Web/API実行は遠隔であり、同一入力の比較対象として使う |
MiniMaxは4〜15秒、24 FPS、32 kHzステレオ、短辺768ピクセルを標準とし、2KはH3-Regenerate-2Kで生成すると説明しています。これはモデルの仕様境界であり、任意の設定が手元のハードウェアで動く保証ではありません。
公開事例は実行可能性を示すが、普遍的な勝者は決めない
この事例は比較方法の参考にし、「ローカルH3は常に優れる」という結論には使わないでください。
映像制作者Sam Wassermanは、DGX Spark上でQwen Image 2.1とMiniMax H3を使ったローカルの「アイデア→画像→動画」実行を公開しました。添付動画は約8秒です。続く投稿では、同じprompt、同じ仕様、同じ最初と最後のフレームを有料Web H3に入力したと述べています。本人の評価では、Web版は不要なカットを挿入し、ローカル版は意図した順序を保ちました。
これは実行可能性の例であり、比較方法として参考になります。しかし、ローカルH3が一般に優れている証拠ではありません。投稿には導入コマンド、ピークメモリ、生成時間、音声処理、seed、失敗例がありません。同じ作者による一つの入力の評価で、独立再現でもありません。
手順1:アイデアを一つの連続ショットに絞る
場所を一つ、動作の流れを一つ、終了状態を一つにします。それをショット契約、つまり指示と結果を照合できる短い仕様として書き出します。
| 項目 | 定義する内容 |
|---|---|
| 主体と背景 | 人物、物体、服装、背景、維持すべき識別特徴 |
| 開始状態 | 最初のフレームの位置、姿勢、視線、カメラ距離、構図、光 |
| 終了状態 | 最後に許可する変化だけ。人物・場所・カメラ位置を同時に変えない |
| 動きの経路 | 主体とカメラの動き、アクションの順序 |
| 連続性の制約 | 「一つの連続ショット」「カットなし」「瞬間移動なし」など |
| 出力仕様 | 長さ、アスペクト比、台詞・環境音・音楽の要否 |
| 禁止事項 | 不要な人物、字幕、場面転換、背景置換、追加動作 |
不要なカットを調べるテストで、複数の場所、時間帯、モンタージュを一つのpromptに要求しないでください。その場合、カットはモデルの失敗ではなく、指示の妥当な解釈になり得ます。
例えば「入口からテーブルまで歩き、カップを持ち上げる。カットなし」は首尾フレーム試験に向いています。「街からオフィスへ移動し、子ども時代を回想する」は複数シーンが自然に必要なので、不要なカットの純粋な試験にはなりません。
手順2:最初のフレームを生成し、それを編集して最後のフレームを作る
互いに無関係な二つのpromptで別々に生成せず、最初のフレームを編集して最後のフレームを作ります。H3を動かす前から人物、服装、構図、背景を維持しやすくなります。
公式モデルIDはQwen/Qwen-Image-2.1です。Qwenは7Bパラメータの視覚生成部分、ローカルDiffusers、生成と編集、ネイティブ2K、最大10枚の参照画像を文書化しています。
pip install "torch>=2.4.0" "transformers>=5.17" accelerate pillow
pip install git+https://github.com/huggingface/diffusers
from pathlib import Path
import torch
from diffusers import QwenImage21Pipeline
first_prompt = Path("first_prompt.txt").read_text(encoding="utf-8").strip()
last_edit_prompt = Path("last_edit_prompt.txt").read_text(encoding="utf-8").strip()
pipe = QwenImage21Pipeline.from_pretrained(
"Qwen/Qwen-Image-2.1",
torch_dtype=torch.bfloat16,
).to("cuda")
first = pipe(
prompt=first_prompt,
width=2752,
height=1536,
num_inference_steps=40,
generator=torch.Generator("cuda").manual_seed(42),
).images[0]
first.convert("RGB").save("first.png")
last = pipe(
prompt=last_edit_prompt,
image=first,
width=2752,
height=1536,
num_inference_steps=40,
generator=torch.Generator("cuda").manual_seed(43),
).images[0]
last.convert("RGB").save("last.png")
このコードは公式の生成インターフェースと単一画像編集を組み合わせ、first_promptとlast_edit_promptは利用者が用意します。文書化された16:9の2Kサイズ2752 × 1536、40ステップ、不透明RGB PNGを使います。H3の公開説明はこの受け渡しでのalpha処理を明記していないため、RGBAを別途検証していなければ不透明フレームで変数を一つ減らせます。
少なくとも次を記録します。
- モデルID、フレームワーク版、最初のprompt、最後の編集prompt
- 二つのseed、幅、高さ、ステップ数、参照画像一覧
- 両ファイルのSHA-256、ピクセル寸法、カラーモード
- 人物、服装、構図、照明、背景の一貫性
- 最後のフレームが最終状態だけを示し、動作全体を詰め込んでいないこと
Qwenはメモリが限られるGPU向けにenable_model_cpu_offload()も記載しています。これはoffload経路の存在を示すだけで、最小VRAMや速度を保証しません。
手順3:ローカル版とホスト版に同じ入力を読ませる
二つの画面へ記憶でパラメータを入力し直さないでください。画像、prompt、出力設定を一つのmanifestにまとめます。seed、長さ、書き換え後のpromptが一つ違うだけで、比較全体の意味が失われます。
experiment_id: "qwen-h3-001"
qwen_model: "Qwen/Qwen-Image-2.1"
h3_model: "MiniMaxAI/MiniMax-H3"
h3_variant: "fl2va"
prompt_file: "prompt.txt"
first_frame: "first.png"
last_frame: "last.png"
prompt_sha256: "<sha256>"
first_frame_sha256: "<sha256>"
last_frame_sha256: "<sha256>"
duration_seconds: "<same value>"
aspect_ratio: "<same value>"
local_seed: "<record if exposed>"
hosted_seed: "<record or not_exposed>"
ローカルとホストの両方がこの記録を読みます。ホストUIがseedを隠す、promptを書き換える、長さを制限する場合はnot_exposedと記録するか、書き換え後のpromptを保存します。確認できない値を同一と扱わないでください。見える入力を制御して初めて差を解釈できます。
手順4:まずH3-Baseのローカル768pを成立させる
2Kを考える前に768p結果を受け入れられる状態にします。Qwenの静止画が2Kでも、ローカルH3-Base動画が2Kになるわけではありません。
MiniMaxは二つのタスク別チェックポイントを公開しています。ここではMiniMax-H3 Base FL2VAを使い、テキスト、最初、最後、または両方のフレームからBF16で音声付き動画を生成します。公式ダウンロードとSGLang例は次の通りです。
hf download MiniMaxAI/MiniMax-H3 \
--include "FL2VA/*" \
--local-dir MiniMax-H3
sglang serve \
--model-path MiniMaxAI/MiniMax-H3 \
--num-gpus 4 \
--ulysses-degree 4 \
--performance-mode speed \
--host 0.0.0.0 \
--port 30010 \
--model-variant fl2va
二つ目はMiniMaxの4 GPU例です。Wassermanが公開したDGX Spark設定でも、最小要件でもありません。選んだフレームワークの文書に従って調整し、変更をすべて記録してください。どの機械でも動く証拠として扱わないでください。
首尾フレームを SGLang プロセスから見える場所に置く
FL2VA の conditions には、role: "keyframe" の画像を1枚または2枚指定できます。SGLang の公式 H3 ガイドでは、frame_index: 0 が最初のフレーム、frame_index: -1 が最後のフレーム、[0, -1] が首尾フレームの組み合わせです。MiniMax の再現スクリプトは最初のフレーム1枚の形を示しているため、以下では同じ fields を使って2枚を指定します。
file:// URI を解決するのは curl を実行する端末ではなく、SGLang サーバープロセスです。両方が同じホストなら realpath の絶対パスを使えます。SGLang がコンテナ内または別マシンで動く場合は、2枚をその環境へ mount または copy し、FIRST_URI と LAST_URI をサーバーから読めるパスに変更します。
ショット契約は prompt.txt に保存します。完全ローカル768pでは、自分で整えた構造化 prompt を使えます。ハイブリッド2Kでは、H3-Context-IR の結果を同じ prompt field に入れ、H3-Base の出力を H3-Regenerate-2K に渡します。
FL2VA を送信し、完了を待って MP4 を保存する
以下は公式の非同期 lifecycle に沿います。POST /v1/videos で job を作成して .id を読み、GET /v1/videos/{id} を poll し、status が completed になった後だけ GET /v1/videos/{id}/content を呼びます。公式 cookbook では failed が終端エラーで、それ以外の空でない status は待機を続けます。
set -euo pipefail
BASE_URL="${BASE_URL:-http://127.0.0.1:30010}"
FIRST_URI="${FIRST_URI:-file://$(realpath first.png)}"
LAST_URI="${LAST_URI:-file://$(realpath last.png)}"
PROMPT_FILE="${PROMPT_FILE:-prompt.txt}"
OUTPUT_FILE="${OUTPUT_FILE:-fl2va.mp4}"
payload=$(
jq -n \
--rawfile prompt "$PROMPT_FILE" \
--arg first "$FIRST_URI" \
--arg last "$LAST_URI" \
'{
model: "MiniMaxAI/MiniMax-H3",
task: "fl2va",
prompt: $prompt,
seconds: 8,
conditions: [
{
type: "image",
uri: $first,
role: "keyframe",
frame_index: 0
},
{
type: "image",
uri: $last,
role: "keyframe",
frame_index: -1
}
],
target: {
short_edge: 768,
aspect_ratio: "auto",
duration_seconds: 8
},
seed: 0
}'
)
response=$(
curl --fail-with-body --silent --show-error \
--request POST \
--url "$BASE_URL/v1/videos" \
--header 'Content-Type: application/json' \
--data-binary "$payload"
)
video_id=$(printf '%s\n' "$response" | jq -er '.id')
printf 'video_id=%s\n' "$video_id"
while true; do
task_json=$(
curl --fail-with-body --silent --show-error \
--request GET \
--url "$BASE_URL/v1/videos/$video_id"
)
status=$(printf '%s\n' "$task_json" | jq -er '.status')
printf 'status=%s\n' "$status"
case "$status" in
completed)
break
;;
failed)
printf '%s\n' "$task_json" | jq .
exit 1
;;
*)
sleep 1
;;
esac
done
curl --fail-with-body --silent --show-error --location \
--request GET \
--url "$BASE_URL/v1/videos/$video_id/content" \
--output "$OUTPUT_FILE"
test -s "$OUTPUT_FILE"
if command -v ffprobe >/dev/null 2>&1; then
ffprobe -v error \
-show_entries stream=codec_type,codec_name,r_frame_rate,sample_rate,channels \
-of default=noprint_wrappers=1 \
"$OUTPUT_FILE"
fi
printf 'saved=%s\n' "$OUTPUT_FILE"
curl --fail-with-body は非2xx応答で停止し、.id または .status がなければ jq -e が失敗します。failed の場合は job の完全な JSON を表示して非0で終了します。成功とみなすには、content の取得が成功し、MP4 が空でないことも必要です。
ffprobe が入っていれば、media stream も表示します。SGLang の文書化された出力 contract は、H.264動画24 FPSとAACステレオ32 kHzを含むMP4です。job が completed でも、ファイルが空、decode不能、またはmedia属性が想定外ならホスト版比較へ進まず、SGLang log、サーバーから見える画像URI、request JSONを先に確認します。
fields と endpoints は、MiniMax公式の再現用FL2VAスクリプト、SGLang MiniMax-H3 cookbook、SGLang video APIガイドに基づきます。完全ローカル経路はここでH3-Baseの768p MP4を得て終了し、完全2Kは前述のハイブリッド経路を使います。
手順5:ローカル経路が安定してからホスト版と比較する
ローカル経路がまだ失敗している段階で品質を比較しないでください。導入エラー、入力差、モデル挙動を切り分けられなくなります。変えるのは実行場所だけです。
- バイトが同じ首尾フレームをアップロードし、hashを確認します。
- prompt、長さ、アスペクト比、言語、音声意図を揃えます。
- Web/APIがpromptを書き換えるか、seedを公開するか、H3-Context-IRを使うか記録します。
- 元の出力を保存し、比較前に編集、再エンコード、音楽追加をしません。
- 出所を隠してブラインド評価し、「ローカルが良い」「有料が良い」という先入観を減らします。
コストを比較するなら、実際のAPI請求、マシン占有時間、電力使用量を記録します。「ローカル」と「有料Web」というラベルだけでは、あなたの処理でどちらが安いか判断できません。
手順6:同じ評価表で自分のショットに合う経路を選ぶ
最初に創作タスクを達成したかを確認し、その後で時間とハードウェアを比べます。高解像度でも不要なカットを繰り返す結果は、制作には向かない場合があります。
| 評価項目 | 見方 | 記録するもの |
|---|---|---|
| 最初のフレームへの忠実度 | 冒頭が人物、構図、主要物体を維持するか、すぐ別画像になるか | ずれと時刻 |
| 最後のフレームへの到達 | 最終状態へ自然に到達するか、最後の画像へ急に切り替わるか | 最終状態と遷移品質 |
| 一つのショットの連続性 | 指示していないカット、瞬間移動、背景置換、時間ジャンプがあるか | カット時刻と前後画像 |
| 人物・背景の安定性 | 顔、服、手、道具、背景形状が安定するか | ずれた対象と継続時間 |
| 動きの経路 | 主体とカメラが指定順・方向で動くか | 方向違い、速度変化、停止 |
| 音声 | 必要時にトラックがあり、同期し、ノイズや無関係な内容がないか | メディア情報、同期ずれ、異常区間 |
| 出力仕様 | 長さ、比率、FPS、解像度が設定通りか | 実メタデータ |
| 実行資源 | 経過時間、アクセラレータ最大メモリ、システムメモリ、再試行 | 推測ではなく各実行の生ログ |
| 再現性 | 同じ入力を再実行したとき問題が繰り返すか | 再実行結果と公開された乱数設定 |
MiniMaxは32 kHzステレオ生成を説明していますが、Wassermanの投稿は音声を有効化・保持・後処理したか示しません。自分の出力は検査できますが、この事例を音質検証として引用できません。
全部を再実行せず、上流の問題から直す
最初のフレームの誤りはQwen、連続性の問題はH3、解像度の不一致はローカル768pとハイブリッド2Kの選択から確認します。層ごとの診断は全パラメータを同時に変えるより短時間です。
| 症状 | 最初に確認 | 対処 |
|---|---|---|
| 最初のフレームがすでに違う | Qwen画像段階 | H3で直そうとせず、prompt、参照、seedを修正 |
| 最後に人物や背景が変わる | Qwen受け渡し画像 | 独立生成ではなく最初の画像から編集し、変更を減らして参照を再利用 |
| 不要なカットが入る | H3 promptと動き制約 | 一つの連続ショットを明記し、モンタージュ・複数場面の語を削除し、同じhashで再実行 |
| 最後へ到達しない | 長さと動作計画 | 動作を減らし、開始—過程—終了を明示 |
| 音声がない、合わない | H3変種、クライアント、コンテナ | 音声付き動画チェックポイントと経路を確認し、同等音声がない実行は比較不可とする |
| Qwenがメモリ不足 | 画像実行環境 | 公式CPU offloadを試し速度影響を測る。普遍的最小VRAMを推測しない |
| H3が起動しない | H3実行環境 | フレームワークの導入ガイドを確認。公式例は4 GPUで、一般GPUは保証されない |
| ローカルは768pで2KにAPIが要る | ワークフロー境界 | 文書化された設計であり故障ではない。768pを受け入れるかハイブリッド2Kへ切り替える |
| ローカルとホストが大きく違う | 入力と前処理 | prompt書き換え、Context-IR、seed、長さ、比率、再エンコードを確認してからモデル差と判断 |
長期運用でローカル版かホスト版かを決める方法
一番良く見えた一例ではなく、自分のショット集合で決めます。固定カメラ、人物動作、物体変形、台詞、環境音を含め、成功と失敗を両方保存し、次の値を分けて記録します。
- 動画の長さ:公開例なら約8秒
- 生成時間:投入から完成までの経過時間。公開例では未開示
- モデル仕様:公式文書に書かれた範囲
- 実際のハードウェア使用量:機器名から推測せず自分で測った値
- 一回の視覚評価:その実行は説明できるが、全体勝率にはできない
素材を手元から出せないなら、ローカル768pを既定にします。最終納品が2K必須でリモートAPIを許容できるなら、ハイブリッド2Kを選びます。連続性を最優先するなら、同じショット集合でローカル版とホスト版をブラインド評価し、評価表をより安定して通過する方を優先します。公開事例はローカル経路が動き、同一入力の一例で不要なカットを避けたことを示すだけで、反復試験の代わりにはなりません。
実行前に確認する8項目
- 「完全ローカル768p」または「ハイブリッド2K」と正しく表示した。
- 両フレームのQwenモデル、prompt、seed、寸法、参照を記録した。
- 画像とpromptにhashがあり、二つのH3実行が同じ入力を使う。
- ローカルは
fl2vaを使い、まずH3-Base 768pとして検収した。 - ホスト側のprompt書き換えや非公開パラメータを正直に記録した。
- 元動画を編集せず、同じ連続性・カット・音声・仕様基準で評価した。
- 経過時間、最大メモリ、再試行、失敗はログから取得した。
- 結論を試した入力、ハードウェア、確認日に限定した。
まとめ
既定の推奨は明確です。**Qwen Image 2.1で首尾フレームをローカル作成し、MiniMax H3-Base fl2vaでローカル768pを成立させます。**2Kが必須でリモートAPIを許容できる場合だけ、H3-Context-IR → ローカルH3-Base → H3-Regenerate-2Kへ進みます。
どちらを選んでも、フレーム、prompt、長さ、アスペクト比を固定し、同じ入力で連続性、不要なカット、音声、時間、ハードウェア使用量を比較します。これで見栄えの良いデモが、監査・比較して採用を判断できるワークフローになります。
参考リンク
- Qwen Image 2.1公式リポジトリ
- MiniMax H3公式オープンソース発表
- MiniMax H3公式の再現用FL2VAリクエスト
- SGLang MiniMax-H3公式cookbook
- SGLang Diffusion video APIガイド
- Sam Wassermanのローカルエンドツーエンド実行
- 同一入力を使った同作者のWeb H3比較
事実確認日:2026年9月26日。