hanxxing's picture
Duplicate from rzgar/Bernini-R-S2V
832fee5
Raw
History Blame Contribute Delete
2.49 kB
import torch
import comfy.utils
WAN_VAE_SCALE = 8
WAN_PATCH_SPATIAL = 2
def _padded_latent_dim(pixels: int) -> int:
latent = pixels // WAN_VAE_SCALE
return latent + (WAN_PATCH_SPATIAL - latent % WAN_PATCH_SPATIAL) % WAN_PATCH_SPATIAL
def token_grid_size(width: int, height: int) -> tuple[int, int]:
return _padded_latent_dim(height) // WAN_PATCH_SPATIAL, _padded_latent_dim(width) // WAN_PATCH_SPATIAL
def mask_to_token_grid(mask_image: torch.Tensor, width: int, height: int) -> torch.Tensor:
token_h, token_w = token_grid_size(width, height)
mask = mask_image[0] if mask_image.ndim == 3 else mask_image
mask = mask.unsqueeze(0).unsqueeze(0)
mask = comfy.utils.common_upscale(mask, width, height, "area", "center")
mask = comfy.utils.common_upscale(mask, token_w, token_h, "area", "center")
return (mask > 0.5).to(dtype=torch.float32).flatten(2).squeeze(1)
def _latent_frame_weight(video_frame: int, start_frame: int, end_frame: int, crossfade_frames: int) -> float:
if video_frame < start_frame or video_frame >= end_frame:
return 0.0
if crossfade_frames <= 0:
return 1.0
weight = 1.0
if video_frame < start_frame + crossfade_frames:
weight = min(weight, (video_frame - start_frame + 1) / crossfade_frames)
if video_frame >= end_frame - crossfade_frames:
weight = min(weight, (end_frame - video_frame) / crossfade_frames)
return max(0.0, weight)
def build_timeline_audio_inject_mask(
width: int,
height: int,
length: int,
segments,
crossfade_frames: int = 0,
device=None,
) -> torch.Tensor:
latent_t = ((length - 1) // 4) + 1
token_h, token_w = token_grid_size(width, height)
n_tokens = token_h * token_w
mask = torch.zeros(1, latent_t, n_tokens, 1)
for segment in segments:
tokens = mask_to_token_grid(segment["mask_image"], width, height)
start_frame = int(segment["start_frame"])
end_frame = int(segment["end_frame"])
for latent_idx in range(latent_t):
vf0 = latent_idx * 4
vf1 = vf0 + 4
weight = 0.0
for video_frame in range(vf0, vf1):
weight = max(weight, _latent_frame_weight(video_frame, start_frame, end_frame, crossfade_frames))
if weight > 0.0:
mask[:, latent_idx, :, 0] = torch.maximum(mask[:, latent_idx, :, 0], tokens * weight)
if device is not None:
mask = mask.to(device)
return mask