Add "Batch Load Image Sequence"

This commit is contained in:
Your Name
2025-12-26 21:56:44 +07:00
parent 8c3e436c4d
commit 8165122b9f
3 changed files with 254 additions and 20 deletions
+154 -18
View File
@@ -1,26 +1,162 @@
# ComfyUI-FrameIO
High-performance frame input/output nodes for AI video pipelines.
High-performance frame input/output nodes for **AI video pipelines** in ComfyUI.
## Features
- Save batch IMAGE tensors to WebP
- Lossy or lossless WebP
- Skip identical frames via hashing
- STRING_LIST output (list-native)
- Optimized for long AI video generation
ComfyUI-FrameIO focuses on **efficient frame storage, loading, and reuse** for long video generation workflows, solving common problems like massive PNG sizes, duplicate frames, and fragile filename-based loading.
## Included Nodes
- Batch Save Image Sequence (WebP)
---
## Installation
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/yourname/ComfyUI-FrameIO.git
## ✨ Features
### 🧩 Frame Saving
- Save batch `IMAGE` tensors as **WebP**
- **Lossy or Lossless WebP**
- **Skip identical frames** using hash-based deduplication
- Massive disk space reduction vs PNG
- Returns **STRING_LIST** (ComfyUI list-native)
### 📥 Frame Loading
- Pattern-based frame loading
- **STRING_LIST → IMAGE loader** (no filename guessing)
- **Frame range selector** (`start`, `end`, `step`)
- **Auto-detect frame count**
- Safe with duplicate paths (from deduplication)
### ⚡ Optimized for AI Video
- Designed for **long sequences**
- Works with WebP / PNG / JPG
- Preserves exact frame ordering
- Compatible with FFmpeg / Video Combine nodes
---
## 📦 Included Nodes
### 🔹 Batch Save Image Sequence (WebP)
Save an image batch efficiently to disk.
**Inputs**
- `images` (IMAGE)
- `path_pattern` (STRING)
- `start_index` (INT)
- `lossless` (true / false)
- `quality` (INT)
- `skip_identical` (true / false)
- `overwrite` (true / false)
**Outputs**
- `paths` (STRING_LIST)
---
### 🔹 Batch Load Image Sequence
Load images from disk using a filename pattern.
**Inputs**
- `path_pattern` (STRING)
- `start_index` (INT)
- `frame_count` (INT)
- `ignore_missing_images` (true / false)
**Outputs**
- `images` (IMAGE)
---
### 🔹 Batch Load Image List (Advanced)
Load images directly from a `STRING_LIST`.
**Inputs**
- `paths` (STRING_LIST)
- `start` (INT, optional)
- `end` (INT, optional)
- `step` (INT, optional)
**Outputs**
- `images` (IMAGE)
- `frame_count` (INT)
> This is the **recommended loader** when using frame deduplication.
---
## 🧠 Why ComfyUI-FrameIO?
| Problem | Solution |
|------|------|
| PNG sequences too large | WebP (5–10× smaller) |
| Duplicate frames | Hash-based skip |
| Filename guessing | STRING_LIST loader |
| Partial re-render | Frame range selector |
| Long videos | Optimized IO |
---
## 🎬 Recommended Workflows
### 🔥 Best Practice (Long Videos)
```
## Recommended Settings
- Quality: 90–95
- Skip Identical Frames: true
KSampler
↓
Batch Save Image Sequence (WebP)
↓ STRING_LIST
Batch Load Image List (Advanced)
↓ IMAGE
Video Combine / FFmpeg
## License
MIT
````
### 🎯 Partial Reload
- `start = 300`
- `end = 900`
- `step = 2`
Perfect for re-encoding or post-processing sections.
---
## ⚙️ Recommended Settings
| Use Case | Settings |
|-------|---------|
| Final video | Quality 95, Skip Identical = true |
| Iteration | Quality 90 |
| Dataset / archival | Lossless = true |
| Static shots | Skip Identical = true |
---
## 📥 Installation
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/<yourname>/ComfyUI-FrameIO.git
````
Restart ComfyUI.
Nodes will appear under:
```
FrameIO
```
---
## 🔮 Roadmap (Planned / Ideas)
* FFmpeg encode node (no frame storage)
* AVIF support
* 10-bit video output
* Keyframe detection
* Frame cache / reuse
* Timeline tools
Contributions and suggestions welcome.
---
## 📄 License
MIT
+23 -2
View File
@@ -1,3 +1,24 @@
from .save_webp_sequence import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
from .save_webp_sequence import (
NODE_CLASS_MAPPINGS as SAVE_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as SAVE_NAMES,
)
from .load_image_sequence import (
NODE_CLASS_MAPPINGS as SEQ_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as SEQ_NAMES,
)
from .load_image_list import (
NODE_CLASS_MAPPINGS as LIST_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as LIST_NAMES,
)
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
NODE_CLASS_MAPPINGS = {}
NODE_CLASS_MAPPINGS.update(SAVE_MAPPINGS)
NODE_CLASS_MAPPINGS.update(SEQ_MAPPINGS)
NODE_CLASS_MAPPINGS.update(LIST_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS.update(SAVE_NAMES)
NODE_DISPLAY_NAME_MAPPINGS.update(SEQ_NAMES)
NODE_DISPLAY_NAME_MAPPINGS.update(LIST_NAMES)
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
+77
View File
@@ -0,0 +1,77 @@
import os
import torch
from PIL import Image
import numpy as np
def load_image(path: str) -> torch.Tensor:
"""
Load image from disk and convert to ComfyUI IMAGE tensor
Shape: [1, H, W, 3], float32 0..1
"""
img = Image.open(path).convert("RGB")
arr = np.array(img).astype(np.float32) / 255.0
return torch.from_numpy(arr)[None,]
class BatchLoadImageList:
CATEGORY = "FrameIO"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"paths": ("STRING_LIST",),
},
"optional": {
"start": ("INT", {"default": 0, "min": 0}),
"end": ("INT", {"default": -1, "min": -1}),
"step": ("INT", {"default": 1, "min": 1}),
},
}
RETURN_TYPES = ("IMAGE", "INT")
RETURN_NAMES = ("images", "frame_count")
FUNCTION = "execute"
def execute(
self,
paths,
start=0,
end=-1,
step=1,
):
if not paths:
raise RuntimeError("STRING_LIST is empty")
total = len(paths)
# Auto-detect end
if end < 0 or end > total:
end = total
if start >= end:
raise ValueError("Invalid frame range")
selected = paths[start:end:step]
if not selected:
raise RuntimeError("No frames selected after slicing")
imgs = []
for path in selected:
if not os.path.exists(path):
raise FileNotFoundError(f"Image does not exist: {path}")
imgs.append(load_image(path))
images = torch.cat(imgs, dim=0)
return (images, len(selected))
NODE_CLASS_MAPPINGS = {
"BatchLoadImageList": BatchLoadImageList
}
NODE_DISPLAY_NAME_MAPPINGS = {
"BatchLoadImageList": "Batch Load Image List (Advanced)"
}