20 Commits

Author SHA1 Message Date
91947c0b8c Use actual input frame count for all_on_gpu and chunk_size estimates
Replace hardcoded 199-frame assumption with 2*N-1 from the actual
images input, giving accurate VRAM/RAM estimates for any batch size.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:56:57 +01:00
c4b69321bb Reorder VFI Optimizer outputs: images first, settings second
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:54:00 +01:00
f1da0f7876 Add images passthrough output to VFI Optimizer
Avoids needing a dual link from the image source — the optimizer
passes images through so they can be connected directly to the
Interpolate node.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:53:28 +01:00
27c5bcf362 Fix total_mem → total_memory attribute on CudaDeviceProperties
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:33:45 +01:00
d2e7db49c7 Bump version to 1.1.0
Some checks failed
Publish to Comfy registry / Publish Custom Node to registry (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:16:11 +01:00
9f66233b53 Add VFI Optimizer node for auto-tuning hardware settings
Benchmarks the user's GPU with the actual model and resolution via a
single calibration frame pair, then outputs optimal batch_size,
chunk_size, keep_device, all_on_gpu, and clear_cache_after_n_frames
as a connectable VFI_SETTINGS type. All 8 Interpolate/SegmentInterpolate
nodes accept the new optional settings input — existing workflows
without the optimizer work unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:15:48 +01:00
7257c1aa4d Fix SVG license labels not rendering in GitHub README
Remove text-anchor="end" (likely stripped by GitHub's SVG sanitizer,
pushing text off-screen). Use left-aligned positioning instead, increase
font size and color brightness for visibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:44:47 +01:00
ebece55ed7 Add license labels to model comparison SVG
BIM-VFI shows "Research only" in amber, others show "Apache 2.0".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:39:42 +01:00
a60fb2a25e Redesign README: add SVG model comparison, reorganize by priority
Move installation to top, add shields.io badges, create visual model
comparison chart, use collapsible sections for node reference, condense
acknowledgments into a table with citations in a collapsible block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:37:50 +01:00
c178f756da Expand cupy install guide in README
Add step-by-step instructions, CUDA version table, troubleshooting
section, and note that EMA-VFI works without cupy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:25:36 +01:00
fb921ae620 Remove cupy auto-install from __init__.py
No more pip calls at import time. Users get a clear error with
install instructions from the Load node if cupy is missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:24:06 +01:00
4723dc329d Add cupy check to Load nodes with install instructions
BIM-VFI, SGM-VFI, and GIMM-VFI Load nodes now check for cupy at
load time and raise a clear error with the user's CUDA version and
the exact pip install command. Updated README with step-by-step
cupy install instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:15:44 +01:00
8fe382e5ec Remove auto-install of all deps except cupy
Dependencies are now handled by pyproject.toml / requirements.txt
via ComfyUI Manager or pip. Only cupy is auto-installed at load time
since it requires matching the PyTorch CUDA version; failures produce
a warning instead of crashing. Also added timm to requirements.txt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:13:01 +01:00
8311fd0261 Add ComfyUI registry publishing workflow and pyproject.toml
Some checks failed
Publish to Comfy registry / Publish Custom Node to registry (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 23:28:21 +01:00
396dafeefc Fix warp cache buildup when all_on_gpu is enabled
The all_on_gpu guard was preventing warp cache clearing and
torch.cuda.empty_cache() from ever running, causing unbounded
VRAM growth during long interpolation runs. Cache clearing now
runs on the clear_cache_after_n_frames interval regardless of
the all_on_gpu setting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:27:47 +01:00
13a89c5831 Add console logging to all VFI interpolation nodes
Log mode/params, pass progress, chunk count, and output frame count
for BIM-VFI, EMA-VFI, SGM-VFI, and GIMM-VFI interpolation nodes.
Segment nodes also log their input frame range and target fps output range.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 21:14:11 +01:00
2f1cc17f5c Add oversampled image output to all VFI Interpolate nodes
Second IMAGE output exposes the full power-of-2 oversampled frames
before target FPS selection. Identical to the first output when
target_fps=0. Document the new output in README.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:39:58 +01:00
b2d7d3b634 Update README: document target FPS mode, fix repo URL, update concat description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:06:55 +01:00
adc4451716 wf update 2026-02-13 22:55:30 +01:00
6dd579dcc7 Add target FPS mode to all VFI models and remove concat preview
Add source_fps/target_fps inputs to all 4 Interpolate and Segment nodes
(BIM, EMA, SGM, GIMM). When target_fps > 0, auto-computes optimal
power-of-2 oversample, runs existing recursive t=0.5 interpolation,
then selects frames at target timestamps. Handles downsampling (no
model calls), same-fps passthrough, and high ratios (e.g. 3→30fps).
Segment boundary logic uses global index computation for gap-free
stitching. When target_fps=0, existing multiplier behavior is preserved.

Remove video preview from TweenConcatVideos: drop preview input,
delete web/js/tween_preview.js, remove WEB_DIRECTORY from __init__.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:51:04 +01:00
9 changed files with 1343 additions and 575 deletions

20
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- master
paths:
- "pyproject.toml"
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@main
with:
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}

292
README.md
View File

@@ -1,40 +1,86 @@
# ComfyUI BIM-VFI + EMA-VFI + SGM-VFI + GIMM-VFI
# Tween — Video Frame Interpolation for ComfyUI
ComfyUI custom nodes for video frame interpolation using [BiM-VFI](https://github.com/KAIST-VICLab/BiM-VFI) (CVPR 2025), [EMA-VFI](https://github.com/MCG-NJU/EMA-VFI) (CVPR 2023), [SGM-VFI](https://github.com/MCG-NJU/SGM-VFI) (CVPR 2024), and [GIMM-VFI](https://github.com/GSeanCDAT/GIMM-VFI) (NeurIPS 2024). Designed for long videos with thousands of frames — processes them without running out of VRAM.
[![ComfyUI](https://img.shields.io/badge/ComfyUI-Custom_Node-0a7ef0)](https://registry.comfy.org/)
[![Python 3.10+](https://img.shields.io/badge/Python-3.10+-3776AB?logo=python&logoColor=white)](https://www.python.org/)
[![License](https://img.shields.io/badge/License-Apache_2.0-green.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![Models](https://img.shields.io/badge/VFI_Models-4-8B5CF6)](#which-model-should-i-use)
Four video frame interpolation models in one package — **BIM-VFI**, **EMA-VFI**, **SGM-VFI**, and **GIMM-VFI**. Designed for long videos with thousands of frames without running out of VRAM.
<p align="center">
<img src="assets/model-comparison.svg" alt="Model Comparison" width="720"/>
</p>
## Installation
Install from the [ComfyUI Registry](https://registry.comfy.org/) (recommended) or clone manually:
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/Ethanfel/ComfyUI-Tween.git
pip install -r requirements.txt
```
All dependencies (`gdown`, `timm`, `omegaconf`, `easydict`, `yacs`, `einops`, `huggingface_hub`) are declared in `pyproject.toml` and `requirements.txt`, installed automatically by ComfyUI Manager or pip.
### cupy (required for BIM-VFI, SGM-VFI, GIMM-VFI)
[cupy](https://cupy.dev/) provides GPU-accelerated optical flow warping. **EMA-VFI works without it.**
1. Find your CUDA version:
```bash
python -c "import torch; print(torch.version.cuda)"
```
2. Install the matching package:
| CUDA | Command |
|------|---------|
| 12.x | `pip install cupy-cuda12x` |
| 11.x | `pip install cupy-cuda11x` |
> Make sure to run pip in the same Python environment as ComfyUI. If cupy is missing, the Load node shows an error with your CUDA version and the exact install command.
<details>
<summary>cupy troubleshooting</summary>
| Problem | Solution |
|---------|----------|
| `ModuleNotFoundError: No module named 'cupy'` | Install cupy using the steps above |
| `cupy` installed but `ImportError` at runtime | CUDA version mismatch — uninstall and reinstall the correct version |
| Install hangs or takes very long | cupy wheels are ~800 MB, be patient |
| Docker / no build tools | Use the prebuilt wheel: `pip install cupy-cuda12x` (not bare `cupy` which compiles from source) |
</details>
## Which model should I use?
| | BIM-VFI | EMA-VFI | SGM-VFI | GIMM-VFI |
|---|---------|---------|---------|----------|
| **Best for** | General-purpose, non-uniform motion | Fast inference, light VRAM | Large motion, occlusion-heavy scenes | High multipliers (4x/8x) in a single pass |
| **Quality** | Highest overall | Good | Best on large motion | Good |
| **Speed** | Moderate | Fastest | Slowest | Fast for 4x/8x (single pass) |
| **Best for** | General-purpose | Fast, low VRAM | Large motion | High multipliers (4x/8x) |
| **Quality** | Highest | Good | Best on large motion | Good |
| **Speed** | Moderate | Fastest | Slowest | Fast for 4x/8x |
| **VRAM** | ~2 GB/pair | ~1.5 GB/pair | ~3 GB/pair | ~2.5 GB/pair |
| **Params** | ~17M | ~1465M | ~15M + GMFlow | ~80M (RAFT) / ~123M (FlowFormer) |
| **Arbitrary timestep** | Yes | Yes (with `_t` checkpoint) | No (fixed 0.5) | Yes (native single-pass) |
| **4x/8x mode** | Recursive 2x passes | Recursive 2x passes | Recursive 2x passes | Single forward pass (or recursive) |
| **Params** | ~17 M | ~1465 M | ~15 M + GMFlow | ~80 M (RAFT) / ~123 M (FlowFormer) |
| **Arbitrary timestep** | Yes | Yes (`_t` checkpoint) | No (fixed 0.5) | Yes (native) |
| **4x/8x** | Recursive passes | Recursive passes | Recursive passes | Single forward pass |
| **Requires cupy** | Yes | No | Yes | Yes |
| **Paper** | CVPR 2025 | CVPR 2023 | CVPR 2024 | NeurIPS 2024 |
| **License** | Research only | Apache 2.0 | Apache 2.0 | Apache 2.0 |
**TL;DR:** Start with **BIM-VFI** for best quality. Use **EMA-VFI** if you need speed or lower VRAM. Use **SGM-VFI** if your video has large camera motion or fast-moving objects that the others struggle with. Use **GIMM-VFI** when you want 4x or 8x interpolation without recursive passes — it generates all intermediate frames in a single forward pass per pair.
**TL;DR:** Start with **BIM-VFI** for best quality. Use **EMA-VFI** for speed or if you can't install cupy. Use **SGM-VFI** for large camera motion. Use **GIMM-VFI** for 4x/8x without recursive passes.
## VRAM Guide
| VRAM | Recommended settings |
|------|----------------------|
| 8 GB | `batch_size=1, chunk_size=500` |
| 24 GB | `batch_size=24, chunk_size=1000` |
| 48 GB+ | `batch_size=416, all_on_gpu=true` |
| 96 GB+ | `batch_size=816, all_on_gpu=true, chunk_size=0` |
## Nodes
### BIM-VFI
#### Load BIM-VFI Model
Loads the BiM-VFI checkpoint. Auto-downloads from Google Drive on first use to `ComfyUI/models/bim-vfi/`.
| Input | Description |
|-------|-------------|
| **model_path** | Checkpoint file from `models/bim-vfi/` |
| **auto_pyr_level** | Auto-select pyramid level by resolution (&lt;540p=3, 540p=5, 1080p=6, 4K=7) |
| **pyr_level** | Manual pyramid level (3-7), only used when auto is off |
#### BIM-VFI Interpolate
Interpolates frames from an image batch.
All Interpolate nodes share a common set of controls:
| Input | Description |
|-------|-------------|
@@ -42,152 +88,142 @@ Interpolates frames from an image batch.
| **model** | Model from the loader node |
| **multiplier** | 2x, 4x, or 8x frame rate (recursive 2x passes) |
| **batch_size** | Frame pairs processed simultaneously (higher = faster, more VRAM) |
| **chunk_size** | Process in segments of N input frames (0 = disabled). Bounds VRAM for very long videos. Result is identical to processing all at once |
| **keep_device** | Keep model on GPU between pairs (faster, ~200MB constant VRAM) |
| **chunk_size** | Process in segments of N input frames (0 = disabled). Bounds VRAM for very long videos |
| **keep_device** | Keep model on GPU between pairs (faster, ~200 MB constant VRAM) |
| **all_on_gpu** | Keep all intermediate frames on GPU (fast, needs large VRAM) |
| **clear_cache_after_n_frames** | Clear CUDA cache every N pairs to prevent VRAM buildup |
| **source_fps** | Input frame rate. Required when target_fps > 0 |
| **target_fps** | Target output FPS. When > 0, overrides multiplier — auto-computes the optimal power-of-2 oversample then selects frames at exact target timestamps. 0 = use multiplier |
| Output | Description |
|--------|-------------|
| **images** | Interpolated frames at the target FPS (or at the multiplied rate when target_fps = 0) |
| **oversampled** | Full power-of-2 oversampled frames before target FPS selection. Same as `images` when target_fps = 0 |
<details>
<summary><strong>BIM-VFI</strong></summary>
#### Load BIM-VFI Model
Loads the BiM-VFI checkpoint. Auto-downloads from Google Drive on first use to `ComfyUI/models/bim-vfi/`.
| Input | Description |
|-------|-------------|
| **model_path** | Checkpoint from `models/bim-vfi/` |
| **auto_pyr_level** | Auto pyramid level by resolution (&lt;540p=3, 540p=5, 1080p=6, 4K=7) |
| **pyr_level** | Manual pyramid level (37), used when auto is off |
#### BIM-VFI Interpolate
Common controls listed above.
#### BIM-VFI Segment Interpolate
Same as Interpolate but processes a single segment of the input. Chain multiple instances with Save nodes between them to bound peak RAM. The model pass-through output forces sequential execution.
Processes a single segment of the input. Chain multiple instances with Save nodes between them to bound peak RAM. The model pass-through output forces sequential execution.
### Tween Concat Videos
</details>
Concatenates segment video files into a single video using ffmpeg. Connect from any Segment Interpolate's model output to ensure it runs after all segments are saved. Works with all three models.
### EMA-VFI
<details>
<summary><strong>EMA-VFI</strong></summary>
#### Load EMA-VFI Model
Loads an EMA-VFI checkpoint. Auto-downloads from Google Drive on first use to `ComfyUI/models/ema-vfi/`. Variant (large/small) and timestep support are auto-detected from the filename.
Auto-downloads from Google Drive to `ComfyUI/models/ema-vfi/`. Variant and timestep support are auto-detected from the filename.
| Input | Description |
|-------|-------------|
| **model_path** | Checkpoint file from `models/ema-vfi/` |
| **tta** | Test-time augmentation: flip input and average with unflipped result (~2x slower, slightly better quality) |
| **model_path** | Checkpoint from `models/ema-vfi/` |
| **tta** | Test-time augmentation (~2x slower, slightly better quality) |
Available checkpoints:
| Checkpoint | Variant | Params | Arbitrary timestep |
|-----------|---------|--------|-------------------|
| `ours_t.pkl` | Large | ~65M | Yes |
| `ours.pkl` | Large | ~65M | No (fixed 0.5) |
| `ours_small_t.pkl` | Small | ~14M | Yes |
| `ours_small.pkl` | Small | ~14M | No (fixed 0.5) |
| `ours_t.pkl` | Large | ~65 M | Yes |
| `ours.pkl` | Large | ~65 M | No (fixed 0.5) |
| `ours_small_t.pkl` | Small | ~14 M | Yes |
| `ours_small.pkl` | Small | ~14 M | No (fixed 0.5) |
#### EMA-VFI Interpolate
#### EMA-VFI Interpolate / Segment Interpolate
Interpolates frames from an image batch. Same controls as BIM-VFI Interpolate.
Same controls as above.
#### EMA-VFI Segment Interpolate
</details>
Same as EMA-VFI Interpolate but processes a single segment. Same pattern as BIM-VFI Segment Interpolate.
### SGM-VFI
<details>
<summary><strong>SGM-VFI</strong></summary>
#### Load SGM-VFI Model
Loads an SGM-VFI checkpoint. Auto-downloads from Google Drive on first use to `ComfyUI/models/sgm-vfi/`. Variant (base/small) is auto-detected from the filename (default is small).
Auto-downloads from Google Drive to `ComfyUI/models/sgm-vfi/`. Requires cupy.
| Input | Description |
|-------|-------------|
| **model_path** | Checkpoint file from `models/sgm-vfi/` |
| **tta** | Test-time augmentation: flip input and average with unflipped result (~2x slower, slightly better quality) |
| **num_key_points** | Sparsity of global matching (0.0 = global everywhere, 0.5 = default balance, higher = faster) |
| **model_path** | Checkpoint from `models/sgm-vfi/` |
| **tta** | Test-time augmentation (~2x slower, slightly better quality) |
| **num_key_points** | Global matching sparsity (0.0 = global everywhere, 0.5 = default, higher = faster) |
Available checkpoints:
| Checkpoint | Variant | Params |
|-----------|---------|--------|
| `ours-1-2-points.pkl` | Small | ~15M + GMFlow |
| `ours-1-2-points.pkl` | Small | ~15 M + GMFlow |
#### SGM-VFI Interpolate
#### SGM-VFI Interpolate / Segment Interpolate
Interpolates frames from an image batch. Same controls as BIM-VFI Interpolate.
Same controls as above.
#### SGM-VFI Segment Interpolate
</details>
Same as SGM-VFI Interpolate but processes a single segment. Same pattern as BIM-VFI Segment Interpolate.
### GIMM-VFI
<details>
<summary><strong>GIMM-VFI</strong></summary>
#### Load GIMM-VFI Model
Loads a GIMM-VFI checkpoint. Auto-downloads from [HuggingFace](https://huggingface.co/Kijai/GIMM-VFI_safetensors) on first use to `ComfyUI/models/gimm-vfi/`. The matching flow estimator (RAFT or FlowFormer) is auto-detected and downloaded alongside the main model.
Auto-downloads from [HuggingFace](https://huggingface.co/Kijai/GIMM-VFI_safetensors) to `ComfyUI/models/gimm-vfi/`. The matching flow estimator (RAFT or FlowFormer) is auto-detected and downloaded alongside.
| Input | Description |
|-------|-------------|
| **model_path** | Checkpoint file from `models/gimm-vfi/` |
| **ds_factor** | Downscale factor for internal processing (1.0 = full res, 0.5 = half). Lower = less VRAM, faster, less quality. Try 0.5 for 4K inputs |
| **model_path** | Checkpoint from `models/gimm-vfi/` |
| **ds_factor** | Downscale factor for internal processing (1.0 = full, 0.5 = half). Try 0.5 for 4K inputs |
Available checkpoints:
| Checkpoint | Variant | Params | Flow estimator (auto-downloaded) |
|-----------|---------|--------|----------------------------------|
| `gimmvfi_r_arb_lpips_fp32.safetensors` | RAFT | ~80M | `raft-things_fp32.safetensors` |
| `gimmvfi_f_arb_lpips_fp32.safetensors` | FlowFormer | ~123M | `flowformer_sintel_fp32.safetensors` |
| `gimmvfi_r_arb_lpips_fp32.safetensors` | RAFT | ~80 M | `raft-things_fp32.safetensors` |
| `gimmvfi_f_arb_lpips_fp32.safetensors` | FlowFormer | ~123 M | `flowformer_sintel_fp32.safetensors` |
#### GIMM-VFI Interpolate
Interpolates frames from an image batch. Same controls as BIM-VFI Interpolate, plus:
Common controls plus:
| Input | Description |
|-------|-------------|
| **single_pass** | When enabled (default), generates all intermediate frames per pair in one forward pass using GIMM-VFI's arbitrary-timestep capability. No recursive 2x passes needed for 4x or 8x. Disable to use the standard recursive approach (same as BIM/EMA/SGM) |
| **single_pass** | Generate all intermediate frames per pair in one forward pass (default on). No recursive 2x passes needed for 4x/8x. Disable to use the standard recursive approach |
#### GIMM-VFI Segment Interpolate
Same as GIMM-VFI Interpolate but processes a single segment. Same pattern as BIM-VFI Segment Interpolate.
Same pattern as other Segment nodes.
**Output frame count (all models):** 2x = 2N-1, 4x = 4N-3, 8x = 8N-7
</details>
## Installation
### Tween Concat Videos
Clone into your ComfyUI `custom_nodes/` directory:
Concatenates segment video files into a single video using ffmpeg. Connect from any Segment Interpolate's model output to ensure it runs after all segments are saved. Works with all four models.
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/your-user/ComfyUI-Tween.git
```
### Output frame count
Dependencies (`gdown`, `cupy`, `timm`, `omegaconf`, `easydict`, `yacs`, `einops`, `huggingface_hub`) are auto-installed on first load. The correct `cupy` variant is detected from your PyTorch CUDA version.
> **Warning:** `cupy` is a large package (~800MB) and compilation/installation can take several minutes. The first ComfyUI startup after installing this node may appear to hang while `cupy` installs in the background. Check the console log for progress. If auto-install fails (e.g. missing build tools in Docker), install manually with:
> ```bash
> pip install cupy-cuda12x # replace 12 with your CUDA major version
> ```
To install manually:
```bash
cd ComfyUI-Tween
python install.py
```
### Requirements
- PyTorch with CUDA
- `cupy` (matching your CUDA version, for BIM-VFI, SGM-VFI, and GIMM-VFI)
- `timm` (for EMA-VFI and SGM-VFI)
- `gdown` (for BIM-VFI/EMA-VFI/SGM-VFI model auto-download)
- `omegaconf`, `easydict`, `yacs`, `einops` (for GIMM-VFI)
- `huggingface_hub` (for GIMM-VFI model auto-download)
## VRAM Guide
| VRAM | Recommended settings |
|------|---------------------|
| 8 GB | batch_size=1, chunk_size=500 |
| 24 GB | batch_size=2-4, chunk_size=1000 |
| 48 GB+ | batch_size=4-16, all_on_gpu=true |
| 96 GB+ | batch_size=8-16, all_on_gpu=true, chunk_size=0 |
- **Multiplier mode:** 2x = 2N-1, 4x = 4N-3, 8x = 8N-7
- **Target FPS mode:** `floor((N-1) / source_fps * target_fps) + 1` frames. Automatically oversamples to the nearest power-of-2 above the ratio, then selects frames at exact target timestamps. Downsampling (target < source) also works — frames are selected from the input with no model calls.
## Acknowledgments
This project wraps the official [BiM-VFI](https://github.com/KAIST-VICLab/BiM-VFI) implementation by the [KAIST VIC Lab](https://github.com/KAIST-VICLab), the official [EMA-VFI](https://github.com/MCG-NJU/EMA-VFI) implementation by MCG-NJU, the official [SGM-VFI](https://github.com/MCG-NJU/SGM-VFI) implementation by MCG-NJU, and the [GIMM-VFI](https://github.com/GSeanCDAT/GIMM-VFI) implementation by S-Lab (NTU). GIMM-VFI architecture files in `gimm_vfi_arch/` are adapted from [kijai/ComfyUI-GIMM-VFI](https://github.com/kijai/ComfyUI-GIMM-VFI) with safetensors checkpoints from [Kijai/GIMM-VFI_safetensors](https://huggingface.co/Kijai/GIMM-VFI_safetensors). Architecture files in `bim_vfi_arch/`, `ema_vfi_arch/`, `sgm_vfi_arch/`, and `gimm_vfi_arch/` are vendored from their respective repositories with minimal modifications (relative imports, device-awareness fixes, inference-only paths).
| Model | Authors | Venue | Links |
|-------|---------|-------|-------|
| **BIM-VFI** | Seo, Oh, Kim (KAIST VIC Lab) | CVPR 2025 | [Paper](https://arxiv.org/abs/2412.11365) · [Code](https://github.com/KAIST-VICLab/BiM-VFI) · [Project](https://kaist-viclab.github.io/BiM-VFI_site/) |
| **EMA-VFI** | Zhang et al. (MCG-NJU) | CVPR 2023 | [Paper](https://arxiv.org/abs/2303.00440) · [Code](https://github.com/MCG-NJU/EMA-VFI) |
| **SGM-VFI** | Zhang et al. (MCG-NJU) | CVPR 2024 | [Paper](https://arxiv.org/abs/2404.06913) · [Code](https://github.com/MCG-NJU/SGM-VFI) |
| **GIMM-VFI** | Guo, Li, Loy (S-Lab NTU) | NeurIPS 2024 | [Paper](https://arxiv.org/abs/2407.08680) · [Code](https://github.com/GSeanCDAT/GIMM-VFI) |
**BiM-VFI:**
> Wonyong Seo, Jihyong Oh, and Munchurl Kim.
> "BiM-VFI: Bidirectional Motion Field-Guided Frame Interpolation for Video with Non-uniform Motions."
> *IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)*, 2025.
> [[arXiv]](https://arxiv.org/abs/2412.11365) [[Project Page]](https://kaist-viclab.github.io/BiM-VFI_site/) [[GitHub]](https://github.com/KAIST-VICLab/BiM-VFI)
GIMM-VFI adaptation from [kijai/ComfyUI-GIMM-VFI](https://github.com/kijai/ComfyUI-GIMM-VFI) with checkpoints from [Kijai/GIMM-VFI_safetensors](https://huggingface.co/Kijai/GIMM-VFI_safetensors). Architecture files in `bim_vfi_arch/`, `ema_vfi_arch/`, `sgm_vfi_arch/`, and `gimm_vfi_arch/` are vendored from their respective repositories with minimal modifications.
<details>
<summary>BibTeX citations</summary>
```bibtex
@inproceedings{seo2025bimvfi,
@@ -196,45 +232,21 @@ This project wraps the official [BiM-VFI](https://github.com/KAIST-VICLab/BiM-VF
booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
year={2025}
}
```
**EMA-VFI:**
> Guozhen Zhang, Yuhan Zhu, Haonan Wang, Youxin Chen, Gangshan Wu, and Limin Wang.
> "Extracting Motion and Appearance via Inter-Frame Attention for Efficient Video Frame Interpolation."
> *IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)*, 2023.
> [[arXiv]](https://arxiv.org/abs/2303.00440) [[GitHub]](https://github.com/MCG-NJU/EMA-VFI)
```bibtex
@inproceedings{zhang2023emavfi,
title={Extracting Motion and Appearance via Inter-Frame Attention for Efficient Video Frame Interpolation},
author={Zhang, Guozhen and Zhu, Yuhan and Wang, Haonan and Chen, Youxin and Wu, Gangshan and Wang, Limin},
booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
year={2023}
}
```
**SGM-VFI:**
> Guozhen Zhang, Yuhan Zhu, Evan Zheran Liu, Haonan Wang, Mingzhen Sun, Gangshan Wu, and Limin Wang.
> "Sparse Global Matching for Video Frame Interpolation with Large Motion."
> *IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)*, 2024.
> [[arXiv]](https://arxiv.org/abs/2404.06913) [[GitHub]](https://github.com/MCG-NJU/SGM-VFI)
```bibtex
@inproceedings{zhang2024sgmvfi,
title={Sparse Global Matching for Video Frame Interpolation with Large Motion},
author={Zhang, Guozhen and Zhu, Yuhan and Liu, Evan Zheran and Wang, Haonan and Sun, Mingzhen and Wu, Gangshan and Wang, Limin},
booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
year={2024}
}
```
**GIMM-VFI:**
> Zujin Guo, Wei Li, and Chen Change Loy.
> "Generalizable Implicit Motion Modeling for Video Frame Interpolation."
> *Advances in Neural Information Processing Systems (NeurIPS)*, 2024.
> [[arXiv]](https://arxiv.org/abs/2407.08680) [[GitHub]](https://github.com/GSeanCDAT/GIMM-VFI)
```bibtex
@inproceedings{guo2024gimmvfi,
title={Generalizable Implicit Motion Modeling for Video Frame Interpolation},
author={Guo, Zujin and Li, Wei and Loy, Chen Change},
@@ -243,12 +255,12 @@ This project wraps the official [BiM-VFI](https://github.com/KAIST-VICLab/BiM-VF
}
```
</details>
## License
The BiM-VFI model weights and architecture code are provided by KAIST VIC Lab for **research and education purposes only**. Commercial use requires permission from the principal investigator (Prof. Munchurl Kim, mkimee@kaist.ac.kr). See the [original repository](https://github.com/KAIST-VICLab/BiM-VFI) for details.
**BIM-VFI:** Research and education only. Commercial use requires permission from Prof. Munchurl Kim (mkimee@kaist.ac.kr). See the [original repository](https://github.com/KAIST-VICLab/BiM-VFI).
The EMA-VFI model weights and architecture code are released under the [Apache 2.0 License](https://github.com/MCG-NJU/EMA-VFI/blob/main/LICENSE). See the [original repository](https://github.com/MCG-NJU/EMA-VFI) for details.
**EMA-VFI, SGM-VFI, GIMM-VFI:** [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). GIMM-VFI ComfyUI adaptation based on [kijai/ComfyUI-GIMM-VFI](https://github.com/kijai/ComfyUI-GIMM-VFI).
The SGM-VFI model weights and architecture code are released under the [Apache 2.0 License](https://github.com/MCG-NJU/SGM-VFI/blob/main/LICENSE). See the [original repository](https://github.com/MCG-NJU/SGM-VFI) for details.
The GIMM-VFI model weights and architecture code are released under the [Apache 2.0 License](https://github.com/GSeanCDAT/GIMM-VFI/blob/main/LICENSE). See the [original repository](https://github.com/GSeanCDAT/GIMM-VFI) for details. ComfyUI adaptation based on [kijai/ComfyUI-GIMM-VFI](https://github.com/kijai/ComfyUI-GIMM-VFI).
**This wrapper code:** [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)

View File

@@ -1,59 +1,11 @@
import subprocess
import sys
import logging
logger = logging.getLogger("Tween")
def _auto_install_deps():
"""Auto-install missing dependencies on first load."""
# gdown
try:
import gdown # noqa: F401
except ImportError:
logger.info("[Tween] Installing gdown...")
subprocess.check_call([sys.executable, "-m", "pip", "install", "gdown"])
# timm (required for EMA-VFI's MotionFormer backbone)
try:
import timm # noqa: F401
except ImportError:
logger.info("[Tween] Installing timm...")
subprocess.check_call([sys.executable, "-m", "pip", "install", "timm"])
# cupy
try:
import cupy # noqa: F401
except ImportError:
try:
import torch
major = int(torch.version.cuda.split(".")[0])
cupy_pkg = f"cupy-cuda{major}x"
logger.info(f"[Tween] Installing {cupy_pkg} (CUDA {torch.version.cuda})...")
subprocess.check_call([sys.executable, "-m", "pip", "install", cupy_pkg])
except Exception as e:
logger.warning(f"[Tween] Could not auto-install cupy: {e}")
# GIMM-VFI dependencies
for pkg in ("omegaconf", "yacs", "easydict", "einops", "huggingface_hub"):
try:
__import__(pkg)
except ImportError:
logger.info(f"[Tween] Installing {pkg}...")
subprocess.check_call([sys.executable, "-m", "pip", "install", pkg])
_auto_install_deps()
from .nodes import (
LoadBIMVFIModel, BIMVFIInterpolate, BIMVFISegmentInterpolate, TweenConcatVideos,
LoadEMAVFIModel, EMAVFIInterpolate, EMAVFISegmentInterpolate,
LoadSGMVFIModel, SGMVFIInterpolate, SGMVFISegmentInterpolate,
LoadGIMMVFIModel, GIMMVFIInterpolate, GIMMVFISegmentInterpolate,
VFIOptimizer,
)
WEB_DIRECTORY = "./web"
NODE_CLASS_MAPPINGS = {
"LoadBIMVFIModel": LoadBIMVFIModel,
"BIMVFIInterpolate": BIMVFIInterpolate,
@@ -68,6 +20,7 @@ NODE_CLASS_MAPPINGS = {
"LoadGIMMVFIModel": LoadGIMMVFIModel,
"GIMMVFIInterpolate": GIMMVFIInterpolate,
"GIMMVFISegmentInterpolate": GIMMVFISegmentInterpolate,
"VFIOptimizer": VFIOptimizer,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -84,4 +37,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"LoadGIMMVFIModel": "Load GIMM-VFI Model",
"GIMMVFIInterpolate": "GIMM-VFI Interpolate",
"GIMMVFISegmentInterpolate": "GIMM-VFI Segment Interpolate",
"VFIOptimizer": "VFI Optimizer",
}

View File

@@ -0,0 +1,84 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 320" width="720" height="320">
<defs>
<linearGradient id="gQ" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#7aa2f7"/><stop offset="100%" stop-color="#7dcfff"/>
</linearGradient>
<linearGradient id="gS" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#9ece6a"/><stop offset="100%" stop-color="#73daca"/>
</linearGradient>
<linearGradient id="gV" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#bb9af7"/><stop offset="100%" stop-color="#d2a8ff"/>
</linearGradient>
</defs>
<!-- Background -->
<rect width="720" height="320" rx="16" fill="#0d1117"/>
<!-- ═══ BIM-VFI (top-left) ═══ -->
<rect x="10" y="10" width="340" height="145" rx="10" fill="#161b22" stroke="#30363d" stroke-width="1"/>
<rect x="11" y="22" width="3" height="121" fill="#3fb950"/>
<text x="30" y="38" fill="#e6edf3" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="15" font-weight="600">BIM-VFI</text>
<text x="30" y="56" fill="#3fb950" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">&#9733; Recommended &#183; Best quality &#183; CVPR 2025</text>
<line x1="30" y1="64" x2="330" y2="64" stroke="#30363d" stroke-width="0.5"/>
<text x="30" y="82" fill="#7aa2f7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Quality</text>
<rect x="88" y="72" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="88" y="72" width="244" height="11" rx="3" fill="url(#gQ)" opacity="0.85"/>
<text x="30" y="100" fill="#9ece6a" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Speed</text>
<rect x="88" y="90" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="88" y="90" width="146" height="11" rx="3" fill="url(#gS)" opacity="0.85"/>
<text x="30" y="118" fill="#bb9af7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">VRAM</text>
<rect x="88" y="108" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="88" y="108" width="195" height="11" rx="3" fill="url(#gV)" opacity="0.85"/>
<text x="262" y="143" fill="#f0883e" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="10">Research only</text>
<!-- ═══ EMA-VFI (top-right) ═══ -->
<rect x="370" y="10" width="340" height="145" rx="10" fill="#161b22" stroke="#30363d" stroke-width="1"/>
<rect x="371" y="22" width="3" height="121" fill="#58a6ff"/>
<text x="390" y="38" fill="#e6edf3" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="15" font-weight="600">EMA-VFI</text>
<text x="390" y="56" fill="#58a6ff" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Fastest &#183; No cupy needed &#183; CVPR 2023</text>
<line x1="390" y1="64" x2="690" y2="64" stroke="#30363d" stroke-width="0.5"/>
<text x="390" y="82" fill="#7aa2f7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Quality</text>
<rect x="448" y="72" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="448" y="72" width="146" height="11" rx="3" fill="url(#gQ)" opacity="0.85"/>
<text x="390" y="100" fill="#9ece6a" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Speed</text>
<rect x="448" y="90" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="448" y="90" width="244" height="11" rx="3" fill="url(#gS)" opacity="0.85"/>
<text x="390" y="118" fill="#bb9af7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">VRAM</text>
<rect x="448" y="108" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="448" y="108" width="244" height="11" rx="3" fill="url(#gV)" opacity="0.85"/>
<text x="632" y="143" fill="#8b949e" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="10">Apache 2.0</text>
<!-- ═══ SGM-VFI (bottom-left) ═══ -->
<rect x="10" y="165" width="340" height="145" rx="10" fill="#161b22" stroke="#30363d" stroke-width="1"/>
<rect x="11" y="177" width="3" height="121" fill="#f0883e"/>
<text x="30" y="193" fill="#e6edf3" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="15" font-weight="600">SGM-VFI</text>
<text x="30" y="211" fill="#f0883e" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Large motion specialist &#183; CVPR 2024</text>
<line x1="30" y1="219" x2="330" y2="219" stroke="#30363d" stroke-width="0.5"/>
<text x="30" y="237" fill="#7aa2f7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Quality</text>
<rect x="88" y="227" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="88" y="227" width="195" height="11" rx="3" fill="url(#gQ)" opacity="0.85"/>
<text x="30" y="255" fill="#9ece6a" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Speed</text>
<rect x="88" y="245" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="88" y="245" width="98" height="11" rx="3" fill="url(#gS)" opacity="0.85"/>
<text x="30" y="273" fill="#bb9af7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">VRAM</text>
<rect x="88" y="263" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="88" y="263" width="98" height="11" rx="3" fill="url(#gV)" opacity="0.85"/>
<text x="272" y="298" fill="#8b949e" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="10">Apache 2.0</text>
<!-- ═══ GIMM-VFI (bottom-right) ═══ -->
<rect x="370" y="165" width="340" height="145" rx="10" fill="#161b22" stroke="#30363d" stroke-width="1"/>
<rect x="371" y="177" width="3" height="121" fill="#bc8cff"/>
<text x="390" y="193" fill="#e6edf3" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="15" font-weight="600">GIMM-VFI</text>
<text x="390" y="211" fill="#bc8cff" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Single-pass 4&#215;/8&#215; &#183; NeurIPS 2024</text>
<line x1="390" y1="219" x2="690" y2="219" stroke="#30363d" stroke-width="0.5"/>
<text x="390" y="237" fill="#7aa2f7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Quality</text>
<rect x="448" y="227" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="448" y="227" width="146" height="11" rx="3" fill="url(#gQ)" opacity="0.85"/>
<text x="390" y="255" fill="#9ece6a" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">Speed</text>
<rect x="448" y="245" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="448" y="245" width="195" height="11" rx="3" fill="url(#gS)" opacity="0.85"/>
<text x="390" y="273" fill="#bb9af7" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="11">VRAM</text>
<rect x="448" y="263" width="244" height="11" rx="3" fill="#21262d"/>
<rect x="448" y="263" width="146" height="11" rx="3" fill="url(#gV)" opacity="0.85"/>
<text x="632" y="298" fill="#8b949e" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI','Noto Sans',Helvetica,Arial,sans-serif" font-size="10">Apache 2.0</text>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -206,100 +206,6 @@
"2"
]
},
{
"id": 12,
"type": "easy forLoopStart",
"pos": [
-8160,
576
],
"size": [
270,
138
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "initial_value1",
"shape": 7,
"type": "*",
"link": 68
},
{
"name": "total",
"type": "INT",
"widget": {
"name": "total"
},
"link": 33
},
{
"name": "initial_value2",
"type": "*",
"link": 44
},
{
"name": "initial_value3",
"type": "*",
"link": null
}
],
"outputs": [
{
"name": "flow",
"shape": 5,
"type": "FLOW_CONTROL",
"links": [
15
]
},
{
"name": "index",
"type": "INT",
"links": [
25,
26
]
},
{
"name": "value1",
"type": "*",
"links": [
18
]
},
{
"name": "value2",
"type": "*",
"links": [
21,
64
]
},
{
"name": "value3",
"type": "*",
"links": null
}
],
"properties": {
"cnr_id": "comfyui-easy-use",
"ver": "7c470c67d6df44498e52c902173c1ac77cd5bdfd",
"Node name for S&R": "easy forLoopStart",
"ue_properties": {
"widget_ue_connectable": {},
"input_ue_unconnectable": {},
"version": "7.6.2"
}
},
"widgets_values": [
6
],
"color": "#223",
"bgcolor": "#335"
},
{
"id": 13,
"type": "easy forLoopEnd",
@@ -371,85 +277,6 @@
"color": "#223",
"bgcolor": "#335"
},
{
"id": 11,
"type": "BIMVFISegmentInterpolate",
"pos": [
-7584,
576
],
"size": [
321.58209228515625,
246
],
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 21
},
{
"name": "model",
"type": "BIM_VFI_MODEL",
"link": 18
},
{
"name": "segment_index",
"type": "INT",
"widget": {
"name": "segment_index"
},
"link": 25
},
{
"name": "segment_size",
"type": "INT",
"widget": {
"name": "segment_size"
},
"link": 35
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
66
]
},
{
"name": "model",
"type": "BIM_VFI_MODEL",
"links": [
67
]
}
],
"properties": {
"aux_id": "Comfyui-BIM-VFI.git",
"ver": "7cf7162143eaa5b0939e0e122f80bc956baf65ea",
"Node name for S&R": "BIMVFISegmentInterpolate",
"ue_properties": {
"widget_ue_connectable": {},
"input_ue_unconnectable": {},
"version": "7.6.2"
}
},
"widgets_values": [
2,
40,
true,
true,
1,
0,
0,
500
]
},
{
"id": 3,
"type": "LoadBIMVFIModel",
@@ -561,7 +388,6 @@
"video/",
"tween_sgm",
"tween_video_sgm.mp4",
true,
true
]
},
@@ -574,7 +400,7 @@
],
"size": [
544,
352
334
],
"flags": {},
"order": 10,
@@ -647,11 +473,227 @@
}
}
},
{
"id": 16,
"type": "PrimitiveInt",
"pos": [
-9184,
544
],
"size": [
270,
82
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "INT",
"type": "INT",
"links": [
31,
35
]
}
],
"title": "Frames number each loops",
"properties": {
"cnr_id": "comfy-core",
"ver": "0.13.0",
"Node name for S&R": "PrimitiveInt",
"ue_properties": {
"widget_ue_connectable": {},
"input_ue_unconnectable": {},
"version": "7.6.2"
}
},
"widgets_values": [
100,
"fixed"
]
},
{
"id": 12,
"type": "easy forLoopStart",
"pos": [
-8160,
576
],
"size": [
270,
138
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "initial_value1",
"shape": 7,
"type": "*",
"link": 68
},
{
"name": "total",
"type": "INT",
"widget": {
"name": "total"
},
"link": 33
},
{
"name": "initial_value2",
"type": "*",
"link": 44
},
{
"name": "initial_value3",
"type": "*",
"link": null
}
],
"outputs": [
{
"name": "flow",
"shape": 5,
"type": "FLOW_CONTROL",
"links": [
15
]
},
{
"name": "index",
"type": "INT",
"links": [
25,
26
]
},
{
"name": "value1",
"type": "*",
"links": [
18
]
},
{
"name": "value2",
"type": "*",
"links": [
21,
64
]
},
{
"name": "value3",
"type": "*",
"links": null
}
],
"properties": {
"cnr_id": "comfyui-easy-use",
"ver": "7c470c67d6df44498e52c902173c1ac77cd5bdfd",
"Node name for S&R": "easy forLoopStart",
"ue_properties": {
"widget_ue_connectable": {},
"input_ue_unconnectable": {},
"version": "7.6.2"
}
},
"widgets_values": [
6
],
"color": "#223",
"bgcolor": "#335"
},
{
"id": 11,
"type": "BIMVFISegmentInterpolate",
"pos": [
-7584,
576
],
"size": [
321.58209228515625,
294
],
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 21
},
{
"name": "model",
"type": "BIM_VFI_MODEL",
"link": 18
},
{
"name": "segment_index",
"type": "INT",
"widget": {
"name": "segment_index"
},
"link": 25
},
{
"name": "segment_size",
"type": "INT",
"widget": {
"name": "segment_size"
},
"link": 35
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
66
]
},
{
"name": "model",
"type": "BIM_VFI_MODEL",
"links": [
67
]
}
],
"properties": {
"aux_id": "Comfyui-BIM-VFI.git",
"ver": "7cf7162143eaa5b0939e0e122f80bc956baf65ea",
"Node name for S&R": "BIMVFISegmentInterpolate",
"ue_properties": {
"widget_ue_connectable": {},
"input_ue_unconnectable": {},
"version": "7.6.2"
}
},
"widgets_values": [
2,
40,
true,
true,
1,
500,
16,
0,
0,
500
]
},
{
"id": 28,
"type": "VHS_LoadVideoPath",
"pos": [
-9152,
-9184,
704
],
"size": [
@@ -659,7 +701,7 @@
286
],
"flags": {},
"order": 2,
"order": 3,
"mode": 0,
"inputs": [
{
@@ -738,47 +780,6 @@
}
}
}
},
{
"id": 16,
"type": "PrimitiveInt",
"pos": [
-9152,
576
],
"size": [
270,
82
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "INT",
"type": "INT",
"links": [
31,
35
]
}
],
"title": "Frames number each loops",
"properties": {
"cnr_id": "comfy-core",
"ver": "0.13.0",
"Node name for S&R": "PrimitiveInt",
"ue_properties": {
"widget_ue_connectable": {},
"input_ue_unconnectable": {},
"version": "7.6.2"
}
},
"widgets_values": [
100,
"fixed"
]
}
],
"links": [
@@ -933,10 +934,10 @@
"workflowRendererVersion": "LG",
"ue_links": [],
"ds": {
"scale": 1.0834705943388552,
"scale": 0.8954302432552531,
"offset": [
10009.878269742538,
-100.68482917709798
10389.297857289295,
79.21414284327875
]
},
"links_added_by_ue": [],

932
nodes.py

File diff suppressed because it is too large Load Diff

22
pyproject.toml Normal file
View File

@@ -0,0 +1,22 @@
[project]
name = "comfyui-tween"
description = "Video frame interpolation nodes for ComfyUI using BIM-VFI, EMA-VFI, SGM-VFI, and GIMM-VFI. Designed for long videos with thousands of frames."
version = "1.1.0"
license = "Apache-2.0"
requires-python = ">=3.10"
dependencies = [
"gdown",
"timm",
"omegaconf",
"yacs",
"easydict",
"einops",
"huggingface_hub",
]
[project.urls]
Repository = "https://github.com/Ethanfel/ComfyUI-Tween"
[tool.comfy]
PublisherId = "ethanfel"
DisplayName = "Tween - Video Frame Interpolation"

View File

@@ -1,4 +1,5 @@
gdown
timm
omegaconf
yacs
easydict

View File

@@ -1,72 +0,0 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
function fitHeight(node) {
node.setSize([node.size[0], node.computeSize([node.size[0], node.size[1]])[1]]);
node?.graph?.setDirtyCanvas(true);
}
app.registerExtension({
name: "Tween.VideoPreview",
async beforeRegisterNodeDef(nodeType, nodeData) {
if (nodeData?.name !== "TweenConcatVideos") return;
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
onNodeCreated?.apply(this, arguments);
const container = document.createElement("div");
const previewWidget = this.addDOMWidget("videopreview", "preview", container, {
serialize: false,
hideOnZoom: false,
getValue() { return container.value; },
setValue(v) { container.value = v; },
});
previewWidget.computeSize = function (width) {
if (this.aspectRatio && !this.videoEl.hidden) {
const height = (previewNode.size[0] - 20) / this.aspectRatio + 10;
return [width, height > 0 ? height : -4];
}
return [width, -4];
};
const previewNode = this;
previewWidget.videoEl = document.createElement("video");
previewWidget.videoEl.controls = true;
previewWidget.videoEl.loop = true;
previewWidget.videoEl.muted = true;
previewWidget.videoEl.style.width = "100%";
previewWidget.videoEl.hidden = true;
previewWidget.videoEl.addEventListener("loadedmetadata", () => {
previewWidget.aspectRatio = previewWidget.videoEl.videoWidth / previewWidget.videoEl.videoHeight;
fitHeight(previewNode);
});
previewWidget.videoEl.addEventListener("error", () => {
previewWidget.videoEl.hidden = true;
fitHeight(previewNode);
});
container.appendChild(previewWidget.videoEl);
};
const onExecuted = nodeType.prototype.onExecuted;
nodeType.prototype.onExecuted = function (message) {
onExecuted?.apply(this, arguments);
if (!message?.gifs?.length) return;
const params = message.gifs[0];
const previewWidget = this.widgets?.find((w) => w.name === "videopreview");
if (!previewWidget) return;
const query = new URLSearchParams(params);
query.set("timestamp", Date.now());
previewWidget.videoEl.src = api.apiURL("/view?" + query);
previewWidget.videoEl.hidden = false;
previewWidget.videoEl.autoplay = true;
};
},
});