[Feature]: TeaCache support for Wan2.2 V2V / VACE pipeline
#5,079 opened on Jul 13, 2026
Repository metrics
- Stars
- (4,990 stars)
- PR merge metrics
- (PR metrics pending)
Description
🚀 The feature, motivation and pitch
Request TeaCache support for Wan2.2-VACE Video-to-Video (V2V) inference. Currently, PR #1365 adds TeaCache for Wan2.2 T2V and I2V, but V2V/VACE is not covered. Why V2V needs TeaCache Wan2.2-VACE V2V inference is expensive (~18-32 min per request for 61 frames at 1280×736 on Ascend 910B). Without cache acceleration, online serving is impractical. However:
cache_dit is broken for V2V: Cached residuals contain stale VACE hint information, causing directional/content deviation from the source video (corr drops from 0.86 to 0.58). See our separate bug report. TeaCache is a better fit for V2V: TeaCache decides whether to skip based on modulated_input similarity. Since VACE hints are injected into the main blocks, modulated_input naturally reflects VACE conditioning changes — TeaCache would only skip steps where VACE conditioning is also similar, avoiding the stale-residual problem of cache_dit.
V2V/VACE is not covered in 1365, because:
V2V uses WanVACETransformer3DModel (extends WanTransformer3DModel with vace_blocks) VACE transformer has additional vace_blocks that compute vace_hints injected into main blocks boundary_ratio mode switches between transformer_1 (high_noise) and transformer_2 (low_noise) — dual-model MoE architecture The extractor's run_transformer_blocks / postprocess pattern needs to handle VACE hint injection
What's Needed
- VACE-aware TeaCache extractor The extractor for V2V must account for WanVACETransformer3DModel.forward():
VACE forward flow (simplified):
1. Patch embedding + condition embedding (same as T2V/I2V)
2. VACE conditioning:
control_hidden_states = self.embed_vace_context(vace_context, ...)
for block in self.vace_blocks:
conditioning_states, control_hidden_states = block(...)
vace_hints.append(conditioning_states)
3. Main blocks WITH vace_hints injection:
for i, block in enumerate(self.blocks):
hidden_states = block(...)
if i in self.vace_layers_mapping:
hidden_states = hidden_states + vace_hints[vace_idx] * vace_context_scale[vace_idx]
4. Output norm + proj + unpatchify
Key considerations:
modulated_input extraction: Same as T2V — block0.norm1(hidden_states, scale_msa, shift_msa). VACE hints are injected AFTER block computation, so modulated_input from block0 is extracted before VACE injection (same as #1365). Skip logic: When TeaCache decides to skip, it must still execute vace_blocks to compute vace_hints for the current step, then reuse cached main-block residuals. This ensures VACE conditioning is always fresh. Alternative: If executing vace_blocks every step is too expensive, the skip decision could incorporate VACE hint L1 distance as an additional signal. 2. Dual-transformer (boundary_ratio) handling V2V pipeline uses boundary_ratio=0.875 to select:
transformer_1 (high_noise model) for timesteps above boundary transformer_2 (low_noise model) for timesteps below boundary TeaCache state must be maintained per-transformer (separate accumulated_rel_l1_distance and previous_* for each), since the two models have different modulated_input distributions.
- Polynomial coefficients Wan2.2-VACE has no calibrated coefficients. Options:
Reuse Wan2.1-T2V-14B coefficients (same transformer architecture, PR #1365 already does this for T2V/I2V): [-3.03e+05, 4.91e+04, -2.66e+03, 5.87e+01, -3.16e-01] Calibrate using coefficient_estimator.py with V2V samples for better accuracy VACE conditioning may shift the optimal coefficients slightly, but Wan2.1 coefficients should be a reasonable starting point
Alternatives
No response
Additional context
V2V request: POST /v1/videos/sync with source video + prompt
Measure: corr between output and source frames, inference time
Before submitting a new issue...
- Make sure you already searched for relevant issues, and asked the chatbot living at the bottom right corner of the documentation page, which can answer lots of frequently asked questions.