Add SCAIL-2 driving-latent conditioning (Phase 1, inference PoC)

Port mechanisms 1+3 of SCAIL-2 (arXiv:2606.10804) to LTX-2: concatenate a
driving video latent directly into the DiT token sequence with a width-axis
RoPE offset (ΔW) so driving coords stay detached from the target video.

- New VideoConditionByDrivingLatent + DrivingMode in ltx-core conditioning,
  modeled on VideoConditionByReferenceLatent (patchify -> positions -> append
  -> attention mask). Applies ΔW width shift, aligns time to the target, and
  guards against RoPE wrap (max_pos) and target/driving shape mismatch.
- Export both from conditioning packages.
- docs/plan.md and docs/tasks.md track the phased port.

Inference-only: no weight changes. Mechanism 2 (in-context mask channels,
patchify_proj widening) and training are deferred to Phase 2+. Validated via
plumbing checks and a real (random-weight) transformer forward smoke run;
visual quality is not validated (requires Phase 2/3 finetuning).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 09:06:35 +08:00
parent 9377758131
commit baa6646fd1
5 changed files with 270 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
# SCAIL-2 → LTX-2 移植計畫
將 SCAIL-2arXiv:2606.10804`zai-org/SCAIL-2`)的端到端角色動畫手法移植到 LTX-2。
> **注意**SCAIL-2 原始實作建構於 **Wan 2.1**,非 LTX-2。座標慣例與架構需翻譯到 LTX 的資料流。
## 三個核心機制
1. **Driving latent 直接串接** — 把驅動影片 latent 直接接進 DiT token 序列(不經骨架/pose 中介),用 width 軸座標偏移 ΔW 讓 driving 座標跟主 video 座標分開。
2. **In-context mask channel** — 疊加額外輸入 channel(1 個環境開關 + K=6 個角色綁定槽,展開為 `4(K+1)=28` channel)到模型輸入,讓模型知道背景/角色對應。
3. **Mode-specific RoPE** — Animation Mode 與 Replacement Mode 用不同的座標指派規則。
## LTX-2 對應落點
| 機制 | LTX-2 落點 | 改權重? |
|---|---|---|
| 1. Driving 串接 + ΔW | 新 `ConditioningItem`clone `reference_video_cond.py`),改 `positions` 偏移 | 否 |
| 3. Mode-specific RoPE | 上述 item 加 `DrivingMode` enum | 否 |
| 2. In-context mask channel | 加寬 `patchify_proj` 輸入 channel + `LatentState` 帶額外 channel + 投影前 concat | **是**(需微調) |
**關鍵洞察**LTX 的 `ConditioningItem.apply_to(latent_state, latent_tools) -> LatentState` 就是「串接進序列」的天然注入點,機制 1+3 **完全不用動 transformer / rope.py**。RoPE 由 `LatentState.positions` `[B,3,T,2]`pixel 座標,axis1=(time,h,w))驅動;ΔW = 對 `positions[:,2]`width)加常數。width 正規化上界 `max_pos[2]=2048`,超過會 wrap。
## SCAIL-2 座標規則(論文)
序列 `[z_ref; z_t; z_driv]`driving 永遠在 width 軸帶固定偏移 ΔW:
| | Animation | Replacement |
|---|---|---|
| z_ref | T=0, H=[0,Hv), W=[0,Wv) | T=0, **H=[ΔH_ref, ΔH_ref+Hv)**, W=[0,Wv) |
| z_t | T=[1,Tv], H=[0,Hv), W=[0,Wv) | T=[0,Tv1], H=[0,Hv), W=[0,Wv) |
| z_driv | T=[1,Tv], H=[0,Hv), **W=[ΔW, ΔW+Wv)** | T=[0,Tv1], H=[0,Hv), **W=[ΔW, ΔW+Wv)** |
## 分階段計畫
### Phase 1 — Driving 串接 item(機制 1+3,推論期 PoC)✅ 已完成
- 純推論、不改權重、不動 `patchify_proj`、不碰 ltx-trainer。
- 用現有 checkpoint 驗證資料流正確性(序列長度、座標偏移、attention mask、denoise_mask、不 wrap)。
- **PoC 僅驗證 plumbing**LTX-2 未經此訓練,畫面不會是正確動畫。
### Phase 2 — In-context mask channel(機制 2checkpoint 手術)⬜ 未開始
- `model.py:158` `patchify_proj``Linear(128, inner)` 加寬到 `Linear(128+28, inner)`
- `LatentState` 增加 optional conditioning-channel 欄位,跟著 patchify/concat/clear 流動。
- 投影前 concat`transformer_args.py:209`)。
- 新輸入欄位 **zero-init**,載入舊 checkpoint 行為不變;寫 checkpoint 轉換 script。
- 新增產生 28-channel mask(環境開關 + 角色槽)的 conditioning item。
### Phase 3 — 訓練整合(ltx-trainer)⬜ 未開始
- dataset 產出 (target, driving, mask),接上 Phase 1/2 conditioning,設微調 loss 與凍結策略。
### Phase 4 — Pipeline + CLI 包裝 ⬜ 未開始
- 仿 `lipdub.py``scail_animation.py` pipeline + arg parser。
## Phase 1 簡化取捨(記錄,Phase 2 需回頭處理)
- (a) driving 時間座標直接複製 target 的(token-wise),故 driving 需與 target 同 F/H/W。
- (b) 單一 frozen driving group 的 `attention_mask` 維持 None(= 全連接,target 完全看得到 driving),與 reference cond 一致。
- (c) **ANIMATION 與 REPLACEMENT 在 Phase 1 產生相同 driving 座標** — mode 差異(z_ref 的 ΔH_ref 高度位移、target 時間原點、mask channel)屬 Phase 2enum 先保留佔位。
## 參考
- 論文:arXiv:2606.10804 — *SCAIL-2: Unifying Controlled Character Animation with End-to-end In-Context Conditioning*
- 官方實作:`zai-org/SCAIL-2`GitHub / HuggingFace),建構於 Wan 2.1
- 藍本檔案:`packages/ltx-core/src/ltx_core/conditioning/types/reference_video_cond.py`