22 Commits
Author SHA1 Message Date
bruefire dced5dc43f updated pyproject.toml 2025-06-29 21:48:01 +09:00
bruefire 711c9d2ed4 fixed wrong input type definitions for start_index and end_index. 2025-06-23 04:00:13 +09:00
bruefire d4332b36a8 Merge pull request #6 from ComfyNodePRs/update-publish-yaml
Update Github Action for Publishing to Comfy Registry
2025-03-29 18:41:23 +09:00
bruefire e23d496c13 added wanvideo workflow as sample. 2025-03-27 20:36:03 +09:00
bruefire c130b4bc88 updated logic to deploy javascript file. 2025-03-13 04:37:34 +09:00
snomiao 6f74f972d0 chore(publish): update GitHub Actions workflow for node publishing
- Add permissions for writing issues
- Update action version to v1 for publish-node-action
- Add condition to run job only for 'bruefire' repository owner
2025-01-21 08:43:08 +00:00
bruefire acfc98bcb3 updated pyproject.toml 2025-01-16 19:54:37 +09:00
bruefire c7142e5c99 adjusted css for new ComfyUI style. 2025-01-16 02:16:12 +09:00
bruefire 0284a7e3eb fixed wrong image format conversion. 2024-11-11 04:10:41 +09:00
bruefire b2cac6f6a9 PR-ComfyUI-SeqImageLoader-9abe3549 2024-09-22 17:10:49 +09:00
bruefire 21649fb0b1 added a new sample workflow for faceswap. 2024-09-22 16:07:14 +09:00
snomiao fa6a4ecc47 chore(licence-update): Update PyProject Toml - License 2024-08-01 16:03:09 +00:00
bruefire ee1ca23bd4 updated the readme.md for explaining editor features. 2024-06-09 00:48:37 +09:00
bruefire 5dfb693749 updated pyproject.toml 2024-06-08 15:04:41 +09:00
bruefire c8374194eb Merge pull request #1 from haohaocreates/pyproject
Add pyproject.toml for Custom Node Registry
2024-06-08 14:28:20 +09:00
bruefire 95ae55be11 Merge pull request #2 from haohaocreates/publish
Add Github Action for Publishing to Comfy Registry
2024-06-08 14:27:58 +09:00
haohaocreates f1691f89e9 chore(pyproject): Add pyproject.toml for Custom Node Registry 2024-05-22 18:08:33 -04:00
haohaocreates ae73ddb236 chore(publish): Add Github Action for Publishing to Comfy Registry 2024-05-22 18:08:30 -04:00
bruefire 31afa6c510 updated dogcat-workflow.json 2024-04-07 03:09:54 +09:00
bruefire cc3fb060a6 added a new logic for redo. 2024-04-03 01:13:26 +09:00
bruefire 1d0d3d799d fixed a bug that discarded masks/sketches are restored. 2024-04-02 23:15:01 +09:00
bruefire e728de22e3 removed the shortcut key for undo, due to the difficulty in avoiding conflict.. 2024-04-01 04:52:18 +09:00
11 changed files with 1072 additions and 229 deletions
+25
View File
@@ -0,0 +1,25 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- main
paths:
- "pyproject.toml"
permissions:
issues: write
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'bruefire' }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@v1
with:
## Add your own personal access token to your Github Repository secrets and reference it here.
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
+5 -5
View File
@@ -93,7 +93,7 @@ class LoadImagesInpaint:
s = ImageOps.exif_transpose(s).convert("RGBA") s = ImageOps.exif_transpose(s).convert("RGBA")
s = s.resize(i.size) s = s.resize(i.size)
image = Image.alpha_composite(i, s) image = Image.alpha_composite(i, s)
image.convert("RGB") image = image.convert("RGB")
image = np.array(image).astype(np.float32) / 255.0 image = np.array(image).astype(np.float32) / 255.0
image = torch.from_numpy(image)[None,] image = torch.from_numpy(image)[None,]
@@ -127,10 +127,10 @@ class LoadImagesFromDirInpaint(LoadImagesInpaint):
return { return {
"required": { "required": {
"sequence_id": ("STRING", {"frames_upload": True}), "sequence_id": ("STRING", {"frames_upload": True}),
},
"optional": {
"start_index": ("INT", {"default": 0, "min": 0, "step": 1}), "start_index": ("INT", {"default": 0, "min": 0, "step": 1}),
"end_index": ("INT", {"default": 0, "min": 0, "step": 1}), "end_index": ("INT", {"default": 0, "min": 0, "step": 1}),
},
"optional": {
} }
} }
@@ -141,10 +141,10 @@ class LoadImagesFromFileInpaint(LoadImagesInpaint):
return { return {
"required": { "required": {
"sequence_id": ("STRING", {"video_upload": True}), "sequence_id": ("STRING", {"video_upload": True}),
},
"optional": {
"start_index": ("INT", {"default": 0, "min": 0, "step": 1}), "start_index": ("INT", {"default": 0, "min": 0, "step": 1}),
"end_index": ("INT", {"default": 0, "min": 0, "step": 1}), "end_index": ("INT", {"default": 0, "min": 0, "step": 1}),
},
"optional": {
} }
} }
+3 -1
View File
@@ -12,9 +12,11 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"VFrame Loader With Mask Editor" : "SequentialImageLoader", "VFrame Loader With Mask Editor" : "SequentialImageLoader",
"Video Loader With Mask Editor" : "VideoFrameExtractor", "Video Loader With Mask Editor" : "VideoFrameExtractor",
} }
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] WEB_DIRECTORY = "./js"
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', "WEB_DIRECTORY"]
# keep this for backward compatibility for a while..
module_js_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), "js") module_js_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), "js")
application_root_directory = os.path.dirname(folder_paths.__file__) application_root_directory = os.path.dirname(folder_paths.__file__)
application_web_extensions_directory = os.path.join(application_root_directory, "web", "extensions", "SequentialImageLoader") application_web_extensions_directory = os.path.join(application_root_directory, "web", "extensions", "SequentialImageLoader")
Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

+85 -36
View File
@@ -66,10 +66,20 @@ class MaskEditorDialog extends ComfyDialog {
constructor() { constructor() {
super(); super();
this.element = $el("div.comfy-modal", { parent: document.body }, this.element = $el("div", { parent: document.body },
[ $el("div.comfy-modal-content", [ $el("div.comfy-modal-content",
[...this.createButtons()]), [...this.createButtons()]),
]); ]);
this.element.style.position = "fixed";
this.element.style.padding = "30px 30px 10px 30px";
this.element.style.backgroundColor = "#353535";
this.element.style.boxShadow = "0 0 20px #888888";
this.element.style.borderRadius = "10px";
this.element.style.fontFamily = "monospace";
this.element.style.fontSize = "15px";
this.element.style.top = "5%";
this.element.style.left = "100px";
} }
createButtons() { createButtons() {
@@ -233,7 +243,8 @@ class MaskEditorDialog extends ComfyDialog {
}); });
var modeButton = this.createLeftButton("sketch", var modeButton = this.createLeftButton("sketch",
(ev) => { (ev) => {
this.workCanvases = []; this.beforeCanvases = [];
this.afterCanvases = [];
this.maskCtx.globalCompositeOperation = "source-over"; this.maskCtx.globalCompositeOperation = "source-over";
if (!this.is_sketch) { if (!this.is_sketch) {
@@ -289,9 +300,10 @@ class MaskEditorDialog extends ComfyDialog {
} }
}); });
var UndoButton = this.createLeftButton("Undo", var UndoButton = this.createLeftButton("Undo",
() => { () => this.unstackBeforeCanvas());
this.unstackWorkCanvas(); var RedoButton = this.createLeftButton("Redo",
}); () => this.unstackAfterCanvas());
var fillModeButton = this.createLeftButton("✨", var fillModeButton = this.createLeftButton("✨",
(ev) => { (ev) => {
this.changeFillMode(ev.target); this.changeFillMode(ev.target);
@@ -329,6 +341,7 @@ class MaskEditorDialog extends ComfyDialog {
bottom_panel.appendChild(cancelButton); bottom_panel.appendChild(cancelButton);
bottom_panel.appendChild(brush_size_slider); bottom_panel.appendChild(brush_size_slider);
bottom_panel.appendChild(UndoButton); bottom_panel.appendChild(UndoButton);
bottom_panel.appendChild(RedoButton);
colorPicker.style.display = "none"; colorPicker.style.display = "none";
@@ -357,8 +370,8 @@ class MaskEditorDialog extends ComfyDialog {
const backSketchCanvases = [...new Array(this.#paths.length)].map(_ => document.createElement("canvas")); const backSketchCanvases = [...new Array(this.#paths.length)].map(_ => document.createElement("canvas"));
imgCanvas.id = "imageCanvas"; imgCanvas.id = "imageCanvas";
maskCanvas.id = "maskCanvas"; maskCanvas.id = "vMaskCanvas";
sketchCanvas.id = "sketchCanvas"; sketchCanvas.id = "vSketchCanvas";
this.setlayout(imgCanvas, maskCanvas, sketchCanvas); this.setlayout(imgCanvas, maskCanvas, sketchCanvas);
@@ -368,7 +381,8 @@ class MaskEditorDialog extends ComfyDialog {
this.sketchCanvas = sketchCanvas; this.sketchCanvas = sketchCanvas;
this.backMaskCanvases = backMaskCanvases; this.backMaskCanvases = backMaskCanvases;
this.backSketchCanvases = backSketchCanvases; this.backSketchCanvases = backSketchCanvases;
this.workCanvases = []; this.beforeCanvases = [];
this.afterCanvases = [];
this.maskCtx = maskCanvas.getContext('2d'); this.maskCtx = maskCanvas.getContext('2d');
this.setMaskEventHandler(maskCanvas); this.setMaskEventHandler(maskCanvas);
@@ -431,8 +445,7 @@ class MaskEditorDialog extends ComfyDialog {
} }
if (hasBackup) { if (hasBackup) {
this.backMaskCanvases = this.backupMaskCanvases; this.#restoreBackCanvases();
this.backSketchCanvases = this.backupSketchCanvases;
} }
else { else {
this.backMaskCanvases.forEach( this.backMaskCanvases.forEach(
@@ -571,8 +584,16 @@ class MaskEditorDialog extends ComfyDialog {
self.moveToPrev(); self.moveToPrev();
} else if (event.key == 'ArrowRight') { } else if (event.key == 'ArrowRight') {
self.moveToNext(); self.moveToNext();
} else if (event.ctrlKey && (event.key == 'z' || event.key == 'Z')) { } else if (event.altKey && event.shiftKey && (event.key == 'z' || event.key == 'Z')) {
self.unstackWorkCanvas(); event.preventDefault();
event.stopPropagation();
self.unstackAfterCanvas();
} else if (event.altKey && (event.key == 'z' || event.key == 'Z')) {
event.preventDefault();
event.stopPropagation();
self.unstackBeforeCanvas();
} }
self.updateBrushPreview(self); self.updateBrushPreview(self);
@@ -738,7 +759,7 @@ class MaskEditorDialog extends ComfyDialog {
} }
handlePointerDown(self, event) { handlePointerDown(self, event) {
this.stackWorkCanvas(); this.stackBeforeCanvas();
if (this.is_magicWand) { if (this.is_magicWand) {
if ([0, 2, 5].includes(event.button)) { if ([0, 2, 5].includes(event.button)) {
@@ -794,25 +815,45 @@ class MaskEditorDialog extends ComfyDialog {
} }
} }
stackWorkCanvas() { stackBeforeCanvas() {
let newCanvas = document.createElement("canvas"); let newCanvas = document.createElement("canvas");
newCanvas.width = this.maskCanvas.width; newCanvas.width = this.maskCanvas.width;
newCanvas.height = this.maskCanvas.height; newCanvas.height = this.maskCanvas.height;
newCanvas.getContext('2d').drawImage(this.maskCanvas, 0, 0); newCanvas.getContext('2d').drawImage(this.maskCanvas, 0, 0);
if (this.workCanvases.length == 32) if (this.beforeCanvases.length == 32)
this.workCanvases.shift(); this.beforeCanvases.shift();
this.workCanvases.push(newCanvas); this.beforeCanvases.push(newCanvas);
this.afterCanvases = [];
} }
unstackWorkCanvas() { unstackBeforeCanvas() {
if (this.workCanvases.length == 0) if (this.beforeCanvases.length == 0)
return; return;
let deactivatedCvs = MaskEditorDialog.#cloneCanvas(this.maskCanvas);
this.maskCtx.globalCompositeOperation = "source-over"; this.maskCtx.globalCompositeOperation = "source-over";
let lastCanvas = this.workCanvases.pop(); let activatedCanvas = this.beforeCanvases.pop();
this.maskCanvas.getContext('2d').clearRect(0, 0, lastCanvas.width, lastCanvas.height); this.maskCanvas.getContext('2d').clearRect(0, 0, activatedCanvas.width, activatedCanvas.height);
this.maskCanvas.getContext('2d').drawImage(lastCanvas, 0, 0); this.maskCanvas.getContext('2d').drawImage(activatedCanvas, 0, 0);
this.afterCanvases.push(deactivatedCvs);
}
unstackAfterCanvas() {
if (this.afterCanvases.length == 0)
return;
let deactivatedCvs = MaskEditorDialog.#cloneCanvas(this.maskCanvas);
this.maskCtx.globalCompositeOperation = "source-over";
let activatedCanvas = this.afterCanvases.pop();
this.maskCanvas.getContext('2d').clearRect(0, 0, activatedCanvas.width, activatedCanvas.height);
this.maskCanvas.getContext('2d').drawImage(activatedCanvas, 0, 0);
this.beforeCanvases.push(deactivatedCvs);
} }
changeFillMode(button) { changeFillMode(button) {
@@ -861,7 +902,8 @@ class MaskEditorDialog extends ComfyDialog {
moveToPrev() { moveToPrev() {
if (this.#selectedIndex > 0) { if (this.#selectedIndex > 0) {
this.workCanvases = []; this.beforeCanvases = [];
this.afterCanvases = [];
this.storeActiveToBack(); this.storeActiveToBack();
const params = new URLSearchParams(this.#paths[--this.#selectedIndex]); const params = new URLSearchParams(this.#paths[--this.#selectedIndex]);
this.image.src = new URL(api.apiURL("/view?" + params.toString()), window.location.href); this.image.src = new URL(api.apiURL("/view?" + params.toString()), window.location.href);
@@ -871,7 +913,8 @@ class MaskEditorDialog extends ComfyDialog {
moveToNext() { moveToNext() {
if (this.#selectedIndex < this.#paths.length - 1) { if (this.#selectedIndex < this.#paths.length - 1) {
this.workCanvases = []; this.beforeCanvases = [];
this.afterCanvases = [];
this.storeActiveToBack(); this.storeActiveToBack();
const params = new URLSearchParams(this.#paths[++this.#selectedIndex]); const params = new URLSearchParams(this.#paths[++this.#selectedIndex]);
this.image.src = new URL(api.apiURL("/view?" + params.toString()), window.location.href); this.image.src = new URL(api.apiURL("/view?" + params.toString()), window.location.href);
@@ -920,25 +963,31 @@ class MaskEditorDialog extends ComfyDialog {
await uploadImages(this.backSketchCanvases[i], i, String(sketchDirId)); await uploadImages(this.backSketchCanvases[i], i, String(sketchDirId));
this.#updatePathDataHnadler(maskDirId, sketchDirId); this.#updatePathDataHnadler(maskDirId, sketchDirId);
this.#createBackupCanvases(); this.#storeBackCanvases();
this.close(); this.close();
} }
#createBackupCanvases() { static #cloneCanvas(canvas) {
const func = canvas => { const backupCanvas = document.createElement('canvas');
const backupCanvas = document.createElement('canvas'); backupCanvas.width = canvas.width;
backupCanvas.width = canvas.width; backupCanvas.height = canvas.height;
backupCanvas.height = canvas.height; backupCanvas.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height);
backupCanvas.getContext('2d').drawImage(canvas, 0, 0, canvas.width, canvas.height); return backupCanvas;
return backupCanvas; }
};
this.backupMaskCanvases = this.backMaskCanvases.map(func); #storeBackCanvases() {
this.backupSketchCanvases = this.backSketchCanvases.map(func); this.backupMaskCanvases = this.backMaskCanvases.map(MaskEditorDialog.#cloneCanvas);
this.backupSketchCanvases = this.backSketchCanvases.map(MaskEditorDialog.#cloneCanvas);
}
#restoreBackCanvases() {
this.backMaskCanvases = this.backupMaskCanvases.map(MaskEditorDialog.#cloneCanvas);
this.backSketchCanvases = this.backupSketchCanvases.map(MaskEditorDialog.#cloneCanvas)
} }
close() { close() {
this.workCanvases = []; this.beforeCanvases = [];
this.afterCanvases = [];
window.removeEventListener("resize", this.resizingEventHandler); window.removeEventListener("resize", this.resizingEventHandler);
super.close(); super.close();
} }
+14
View File
@@ -0,0 +1,14 @@
[project]
name = "comfyui-seqimageloader"
description = "This is an extension node for ComfyUI that allows you to load frames from a video in bulk and perform masking and sketching on each frame through a GUI."
version = "1.0.8"
license = { file = "LICENSE.txt" }
[project.urls]
Repository = "https://github.com/bruefire/ComfyUI-SeqImageLoader"
# Used by Comfy Registry https://comfyregistry.org
[tool.comfy]
PublisherId = "bruefire"
DisplayName = "ComfyUI-SeqImageLoader"
Icon = "docs/icon.png"
+13 -1
View File
@@ -31,10 +31,22 @@ Otherwise, it is the same as the SequentialImageLoader Node.
1. After loading the frames, right-click the node and select "Open In MaskEditor". 1. After loading the frames, right-click the node and select "Open In MaskEditor".
2. In the editor that appears, perform masking and sketching as needed. It is based on the standard Mask Editor. 2. In the editor that appears, perform masking and sketching as needed. It is based on the standard Mask Editor.
### Editor Features
![image](docs/editor_features.png)
1. Switch between automatic masking (magic wand) and manual masking.
2. Switch between masking and sketching.
3. Canvas. Right-click to mask, left-click to unmask.
4. Change edit frame.
5. Clear mask on the current frame.
6. Paste the mask from the previous frame to the current frame.
7. Change the thickness of the masking.
8. Undo/Redo operations. Shortcut keys are alt+Z/shift+alt+Z. ( **not Ctrl+Z!** That's the standard shortcuts for ComfyUI. It might cause unexpected behavior.)
9. Save or cancel the results.
## Example With AnimateDiff ## Example With AnimateDiff
![iamge](docs/dogcat.gif) ![iamge](docs/dogcat.gif)
[Workflow](dogcat-workflow.json) (It's depend on [ComfyUI-AnimateDiff-Evolved](https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved)) [Workflow](sample_workflows/cat2dog_with_animatediff.json) (It's depend on [ComfyUI-AnimateDiff-Evolved](https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved))
[Video source](https://www.pexels.com/video/a-pet-cat-standing-on-the-brick-floor-of-a-garden-3009091/) [Video source](https://www.pexels.com/video/a-pet-cat-standing-on-the-brick-floor-of-a-garden-3009091/)
## Other ## Other
@@ -1,6 +1,6 @@
{ {
"last_node_id": 38, "last_node_id": 40,
"last_link_id": 37, "last_link_id": 39,
"nodes": [ "nodes": [
{ {
"id": 13, "id": 13,
@@ -475,7 +475,7 @@
], ],
"size": { "size": {
"0": 342.5999755859375, "0": 342.5999755859375,
"1": 190 "1": 230
}, },
"flags": {}, "flags": {},
"order": 7, "order": 7,
@@ -500,6 +500,16 @@
"name": "motion_model_settings", "name": "motion_model_settings",
"type": "MOTION_MODEL_SETTINGS", "type": "MOTION_MODEL_SETTINGS",
"link": null "link": null
},
{
"name": "sample_settings",
"type": "SAMPLE_SETTINGS",
"link": null
},
{
"name": "ad_keyframes",
"type": "AD_KEYFRAMES",
"link": null
} }
], ],
"outputs": [ "outputs": [
@@ -556,47 +566,6 @@
"RealESRGAN_x2plus.pth" "RealESRGAN_x2plus.pth"
] ]
}, },
{
"id": 8,
"type": "VAEDecode",
"pos": [
1510,
227
],
"size": {
"0": 210,
"1": 46
},
"flags": {},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 21
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
23,
35
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAEDecode"
}
},
{ {
"id": 16, "id": 16,
"type": "ADE_AnimateDiffUniformContextOptions", "type": "ADE_AnimateDiffUniformContextOptions",
@@ -606,13 +575,25 @@
], ],
"size": { "size": {
"0": 315, "0": 315,
"1": 154 "1": 270
}, },
"flags": { "flags": {
"collapsed": true "collapsed": true
}, },
"order": 3, "order": 3,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "prev_context",
"type": "CONTEXT_OPTIONS",
"link": null
},
{
"name": "view_opts",
"type": "VIEW_OPTS",
"link": null
}
],
"outputs": [ "outputs": [
{ {
"name": "CONTEXT_OPTIONS", "name": "CONTEXT_OPTIONS",
@@ -632,141 +613,11 @@
1, 1,
4, 4,
"uniform", "uniform",
false
]
},
{
"id": 37,
"type": "ADE_AnimateDiffCombine",
"pos": [
2027,
-1117
],
"size": {
"0": 999.5999755859375,
"1": 1191.5999755859375
},
"flags": {},
"order": 14,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 35
}
],
"outputs": [
{
"name": "GIF",
"type": "GIF",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "ADE_AnimateDiffCombine"
},
"widgets_values": [
12,
0,
"AnimateDiff",
"video/h264-mp4",
false, false,
true "flat",
]
},
{
"id": 17,
"type": "ADE_AnimateDiffCombine",
"pos": [
2462,
137
],
"size": {
"0": 999.5999755859375,
"1": 1191.5999755859375
},
"flags": {},
"order": 19,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 37
}
],
"outputs": [
{
"name": "GIF",
"type": "GIF",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "ADE_AnimateDiffCombine"
},
"widgets_values": [
12,
0,
"AnimateDiff",
"video/h264-mp4",
false, false,
true
]
},
{
"id": 11,
"type": "VFrame Loader With Mask Editor",
"pos": [
-192,
925
],
"size": {
"0": 321.0398864746094,
"1": 386.9773254394531
},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
11
],
"shape": 3,
"slot_index": 0
},
{
"name": "mask_images",
"type": "IMAGE",
"links": [
14
],
"shape": 3,
"slot_index": 1
},
{
"name": "image_count",
"type": "INT",
"links": null,
"shape": 3,
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "VFrame Loader With Mask Editor"
},
"widgets_values": [
"frame_0001.png:frame_0002.png:frame_0003.png:frame_0004.png:frame_0005.png:frame_0006.png:frame_0007.png:frame_0008.png:frame_0009.png:frame_0010.png:frame_0011.png:frame_0012.png:frame_0013.png:frame_0014.png:frame_0015.png:frame_0016.png:frame_0017.png:frame_0018.png:frame_0019.png:frame_0020.png:frame_0021.png:frame_0022.png:frame_0023.png:frame_0024.png:frame_0025.png:frame_0026.png:frame_0027.png:frame_0028.png:frame_0029.png:frame_0030.png:frame_0031.png:frame_0032.png:frame_0033.png:frame_0034.png:frame_0035.png:frame_0036.png:frame_0037.png:frame_0038.png:frame_0039.png:frame_0040.png:frame_0041.png:frame_0042.png:frame_0043.png:frame_0044.png:frame_0045.png:frame_0046.png:frame_0047.png:frame_0048.png:frame_0049.png:frame_0050.png:frame_0051.png:frame_0052.png:frame_0053.png:frame_0054.png:frame_0055.png:frame_0056.png:frame_0057.png:frame_0058.png:frame_0059.png:frame_0060.png:frame_0061.png:frame_0062.png:frame_0063.png:frame_0064.png:frame_0065.png:frame_0066.png:frame_0067.png:frame_0068.png:frame_0069.png:frame_0070.png:frame_0071.png:frame_0072.png:frame_0073.png:frame_0074.png:frame_0075.png:frame_0076.png:frame_0077.png:frame_0078.png:frame_0079.png:frame_0080.png:frame_0081.png:frame_0082.png:frame_0083.png:frame_0084.png:frame_0085.png:frame_0086.png:frame_0087.png:frame_0088.png:frame_0089.png:frame_0090.png:frame_0091.png:frame_0092.png:frame_0093.png:frame_0094.png:frame_0095.png:frame_0096.png:frame_0097.png:frame_0098.png:frame_0099.png:frame_0100.png:frame_0101.png:frame_0102.png:1702184442391/1702188855662/1702188855663",
"image",
0, 0,
202 1
] ]
}, },
{ {
@@ -828,11 +679,155 @@
0.45 0.45
] ]
}, },
{
"id": 11,
"type": "VFrame Loader With Mask Editor",
"pos": [
-192,
925
],
"size": {
"0": 321.0398864746094,
"1": 386.9773254394531
},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
11
],
"shape": 3,
"slot_index": 0
},
{
"name": "mask_images",
"type": "IMAGE",
"links": [
14
],
"shape": 3,
"slot_index": 1
},
{
"name": "image_count",
"type": "INT",
"links": null,
"shape": 3,
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "VFrame Loader With Mask Editor"
},
"widgets_values": [
"frame_0001.png:frame_0002.png:frame_0003.png:frame_0004.png:frame_0005.png:frame_0006.png:frame_0007.png:frame_0008.png:frame_0009.png:frame_0010.png:frame_0011.png:frame_0012.png:frame_0013.png:frame_0014.png:frame_0015.png:frame_0016.png:frame_0017.png:frame_0018.png:frame_0019.png:frame_0020.png:frame_0021.png:frame_0022.png:frame_0023.png:frame_0024.png:frame_0025.png:frame_0026.png:frame_0027.png:frame_0028.png:frame_0029.png:frame_0030.png:frame_0031.png:frame_0032.png:frame_0033.png:frame_0034.png:frame_0035.png:frame_0036.png:frame_0037.png:frame_0038.png:frame_0039.png:frame_0040.png:frame_0041.png:frame_0042.png:frame_0043.png:frame_0044.png:frame_0045.png:frame_0046.png:frame_0047.png:frame_0048.png:frame_0049.png:frame_0050.png:frame_0051.png:frame_0052.png:frame_0053.png:frame_0054.png:frame_0055.png:frame_0056.png:frame_0057.png:frame_0058.png:frame_0059.png:frame_0060.png:frame_0061.png:frame_0062.png:frame_0063.png:frame_0064.png:frame_0065.png:frame_0066.png:frame_0067.png:frame_0068.png:frame_0069.png:frame_0070.png:frame_0071.png:frame_0072.png:frame_0073.png:frame_0074.png:frame_0075.png:frame_0076.png:frame_0077.png:frame_0078.png:frame_0079.png:frame_0080.png:frame_0081.png:frame_0082.png:frame_0083.png:frame_0084.png:frame_0085.png:frame_0086.png:frame_0087.png:frame_0088.png:frame_0089.png:frame_0090.png:frame_0091.png:frame_0092.png:frame_0093.png:frame_0094.png:frame_0095.png:frame_0096.png:frame_0097.png:frame_0098.png:frame_0099.png:frame_0100.png:frame_0101.png:frame_0102.png:1702184442391/1702188855662/1702188855663",
"image",
0,
202
]
},
{
"id": 8,
"type": "VAEDecode",
"pos": [
1569,
239
],
"size": {
"0": 210,
"1": 46
},
"flags": {},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 21
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
23,
39
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAEDecode"
}
},
{
"id": 40,
"type": "VHS_VideoCombine",
"pos": [
2028,
-293
],
"size": {
"0": 315,
"1": 198
},
"flags": {},
"order": 14,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 39
},
{
"name": "audio",
"type": "VHS_AUDIO",
"link": null
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 12,
"loop_count": 0,
"filename_prefix": "AnimateDiff",
"format": "image/gif",
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {}
}
}
},
{ {
"id": 27, "id": 27,
"type": "VAEDecode", "type": "VAEDecode",
"pos": [ "pos": [
2116, 2246,
119 119
], ],
"size": { "size": {
@@ -859,7 +854,7 @@
"name": "IMAGE", "name": "IMAGE",
"type": "IMAGE", "type": "IMAGE",
"links": [ "links": [
37 38
], ],
"shape": 3, "shape": 3,
"slot_index": 0 "slot_index": 0
@@ -868,6 +863,57 @@
"properties": { "properties": {
"Node name for S&R": "VAEDecode" "Node name for S&R": "VAEDecode"
} }
},
{
"id": 39,
"type": "VHS_VideoCombine",
"pos": [
2540,
136
],
"size": {
"0": 315,
"1": 198
},
"flags": {},
"order": 19,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 38
},
{
"name": "audio",
"type": "VHS_AUDIO",
"link": null
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 12,
"loop_count": 0,
"filename_prefix": "AnimateDiff",
"format": "image/gif",
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {}
}
}
} }
], ],
"links": [ "links": [
@@ -1088,18 +1134,18 @@
"MODEL" "MODEL"
], ],
[ [
35, 38,
8, 27,
0, 0,
37, 39,
0, 0,
"IMAGE" "IMAGE"
], ],
[ [
37, 39,
27, 8,
0, 0,
17, 40,
0, 0,
"IMAGE" "IMAGE"
] ]
@@ -0,0 +1,694 @@
{
"last_node_id": 33,
"last_link_id": 42,
"nodes": [
{
"id": 24,
"type": "ImpactImageBatchToImageList",
"pos": [
-443,
-440
],
"size": {
"0": 210,
"1": 26
},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 27
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
28,
29
],
"shape": 6,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "ImpactImageBatchToImageList"
}
},
{
"id": 27,
"type": "ImageToMask",
"pos": [
-414,
104
],
"size": {
"0": 315,
"1": 58
},
"flags": {
"collapsed": false
},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 33
}
],
"outputs": [
{
"name": "MASK",
"type": "MASK",
"links": [
34
],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "ImageToMask"
},
"widgets_values": [
"red"
]
},
{
"id": 32,
"type": "ImageListToImageBatch",
"pos": [
355,
113
],
"size": {
"0": 210,
"1": 26
},
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 39
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
40
],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "ImageListToImageBatch"
}
},
{
"id": 28,
"type": "VHS_VideoCombine",
"pos": [
1285,
-449
],
"size": [
320,
789.5555555555555
],
"flags": {},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 38
},
{
"name": "audio",
"type": "VHS_AUDIO",
"link": null
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 30,
"loop_count": 0,
"filename_prefix": "fs",
"format": "video/h265-mp4",
"pix_fmt": "yuv420p10le",
"crf": 22,
"save_metadata": true,
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {
"filename": "fs_00009.mp4",
"subfolder": "",
"type": "output",
"format": "video/h265-mp4"
}
}
}
},
{
"id": 31,
"type": "ImageListToImageBatch",
"pos": [
859,
-440
],
"size": {
"0": 210,
"1": 26
},
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 37
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
38
],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "ImageListToImageBatch"
}
},
{
"id": 16,
"type": "ReActorMaskHelper",
"pos": [
333,
-436
],
"size": {
"0": 330,
"1": 454
},
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 28
},
{
"name": "swapped_image",
"type": "IMAGE",
"link": 18
},
{
"name": "mask_optional",
"type": "MASK",
"link": 42
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
37
],
"shape": 3,
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"shape": 3
},
{
"name": "MASK_PREVIEW",
"type": "IMAGE",
"links": [
41
],
"shape": 3,
"slot_index": 2
},
{
"name": "SWAPPED_FACE",
"type": "IMAGE",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "ReActorMaskHelper"
},
"widgets_values": [
"bbox/face_yolov8m.pt",
0.5,
10,
3,
10,
"sam_vit_b_01ec64.pth",
0,
0.93,
0,
0.7,
"False",
"dilate",
0,
9,
1
]
},
{
"id": 10,
"type": "ReActorFaceSwap",
"pos": [
-175,
-340
],
"size": {
"0": 315,
"1": 358
},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "input_image",
"type": "IMAGE",
"link": 29
},
{
"name": "source_image",
"type": "IMAGE",
"link": 11
},
{
"name": "face_model",
"type": "FACE_MODEL",
"link": null,
"slot_index": 2
},
{
"name": "face_boost",
"type": "FACE_BOOST",
"link": null,
"slot_index": 3
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
18,
39
],
"shape": 3,
"slot_index": 0
},
{
"name": "FACE_MODEL",
"type": "FACE_MODEL",
"links": null,
"shape": 3,
"slot_index": 1
}
],
"properties": {
"Node name for S&R": "ReActorFaceSwap"
},
"widgets_values": [
true,
"inswapper_128.onnx",
"retinaface_resnet50",
"none",
1,
0.5,
"no",
"no",
"0",
"0",
1
]
},
{
"id": 22,
"type": "MasksToMaskList",
"pos": [
-42,
105
],
"size": {
"0": 210,
"1": 26
},
"flags": {
"collapsed": false
},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "masks",
"type": "MASK",
"link": 34
}
],
"outputs": [
{
"name": "MASK",
"type": "MASK",
"links": [
42
],
"shape": 6,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "MasksToMaskList"
}
},
{
"id": 29,
"type": "VHS_VideoCombine",
"pos": [
796,
33
],
"size": [
320,
789.5555555555555
],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 40
},
{
"name": "audio",
"type": "VHS_AUDIO",
"link": null
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 30,
"loop_count": 0,
"filename_prefix": "fs",
"format": "video/h265-mp4",
"pix_fmt": "yuv420p10le",
"crf": 22,
"save_metadata": true,
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {
"filename": "fs_00008.mp4",
"subfolder": "",
"type": "output",
"format": "video/h265-mp4"
}
}
}
},
{
"id": 33,
"type": "PreviewImage",
"pos": [
852,
-328
],
"size": {
"0": 210,
"1": 246
},
"flags": {},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 41
}
],
"properties": {
"Node name for S&R": "PreviewImage"
}
},
{
"id": 12,
"type": "LoadImage",
"pos": [
-814,
17
],
"size": {
"0": 315,
"1": 314
},
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
11
],
"shape": 3,
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"keanu-reeves-the-matrix-1200x802.jpg",
"image"
]
},
{
"id": 23,
"type": "Video Loader With Mask Editor",
"pos": [
-816,
-440
],
"size": {
"0": 315,
"1": 382
},
"flags": {},
"order": 1,
"mode": 0,
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
27
],
"shape": 3,
"slot_index": 0
},
{
"name": "mask_images",
"type": "IMAGE",
"links": [
33
],
"shape": 3,
"slot_index": 1
},
{
"name": "image_count",
"type": "INT",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "Video Loader With Mask Editor"
},
"widgets_values": [
"",
"image",
0,
103
]
}
],
"links": [
[
11,
12,
0,
10,
1,
"IMAGE"
],
[
18,
10,
0,
16,
1,
"IMAGE"
],
[
27,
23,
0,
24,
0,
"IMAGE"
],
[
28,
24,
0,
16,
0,
"IMAGE"
],
[
29,
24,
0,
10,
0,
"IMAGE"
],
[
33,
23,
1,
27,
0,
"IMAGE"
],
[
34,
27,
0,
22,
0,
"MASK"
],
[
37,
16,
0,
31,
0,
"IMAGE"
],
[
38,
31,
0,
28,
0,
"IMAGE"
],
[
39,
10,
0,
32,
0,
"IMAGE"
],
[
40,
32,
0,
29,
0,
"IMAGE"
],
[
41,
16,
2,
33,
0,
"IMAGE"
],
[
42,
22,
0,
16,
2,
"MASK"
]
],
"groups": [],
"config": {},
"extra": {},
"version": 0.4
}
File diff suppressed because one or more lines are too long