mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-04-25 18:02:37 +08:00
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Build package / Build Test (3.10) (push) Has been cancelled
Build package / Build Test (3.11) (push) Has been cancelled
Build package / Build Test (3.12) (push) Has been cancelled
Build package / Build Test (3.13) (push) Has been cancelled
Build package / Build Test (3.14) (push) Has been cancelled
* fix: pin SQLAlchemy>=2.0 in requirements.txt (fixes #13036) (#13316) * Refactor io to IO in nodes_ace.py (#13485) * Bump comfyui-frontend-package to 1.42.12 (#13489) * Make the ltx audio vae more native. (#13486) * feat(api-nodes): add automatic downscaling of videos for ByteDance 2 nodes (#13465) * Support standalone LTXV audio VAEs (#13499) * [Partner Nodes] added 4K resolution for Veo models; added Veo 3 Lite model (#13330) * feat(api nodes): added 4K resolution for Veo models; added Veo 3 Lite model Signed-off-by: bigcat88 <bigcat88@icloud.com> * increase poll_interval from 5 to 9 --------- Signed-off-by: bigcat88 <bigcat88@icloud.com> Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com> * Bump comfyui-frontend-package to 1.42.14 (#13493) * Add gpt-image-2 as version option (#13501) * Allow logging in comfy app files. (#13505) * chore: update workflow templates to v0.9.59 (#13507) * fix(veo): reject 4K resolution for veo-3.0 models in Veo3VideoGenerationNode (#13504) The tooltip on the resolution input states that 4K is not available for veo-3.1-lite or veo-3.0 models, but the execute guard only rejected the lite combination. Selecting 4K with veo-3.0-generate-001 or veo-3.0-fast-generate-001 would fall through and hit the upstream API with an invalid request. Broaden the guard to match the documented behavior and update the error message accordingly. Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com> * feat: RIFE and FILM frame interpolation model support (CORE-29) (#13258) * initial RIFE support * Also support FILM * Better RAM usage, reduce FILM VRAM peak * Add model folder placeholder * Fix oom fallback frame loss * Remove torch.compile for now * Rename model input * Shorter input type name --------- * fix: use Parameter assignment for Stable_Zero123 cc_projection weights (fixes #13492) (#13518) On Windows with aimdo enabled, disable_weight_init.Linear uses lazy initialization that sets weight and bias to None to avoid unnecessary memory allocation. This caused a crash when copy_() was called on the None weight attribute in Stable_Zero123.__init__. Replace copy_() with direct torch.nn.Parameter assignment, which works correctly on both Windows (aimdo enabled) and other platforms. * Derive InterruptProcessingException from BaseException (#13523) * bump manager version to 4.2.1 (#13516) * ModelPatcherDynamic: force cast stray weights on comfy layers (#13487) the mixed_precision ops can have input_scale parameters that are used in tensor math but arent a weight or bias so dont get proper VRAM management. Treat these as force-castable parameters like the non comfy weight, random params are buffers already are. * Update logging level for invalid version format (#13526) * [Partner Nodes] add SD2 real human support (#13509) * feat(api-nodes): add SD2 real human support Signed-off-by: bigcat88 <bigcat88@icloud.com> * fix: add validation before uploading Assets Signed-off-by: bigcat88 <bigcat88@icloud.com> * Add asset_id and group_id displaying on the node Signed-off-by: bigcat88 <bigcat88@icloud.com> * extend poll_op to use instead of custom async cycle Signed-off-by: bigcat88 <bigcat88@icloud.com> * added the polling for the "Active" status after asset creation Signed-off-by: bigcat88 <bigcat88@icloud.com> * updated tooltip for group_id * allow usage of real human in the ByteDance2FirstLastFrame node * add reference count limits * corrected price in status when input assets contain video Signed-off-by: bigcat88 <bigcat88@icloud.com> --------- Signed-off-by: bigcat88 <bigcat88@icloud.com> * feat: SAM (segment anything) 3.1 support (CORE-34) (#13408) * [Partner Nodes] GPTImage: fix price badges, add new resolutions (#13519) * fix(api-nodes): fixed price badges, add new resolutions Signed-off-by: bigcat88 <bigcat88@icloud.com> * proper calculate the total run cost when "n > 1" Signed-off-by: bigcat88 <bigcat88@icloud.com> --------- Signed-off-by: bigcat88 <bigcat88@icloud.com> * chore: update workflow templates to v0.9.61 (#13533) * chore: update embedded docs to v0.4.4 (#13535) * add 4K resolution to Kling nodes (#13536) Signed-off-by: bigcat88 <bigcat88@icloud.com> * Fix LTXV Reference Audio node (#13531) * comfy-aimdo 0.2.14: Hotfix async allocator estimations (#13534) This was doing an over-estimate of VRAM used by the async allocator when lots of little small tensors were in play. Also change the versioning scheme to == so we can roll forward aimdo without worrying about stable regressions downstream in comfyUI core. * Disable sageattention for SAM3 (#13529) Causes Nans * execution: Add anti-cycle validation (#13169) Currently if the graph contains a cycle, the just inifitiate recursions, hits a catch all then throws a generic error against the output node that seeded the validation. Instead, fail the offending cycling mode chain and handlng it as an error in its own right. Co-authored-by: guill <jacob.e.segal@gmail.com> * chore: update workflow templates to v0.9.62 (#13539) --------- Signed-off-by: bigcat88 <bigcat88@icloud.com> Co-authored-by: Octopus <liyuan851277048@icloud.com> Co-authored-by: comfyanonymous <121283862+comfyanonymous@users.noreply.github.com> Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com> Co-authored-by: Alexander Piskun <13381981+bigcat88@users.noreply.github.com> Co-authored-by: Jukka Seppänen <40791699+kijai@users.noreply.github.com> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: Daxiong (Lin) <contact@comfyui-wiki.com> Co-authored-by: Matt Miller <matt@miller-media.com> Co-authored-by: blepping <157360029+blepping@users.noreply.github.com> Co-authored-by: Dr.Lt.Data <128333288+ltdrdata@users.noreply.github.com> Co-authored-by: rattus <46076784+rattus128@users.noreply.github.com> Co-authored-by: guill <jacob.e.segal@gmail.com>
129 lines
5.9 KiB
Python
129 lines
5.9 KiB
Python
import torch
|
|
import torch.nn as nn
|
|
import torch.nn.functional as F
|
|
|
|
import comfy.ops
|
|
|
|
ops = comfy.ops.disable_weight_init
|
|
|
|
|
|
def _warp(img, flow, warp_grids):
|
|
B, _, H, W = img.shape
|
|
base_grid, flow_div = warp_grids[(H, W)]
|
|
flow_norm = torch.cat([flow[:, 0:1] / flow_div[0], flow[:, 1:2] / flow_div[1]], 1).float()
|
|
grid = (base_grid.expand(B, -1, -1, -1) + flow_norm).permute(0, 2, 3, 1)
|
|
return F.grid_sample(img.float(), grid, mode="bilinear", padding_mode="border", align_corners=True).to(img.dtype)
|
|
|
|
|
|
class Head(nn.Module):
|
|
def __init__(self, out_ch=4, device=None, dtype=None, operations=ops):
|
|
super().__init__()
|
|
self.cnn0 = operations.Conv2d(3, 16, 3, 2, 1, device=device, dtype=dtype)
|
|
self.cnn1 = operations.Conv2d(16, 16, 3, 1, 1, device=device, dtype=dtype)
|
|
self.cnn2 = operations.Conv2d(16, 16, 3, 1, 1, device=device, dtype=dtype)
|
|
self.cnn3 = operations.ConvTranspose2d(16, out_ch, 4, 2, 1, device=device, dtype=dtype)
|
|
self.relu = nn.LeakyReLU(0.2, True)
|
|
|
|
def forward(self, x):
|
|
x = self.relu(self.cnn0(x))
|
|
x = self.relu(self.cnn1(x))
|
|
x = self.relu(self.cnn2(x))
|
|
return self.cnn3(x)
|
|
|
|
|
|
class ResConv(nn.Module):
|
|
def __init__(self, c, device=None, dtype=None, operations=ops):
|
|
super().__init__()
|
|
self.conv = operations.Conv2d(c, c, 3, 1, 1, device=device, dtype=dtype)
|
|
self.beta = nn.Parameter(torch.ones((1, c, 1, 1), device=device, dtype=dtype))
|
|
self.relu = nn.LeakyReLU(0.2, True)
|
|
|
|
def forward(self, x):
|
|
return self.relu(torch.addcmul(x, self.conv(x), self.beta))
|
|
|
|
|
|
class IFBlock(nn.Module):
|
|
def __init__(self, in_planes, c=64, device=None, dtype=None, operations=ops):
|
|
super().__init__()
|
|
self.conv0 = nn.Sequential(
|
|
nn.Sequential(operations.Conv2d(in_planes, c // 2, 3, 2, 1, device=device, dtype=dtype), nn.LeakyReLU(0.2, True)),
|
|
nn.Sequential(operations.Conv2d(c // 2, c, 3, 2, 1, device=device, dtype=dtype), nn.LeakyReLU(0.2, True)))
|
|
self.convblock = nn.Sequential(*(ResConv(c, device=device, dtype=dtype, operations=operations) for _ in range(8)))
|
|
self.lastconv = nn.Sequential(operations.ConvTranspose2d(c, 4 * 13, 4, 2, 1, device=device, dtype=dtype), nn.PixelShuffle(2))
|
|
|
|
def forward(self, x, flow=None, scale=1):
|
|
x = F.interpolate(x, scale_factor=1.0 / scale, mode="bilinear")
|
|
if flow is not None:
|
|
flow = F.interpolate(flow, scale_factor=1.0 / scale, mode="bilinear").div_(scale)
|
|
x = torch.cat((x, flow), 1)
|
|
feat = self.convblock(self.conv0(x))
|
|
tmp = F.interpolate(self.lastconv(feat), scale_factor=scale, mode="bilinear")
|
|
return tmp[:, :4] * scale, tmp[:, 4:5], tmp[:, 5:]
|
|
|
|
|
|
class IFNet(nn.Module):
|
|
def __init__(self, head_ch=4, channels=(192, 128, 96, 64, 32), device=None, dtype=None, operations=ops):
|
|
super().__init__()
|
|
self.encode = Head(out_ch=head_ch, device=device, dtype=dtype, operations=operations)
|
|
block_in = [7 + 2 * head_ch] + [8 + 4 + 8 + 2 * head_ch] * 4
|
|
self.blocks = nn.ModuleList([IFBlock(block_in[i], channels[i], device=device, dtype=dtype, operations=operations) for i in range(5)])
|
|
self.scale_list = [16, 8, 4, 2, 1]
|
|
self.pad_align = 64
|
|
self._warp_grids = {}
|
|
|
|
def get_dtype(self):
|
|
return self.encode.cnn0.weight.dtype
|
|
|
|
def _build_warp_grids(self, H, W, device):
|
|
if (H, W) in self._warp_grids:
|
|
return
|
|
self._warp_grids = {} # clear old resolution grids to prevent memory leaks
|
|
grid_y, grid_x = torch.meshgrid(
|
|
torch.linspace(-1.0, 1.0, H, device=device, dtype=torch.float32),
|
|
torch.linspace(-1.0, 1.0, W, device=device, dtype=torch.float32), indexing="ij")
|
|
self._warp_grids[(H, W)] = (
|
|
torch.stack((grid_x, grid_y), dim=0).unsqueeze(0),
|
|
torch.tensor([(W - 1.0) / 2.0, (H - 1.0) / 2.0], dtype=torch.float32, device=device))
|
|
|
|
def warp(self, img, flow):
|
|
return _warp(img, flow, self._warp_grids)
|
|
|
|
def extract_features(self, img):
|
|
"""Extract head features for a single frame. Can be cached across pairs."""
|
|
return self.encode(img)
|
|
|
|
def forward(self, img0, img1, timestep=0.5, cache=None):
|
|
if not isinstance(timestep, torch.Tensor):
|
|
timestep = torch.full((img0.shape[0], 1, img0.shape[2], img0.shape[3]), timestep, device=img0.device, dtype=img0.dtype)
|
|
|
|
self._build_warp_grids(img0.shape[2], img0.shape[3], img0.device)
|
|
|
|
B = img0.shape[0]
|
|
f0 = cache["img0"].expand(B, -1, -1, -1) if cache and "img0" in cache else self.encode(img0)
|
|
f1 = cache["img1"].expand(B, -1, -1, -1) if cache and "img1" in cache else self.encode(img1)
|
|
flow = mask = feat = None
|
|
warped_img0, warped_img1 = img0, img1
|
|
for i, block in enumerate(self.blocks):
|
|
if flow is None:
|
|
flow, mask, feat = block(torch.cat((img0, img1, f0, f1, timestep), 1), None, scale=self.scale_list[i])
|
|
else:
|
|
fd, mask, feat = block(
|
|
torch.cat((warped_img0, warped_img1, self.warp(f0, flow[:, :2]), self.warp(f1, flow[:, 2:4]), timestep, mask, feat), 1),
|
|
flow, scale=self.scale_list[i])
|
|
flow = flow.add_(fd)
|
|
warped_img0 = self.warp(img0, flow[:, :2])
|
|
warped_img1 = self.warp(img1, flow[:, 2:4])
|
|
return torch.lerp(warped_img1, warped_img0, torch.sigmoid(mask))
|
|
|
|
|
|
def detect_rife_config(state_dict):
|
|
head_ch = state_dict["encode.cnn3.weight"].shape[1] # ConvTranspose2d: (in_ch, out_ch, kH, kW)
|
|
channels = []
|
|
for i in range(5):
|
|
key = f"blocks.{i}.conv0.1.0.weight"
|
|
if key in state_dict:
|
|
channels.append(state_dict[key].shape[0])
|
|
if len(channels) != 5:
|
|
raise ValueError(f"Unsupported RIFE model: expected 5 blocks, found {len(channels)}")
|
|
return head_ch, channels
|