MiniMax-H3(旧 /home/animede/minimax-h3、port 8611)と LTX-2.5
(旧 /home/animede/diffusers-ltx2_5、port 8000)を1つのゲートウェイに統合した
動画+音声生成サーバ。torch のメジャーバージョンが衝突する2バックエンドを
「専用 venv の別プロセス + 統一ゲートウェイ」で共存させる。
- 計画・経緯:
docs/INTEGRATION_PLAN.md(非公開・ローカル) - API 完全仕様:
docs/API_SPEC.md - 旧サーバからの移行:
docs/MIGRATION.md(非公開・ローカル) - 各フェーズの作業記録:
docs/phase0-*.md〜(非公開・ローカル)
動画生成の最新版はこのリポジトリに集約します。
diffusers-server(8601)このサーバ(8630) 画像系(T2I/I2I/Edit/ControlNet/Tポーズ 等) あり なし 動画 LTX-2.3 LTX-2.5 / MiniMax-H3 リップシンク(歌唱の口パク) なし あり(vocal_lock)
diffusers-serverにも LTX-2.3 の動画機能がありますが、両方を追従して保守するのは 手間に見合わないため、LTX-2.5 / H3 への更新は行いません(現状維持)。 動画系の新規開発・上流追従はこのリポジトリだけで行います。アプリ側は「画像は 8601(または 8620)、動画は 8630」と接続先を分けて併用する構成を 想定しています(実例:
mv_studio_V3)。
クライアント / ブラウザ
│
▼
┌──────────────────────────── gateway (port 8630, 軽量venv) ────────────────────────────┐
│ GET / タブ切替GUI(iframe で既存SPAを表示 + バックエンド管理) │
│ /api/v1/* 統一API(backends/status/load/unload/generate/jobs/assets…)│
│ /h3/* → 127.0.0.1:8631 パススルー(未起動時 502) │
│ /ltx25/* → 127.0.0.1:8632 パススルー(未起動時 502) │
│ /h3/outputs /ltx25/outputs 静的配信(バックエンド停止後も成果物URLが生きる) │
│ procman: 既定は同時1バックエンド(切替 = 旧stop → 新start)。coresident では両方常駐 │
└───────────────┬───────────────────────────────┬───────────────────────────────────────┘
▼ ▼
backends/minimax-h3 (port 8631) backends/ltx2_5 (port 8632)
torch 2.9.0+cu128 / 同期API torch 2.11.0+cu130 / 非同期ジョブAPI
venv → /home/animede/minimax-h3 .venv → /home/animede/diffusers-ltx2_5
1プロセス統合が不可能な理由(torch/diffusers/transformers の非互換)は
docs/INTEGRATION_PLAN.md(非公開・ローカル)冒頭の表を参照。
| ポート | 用途 |
|---|---|
| 8630 | gateway(統一API・GUI・パススルー)。GW_PORT で上書き可 |
| 8631 | MiniMax-H3 バックエンド(内部)。H3_PORT で上書き可 |
| 8632 | LTX-2.5 バックエンド(内部)。LTX25_PORT で上書き可 |
LAN クライアントから GUI を使う場合、iframe がバックエンドポートへ直接接続するため 8630 だけでなく 8631/8632 も開放が必要(既知の制約参照)。
venv・モデル・量子化済み重みは旧ディレクトリへの symlink 共有(Phase 0 方針)。 以下が存在しないと動かない:
| symlink | 実体 |
|---|---|
backends/minimax-h3/venv |
/home/animede/minimax-h3/venv(torch2.9+cu128、diffusers PR#14355 ピン留め) |
backends/minimax-h3/models |
/home/animede/minimax-h3/models(prequant TE キャッシュ 36GB) |
backends/ltx2_5/.venv |
/home/animede/diffusers-ltx2_5/.venv(torch2.11+cu130、NATTEN) |
backends/ltx2_5/LTX-2.5-Diffusers-bnb-4bit |
旧ディレクトリの量子化済み 27GB |
backends/ltx2_5/loras |
旧ディレクトリ(IC-LoRA 2本、1.6GB) |
旧ディレクトリ(/home/animede/minimax-h3・/home/animede/diffusers-ltx2_5)は
削除禁止。完全独立化(venv 再構築)は Phase 5 の任意タスク
(手順: backends/*/VENV_REBUILD.md)。
gateway だけは自前の軽量 venv(CUDA 系依存なし):
cd gateway
python3 -m venv venv
venv/bin/pip install -r requirements.txt # fastapi / uvicorn / httpx / python-multipart./run.sh # gateway を port 8630 で起動(バックエンドは起動しない)バックエンドは API か GUI から起動する:
curl -X POST http://127.0.0.1:8630/api/v1/backend/load \
-H 'Content-Type: application/json' -d '{"backend":"h3"}' # 既定 96gb
curl -X POST http://127.0.0.1:8630/api/v1/backend/load \
-H 'Content-Type: application/json' \
-d '{"backend":"h3","preset":"48gb-lowvram"}' # プリセット指定
curl -X POST http://127.0.0.1:8630/api/v1/backend/unload # 停止既定では同時にロードできるのは1バックエンドのみ。別バックエンドの load は自動で 旧 stop → 新 start(排他切替)。生成中(busy)の load/unload/generate は 409。
VRAM は両方に載せたまま、生成(実行)だけを排他するモード。LTX をリアルタイム用に 常駐させたまま H3 も使いたい、という用途のために足した。切替コストがゼロになる。
curl -X POST http://127.0.0.1:8630/api/v1/backend/load \
-H 'Content-Type: application/json' -d '{
"backend":"ltx25","preset":"nvfp4-fast","gpus":"0","strategy":"coresident"}'
curl -X POST http://127.0.0.1:8630/api/v1/backend/load \
-H 'Content-Type: application/json' -d '{
"backend":"h3","preset":"48gb-lowvram","gpus":"0","strategy":"coresident",
"toggles":{"turbo":true}}'
# 片方だけ降ろす(プロセスは温存、次回は reactivate で復帰)
curl -X POST http://127.0.0.1:8630/api/v1/backend/unload \
-H 'Content-Type: application/json' -d '{"strategy":"coresident","backend":"h3"}'-
/api/v1/statusのloaded_backendsが同時ロード中のバックエンド一覧。active_backendは単一値なので同居時は先頭しか表せない(後方互換用) -
生成は直列化される。他バックエンドが生成中の
/api/v1/generateは 409 (同一GPUで生成を重ねると LTX 1.89倍・H3 1.49倍に遅くなり、LTX のリアルタイム 予算 4.8秒を割るため) -
auto_loadは coresident にならない(既定の process 戦略で起動するので 他バックエンドを停止する)。同居させたいときは上のように明示的に load すること -
h3 は同居時だけプリセットを落とす。
96gb(常駐87GB)や96gb-int8(ref2va ピーク 73.8GB)は LTX(常駐33GB)と同じ GPU に載らない。48gb-lowvramが同居の既定解で、実測は下表のとおり:構成(ref2va 768×448・5秒・turbo、LTX 常駐中、定常値) 所要 GPU0 全体ピーク TE 48gb-lowvram40.5秒 74.5GiB(余裕21.0) 32B のまま 96gb-int8+ 投影TE27.5秒 83.2GiB(余裕12.4) 投影4B denoise(14.4s)も decode(3.4s)もほぼ同一で、差は全部フェーズ循環の固定費。 1本13秒の代償で品質劣化ゼロ + 余裕 8.6GiB 増なので、品質重視の用途では
48gb-lowvramを選ぶこと。投影TE(H3_TE_PROJ)は近似で、細部のプロンプト追従が 落ちる(PSNR 22.64dB / 鮮鋭度 -23%)。速度が要る用途でだけ検討する -
LTX の
upscaleは同居時 409 で止める(ガード実装済み)。2段アップスケールの デコードは 480×640×97f でも GPU 全体 94.3GiB に達し、同居すると確実に OOM するため。upscaleの既定は true なので、何も指定しないクライアントが踏む点に注意 (リアルタイム経路の realtime-narration-video は常にextra.upscale=falseを送るので無影響)。 静止画モード(t2i/ref2i/refine_image)は跳ね上がらないので対象外(同居中の t2i 512² を実測 80.9GiB で完走確認)。逃げ道はGW_ALLOW_UPSCALE_CORESIDENT=1
同居しただけでは「先に生成を始めた方が勝つ」ので、H3 の t2va(約25秒)が走り出した 直後に会話チャンクが来ると、LTX の 4.8秒予算に対して25秒待たされる。H3 は途中で 止められないので、始まってから優先度を付けても間に合わない。そこで会話アプリに 会話の開始を宣言してもらい、その間は相手の投入を入口で断る。
# 会話ターン開始
curl -X POST http://127.0.0.1:8630/api/v1/realtime/lease \
-H 'Content-Type: application/json' -d '{"backend":"ltx25","ttl_s":60}'
# → {"result":"acquired","lease_id":"...","expires_at":...}
# チャンクごとに延長(lease_id を渡すと renew)
curl -X POST http://127.0.0.1:8630/api/v1/realtime/lease \
-H 'Content-Type: application/json' -d '{"backend":"ltx25","ttl_s":60,"lease_id":"..."}'
# 会話ターン終了
curl -X DELETE 'http://127.0.0.1:8630/api/v1/realtime/lease?lease_id=...'
curl http://127.0.0.1:8630/api/v1/realtime/lease # 現在の保持者保持している間:
| 操作 | 結果 |
|---|---|
保持者の /api/v1/generate |
通常どおり |
他バックエンドの /api/v1/generate |
409 |
他バックエンドの backend/load(process / resident) |
409(保持者の VRAM を奪うため) |
他バックエンドの backend/load(coresident) |
許可(保持者に触らないため) |
保持者の backend/unload |
409 |
| 別バックエンドによるリース取得 | 409 |
- TTL は必須の安全網。会話アプリが落ちてもリースは自動失効し、ゲートが開きっぱなしに ならない。既定60秒・範囲5〜600秒。チャンクごとの renew を推奨
releaseにlease_idを渡すと一致するときだけ解放する(古いターンの release が 新しいターンのリースを消さないため)/api/v1/statusのrealtime_leaseで現在の保持者・残り時間が見える
実測(2026-09-15、GPU0 = RTX PRO 6000 96GB / 95.6GiB):
| 状態 | GPU0 |
|---|---|
LTX nvfp4-fast 常駐のみ |
33.1GiB |
| LTX + H3 両方常駐 | 69.6GiB |
| H3 ref2va×2 ピーク(最大) | 83.2GiB(余裕 12.4GiB) |
| LTX 生成(480×640×97f・steps4) | 単独 3.46秒 → 同居 3.56〜3.81秒(劣化なし) |
| H3 t2i 768² / t2va 5秒 / ref2va 連続 | 7.14秒 / 24.8秒 / 27〜28秒 |
| 切替コスト | 0(再ロードなし) |
バックエンドは gateway が subprocess.Popen で起動・管理する。run.sh を直接叩いて
手動起動すると、gateway からは管理外のリスナーに見えるため、
procman.py の _start_locked() がポート使用中を検出して ForeignListenerError
→ /api/v1/generate が常に 409 になる(2026-09-02 に実際に発生)。
gateway は起動時の adopt_orphans() でのみ既存プロセスを引き取れる。条件は
gateway/run/{backend}.pid があり、その PID が生きていて、ポートが listen 中の3つ。
手動起動するなら PID ファイルもセットで書き、gateway を再起動して adopt させること:
# 例: 手動起動した h3 を gateway に引き取らせる
echo <PID> > gateway/run/h3.pid # backend 名は h3 / ltx25
kill -TERM <gateway PID> && ./run.sh # 起動時に adopt_orphans() が走る/api/v1/status で process_alive: true かつ adopted: true になれば成功
(gateway のログにも「孤児プロセスを adopt しました」が出る)。
なお adopt されたプロセスは preset が (adopted: 不明) になる。素直に
POST /api/v1/backend/load で gateway に起動させる方が状態は綺麗。
| preset | env | 想定/実測 VRAM |
|---|---|---|
96gb(既定) |
なし | 常駐 87.3GB、t2v 768²×5s peak 91.93GB(実測)。96GB 専有前提 |
48gb-lowvram |
H3_LOWVRAM=1 H3_TE_PRUNE=1 H3_VIDEO_VAE_FP16=1 |
t2v peak ~38.9GB |
32gb-group |
H3_LOWVRAM=group H3_TE_PRUNE=1 |
peak ~17.7〜28.7GB |
16gb-proj |
H3_LOWVRAM=group H3_TE_PROJ=… H3_VIDEO_VAE_FP16=1 H3_ATTN_BACKEND=default |
peak ~11.4GB |
dual-realtime-ref2va |
pruned ck-w4a8 + 2GPU decode 分離ほか(backends.py 参照) | ref2va リアルタイム(0.89x)。GPU0 96GB 級 + GPU1 8GB 級 |
dual-realtime-ref2va-32gb |
同上の低VRAM版 | GPU0 peak 27.3GB(32GB 級可)+ GPU1 8GB 級、0.93x |
ref2va-only-32gb |
ref2va 単独(待機 = 無音 ref2va、base 不使用) | 単機 1GPU、peak 25.6GB、320×448 で 0.95x |
ref2va-only-24gb |
同上の 24GB 版(VAE 退避) | 単機 1GPU、peak 20.4GB、320×448 で 1.21x |
- GPU 専有が前提: 空き VRAM が 24GB 級は 23GiB 以上、32GB 級は 28GiB 以上 必要。TTS・LLM は同じ GPU に同居できない(CPU か別ホストへ)。 デスクトップ描画が同じ GPU に乗っている場合はその分も差し引くこと。
- 初回はキャッシュ作成の要件が別にある(2回目以降は不要):
- ref 側 ck-w4a8 キャッシュ:
multimodalart/MiniMax-H3-Prunedの bf16(~38GB DL) から初回リクエスト時に自動量子化。空きホスト RAM 45GB 以上が必要 (当方は 48GB 級 GPU 上で作成。24GB カード上での初回量子化は未検証) - base 側 ck-w4a8 キャッシュ:
Kijai/MiniMax-H3-experimentalのminimax_h3_fl2va_pruned_w4a8_mixed.safetensors(12.5GB)をダウンロードしてbackends/minimax-h3/scripts/convert_kijai_w4a8.pyで変換(GPU 不要)
- ref 側 ck-w4a8 キャッシュ:
- ホスト RAM: pinned 常駐を合計 ~32〜45GiB 消費する(TE_STREAM 13 +
base 13 + ref 13.6 + VAE 5.4)。RAM 64GB 機では
H3_REF_PINNEDかH3_TE_STREAMのどちらかを overrides で外すこと(128GB 機は問題なし)。 - 解像度は 320×448 推奨(32GB 単騎リアルタイム 0.95x の実測点)。352×640 も 動くが 1.55x(非リアルタイムの画質枠)。
- 会話アプリ(r-n-v)と組む場合:
ref2va-only-*では待機動画の生成方式をsilent_ref2va(UI のライブ設定)にすること。既定の fl2va のままだと待機の たびに base のロードが走り、24GB では窮屈になる。 ref2va-only-24gbのH3_KEEP_REF2VA_VAE=0を 1 に変えないこと: 発話の 連投は通っても、発話⇄待機のプロンプト切替(prefix 再エンコード)で OOM する (実機再現済み)。
- トグル:
turbo(H3_TURBO_LORA=1)。int8 量子化・H3_LOWVRAM=groupとは併用不可(400) - overrides は
H3_プレフィックスのみ許可 - MV 本番の既定値は
backends/minimax-h3/run.shが持つ(2026-09-02 に追加)。H3_TURBO_LORA_FILE(= ref2v 専用蒸留minimax_h3_ref2v_turbo_4step_v0.1_bf16。 2026-08-26 の A/B で採用、commit 025e0c0)・H3_VOCAL_LOCK=1・H3_REF_PREFIX_CACHE_SINGLE=1の3つで、いずれもcore/runner.pyの既定とは異なる。 以前はプロセスの環境変数にしか無く、再起動のたびに失われていた。 すべて${VAR:-...}なので preset/トグル/手動 export で上書きできる。H3_TRANSFORMER_QUANTは run.sh に書かないこと —96gbがenv={}(bf16)、96gb-int8だけが int8 を渡す設計なので、既定値を与えると96gbが黙って int8 になる H3_KEEP_TRANSFORMER=1はH3_TE_DEVICE(またはH3_TE_PROJ)+H3_VIDEO_VAE_FP16=1が前提(満たさないと 400。単独GPU構成の既定プリセットには含めていない)
| preset | env | 想定/実測 VRAM |
|---|---|---|
nf4(既定) |
なし | t2i peak ~17.2GB。t2v 121f(2段アップスケール込み)は nvidia-smi 観測 31.5GB(実測) |
fp8 |
LTX25_TRANSFORMER_PRECISION=fp8 |
常駐 ~18GB / peak ~29GB |
bf16 |
LTX25_TRANSFORMER_PRECISION=bf16 OFFLOAD_MODE=none |
transformer ~38GB + TE/VAE。96GB級向け |
- overrides は
LTX25_*+ config.py 由来キー(OFFLOAD_MODE/OUTPUT_DIR等)のみ許可
完全仕様は docs/API_SPEC.md。
# 生成(未起動なら auto_load で自動起動。202 → ジョブID をポーリング)
curl -X POST http://127.0.0.1:8630/api/v1/generate \
-H 'Content-Type: application/json' -d '{
"backend": "ltx25", "mode": "t2v",
"params": {"prompt": "a red fox in a snowy forest", "width": 512, "height": 512,
"num_frames": 121, "seed": 42},
"auto_load": true, "preset": "nf4"}'
# ジョブ照会 / 一覧
curl http://127.0.0.1:8630/api/v1/jobs/<job_id>
curl 'http://127.0.0.1:8630/api/v1/jobs?limit=20'
# 画像アセットをアップロードして i2v
curl -X POST http://127.0.0.1:8630/api/v1/assets -F file=@input.png # → {"id": "..."}
curl -X POST http://127.0.0.1:8630/api/v1/generate \
-H 'Content-Type: application/json' -d '{
"backend": "ltx25", "mode": "i2v",
"params": {"prompt": "the scene comes alive", "seconds": 2},
"asset_ids": ["<asset_id>"]}'
# 成果物の統合一覧 / プロンプト強化
curl http://127.0.0.1:8630/api/v1/outputs
curl -X POST http://127.0.0.1:8630/api/v1/prompt/enhance \
-H 'Content-Type: application/json' -d '{"backend":"h3","prompt":"a cat"}'統一 mode: t2v / i2v / flf2v / ref2v / t2i / ref2i(両対応)、
a2v / extend / retake / iclora / refine_image(ltx25 のみ、h3 は 400)。
旧クライアントはパススルー URL に置き換えるだけで移行できる(API 仕様は不変)。
詳細は docs/MIGRATION.md(非公開・ローカル)。
| 旧 | 新 |
|---|---|
POST :8611/api/t2va |
POST :8630/h3/api/t2va |
POST :8611/api/fl2va |
POST :8630/h3/api/fl2va |
POST :8611/api/ref2va(/ref2va_batch /ref2i_batch) |
POST :8630/h3/api/ref2va(同) |
POST :8611/api/t2i(/t2i_batch) |
POST :8630/h3/api/t2i(同) |
GET :8611/api/status / /api/progress |
GET :8630/h3/api/status / /h3/api/progress |
GET :8611/api/settings / POST /api/settings/apply |
:8630/h3/api/settings(同) |
GET :8611/api/outputs / POST /api/outputs/delete / /api/outputs/concat |
:8630/h3/api/outputs(同) |
POST :8611/api/prompt/enhance |
POST :8630/h3/api/prompt/enhance |
GET :8611/outputs/<file> |
GET :8630/h3/outputs/<file>(gateway 静的配信) |
GET :8611/(SPA) |
GET :8630/(GUI の H3 タブ)または直接 :8631/ |
| 旧 | 新 |
|---|---|
POST :8000/api/jobs / GET /api/jobs / GET・DELETE /api/jobs/{id} / POST /api/jobs/concat |
:8630/ltx25/api/jobs…(同) |
POST :8000/api/assets |
POST :8630/ltx25/api/assets |
GET :8000/api/health / /api/loras |
:8630/ltx25/api/health / /ltx25/api/loras |
POST :8000/api/sessions |
POST :8630/ltx25/api/sessions |
POST :8000/api/prompts/enhance |
POST :8630/ltx25/api/prompts/enhance |
GET :8000/outputs/<file> |
GET :8630/ltx25/outputs/<file>(gateway 静的配信) |
GET :8000/(SPA) |
GET :8630/(GUI の LTX タブ)または直接 :8632/ |
GET http://127.0.0.1:8630/ — タブ3つ(MiniMax-H3 / LTX-2.5 / バックエンド管理)。
- バックエンドタブは既存 SPA を iframe 表示。未起動ならプリセット選択付きの 起動オーバーレイ(別バックエンド稼働中は確認ダイアログ付き切替)
- 管理タブ: 状態カード(アクティブ/preset/PID/VRAM バー)・起動/切替/アンロード・ 統一ジョブ一覧(進捗バー・成果物リンク、DOM 差分更新でちらつきなし)
- 詳細・検証記録:
docs/phase3-gui.md(非公開・ローカル)
| 操作 | 所要時間 | VRAM |
|---|---|---|
h3 96gb 起動(クリーン → ヘルスOK) |
45s(切替込みの2回目 64.1s) | 常駐 86.6GB |
| h3 t2v 768²×5秒(124f・30steps) | 155.6s(denoise 103.7s) | peak 91.93GB |
| h3 t2i 512² | 54.1s | peak 87.7GB |
h3 48gb-lowvram 起動 |
~10〜14s | t2v peak 38.94GB / t2i 34.96GB |
| h3 t2v 768²×5秒(48gb-lowvram) | 177.5s | peak 38.94GB |
ltx25 nf4 起動 |
2.1s(遅延ロード) | — |
| ltx25 t2i 512²(初回ロード込み) | 61.2s | peak 17.2GB |
| ltx25 t2v 512²×121f | 97.5s | 20.9GB(nvidia-smi 観測 31.5GB) |
| ltx25 i2v 512²×2秒 | 16.3s | peak 19.0GB |
| バックエンド切替(h3⇔ltx25) | 9.1s(→ltx25)/ 64.1s(→h3 96gb) | — |
| unload → ベースライン復帰 | 4.1s | GPU:0 2.8GB |
- h3
96gbは 96GB 専有前提。t2v 768²×5s の peak 91.93GB はベースライン ~3GB との合算で 94.7GB/97.9GB と際どい。他プロセスが VRAM を使う環境では48gb-lowvramを使うこと(Phase 4 発見事項)。 H3_KEEP_TRANSFORMER=1は単独GPU構成の既定プリセットでは使えない (TE_DEVICE/TE_PROJ + VIDEO_VAE_FP16=1 が前提。overrides で明示、Phase 1 発見事項)。- h3 の progress は混線しうる:
/api/progressはグローバル状態のため、統一 API の ジョブ実行中にパススルーで別生成を直接叩くと progress 値が混ざる(統一 API のみの 単一飛行なら問題なし)。また起動プリロード中のフェーズ表示がloading_transformerのまま TE ロードを表示する場面がある(表示上のみ)。 - LAN クライアントは 8631/8632 も開放が必要(GUI の iframe がバックエンドポート へ直接接続するため)。
- ltx25 の
.envに HF_TOKEN は入っていない。HF キャッシュ共有 + pinned revision で動作しており、キャッシュ削除時や gated repo 利用時はbackends/ltx2_5/.envへのHF_TOKEN=追記が必要(Phase 0 発見事項)。 - ltx25 nf4 の VRAM ヒント(~17.2GB)は t2i 実測。長尺 t2v(121f、既定2段 アップスケール)は nvidia-smi 観測 31.5GB に達する。24GB 級では要調整 (Phase 4 発見事項)。
- 統一ジョブは非永続(gateway 再起動で消える。成果物・ltx25 履歴 DB は残る)。
GET /api/v1/outputsは既定 outputs/ 固定(OUTPUT_DIR overrides に非追従)。 - h3
/api/t2iに512x512の resolution プリセットは無い (height=512&width=512を明示。統一 API は常に width/height を明示送信する)。 - h3 の
negative_prompt/guidance_scale/fpsは無視される(notes に記録)。 - venv・モデルは旧ディレクトリへの symlink 共有 — 旧ディレクトリ削除禁止
(
docs/MIGRATION.md(非公開・ローカル)参照)。
このリポジトリで独自に実装したアプリケーションコードは Apache License 2.0 で提供します。
Important
Apache License 2.0 は MiniMax-H3 / LTX-2.5 / Gemma 等のモデル重み、派生 LoRA・チェックポイント、その他の第三者製コンポーネントには適用されません。各モデルのライセンスを個別に確認してください。