feat(wan video): Introduce transition_video for seamless action-transfer concatenation, compatible with context mode and Wan Animate loop#1946
Open
wuwukaka wants to merge 20 commits into
Open
Conversation
|
Does this support I2V and T2V? Is the input frame length configurable, or is it hardcoded to 32 frames? |
…ext_options This commit addresses an issue where the `transition_video` padding conflicted with WanAnimate's built-in loop logic: - Issue: The 32-frame padding added for `transition_video` artificially increased `num_frames`, causing the condition `num_frames > frame_window_size` to evaluate to True. This falsely triggered the built-in loop mechanism, which subsequently crashed when `context_options` was also enabled. - Fix: Introduced an `effective_frames` calculation that subtracts the 32 padding frames before evaluating the loop condition. This ensures that the built-in loop is only triggered based on the actual target video length.
Author
Resolves a RuntimeError during standard WanAnimate loop generation when transition_video is disabled. The error occurred because the VAE time dimension alignment logic was incorrectly scoped inside the `else` block during the transition_video feature integration.
Use the same BHWC -> CTHW -> RGB -> normalize -> VAE encode flow for transition_video regardless of input size. For mismatched spatial dimensions, resize in BCHW and convert back to BHWC, removing reshape-based tensor reinterpretation that could corrupt channel/frame ordering.
In the context-window sampling branch, partial_img_emb can be None when no image condition is provided (for example, some SCAIL runs). The previous code unconditionally called partial_img_emb.clone(), causing: AttributeError: 'NoneType' object has no attribute 'clone' This change makes image conditioning optional in that path: - build image_cond_in only when partial_img_emb is available - otherwise pass None through to predict_with_cfg This restores safe behavior for context-window sampling without image conditioning and prevents the runtime crash.
- Embed prefix images into bg canvas at encode time (like transition_video), replacing per-window injection during sampling
- Canvas expands by 37 frames (17 prefix + 20 reserve for optional transition)
- Dynamic 1-5 image support: img0(×1), img1(×4), ..., imgN-1(×4)
- Prefix mask=1 for actual frames, unused reserve stays mask=0
- Compatible with transition_video: when both present, transition also embedded in canvas (last 20 frames of 37 expansion), sampler injection skipped
- Non-first context windows prepend indices 0-5 (ref+prefix) to model input for consistency, predictions sliced off after model call
- VAE decode trims first 37 pixel frames when prefix is active
- Fix latent_window_size for non-looping to cover full expanded bg range
…of repeating frame 0 Replace pose_images[0:1].repeat(37) and face_images[0:1].repeat(37) with sparse temporal sampling (every 2nd frame from index 0, reversed) so the 37-frame expansion region carries a varied motion preview rather than a static copy of the first frame.
Replace repeat-first-frame padding with sparse stride-2 reversed sampling for mask and bg_images, matching the pose/face expansion logic. All four control signals now share consistent temporal context in the 37-frame expansion region.
- Add dynamic prefix frames (1-5 images, img0×1 + imgN×4 pattern) - Expand canvas by 21/37 frames at encode time (transition/prefix) - Embed prefix and transition into canvas before VAE encode, removing per-window injection logic from the sampling loop - Unify pose/face/mask/bg padding to stride-2 reversed sampling - Support looping mode: prefix_ctx (ref+prefix latent) prepended to every chunk like ref_latent; pose/face copy first frame of current chunk to fill prefix region - Dynamic decode trim via canvas_expansion_px (21/37/0) - Fix latent_window_size to cover full expanded bg range, preventing pose index clamping in non-first context windows - Pad uni3c render_latent with 10 leading first-frame copies when prefix is active - Remove independent VAE encode for transition (now embedded in canvas)
…ing VAE unsqueeze, transition 12-frame adjustment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Motivation
Currently, concatenating video batches for action transfer heavily relies on the
start_ref_imageparameter. However, under the current logic, using this parameter forces the generation into thelooping(Wan Animate) mode and is architecturally incompatible with thecontext(context windowing) mode. In long video generation, relying solely on theloopingmode leads to error accumulation, resulting in noticeable visual degradation in subsequent frames.This PR introduces the
transition_videoparameter, allowing users to input a short video clip as a hard conditioning guide. This approach removes the restriction that video concatenation must be strictly bound to theloopingmode, making it compatible with bothcontextmode andWan Animate loopmode. This grants users the option to utilize thecontextmode during action-transfer concatenation to maintain higher visual stability.Usage
transition_videoinput.Implementation Details by File
1.
nodes.py(Wrapper Node & Preprocessing)Responsible for robust video preprocessing and strictly aligning the timing of control signals.
transition_videoinput. When provided, the totalnum_framesis forced to expand by 32 frames (corresponding to 8 latent frames).pose_images,face_images,bg_images,mask). Extracts the 0-th frame of each signal, duplicates it 32 times using.repeat(32, ...), and prepends it to the original sequence, ensuring the original control actions are accurately shifted to the 33rd frame.b > 32, usestorch.linspaceto generate uniform indices for downsampling; ifb < 32, calculates the ceilingrepeat_factorto duplicate the video tensor, then truncates it using[:32]slicing, ensuring the output is strictly 32 frames.[C, T, H, W], extracts the first 3 RGB channels, and normalizes the values to[-1, 1]via* 2 - 1.transition_latentvia VAE; constructs an all-1.0tensor of length 8 astransition_mask_values, instructing the sampler to execute a 100% hard replacement.transition_videoandstart_ref_imageare provided, logs a warning and prioritizes thetransition_videopipeline.2.
nodes_sampler.py(Sampler)Responsible for precisely slicing and replacing the starting tensors of the target latent sequence during the initialization phase.
Context Windowing Mode Adaptation:
image_condaswindow_msk.c[0] == 0), slicespartial_img_emb. Skips the first 4 mask channels and directly replaces the target latent section (channels4:20, frames1:1+transition_len) withtransition_latent.transition_mask_valuesto the corresponding timesteps ofwindow_msk, and overwrites the first 4 channels of the input conditionimage_cond_inbefore passing it to the model prediction.Wan Animate (Looping) Mode Adaptation:
has_transitionflag to the logic evaluating the reconstruction oftemporal_ref_latents.current_ref_imagesandbg_image_slice, concatenates them usingtorch.cat, and sends them to VAE encoding.start == 0), retains the original target latent sequence aftertransition_len, and hard-replaces the first 8 frames withtransition_latent.Impact