From 615c2494f169b8221fd0c9d2bbd8a7fb4b981a10 Mon Sep 17 00:00:00 2001 From: WarpedAnimation Date: Tue, 2 Sep 2025 09:59:47 -0500 Subject: [PATCH] V1.7.2 (#12) * Add files via upload * v1.7.2 * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Add files via upload * v1.7.2 * V1.7.2 * v1.7.2 --- README.md | 8 + .../Warped Caption Images Workflow.json | 518 ++ .../Warped Framepack I2V or T2V Workflow.json | 97 +- .../Warped Framepack V2V Workflow.json | 9 +- .../Warped Modify Captions Workflow.json | 236 + .../Warped Modify Cation File Workflow.json | 237 + .../Warped Resize Images Workflow.json | 297 ++ .../Warped Scripted Sampling Workflow.json | 1384 +++++ .../Warped Upscale By Model Workflow.json | 72 +- __init__.py | 30 +- gguf_nodes.py | 121 +- nodes.py | 4594 +++++++---------- pyproject.toml | 3 +- 13 files changed, 4698 insertions(+), 2908 deletions(-) create mode 100644 Sample_Workflows/Warped Caption Images Workflow.json create mode 100644 Sample_Workflows/Warped Modify Captions Workflow.json create mode 100644 Sample_Workflows/Warped Modify Cation File Workflow.json create mode 100644 Sample_Workflows/Warped Resize Images Workflow.json create mode 100644 Sample_Workflows/Warped Scripted Sampling Workflow.json diff --git a/README.md b/README.md index 4ca5125..57c3914 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,14 @@
+# V1.7.2 Updates + +1) Added Scripting Nodes, Sampler, and Capabilities +2) New/Updated Sample Workflows +3) Added Captioning Capability + +
+ # V1.7.1 Updates 1) Added Fast Loading GGUF Unet, Clip, and Dual Clip Loader Nodes diff --git a/Sample_Workflows/Warped Caption Images Workflow.json b/Sample_Workflows/Warped Caption Images Workflow.json new file mode 100644 index 0000000..8fd2342 --- /dev/null +++ b/Sample_Workflows/Warped Caption Images Workflow.json @@ -0,0 +1,518 @@ +{ + "id": "00000000-0000-0000-0000-000000000000", + "revision": 0, + "last_node_id": 14, + "last_link_id": 24, + "nodes": [ + { + "id": 3, + "type": "PreviewImage", + "pos": [ + 584, + 49 + ], + "size": [ + 277, + 246 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 2 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.36", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 2, + "type": "LoadImageFromPath", + "pos": [ + 209, + 352 + ], + "size": [ + 270, + 78 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "STRING", + "widget": { + "name": "image" + }, + "link": 16 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 2, + 7 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI_Ib_CustomNodes", + "ver": "59746dc1f9d5e3f52c13e21dba1aacb82d5f1c2a", + "Node name for S&R": "LoadImageFromPath" + }, + "widgets_values": [ + "ComfyUI_00001_-assets\\ComfyUI_00001_.png [output]" + ] + }, + { + "id": 7, + "type": "PreviewTextNode", + "pos": [ + 1354, + 52 + ], + "size": [ + 289, + 263 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 8 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "1.0.60", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "", + [ + false, + true + ] + ] + }, + { + "id": 6, + "type": "WD14Tagger|pysssss", + "pos": [ + 950, + 51 + ], + "size": [ + 270.06640625, + 220 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 7 + } + ], + "outputs": [ + { + "name": "STRING", + "shape": 6, + "type": "STRING", + "links": [ + 8, + 9 + ] + } + ], + "properties": { + "cnr_id": "comfyui-wd14-tagger", + "ver": "1.0.0", + "Node name for S&R": "WD14Tagger|pysssss" + }, + "widgets_values": [ + "wd-v1-4-moat-tagger-v2", + 0.35, + 0.85, + false, + false, + "" + ] + }, + { + "id": 8, + "type": "PreviewTextNode", + "pos": [ + 1354, + 383 + ], + "size": [ + 289, + 263 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 22 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "1.0.60", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "", + [ + false, + true + ] + ] + }, + { + "id": 12, + "type": "WarpedLoadImages", + "pos": [ + 209, + 53 + ], + "size": [ + 270, + 234 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "filename", + "type": "STRING", + "links": [ + 16, + 20 + ] + }, + { + "name": "index", + "type": "INT", + "links": null + }, + { + "name": "prefixorg", + "type": "STRING", + "links": null + }, + { + "name": "prefixseg", + "type": "STRING", + "links": null + }, + { + "name": "prefixmsk", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedLoadImages" + }, + "widgets_values": [ + "incremental_image", + 0, + "Batch 001", + "H:\\TrainHy\\AmandaHolden\\S1", + "" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 13, + "type": "WarpedSaveImageCaption", + "pos": [ + 976, + 762 + ], + "size": [ + 219.14511108398438, + 46 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "image_path", + "type": "STRING", + "link": 20 + }, + { + "name": "caption", + "type": "STRING", + "link": 24 + } + ], + "outputs": [ + { + "name": "caption", + "type": "STRING", + "links": [ + 22 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedSaveImageCaption" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 9, + "type": "Text Find and Replace", + "pos": [ + 955, + 344 + ], + "size": [ + 273.767578125, + 142 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 9 + } + ], + "outputs": [ + { + "name": "result_text", + "type": "STRING", + "links": [ + 23 + ] + }, + { + "name": "replacement_count_number", + "type": "NUMBER", + "links": null + }, + { + "name": "replacement_count_float", + "type": "FLOAT", + "links": null + }, + { + "name": "replacement_count_int", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "was-node-suite-comfyui", + "ver": "1.0.2", + "Node name for S&R": "Text Find and Replace" + }, + "widgets_values": [ + "1girl,", + "amandaholden, 1girl," + ] + }, + { + "id": 14, + "type": "Text Find and Replace", + "pos": [ + 963, + 550 + ], + "size": [ + 273.767578125, + 142 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 23 + } + ], + "outputs": [ + { + "name": "result_text", + "type": "STRING", + "links": [ + 24 + ] + }, + { + "name": "replacement_count_number", + "type": "NUMBER", + "links": null + }, + { + "name": "replacement_count_float", + "type": "FLOAT", + "links": null + }, + { + "name": "replacement_count_int", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "was-node-suite-comfyui", + "ver": "1.0.2", + "Node name for S&R": "Text Find and Replace" + }, + "widgets_values": [ + ", portrait,", + "," + ] + } + ], + "links": [ + [ + 2, + 2, + 0, + 3, + 0, + "IMAGE" + ], + [ + 7, + 2, + 0, + 6, + 0, + "IMAGE" + ], + [ + 8, + 6, + 0, + 7, + 0, + "STRING" + ], + [ + 9, + 6, + 0, + 9, + 0, + "STRING" + ], + [ + 16, + 12, + 0, + 2, + 0, + "STRING" + ], + [ + 20, + 12, + 0, + 13, + 0, + "STRING" + ], + [ + 22, + 13, + 0, + 8, + 0, + "STRING" + ], + [ + 23, + 9, + 0, + 14, + 0, + "STRING" + ], + [ + 24, + 14, + 0, + 13, + 1, + "STRING" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + 0, + 1 + ] + }, + "frontendVersion": "1.23.4", + "VHS_latentpreview": true, + "VHS_latentpreviewrate": 15, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file diff --git a/Sample_Workflows/Warped Framepack I2V or T2V Workflow.json b/Sample_Workflows/Warped Framepack I2V or T2V Workflow.json index 169c46c..b901d82 100644 --- a/Sample_Workflows/Warped Framepack I2V or T2V Workflow.json +++ b/Sample_Workflows/Warped Framepack I2V or T2V Workflow.json @@ -1295,6 +1295,11 @@ "links": [ 367 ] + }, + { + "name": "valid_output", + "type": "BOOLEAN", + "links": null } ], "properties": { @@ -1681,6 +1686,50 @@ ] ] }, + { + "id": 172, + "type": "WarpedVAELoader", + "pos": [ + 259.8695373535156, + 754.8338623046875 + ], + "size": [ + 315, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 8, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "vae", + "type": "VAE", + "links": [ + 370 + ] + }, + { + "name": "vae_state_dict", + "type": "DICT", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WarpedToolset", + "ver": "4e08ee52f8f8f1b9b672937866812d63bbb520eb", + "Node name for S&R": "WarpedVAELoader", + "aux_id": "WarpedAnimation/ComfyUI-WarpedToolset", + "widget_ue_connectable": {} + }, + "widgets_values": [ + "hunyuan_video_vae_bf16.safetensors" + ], + "color": "#323", + "bgcolor": "#535" + }, { "id": 169, "type": "WarpedLoadFramePackModel", @@ -1731,55 +1780,11 @@ "FramePack_F1_I2V_HY_20250503_fp8_e4m3fn.safetensors", "bf16", "fp8_e4m3fn", - "cpu", + "cuda", "sdpa" ], "color": "#323", "bgcolor": "#535" - }, - { - "id": 172, - "type": "WarpedVAELoader", - "pos": [ - 259.8695373535156, - 754.8338623046875 - ], - "size": [ - 315, - 58 - ], - "flags": { - "collapsed": true - }, - "order": 8, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vae", - "type": "VAE", - "links": [ - 370 - ] - }, - { - "name": "vae_state_dict", - "type": "DICT", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-WarpedToolset", - "ver": "4e08ee52f8f8f1b9b672937866812d63bbb520eb", - "Node name for S&R": "WarpedVAELoader", - "aux_id": "WarpedAnimation/ComfyUI-WarpedToolset", - "widget_ue_connectable": {} - }, - "widgets_values": [ - "hunyuan_video_vae_bf16.safetensors" - ], - "color": "#323", - "bgcolor": "#535" } ], "links": [ @@ -2177,7 +2182,7 @@ -153.6730000000042 ] }, - "frontendVersion": "1.20.5", + "frontendVersion": "1.23.4", "ue_links": [], "VHS_latentpreview": true, "VHS_latentpreviewrate": 15, diff --git a/Sample_Workflows/Warped Framepack V2V Workflow.json b/Sample_Workflows/Warped Framepack V2V Workflow.json index 134bc26..2a24609 100644 --- a/Sample_Workflows/Warped Framepack V2V Workflow.json +++ b/Sample_Workflows/Warped Framepack V2V Workflow.json @@ -1316,6 +1316,11 @@ "links": [ 608 ] + }, + { + "name": "valid_output", + "type": "BOOLEAN", + "links": null } ], "properties": { @@ -1847,7 +1852,7 @@ "FramePack_F1_I2V_HY_20250503_fp8_e4m3fn.safetensors", "bf16", "fp8_e4m3fn", - "cpu", + "cuda", "sdpa" ], "color": "#323", @@ -2304,7 +2309,7 @@ "VHS_MetadataImage": true, "VHS_KeepIntermediate": true, "links_added_by_ue": [], - "frontendVersion": "1.20.5" + "frontendVersion": "1.23.4" }, "version": 0.4 } \ No newline at end of file diff --git a/Sample_Workflows/Warped Modify Captions Workflow.json b/Sample_Workflows/Warped Modify Captions Workflow.json new file mode 100644 index 0000000..30a8c35 --- /dev/null +++ b/Sample_Workflows/Warped Modify Captions Workflow.json @@ -0,0 +1,236 @@ +{ + "id": "00000000-0000-0000-0000-000000000000", + "revision": 0, + "last_node_id": 4, + "last_link_id": 4, + "nodes": [ + { + "id": 3, + "type": "PreviewTextNode", + "pos": [ + 1226, + 167 + ], + "size": [ + 378, + 267 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 1 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "Original Prompt", + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "1.0.60", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "", + [ + false, + true + ] + ] + }, + { + "id": 2, + "type": "WarpedSaveImageCaption", + "pos": [ + 861, + 494 + ], + "size": [ + 219.14511108398438, + 46 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "image_path", + "type": "STRING", + "link": 3 + }, + { + "name": "caption", + "type": "STRING", + "link": 2 + } + ], + "outputs": [ + { + "name": "caption", + "type": "STRING", + "links": [ + 4 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedSaveImageCaption" + }, + "widgets_values": [] + }, + { + "id": 1, + "type": "WarpedModifyCaptionFile", + "pos": [ + 497, + 191 + ], + "size": [ + 272.1177673339844, + 194 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "filename", + "type": "STRING", + "links": [ + 3 + ] + }, + { + "name": "original", + "type": "STRING", + "links": [ + 1 + ] + }, + { + "name": "modified", + "type": "STRING", + "links": [ + 2 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedModifyCaptionFile" + }, + "widgets_values": [ + "incremental_caption", + 0, + "N:\\Train\\Mandy\\S1", + "1girl,", + "mandy, 1girl," + ] + }, + { + "id": 4, + "type": "PreviewTextNode", + "pos": [ + 1226, + 497 + ], + "size": [ + 378, + 267 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 4 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "Modified Prompt", + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "1.0.60", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "", + [ + false, + true + ] + ] + } + ], + "links": [ + [ + 1, + 1, + 1, + 3, + 0, + "STRING" + ], + [ + 2, + 1, + 2, + 2, + 1, + "STRING" + ], + [ + 3, + 1, + 0, + 2, + 0, + "STRING" + ], + [ + 4, + 2, + 0, + 4, + 0, + "STRING" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + -131, + -27 + ] + }, + "frontendVersion": "1.23.4", + "VHS_latentpreview": true, + "VHS_latentpreviewrate": 15, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file diff --git a/Sample_Workflows/Warped Modify Cation File Workflow.json b/Sample_Workflows/Warped Modify Cation File Workflow.json new file mode 100644 index 0000000..53cfd53 --- /dev/null +++ b/Sample_Workflows/Warped Modify Cation File Workflow.json @@ -0,0 +1,237 @@ +{ + "id": "00000000-0000-0000-0000-000000000000", + "revision": 0, + "last_node_id": 4, + "last_link_id": 4, + "nodes": [ + { + "id": 3, + "type": "PreviewTextNode", + "pos": [ + 1155, + 487 + ], + "size": [ + 338, + 230 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 3 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "1.0.60", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "", + [ + false, + true + ] + ] + }, + { + "id": 4, + "type": "PreviewTextNode", + "pos": [ + 1154, + 201 + ], + "size": [ + 338, + 230 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 4 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "1.0.60", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "", + [ + false, + true + ] + ] + }, + { + "id": 1, + "type": "WarpedModifyCaptionFile", + "pos": [ + 692, + 229 + ], + "size": [ + 272.1177673339844, + 194 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "filename", + "type": "STRING", + "links": [ + 1 + ] + }, + { + "name": "original", + "type": "STRING", + "links": [ + 4 + ] + }, + { + "name": "modified", + "type": "STRING", + "links": [ + 2 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedModifyCaptionFile" + }, + "widgets_values": [ + "incremental_caption", + 0, + "", + "", + "" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 2, + "type": "WarpedSaveImageCaption", + "pos": [ + 704, + 487 + ], + "size": [ + 219.14511108398438, + 46 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "image_path", + "type": "STRING", + "link": 1 + }, + { + "name": "caption", + "type": "STRING", + "link": 2 + } + ], + "outputs": [ + { + "name": "caption", + "type": "STRING", + "links": [ + 3 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedSaveImageCaption" + }, + "color": "#323", + "bgcolor": "#535" + } + ], + "links": [ + [ + 1, + 1, + 0, + 2, + 0, + "STRING" + ], + [ + 2, + 1, + 2, + 2, + 1, + "STRING" + ], + [ + 3, + 2, + 0, + 3, + 0, + "STRING" + ], + [ + 4, + 1, + 1, + 4, + 0, + "STRING" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + 0, + 0 + ] + }, + "frontendVersion": "1.20.5", + "VHS_latentpreview": true, + "VHS_latentpreviewrate": 15, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file diff --git a/Sample_Workflows/Warped Resize Images Workflow.json b/Sample_Workflows/Warped Resize Images Workflow.json new file mode 100644 index 0000000..70f8d82 --- /dev/null +++ b/Sample_Workflows/Warped Resize Images Workflow.json @@ -0,0 +1,297 @@ +{ + "id": "00000000-0000-0000-0000-000000000000", + "revision": 0, + "last_node_id": 15, + "last_link_id": 25, + "nodes": [ + { + "id": 3, + "type": "PreviewImage", + "pos": [ + 584, + 49 + ], + "size": [ + 277, + 246 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 2 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.36", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 2, + "type": "LoadImageFromPath", + "pos": [ + 209, + 352 + ], + "size": [ + 270, + 78 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "STRING", + "widget": { + "name": "image" + }, + "link": 16 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 2, + 23 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI_Ib_CustomNodes", + "ver": "59746dc1f9d5e3f52c13e21dba1aacb82d5f1c2a", + "Node name for S&R": "LoadImageFromPath" + }, + "widgets_values": [ + "ComfyUI_00001_-assets\\ComfyUI_00001_.png [output]" + ] + }, + { + "id": 14, + "type": "WarpedImageScaleToSide", + "pos": [ + 209.18991088867188, + 492.51904296875 + ], + "size": [ + 280.6968688964844, + 146 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 23 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 24 + ] + }, + { + "name": "width", + "type": "INT", + "links": null + }, + { + "name": "height", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedImageScaleToSide" + }, + "widgets_values": [ + 1024, + "long_side", + false + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 12, + "type": "WarpedLoadImages", + "pos": [ + 209, + 53 + ], + "size": [ + 270, + 234 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "filename", + "type": "STRING", + "links": [ + 16 + ] + }, + { + "name": "index", + "type": "INT", + "links": null + }, + { + "name": "prefixorg", + "type": "STRING", + "links": [ + 25 + ] + }, + { + "name": "prefixseg", + "type": "STRING", + "links": null + }, + { + "name": "prefixmsk", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedLoadImages" + }, + "widgets_values": [ + "incremental_image", + 0, + "Batch 001", + "N:\\Train\\!Done\\TraciLords\\S2\\50s", + "" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 15, + "type": "SaveImage", + "pos": [ + 941.0078735351562, + 49.79180908203125 + ], + "size": [ + 459.0909118652344, + 426.18182373046875 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 24 + }, + { + "name": "filename_prefix", + "type": "STRING", + "widget": { + "name": "filename_prefix" + }, + "link": 25 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.36", + "Node name for S&R": "SaveImage" + }, + "widgets_values": [ + "ComfyUI" + ] + } + ], + "links": [ + [ + 2, + 2, + 0, + 3, + 0, + "IMAGE" + ], + [ + 16, + 12, + 0, + 2, + 0, + "STRING" + ], + [ + 23, + 2, + 0, + 14, + 0, + "IMAGE" + ], + [ + 24, + 14, + 0, + 15, + 0, + "IMAGE" + ], + [ + 25, + 12, + 2, + 15, + 1, + "STRING" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1.1, + "offset": [ + -13.735092727272452, + 49.29911909090902 + ] + }, + "frontendVersion": "1.20.5", + "VHS_latentpreview": true, + "VHS_latentpreviewrate": 15, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file diff --git a/Sample_Workflows/Warped Scripted Sampling Workflow.json b/Sample_Workflows/Warped Scripted Sampling Workflow.json new file mode 100644 index 0000000..872a42c --- /dev/null +++ b/Sample_Workflows/Warped Scripted Sampling Workflow.json @@ -0,0 +1,1384 @@ +{ + "id": "6fee7bc1-689d-4cd1-b4f9-7c20316a44f8", + "revision": 0, + "last_node_id": 342, + "last_link_id": 1108, + "nodes": [ + { + "id": 311, + "type": "MagCache", + "pos": [ + -51.868019104003906, + 28.558996200561523 + ], + "size": [ + 270, + 178 + ], + "flags": { + "collapsed": true + }, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1046 + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 1047 + ] + } + ], + "properties": { + "aux_id": "Zehong-Ma/ComfyUI-MagCache", + "ver": "7d4e982bf7955498afca891c7094c48a70985537", + "Node name for S&R": "MagCache" + }, + "widgets_values": [ + "hunyuan_video", + 0.12000000000000002, + 0.2, + 3, + 0, + -1 + ] + }, + { + "id": 316, + "type": "WarpedNumericalConversion", + "pos": [ + 1150.0250244140625, + -203.03500366210938 + ], + "size": [ + 230.00741577148438, + 86 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "int_value", + "shape": 7, + "type": "INT", + "link": 1089 + }, + { + "name": "float_value", + "shape": 7, + "type": "FLOAT", + "link": null + }, + { + "name": "number_value", + "shape": 7, + "type": "NUMBER", + "link": null + } + ], + "outputs": [ + { + "name": "int", + "type": "INT", + "links": null + }, + { + "name": "float", + "type": "FLOAT", + "links": null + }, + { + "name": "number", + "type": "NUMBER", + "links": null + }, + { + "name": "string", + "type": "STRING", + "links": [ + 1061 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedNumericalConversion" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 67, + "type": "ModelSamplingSD3", + "pos": [ + -56.19779968261719, + 79.80845642089844 + ], + "size": [ + 210, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1047 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "slot_index": 0, + "links": [ + 1082 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "ModelSamplingSD3" + }, + "widgets_values": [ + 12 + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 81, + "type": "Reroute", + "pos": [ + -185.6532745361328, + 515.78955078125 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 1105 + } + ], + "outputs": [ + { + "name": "", + "type": "MODEL", + "slot_index": 0, + "links": [ + 526, + 1014, + 1046 + ] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 177, + "type": "BasicScheduler", + "pos": [ + -55.761207580566406, + 131.716552734375 + ], + "size": [ + 315, + 106 + ], + "flags": { + "collapsed": true + }, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 526 + } + ], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "slot_index": 0, + "links": [ + 993, + 1084 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "BasicScheduler" + }, + "widgets_values": [ + "simple", + 25, + 1 + ] + }, + { + "id": 309, + "type": "WarpedVAELoader", + "pos": [ + -429.87164306640625, + 514.3742065429688 + ], + "size": [ + 315, + 70 + ], + "flags": { + "collapsed": true + }, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "vae", + "type": "VAE", + "links": [ + 1042, + 1081 + ] + }, + { + "name": "vae_state_dict", + "type": "DICT", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WarpedToolset", + "ver": "4e08ee52f8f8f1b9b672937866812d63bbb520eb", + "Node name for S&R": "WarpedVAELoader", + "widget_ue_connectable": {} + }, + "widgets_values": [ + "hunyuan_video_vae_bf16.safetensors" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 310, + "type": "WarpedCLIPVisionLoader", + "pos": [ + -432.5339050292969, + 576.9319458007812 + ], + "size": [ + 315, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "clip_vision", + "type": "CLIP_VISION", + "links": [ + 1085 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-WarpedToolset", + "ver": "4e08ee52f8f8f1b9b672937866812d63bbb520eb", + "Node name for S&R": "WarpedCLIPVisionLoader", + "widget_ue_connectable": {} + }, + "widgets_values": [ + "clip_vision_h_fp8_e4m3fn.safetensors" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 16, + "type": "KSamplerSelect", + "pos": [ + -53.90724182128906, + 179.31997680664062 + ], + "size": [ + 315, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "slot_index": 0, + "links": [ + 992, + 1083 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "uni_pc" + ] + }, + { + "id": 331, + "type": "WarpedLoaderGGUF", + "pos": [ + -986.5651245117188, + 386.439208984375 + ], + "size": [ + 417.9764404296875, + 64.65499877929688 + ], + "flags": { + "collapsed": true + }, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 1093 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.0", + "Node name for S&R": "WarpedLoaderGGUF" + }, + "widgets_values": [ + "hunyuan-video-i2v-720p-Q4_K_M.gguf" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 336, + "type": "MagCache", + "pos": [ + -974.7998046875, + 435.5965576171875 + ], + "size": [ + 270, + 178 + ], + "flags": { + "collapsed": true + }, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1097 + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 1098 + ] + } + ], + "properties": { + "aux_id": "Zehong-Ma/ComfyUI-MagCache", + "ver": "7d4e982bf7955498afca891c7094c48a70985537", + "Node name for S&R": "MagCache" + }, + "widgets_values": [ + "hunyuan_video", + 0.12000000000000002, + 0.2, + 3, + 0, + -1 + ] + }, + { + "id": 334, + "type": "ModelSamplingSD3", + "pos": [ + -969.500244140625, + 482.397705078125 + ], + "size": [ + 210, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1098 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "slot_index": 0, + "links": [ + 1099, + 1101 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "ModelSamplingSD3" + }, + "widgets_values": [ + 12 + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 335, + "type": "BasicScheduler", + "pos": [ + -962.8997802734375, + 530.6984252929688 + ], + "size": [ + 315, + 106 + ], + "flags": { + "collapsed": true + }, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1099 + } + ], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "slot_index": 0, + "links": [ + 1096 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "BasicScheduler" + }, + "widgets_values": [ + "simple", + 25, + 1 + ] + }, + { + "id": 152, + "type": "PreviewTextNode", + "pos": [ + 742.5791015625, + -236.30349731445312 + ], + "size": [ + 342.3085632324219, + 114.48214721679688 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 1090 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "7b3d6f190aeca261422bdfb74b5af37937e5bf68", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "****** WarpedSamplerCustomScripted: Total Images Generated 89 ******", + [ + false, + true + ] + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 317, + "type": "PreviewTextNode", + "pos": [ + 1446.8729248046875, + -223.878173828125 + ], + "size": [ + 210, + 98.67514038085938 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 1061 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui_custom_nodes_alekpet", + "ver": "7b3d6f190aeca261422bdfb74b5af37937e5bf68", + "Node name for S&R": "PreviewTextNode" + }, + "widgets_values": [ + "858614460513588", + [ + false, + true + ] + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 190, + "type": "VHS_VideoCombine", + "pos": [ + 1258.2879638671875, + 536.257080078125 + ], + "size": [ + 680.8053588867188, + 1198.0067138671875 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 1088 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": null + }, + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + }, + { + "name": "save_output", + "type": "BOOLEAN", + "widget": { + "name": "save_output" + }, + "link": 1103 + }, + { + "name": "save_images", + "type": "BOOLEAN", + "widget": { + "name": "save_images" + }, + "link": 1104 + } + ], + "outputs": [ + { + "name": "Filenames", + "type": "VHS_FILENAMES", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-videohelpersuite", + "ver": "1.5.12", + "Node name for S&R": "VHS_VideoCombine" + }, + "widgets_values": { + "frame_rate": 15, + "loop_count": 0, + "filename_prefix": "Hunyuan/%date:yyyy_MM_dd%/lowres/vid", + "format": "video/nvenc_h264-mp4", + "pix_fmt": "yuv420p", + "bitrate": 10, + "megabit": true, + "save_metadata": true, + "pingpong": false, + "save_output": true, + "save_images": true, + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "vid_00043.mp4", + "subfolder": "Hunyuan\\2025_08_27\\lowres", + "type": "output", + "format": "video/nvenc_h264-mp4", + "frame_rate": 15, + "workflow": "vid_first_00043.png", + "fullpath": "N:\\Projects\\ComfyUI_windows_portable\\ComfyUI\\output\\Hunyuan\\2025_08_27\\lowres\\vid_00043.mp4" + }, + "muted": false + } + } + }, + { + "id": 314, + "type": "WarpedDualClipLoaderGGUF", + "pos": [ + -437.8577880859375, + 462.46478271484375 + ], + "size": [ + 300.9039001464844, + 130 + ], + "flags": { + "collapsed": true + }, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 1080 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.0", + "Node name for S&R": "WarpedDualClipLoaderGGUF" + }, + "widgets_values": [ + "clip_l.safetensors", + "Kijai\\llava-llama-3-8B-v1_1-Q4_K_M.gguf", + "hunyuan_video", + "default" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 313, + "type": "WarpedLoaderGGUF", + "pos": [ + -433.8647766113281, + 401.239501953125 + ], + "size": [ + 417.9764404296875, + 64.65499877929688 + ], + "flags": { + "collapsed": true + }, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 1106 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.0", + "Node name for S&R": "WarpedLoaderGGUF" + }, + "widgets_values": [ + "hunyuan-video-t2v-720p-Q4_K_M.gguf" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 339, + "type": "WarpedSamplerScripts5", + "pos": [ + -49.16597366333008, + 248.001708984375 + ], + "size": [ + 522.111572265625, + 631.2182006835938 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "scripts", + "type": "WARPEDSCRIPTS", + "links": [ + 1102 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedSamplerScripts5" + }, + "widgets_values": [ + "video of angelkelly flirting with the viewer. 1girl, solo, long_hair, curly hair, breasts, looking_at_viewer, smile, brown_hair, navel, brown_eyes, jewelry, very small_breasts, underwear, nipples, panties, full_body, nude, dark_skin, dark-skinned female, bikini tan, spread_legs, necklace, nail_polish, grin, high_heels, bracelet, lips, fingernails, toes, piercing, squatting, ring, breasts_apart, toenails, realistic, nose, covering_crotch, platform_footwear, navel_piercing, dark_nipples, stiletto_heels, platform_heels", + "", + "video of angelkelly flirting with the viewer as she pulls her panties to the side to show her pussy to the viewer. 1girl, solo, long_hair, curly hair, breasts, looking_at_viewer, smile, brown_hair, navel, brown_eyes, jewelry, very small_breasts, underwear, nipples, panties, full_body, nude, dark_skin, dark-skinned female, bikini tan, spread_legs, necklace, nail_polish, grin, high_heels, bracelet, lips, fingernails, toes, piercing, squatting, ring, breasts_apart, toenails, realistic, nose, platform_footwear, navel_piercing, dark_nipples, stiletto_heels, platform_heels", + "", + "", + "" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 340, + "type": "WarpedHunyuanMultiLoraLoader", + "pos": [ + -440.65118408203125, + -32.33539962768555 + ], + "size": [ + 360.6158142089844, + 390 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1106 + }, + { + "name": "lora_name", + "shape": 7, + "type": "STRING", + "link": null + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 1105 + ] + }, + { + "name": "lora_metadata", + "shape": 6, + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedHunyuanMultiLoraLoader" + }, + "widgets_values": [ + "RsmHy\\RsmAngelKellyHy.safetensors", + 1.1000000000000003, + "double_blocks", + "None", + 1, + "all", + "None", + 1, + "all", + "None", + 1, + "all", + 1.1000000000000003, + "double_blocks" + ] + }, + { + "id": 99, + "type": "Fast Groups Muter (rgthree)", + "pos": [ + 320.3949890136719, + -243.12155151367188 + ], + "size": [ + 386.92010498046875, + 138.19512939453125 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "OPT_CONNECTION", + "type": "*", + "links": null + } + ], + "properties": { + "matchColors": "", + "matchTitle": "", + "showNav": true, + "sort": "position", + "customSortAlphabet": "", + "toggleRestriction": "default" + } + }, + { + "id": 332, + "type": "HunyuanMultiLoraLoader", + "pos": [ + -1003.7517700195312, + -19.239805221557617 + ], + "size": [ + 364.0858154296875, + 346.54290771484375 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 1093 + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "slot_index": 0, + "links": [ + 1097 + ] + } + ], + "properties": { + "cnr_id": "Hunyuan-Multi-Lora-Loader", + "ver": "dd009a9d44b47bfaf01a4ffa38d7098f523e2cce", + "Node name for S&R": "HunyuanMultiLoraLoader" + }, + "widgets_values": [ + "RsmHy\\RsmAngelKellyHy.safetensors", + 1.1000000000000003, + "double_blocks", + "None", + 1.0000000000000002, + "all", + "None", + 1.0000000000000002, + "all", + "None", + 1, + "all" + ] + }, + { + "id": 330, + "type": "WarpedSamplerCustomScripted", + "pos": [ + 553.5939331054688, + -16.0568904876709 + ], + "size": [ + 687.9935913085938, + 1758.991943359375 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 1080 + }, + { + "name": "vae", + "type": "VAE", + "link": 1081 + }, + { + "name": "model", + "type": "MODEL", + "link": 1082 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 1083 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 1084 + }, + { + "name": "clip_vision_model", + "shape": 7, + "type": "CLIP_VISION", + "link": 1085 + }, + { + "name": "start_image", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "secondary_sigmas", + "shape": 7, + "type": "SIGMAS", + "link": 1096 + }, + { + "name": "secondary_model", + "shape": 7, + "type": "MODEL", + "link": 1101 + }, + { + "name": "batches_script", + "shape": 7, + "type": "WARPEDSCRIPTS", + "link": 1102 + } + ], + "outputs": [ + { + "name": "images", + "type": "IMAGE", + "links": [ + 1088 + ] + }, + { + "name": "latents", + "type": "LATENT", + "links": null + }, + { + "name": "seed", + "type": "INT", + "links": [ + 1089 + ] + }, + { + "name": "generation_status", + "type": "STRING", + "links": [ + 1090 + ] + }, + { + "name": "image_used", + "type": "IMAGE", + "links": null + }, + { + "name": "valid_output", + "type": "BOOLEAN", + "links": [ + 1103, + 1104 + ] + } + ], + "properties": { + "cnr_id": "comfyui-warpedtoolset", + "ver": "1.7.1", + "Node name for S&R": "WarpedSamplerCustomScripted" + }, + "widgets_values": [ + "", + "", + 177, + 89, + "next_lowest", + 647057505343014, + "randomize", + 256, + 64, + 64, + 8, + 0, + 1, + "Hunyuan", + "v2 (replace)", + 1, + 1, + 0, + 576, + 720, + 1, + 7, + false, + 33, + true, + false, + "last", + false, + true, + "" + ], + "color": "#323", + "bgcolor": "#535" + } + ], + "links": [ + [ + 526, + 81, + 0, + 177, + 0, + "MODEL" + ], + [ + 1046, + 81, + 0, + 311, + 0, + "MODEL" + ], + [ + 1047, + 311, + 0, + 67, + 0, + "MODEL" + ], + [ + 1061, + 316, + 3, + 317, + 0, + "STRING" + ], + [ + 1080, + 314, + 0, + 330, + 0, + "CLIP" + ], + [ + 1081, + 309, + 0, + 330, + 1, + "VAE" + ], + [ + 1082, + 67, + 0, + 330, + 2, + "MODEL" + ], + [ + 1083, + 16, + 0, + 330, + 3, + "SAMPLER" + ], + [ + 1084, + 177, + 0, + 330, + 4, + "SIGMAS" + ], + [ + 1085, + 310, + 0, + 330, + 5, + "CLIP_VISION" + ], + [ + 1088, + 330, + 0, + 190, + 0, + "IMAGE" + ], + [ + 1089, + 330, + 2, + 316, + 0, + "INT" + ], + [ + 1090, + 330, + 3, + 152, + 0, + "STRING" + ], + [ + 1093, + 331, + 0, + 332, + 0, + "MODEL" + ], + [ + 1096, + 335, + 0, + 330, + 7, + "SIGMAS" + ], + [ + 1097, + 332, + 0, + 336, + 0, + "MODEL" + ], + [ + 1098, + 336, + 0, + 334, + 0, + "MODEL" + ], + [ + 1099, + 334, + 0, + 335, + 0, + "MODEL" + ], + [ + 1101, + 334, + 0, + 330, + 8, + "MODEL" + ], + [ + 1102, + 339, + 0, + 330, + 9, + "WARPEDSCRIPTS" + ], + [ + 1103, + 330, + 5, + 190, + 4, + "BOOLEAN" + ], + [ + 1104, + 330, + 5, + 190, + 5, + "BOOLEAN" + ], + [ + 1105, + 340, + 0, + 81, + 0, + "*" + ], + [ + 1106, + 313, + 0, + 340, + 0, + "MODEL" + ] + ], + "groups": [ + { + "id": 2, + "title": "Hunyuan Primary Model", + "bounding": [ + -479.1864318847656, + -109.82951354980469, + 2432.05615234375, + 2123.07666015625 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 3, + "title": "Secondary Model", + "bounding": [ + -1060.8065185546875, + -106.47135162353516, + 564.5999755859375, + 687.2000122070312 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + } + ], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + -421.09625804248935, + -888.7121926781934 + ] + }, + "frontendVersion": "1.23.4", + "groupNodes": {}, + "ue_links": [], + "VHS_latentpreview": true, + "VHS_latentpreviewrate": 15, + "node_versions": { + "ComfyUI_Custom_Nodes_AlekPet": "7b3d6f190aeca261422bdfb74b5af37937e5bf68", + "ComfyUI-GGUF": "298192ed60f8ca821c6fe5f8030cae23424cada5", + "comfy-core": "0.3.26", + "comfyui-videohelpersuite": "5e61bcf218fe3bb7c899bbd584bbc99a9d05fb42", + "teacache": "1.4.5", + "comfyui-kjnodes": "e3b4bcf21e03402a2b11927eb5a4e3df500795b7", + "Hunyuan-Multi-Lora-Loader": "dd009a9d44b47bfaf01a4ffa38d7098f523e2cce" + }, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file diff --git a/Sample_Workflows/Warped Upscale By Model Workflow.json b/Sample_Workflows/Warped Upscale By Model Workflow.json index d51d326..2602421 100644 --- a/Sample_Workflows/Warped Upscale By Model Workflow.json +++ b/Sample_Workflows/Warped Upscale By Model Workflow.json @@ -336,6 +336,40 @@ } } }, + { + "id": 201, + "type": "UpscaleModelLoader", + "pos": [ + 381.0227966308594, + 339.8635559082031 + ], + "size": [ + 315, + 58 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "UPSCALE_MODEL", + "type": "UPSCALE_MODEL", + "slot_index": 0, + "links": [ + 885 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.27", + "Node name for S&R": "UpscaleModelLoader" + }, + "widgets_values": [ + "4x_foolhardy_Remacri.pth" + ] + }, { "id": 276, "type": "WarpedUpscaleWithModel", @@ -380,44 +414,10 @@ }, "widgets_values": [ 2, - "bilinear" + "lanczos" ], "color": "#323", "bgcolor": "#535" - }, - { - "id": 201, - "type": "UpscaleModelLoader", - "pos": [ - 381.0227966308594, - 339.8635559082031 - ], - "size": [ - 315, - 58 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "UPSCALE_MODEL", - "type": "UPSCALE_MODEL", - "slot_index": 0, - "links": [ - 885 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.27", - "Node name for S&R": "UpscaleModelLoader" - }, - "widgets_values": [ - "4x_foolhardy_Remacri.pth" - ] } ], "links": [ @@ -507,7 +507,7 @@ -103.0950000000065 ] }, - "frontendVersion": "1.20.5", + "frontendVersion": "1.23.4", "groupNodes": {}, "ue_links": [], "VHS_latentpreview": true, diff --git a/__init__.py b/__init__.py index 76cef2c..e99417f 100644 --- a/__init__.py +++ b/__init__.py @@ -12,9 +12,9 @@ NODE_CLASS_MAPPINGS = { "WarpedWanLoraMerge": WarpedWanLoraMerge, "WarpedSamplerCustomAdv": WarpedSamplerCustomAdv, "WarpedSamplerCustomAdvLatent": WarpedSamplerCustomAdvLatent, - # "WarpedSamplerCustomBatch": WarpedSamplerCustomBatch, - # "WarpedSamplerCustomScripted": WarpedSamplerCustomScripted, + "WarpedSamplerCustomScripted": WarpedSamplerCustomScripted, "WarpedFramepackSampler": WarpedFramepackSampler, + # "WarpedFramepackSamplerScripted": WarpedFramepackSamplerScripted, "WarpedCreateSpecialImageBatch": WarpedCreateSpecialImageBatch, "WarpedCreateEmptyImageBatch": WarpedCreateEmptyImageBatch, "WarpedCreateEmptyLatentBatch": WarpedCreateEmptyLatentBatch, @@ -34,6 +34,7 @@ NODE_CLASS_MAPPINGS = { "WarpedHunyuanVideoLoraLoader": WarpedHunyuanVideoLoraLoader, "WarpedHunyuanMultiLoraLoader": WarpedHunyuanMultiLoraLoader, "WarpedHunyuanLoraConvertKeys": WarpedHunyuanLoraConvertKeys, + # "WarpedHunyuanLoraConvertKeys2": WarpedHunyuanLoraConvertKeys2, "WarpedLoraKeysAndMetadataReader": WarpedLoraKeysAndMetadataReader, "WarpedHunyuanLoraConvert": WarpedHunyuanLoraConvert, "WarpedFramepackLoraSelectBatch": WarpedFramepackLoraSelectBatch, @@ -56,6 +57,16 @@ NODE_CLASS_MAPPINGS = { "WarpedLoaderGGUF": WarpedLoaderGGUF, "WarpedClipLoaderGGUF": WarpedClipLoaderGGUF, "WarpedDualClipLoaderGGUF": WarpedDualClipLoaderGGUF, + "WarpedSamplerScripts5": WarpedSamplerScripts5, + "WarpedSamplerScripts8": WarpedSamplerScripts8, + "WarpedSamplerScripts12": WarpedSamplerScripts12, + "WarpedSamplerScripts16": WarpedSamplerScripts16, + "WarpedSamplerScripts20": WarpedSamplerScripts20, + "WarpedSamplerScripts30": WarpedSamplerScripts30, + "WarpedSamplerScripts40": WarpedSamplerScripts40, + "WarpedLoadImages": WarpedLoadImages, + "WarpedSaveImageCaption": WarpedSaveImageCaption, + "WarpedModifyCaptionFile": WarpedModifyCaptionFile, } NODE_DISPLAY_NAME_MAPPINGS = { @@ -69,9 +80,9 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WarpedWanLoraMerge": "Warped Wan Lora Merge", "WarpedSamplerCustomAdv": "Warped Sampler Custom Advanced (Image)", "WarpedSamplerCustomAdvLatent": "Warped Sampler Custom Advanced (Latent)", - # "WarpedSamplerCustomBatch": "Warped Sampler Custom Batch", - # "WarpedSamplerCustomScripted": "Warped Sampler Custom Scripted", + "WarpedSamplerCustomScripted": "Warped Sampler Custom Scripted", "WarpedFramepackSampler": "Warped Framepack Sampler", + # "WarpedFramepackSamplerScripted": "Warped Framepack Sampler Scripted", "WarpedCreateSpecialImageBatch": "Warped Create Special Image Batch", "WarpedCreateEmptyImageBatch": "Warped Create Empty Image Batch", "WarpedCreateEmptyLatentBatch": "Warped Create Empty Latent Batch", @@ -91,6 +102,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WarpedHunyuanVideoLoraLoader": "Warped Hunyuan Video Lora Loader", "WarpedHunyuanMultiLoraLoader": "Warped Hunyuan Video Multi Lora Loader", "WarpedHunyuanLoraConvertKeys": "Warped Hunyuan Lora Convert Keys", + # "WarpedHunyuanLoraConvertKeys2": "Warped Hunyuan Lora Convert Keys 2", "WarpedLoraKeysAndMetadataReader": "Warped Lora Keys And Metadata Reader", "WarpedHunyuanLoraConvert": "Warped Hunyuan Lora Convert", "WarpedFramepackLoraSelectBatch": "Warped Framepack Lora Select Batch", @@ -113,6 +125,16 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WarpedLoaderGGUF": "Warped UNET Loader GGUF", "WarpedClipLoaderGGUF": "Warped Clip Loader GGUF", "WarpedDualClipLoaderGGUF": "Warped Dual Clip Loader GGUF", + "WarpedSamplerScripts5": "Warped Sampler Scripts 5", + "WarpedSamplerScripts8": "Warped Sampler Scripts 8", + "WarpedSamplerScripts12": "Warped Sampler Scripts 12", + "WarpedSamplerScripts16": "Warped Sampler Scripts 16", + "WarpedSamplerScripts20": "Warped Sampler Scripts 20", + "WarpedSamplerScripts30": "Warped Sampler Scripts 30", + "WarpedSamplerScripts40": "Warped Sampler Scripts 40", + "WarpedLoadImages": "Warped Load Images", + "WarpedSaveImageCaption": "Warped Save Image Caption", + "WarpedModifyCaptionFile": "Warped Modify Caption File", } WEB_DIRECTORY = "./web" diff --git a/gguf_nodes.py b/gguf_nodes.py index e5a402c..6b63464 100644 --- a/gguf_nodes.py +++ b/gguf_nodes.py @@ -15,6 +15,22 @@ from .gguf_connector.quant import quantize, dequantize, QuantError from .gguf_connector.quant2d import dequantize_tensor, is_quantized, is_torch_compatible from .gguf_connector.tkn import get_field, tokenizer_builder +def get_available_devices(): + available_devices = ["default", "cpu"] + + if torch.cuda.is_available(): + available_devices.append("cuda") + + if torch.cuda.device_count() > 1: + for i in range(torch.cuda.device_count()): + temp_device = "cuda:{}".format(i) + available_devices.append(temp_device) + + return available_devices + +def get_offload_device(): + return torch.device("cpu") + if hasattr(torch, 'compiler') and hasattr(torch.compiler, 'disable'): torch_compiler_disable = torch.compiler.disable else: @@ -29,8 +45,17 @@ def get_clip_type(type): def get_device(device): model_options = {} + + print("get_device: input device: {}".format(device)) + if device == "cpu": model_options["load_device"] = model_options["offload_device"] = torch.device("cpu") + elif device.startswith("cuda"): + model_options["load_device"] = torch.device(device) + model_options["offload_device"] = torch.device("cpu") + + print("get_device: model_options: {}".format(model_options)) + return model_options def tensor_swap(raw_sd, key_map): @@ -435,12 +460,22 @@ class WarpedLoaderGGUF: sd = load_gguf_sd(temp_io) print("Loading Checkpoint...Done!") + # print("\n") + # for key in sd.keys(): + # print(key) + # print("\n") + model = comfy.sd.load_diffusion_model_state_dict(sd, model_options= {'custom_operations': ops}) if model is None: logging.error('ERROR UNSUPPORTED MODEL {}'.format(model_path)) raise RuntimeError('ERROR: Could not detect model type of: {}'. format(model_path)) + + # print("\n") + # print(model.model) + # print("\n") + model = GGUFModelPatcher.clone(model) model.patch_on_device = patch_on_device @@ -518,9 +553,14 @@ class WarpedClipLoaderGGUF: @classmethod def INPUT_TYPES(s): base = nodes.CLIPLoader.INPUT_TYPES() - return {'required': {'clip_name': (s.get_filename_list(),), 'type': - base['required']['type']}, - 'optional':{'device':(['default','cpu'],{'advanced':True}),}} + return {'required': { + 'clip_name': (s.get_filename_list(),), + 'type': base['required']['type'] + }, + 'optional': { + 'device':(get_available_devices(),{'advanced':True}), + } + } RETURN_TYPES = 'CLIP', FUNCTION = 'load_clip' CATEGORY = 'Warped/GGUF/Loaders' @@ -556,29 +596,84 @@ class WarpedClipLoaderGGUF: clip.patcher = GGUFModelPatcher.clone(clip.patcher) return clip - def load_clip(self, clip_name, type='stable_diffusion', device='default'): - clip_path = folder_paths.get_full_path('clip', clip_name) - if clip_name.endswith('.safetensors') and device != 'default': - clip = comfy.sd.load_clip(ckpt_paths=[clip_path], embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=get_clip_type(type), model_options=get_device(device)) - return (clip,) + def sd_load_clip(self, ckpt_paths, embedding_directory=None, clip_type=comfy.sd.CLIPType.STABLE_DIFFUSION, model_options={"offload_device": get_offload_device()}): + checkpoint_temp = [] + for p in ckpt_paths: + print("Reading: {}".format(p)) + with open(p, "rb") as file: + content = file.read() + + checkpoint_temp.append(content) + + clip_data = [] + + for p in checkpoint_temp: + print("Loading Clip...") + clip_data.append(warped_load_torch_file(p)) + print("Loading Clip...Done") + + return_clip = comfy.sd.load_text_encoder_state_dicts(clip_data, embedding_directory=embedding_directory, clip_type=clip_type, model_options=model_options) + + checkpoint_temp = None + clip_data = None + + return return_clip + + def load_clip(self, clip_name, clip_type="stable_diffusion", device="cpu"): + clip_type_attr = getattr(comfy.sd.CLIPType, clip_type.upper(), comfy.sd.CLIPType.STABLE_DIFFUSION) + + print("WarpedCLIPLoader: Clip Type: {} | {}".format(clip_type, clip_type_attr)) + + model_options = {} + if device == "cpu": + model_options["load_device"] = model_options["offload_device"] = torch.device("cpu") else: - return (self.load_patcher([clip_path], get_clip_type(type), self.load_data([clip_path])), get_device(device)) + model_options["load_device"] = model_options["offload_device"] = torch.device("cpu") + + if torch.cuda.is_available(): + if device == "cuda": + model_options["load_device"] = torch.cuda.current_device() + else: + temp_device = device.split(':') + device_number = int(temp_device[len(temp_device) - 1]) + model_options["load_device"] = torch.device(device_number) + + print("WarpedCLIPLoader: {}".format(model_options)) + + clip_path = folder_paths.get_full_path_or_raise("text_encoders", clip_name) + clip = self.sd_load_clip(ckpt_paths=[clip_path], embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=clip_type_attr, model_options=model_options) + return (clip,) + + # def load_clip(self, clip_name, type='stable_diffusion', device='default'): + # clip_path = folder_paths.get_full_path('clip', clip_name) + # if clip_name.endswith('.safetensors') and device != 'default': + # clip = comfy.sd.load_clip(ckpt_paths=[clip_path], embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=get_clip_type(type), model_options=get_device(device)) + # return (clip,) + # else: + # return (self.load_patcher([clip_path], get_clip_type(type), self.load_data([clip_path])), get_device(device)) class WarpedDualClipLoaderGGUF(WarpedClipLoaderGGUF): @classmethod def INPUT_TYPES(s): base = nodes.DualCLIPLoader.INPUT_TYPES() file_options = s.get_filename_list(), - return {'required': {'clip_name1':file_options, 'clip_name2':file_options, 'type': - base['required']['type']}, - 'optional':{'device':(['default','cpu'],{'advanced':True}),}} + return {'required': { + 'clip_name1':file_options, + 'clip_name2':file_options, + 'type': base['required']['type'] + }, + 'optional': { + 'device':(get_available_devices(),{'advanced':True}), + } + } def load_clip(self, clip_name1, clip_name2, type, device='default'): clip_path1 = folder_paths.get_full_path('clip', clip_name1) clip_path2 = folder_paths.get_full_path('clip', clip_name2) clip_paths = [clip_path1, clip_path2] if device != 'default' and (clip_name1.endswith('.safetensors') and clip_name2.endswith('.safetensors')): - clip = comfy.sd.load_clip(ckpt_paths=clip_paths, embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=get_clip_type(type), model_options=get_device(device)) + clip = self.load_clip(ckpt_paths=clip_paths, embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=get_clip_type(type), model_options=get_device(device)) + # clip = comfy.sd.load_clip(ckpt_paths=clip_paths, embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=get_clip_type(type), model_options=get_device(device)) return (clip,) else: return (self.load_patcher(clip_paths, get_clip_type(type), self.load_data(clip_paths)), get_device(device)) diff --git a/nodes.py b/nodes.py index 2e430db..47560ab 100644 --- a/nodes.py +++ b/nodes.py @@ -43,6 +43,7 @@ from comfy.cli_args import args from PIL.PngImagePlugin import PngInfo import random from tqdm import tqdm +import io import node_helpers @@ -66,13 +67,16 @@ import copy import safetensors import einops -import io +import socket +import re import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) +ALLOWED_EXT = ('.jpeg', '.jpg', '.png', '.tiff', '.gif', '.bmp', '.webp', '.avif', '.vfif') ALLOWED_VIDEO_EXT = ('mp4', 'flv', 'mov', 'avi', 'mpg', 'webm', 'mkv') +ALLOWED_CAPTION_EXT = ('.txt') vae_scaling_factor = 0.476986 @@ -2283,8 +2287,8 @@ class WarpedSamplerCustomAdv: } } - RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", ) - RETURN_NAMES = ("images", "latents", "seed", "generation_status", ) + RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", "BOOLEAN", ) + RETURN_NAMES = ("images", "latents", "seed", "generation_status", "valid_output", ) FUNCTION = "sample" @@ -2337,6 +2341,7 @@ class WarpedSamplerCustomAdv: output_images = None output_images_latents = None interrupted = False + valid_output = False try: mm.soft_empty_cache() @@ -2370,6 +2375,7 @@ class WarpedSamplerCustomAdv: samples = None output_images = self.process_skip_images(output_images, skip_frames) + valid_output = True print("WarpedSamplerCustomAdv: Decoded Images Shape: {}".format(output_images.shape[0])) if output_latents: @@ -2397,7 +2403,7 @@ class WarpedSamplerCustomAdv: except mm.InterruptProcessingException as ie: interrupted = True print(f"\nWarpedSamplerCustomAdv: Processing Interrupted.") - print("WarpedSamplerCustomAdv: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned.\n") + print("WarpedSamplerCustomAdv: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned, and valid_output will indicate False.\n") mm.unload_all_models() mm.soft_empty_cache() gc.collect() @@ -2409,16 +2415,18 @@ class WarpedSamplerCustomAdv: raise mm.InterruptProcessingException(f"WarpedSamplerCustomAdv: Processing Interrupted.") + pass + except BaseException as e: print(f"\nWarpedSamplerCustomAdv: Exception During Processing: {str(e)}") - print("WarpedSamplerCustomAdv: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned.\n") + print("WarpedSamplerCustomAdv: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned, and valid_output will indicate False.\n") mm.unload_all_models() mm.soft_empty_cache() gc.collect() time.sleep(1) generation_status = f"WarpedSamplerCustomAdv: Exception During Processing: {str(e)}" - generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomAdv: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned.") + generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomAdv: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned, and valid_output will indicate False.") traceback.print_tb(e.__traceback__, limit=99, file=sys.stdout) @@ -2456,7 +2464,7 @@ class WarpedSamplerCustomAdv: if output_images_latents is None: output_images_latents = torch.zeros([1, 16, 1, self.height // 8, self.width // 8], dtype=torch.float32, device=self.offload_device) - return (output_images, {"samples": output_images_latents}, self.seed, generation_status,) + return (output_images, {"samples": output_images_latents}, self.seed, generation_status, valid_output, ) def generate_noise(self, input_latent, generator=None): latent_image = input_latent["samples"] @@ -2652,8 +2660,8 @@ class WarpedSamplerCustomAdvLatent: } } - RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", ) - RETURN_NAMES = ("images", "latents", "seed", "generation_status", ) + RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", "BOOLEAN", ) + RETURN_NAMES = ("images", "latents", "seed", "generation_status", "valid_output", ) FUNCTION = "sample" @@ -2682,12 +2690,17 @@ class WarpedSamplerCustomAdvLatent: callback = self.setup_callbacks() disable_pbar = not utils.PROGRESS_BAR_ENABLED + print("\nSigmas: {}".format(self.sigmas)) + latents = latent["samples"] if len(latents.shape) < 5: latents = latents.unsqueeze(0) num_frames = int(((latents.shape[2] - 1) * 4) + 1) + self.latents_depth = latents.shape[1] + + print("latents_depth: {}".format(self.latents_depth)) self.width = latents.shape[4] self.height = latents.shape[3] @@ -2704,6 +2717,7 @@ class WarpedSamplerCustomAdvLatent: output_images = None output_images_latents = None interrupted = False + valid_output = False try: mm.soft_empty_cache() @@ -2733,6 +2747,7 @@ class WarpedSamplerCustomAdvLatent: print("WarpedSamplerCustomAdvLatent: Decoding Latents...") output_images = self.decode_tiled(samples) samples = None + valid_output = True output_images = self.process_skip_images(output_images, skip_frames) print("WarpedSamplerCustomAdvLatent: Decoded Images Shape: {}".format(output_images.shape[0])) @@ -2762,7 +2777,7 @@ class WarpedSamplerCustomAdvLatent: except mm.InterruptProcessingException as ie: interrupted = True print(f"\nWarpedSamplerCustomAdvLatent: Processing Interrupted.") - print("WarpedSamplerCustomAdvLatent: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned.\n") + print("WarpedSamplerCustomAdvLatent: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned, and valid_output will indicate False.\n") mm.unload_all_models() mm.soft_empty_cache() gc.collect() @@ -2773,17 +2788,18 @@ class WarpedSamplerCustomAdvLatent: traceback.print_tb(ie.__traceback__, limit=99, file=sys.stdout) raise mm.InterruptProcessingException(f"WarpedSamplerCustomAdvLatent: Processing Interrupted.") + pass except BaseException as e: print(f"\nWarpedSamplerCustomAdvLatent: Exception During Processing: {str(e)}") - print("WarpedSamplerCustomAdvLatent: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned.\n") + print("WarpedSamplerCustomAdvLatent: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned, and valid_output will indicate False.\n") mm.unload_all_models() mm.soft_empty_cache() gc.collect() time.sleep(1) generation_status = f"WarpedSamplerCustomAdvLatent: Exception During Processing: {str(e)}" - generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomAdvLatent: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned.") + generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomAdvLatent: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned, and valid_output will indicate False.") traceback.print_tb(e.__traceback__, limit=99, file=sys.stdout) @@ -2821,7 +2837,7 @@ class WarpedSamplerCustomAdvLatent: if output_images_latents is None: output_images_latents = torch.zeros([1, 16, 1, self.height, self.width], dtype=torch.float32, device=self.offload_device) - return (output_images, {"samples": output_images_latents}, self.seed, generation_status,) + return (output_images, {"samples": output_images_latents}, self.seed, generation_status, valid_output, ) def generate_noise(self, input_latent, generator=None): latent_image = input_latent["samples"] @@ -2872,7 +2888,7 @@ class WarpedSamplerCustomAdvLatent: return new_noise def pad_noise(self, latent, num_frames=1): - pad_frames = torch.zeros([1, 16, num_frames, self.height, self.width], dtype=torch.float32, device=self.offload_device) + pad_frames = torch.zeros([1, self.latents_depth, num_frames, self.height, self.width], dtype=torch.float32, device=self.offload_device) pad_frames = torch.cat((latent, pad_frames), 2) return pad_frames @@ -2891,7 +2907,7 @@ class WarpedSamplerCustomAdvLatent: return decoded_data def initialize_noise(self, frame_count, clear_cache=True): - noise_latents_full = torch.zeros([1, 16, int(frame_count), self.height, self.width], dtype=torch.float32, device=self.offload_device) + noise_latents_full = torch.zeros([1, self.latents_depth, int(frame_count), self.height, self.width], dtype=torch.float32, device=self.offload_device) print("WarpedSamplerCustomAdvLatent: Encoded noise_latents_full Shape: {}".format(noise_latents_full.shape)) if Decimal(self.noise_scale).compare(Decimal(0.00)) != 0: @@ -2983,2765 +2999,986 @@ PROMPT_TEMPLATE_ENCODE_VIDEO_I2V = ( "<|start_header_id|>assistant<|end_header_id|>\n\n" ) -# class WarpedSamplerCustomBatch: -# @classmethod -# def INPUT_TYPES(s): -# return {"required": -# { -# "positive": ("STRING", ), -# "negative": ("STRING", {"default": None}), -# "clip": ("CLIP", ), -# "preferred_frame_count": ("INT", {"default": 81, "min": 17, "max": nodes.MAX_RESOLUTION, "step": 4}), -# "preferred_batch_size": ("INT", {"default": 17, "min": 17, "max": 161, "step": 4}), -# "use_batch_size": (["next_lowest", "next_highest", "closest", "exact"], {"default": "next_lowest", "tooltip": "Number of frames generated may be impacted by choice."}), -# "vae": ("VAE", ), -# "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), -# "model": ("MODEL", ), -# "sampler": ("SAMPLER", ), -# "sigmas": ("SIGMAS", ), -# "dec_tile_size": ("INT", {"default": 256, "min": 64, "max": 4096, "step": 32}), -# "dec_overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}), -# "dec_temporal_size": ("INT", {"default": 64, "min": 8, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to decode at a time."}), -# "dec_temporal_overlap": ("INT", {"default": 8, "min": 4, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to overlap."}), -# "skip_frames": ("INT", {"default": 0, "min": 0, "max": 32, "step": 4}), -# "noise_scale": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 1.00, "step": 0.01}), -# "mode": (["Hunyuan", "Wan"], {"default": "Hunyuan"}), -# "hunyuan_guidance_type": (["v1 (concat)", "v2 (replace)", "custom"], {"default": "v2 (replace)", "tooltip": "Only used if mode is \"Hunyuan\"."}), -# "hunyuan_image_interleave": ("INT", {"default": 1, "min": 1, "max": 512, "tooltip": "How much the image influences things vs the text prompt. Higher number means more influence from the text prompt."}), -# }, -# "optional": -# {"noise_strength": ("FLOAT", {"default": 1.00, "min": 0.10, "max": 1.00, "step": 0.01}), -# "blend_frames": ("INT", {"default":5, "min":0, "max": 16, "step": 1}), -# "t2v_width": ("INT", {"default":480, "min":256, "max": 1280, "step": 16}), -# "t2v_height": ("INT", {"default":720, "min":256, "max": 1280, "step": 16}), -# "scaling_strength": ("FLOAT", {"default": 1.0}), -# "clip_vision_model": ("CLIP_VISION", ), -# "start_image": ("IMAGE", ), -# "flux_guidance": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step": 0.1}), -# "use_flux_guidance": ("BOOLEAN", {"default": False}), -# "dummy_frames": ("INT", {"default":17, "min":17, "max": 121, "step": 4, "tooltip": "Number of frames to generate in dummy batch."}), -# "gen_dummy": ("BOOLEAN", {"default": False, "tooltip": "For t2v or i2v only. Will generate a dummy batch to obtain a starting image for main generation."}), -# "gen_dummy_only": ("BOOLEAN", {"default": False, "tooltip": "Will generate dummy batch only."}), -# "use_dummy_image": (["first", "middle", "last", "random", "all"], {"default": "last", "tooltip": "Which dummy batch image to start main generation."}), -# "output_latents": ("BOOLEAN", {"default": False}), -# "verbose_messaging": ("BOOLEAN", {"default": False}), -# "i2v_sigmas": ("SIGMAS", {"default": None}), -# "i2v_model": ("MODEL", {"default": None}), -# } -# } -# -# RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", "IMAGE", ) -# RETURN_NAMES = ("images", "latents", "seed", "generation_status", "image_used",) -# -# FUNCTION = "sample" -# -# CATEGORY = "Warped/General/Sampling" -# -# def sample(self, positive, negative, clip, preferred_frame_count, preferred_batch_size, use_batch_size, vae, seed, model, sampler, sigmas, dec_tile_size, dec_overlap, dec_temporal_size, dec_temporal_overlap, -# skip_frames, noise_scale, mode="Hunyuan", hunyuan_guidance_type="v2 (replace)", hunyuan_image_interleave=2, noise_strength=1.0, blend_frames=5, t2v_width=480, t2v_height=720, scaling_strength=1.0, -# clip_vision_model=None, start_image=None, flux_guidance=3.5, dummy_frames=17, gen_dummy=False, gen_dummy_only=False, use_dummy_image="last", use_flux_guidance=False, output_latents=False, verbose_messaging=False, -# i2v_sigmas=None, i2v_model=None,): -# self.device = mm.get_torch_device() -# self.offload_device = get_offload_device() -# mm.unload_all_models() -# gc.collect() -# time.sleep(1) -# -# self.positive = positive -# self.negative = negative -# self.clip = clip -# self.use_clip = clip.clone() -# self.preferred_frame_count = preferred_frame_count -# self.preferred_batch_size = preferred_batch_size -# self.vae = vae -# self.seed = seed -# self.sampler = sampler -# self.sigmas = sigmas -# self.i2v_sigmas = i2v_sigmas -# self.noise_scale = noise_scale -# self.mode = mode -# self.dec_tile_size = dec_tile_size -# self.dec_overlap = dec_overlap -# self.dec_temporal_size = dec_temporal_size -# self.dec_temporal_overlap = dec_temporal_overlap -# self.clip_vision = clip_vision_model -# self.noise_strength = noise_strength -# self.blend_frames = blend_frames -# self.t2v_width = t2v_width -# self.t2v_height = t2v_height -# self.dummy_frames = dummy_frames -# self.dummy_latents = int((dummy_frames - 1) // 4) + 1 -# self.gen_dummy = gen_dummy -# self.gen_dummy_only = gen_dummy_only -# self.use_dummy_image = use_dummy_image -# self.skip_frames = skip_frames -# self.verbose_messaging = verbose_messaging -# self.model = model -# self.i2v_model = i2v_model -# self.g_output = {} -# -# disable_pbar = not utils.PROGRESS_BAR_ENABLED -# -# self.use_sigmas = self.sigmas -# -# self.guider = WarpedGuider_Basic() -# self.guider.set_model(self.model) -# callback = self.setup_callbacks() -# -# self.latent_window_size, self.batch_count, self.truncated_frame_count = self.get_latent_window_size(preferred_batch_size, self.preferred_frame_count, use_batch_size=use_batch_size) -# -# is_i2v = True -# -# if start_image is None: -# start_image = torch.zeros([1, self.t2v_height, self.t2v_width, 3], dtype=torch.float32, device=self.offload_device) -# is_i2v = False -# -# print("start_image Shape: {}".format(start_image.shape)) -# -# self.width = int(start_image.shape[2] // 8) -# self.height = int(start_image.shape[1] // 8) -# -# noise, dummy_noise = self.setup_latent_noise() -# -# output_images = [] -# output_images_latents = None -# interrupted = False -# generation_status = "" -# total_images_generated = 0 -# is_dummy_section = False -# is_first_section = False -# is_last_section = False -# switch_guider = True -# last_image = None -# -# if not self.gen_dummy: -# print("Generating {} Batches".format(self.batch_count)) -# else: -# print("Generating Dummy Batch Plus {} Batches".format(self.batch_count)) -# -# generation_batches = list(range(self.batch_count)) -# -# if self.gen_dummy and (not self.gen_dummy_only): -# generation_batches = [0] + generation_batches -# is_dummy_section = True -# else: -# generation_batches = [0] -# is_dummy_section = True -# -# print("generation_batches: {}".format(generation_batches)) -# -# try: -# for i, generation_batch in enumerate(generation_batches): -# batch_number = generation_batches[i] -# # batch_key = "{}".format(batch_number) -# -# if is_dummy_section: -# print("Generating Dummy Batch.") -# is_first_section = False -# -# if not self.gen_dummy_only: -# is_last_section = False -# else: -# is_last_section = True -# else: -# print("Generating Batch {}.".format(batch_number)) -# -# is_first_section = batch_number == min(generation_batches) -# is_last_section = batch_number == max(generation_batches) -# -# print("is_first_section: {} | is_last_section: {} | is_dummy_section: {}".format(is_first_section, is_last_section, is_dummy_section)) -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# image_embeds = None -# -# print("start_image Shape: {}".format(start_image.shape)) -# -# if is_i2v: -# if len(start_image.shape) < 4: -# start_image = start_image.unsqueeze(0) -# -# print("Performing clip_vision_encode.") -# image_embeds = self.clip_vision_encode(start_image.clone().detach()) -# -# if not is_dummy_section: -# noise_latents = noise[batch_number] -# else: -# noise_latents = dummy_noise -# -# print("noise_latents Shape: {}".format(noise_latents.shape)) -# -# noise_mask = None -# -# if mode == "Hunyuan": -# if is_i2v: -# if (not self.i2v_model is None) and switch_guider: -# switch_guider = False -# callback = None -# self.guider = WarpedGuider_Basic() -# self.guider.set_model(self.i2v_model) -# callback = self.setup_callbacks() -# -# self.use_clip = self.clip.clone() -# temp_cond = self.hunyuan_text_encode(self.use_clip, image_embeds, positive, hunyuan_image_interleave) -# positive_cond, latents = self.hunyuan_encode(temp_cond, self.vae, start_image.shape[2], start_image.shape[1], self.truncated_frame_count, 1, hunyuan_guidance_type, start_image=start_image) -# -# if "noise_mask" in latents: -# noise_mask = latents["noise_mask"] -# -# latents = latents["samples"] -# -# # latents = latents["samples"] * (scaling_strength * vae_scaling_factor) -# else: -# positive_cond = self.do_text_encode(self.use_clip, positive) -# latents = torch.zeros([1, 16, noise_latents.shape[2], self.height, self.width], dtype=torch.float32, device=self.offload_device) -# -# latents = latents * scaling_strength # scaling_strength -# latents = latents * (scaling_strength * vae_scaling_factor) -# -# if use_flux_guidance: -# positive_cond = self.apply_flux_guidance(positive_cond, flux_guidance) -# -# self.guider.set_conds(positive_cond) -# # else: -# # positive_cond, negative_cond = wan_text_encode(self.use_clip, positive_text=positive, negative_text=negative) -# # positive_cond, negative_cond, latents = self.wan_encode(positive_cond, negative_cond, self.vae, start_image.shape[3], start_image.shape[2], ((noise_latents.shape[2] - 1) * 4) + 1, 1, start_image=start_image, clip_vision_output=image_embeds) -# -# # self.guider.set_conds(positive_cond, negative_cond) -# -# print("latents Shape: {}".format(latents.shape)) -# -# num_frames = int(((latents.shape[2] - 1) * 4) + 1) -# -# print("\nDecoded Width is {} | Decoded Height is {}".format(int(self.width * 8), int(self.height * 8))) -# -# print("-------------------------------------------------------------------------------------------") -# print("WarpedSamplerCustomBatch: Latents Shape: {} | Noise Latents Shape: {}".format(latents.shape, noise_latents.shape)) -# print("-------------------------------------------------------------------------------------------") -# -# print("Noise Shape: {} | Latents Shape: {}".format(noise_latents.shape, latents.shape)) -# print("WarpedSamplerCustomBatch: Generating {} Frames in {} Latents....".format(num_frames, latents.shape[2])) -# -# samples = self.guider.sample(noise_latents, latents, self.sampler, self.use_sigmas, denoise_mask=noise_mask, callback=callback, disable_pbar=disable_pbar, seed=self.seed) -# samples = samples.to(mm.intermediate_device()) -# -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# if len(samples.shape) < 5: -# samples = samples.unsqueeze(0) -# -# samples = samples.clone().detach() / scaling_strength # (scaling_strength * vae_scaling_factor) -# -# print("WarpedSamplerCustomBatch: Decoding Latents...") -# decoded_images = self.decode_tiled(samples) -# -# if not is_dummy_section or (is_dummy_section and ((self.use_dummy_image == "all")) or self.gen_dummy_only): -# output_images.append(decoded_images) -# total_images_generated += decoded_images.shape[0] -# -# samples = None -# -# # output_images = self.process_skip_images(output_images, skip_frames) -# print("WarpedSamplerCustomBatch: Decoded Images Shape: {}".format(decoded_images.shape[0])) -# -# # if output_latents: -# # output_images_latents = self.encode_tiled(output_images) -# -# print("WarpedSamplerCustomBatch: Generating {} frames in {} latents...Done.".format(num_frames, latents.shape[2])) -# -# if not is_i2v: -# self.guider.model_patcher.model.to(get_offload_device()) -# # guider.set_i2v_model() -# -# if not self.i2v_sigmas is None: -# self.use_sigmas = self.i2v_sigmas -# -# if not is_last_section: -# print("HERE 9090000") -# decoded_tuple = torch.split(decoded_images, 1, dim=0) -# decoded_split = [item for item in decoded_tuple] -# decoded_images = decoded_images.to(get_offload_device()) -# decoded_images = None -# -# if (not is_dummy_section) or (is_dummy_section and ((self.use_dummy_image == "last") or (self.use_dummy_image == "all"))): -# print("HERE 9090000a") -# start_image = decoded_split[len(decoded_split) - 1].clone().detach() -# elif is_dummy_section: -# print("HERE 9090000b") -# if self.use_dummy_image == "first": -# print("HERE 9090000c") -# start_image = decoded_split[0].clone().detach() -# elif self.use_dummy_image == "middle": -# print("HERE 9090000d") -# start_image = decoded_split[int(len(decoded_split) // 2)].clone().detach() -# else: -# print("HERE 9090000e") -# random.seed(self.seed) -# start_image = dummy_split[random.randrange(0, len(decoded_split) - 1, 1)].clone().detach() -# -# is_i2v = True -# -# if last_image is None: -# last_image = start_image.clone().detach() -# -# print("HERE 9090001") -# -# samples = None -# latents = None -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# print("*******************************************") -# print("****** WarpedSamplerCustomBatch: Total Images Generated {}".format(total_images_generated)) -# print("*******************************************\n") -# -# generation_status = "****** WarpedSamplerCustomBatch: Total Images Generated {} ******".format(total_images_generated) -# -# interrupted = False -# -# print("HERE 9090002") -# -# if is_dummy_section: -# print("HERE 9090003") -# -# if self.gen_dummy_only: -# print("HERE 9090004") -# break -# -# print("HERE 9090005") -# -# is_dummy_section = False -# -# print("HERE 9090006") -# except mm.InterruptProcessingException as ie: -# interrupted = True -# print(f"\nWarpedSamplerCustomBatch: Processing Interrupted.") -# print("WarpedSamplerCustomBatch: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned.\n") -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# generation_status = f"\nWarpedSamplerCustomBatch: Processing Interrupted." -# -# traceback.print_tb(ie.__traceback__, limit=99, file=sys.stdout) -# -# raise mm.InterruptProcessingException(f"WarpedSamplerCustomBatch: Processing Interrupted.") -# -# except BaseException as e: -# print(f"\nWarpedSamplerCustomBatch: Exception During Processing: {str(e)}") -# print("WarpedSamplerCustomBatch: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned.\n") -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# generation_status = f"WarpedSamplerCustomBatch: Exception During Processing: {str(e)}" -# generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomBatch: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned.") -# -# traceback.print_tb(e.__traceback__, limit=99, file=sys.stdout) -# -# pass -# -# callback = None -# self.guider.model_patcher.model.to(get_offload_device()) -# -# latent = None -# latent_image = None -# noise_mask = None -# samples = None -# -# torch.cuda.empty_cache() -# torch.cuda.ipc_collect() -# gc.collect() -# time.sleep(1) -# -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# image = None -# -# if interrupted and (len(output_images) < 1): -# temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'yellow') -# image = pil2tensorSwap(temp_image) -# final_images = image -# elif (len(output_images) < 1): -# temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'red') -# image = pil2tensorSwap(temp_image) -# final_images = image -# else: -# final_images = self.assemble_final_result(output_images) -# -# if output_images_latents is None: -# output_images_latents = torch.zeros([1, 16, 1, self.height, self.width], dtype=torch.float32, device=self.offload_device) -# -# return (final_images, {"samples": output_images_latents}, self.seed, generation_status, last_image,) -# -# def assemble_final_result(self, image_batches): -# if self.blend_frames < 1: -# resulting_images = None -# for entry in image_batches: -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, entry), 0) -# else: -# resulting_images = entry -# -# entry.to(device=self.offload_device) -# entry = None -# else: -# blend_value = 1.0 / self.blend_frames -# i = 0 -# while i < (len(image_batches) - 1): -# alpha_blend_val = blend_value -# blend_count = self.blend_frames -# -# image_batches_tuple = torch.split(image_batches[i], 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image1 = image_batches_split[len(image_batches_split) - 1] -# # image1 = image_batches_split[len(image_batches_split) - 4] -# image_batches_tuple = None -# image_batches_split = None -# -# image_batches_tuple = torch.split(image_batches[i + 1], 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image2 = image_batches_split[0] -# image_batches_tuple = None -# image_batches_split = None -# -# image1 = tensor2pilSwap(image1)[0] -# image2 = tensor2pilSwap(image2)[0] -# -# blend_latents = None -# -# while blend_count > 0: -# blended_image = Image.blend(image1, image2, alpha_blend_val) -# temp_latent = pil2tensorSwap(blended_image) -# blended_image = None -# -# if len(temp_latent.shape) < 4: -# temp_latent = temp_latent.unsqueeze(0) -# -# if not blend_latents is None: -# blend_latents = torch.cat((blend_latents, temp_latent), 0) -# else: -# blend_latents = temp_latent -# -# alpha_blend_val += blend_value -# blend_count -= 1 -# -# image_batches_tuple = torch.split(image_batches[i], image_batches[i].shape[0] - 3, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image_batches_tuple = None -# -# image_batches[i] = torch.cat((image_batches_split[0], blend_latents), 0) -# blend_latents = None -# image_batches_split = None -# -# self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) -# -# i += 1 -# -# resulting_images = None -# for entry in image_batches: -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, entry), 0) -# else: -# resulting_images = entry -# -# entry.to(device=self.offload_device) -# -# image_batches = None -# -# self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) -# -# -# print("assemble_final_result: Full decoded images count: {}".format(resulting_images.shape[0])) -# -# if self.skip_frames < 1: -# return resulting_images -# -# skipped_frames = 1 -# -# image_batches_tuple = torch.split(resulting_images, 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# -# resulting_images = None -# -# for image in image_batches_split: -# if skipped_frames <= self.skip_frames: -# skipped_frames += 1 -# continue -# -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, image), 0) -# else: -# resulting_images = image -# -# print("assemble_final_result: Final decoded images count: {}".format(resulting_images.shape[0])) -# -# return resulting_images -# -# def cleanup(self, unload_models=False, cleanup_models=False, cleanup_cuda=False): -# if unload_models: -# mm.unload_all_models() -# -# if cleanup_models: -# mm.cleanup_models() -# -# if cleanup_cuda: -# mm.soft_empty_cache() -# -# gc.collect() -# time.sleep(1) -# -# return -# -# def generate_noise(self, input_latent, generator=None): -# latent_image = input_latent["samples"] -# return warped_prepare_noise(latent_image, self.seed, generator=generator) -# -# def setup_latent_noise(self): -# dummy_noise = None -# -# if self.gen_dummy: -# rnd = torch.Generator("cpu").manual_seed(self.seed) -# dummy_noise = torch.randn((1, 16, self.dummy_latents, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) -# -# noise = [] -# -# for i in range(self.batch_count): -# rnd = torch.Generator("cpu").manual_seed(self.seed) -# temp_noise = torch.randn((1, 16, self.latent_window_size, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) -# -# noise.append(temp_noise) -# temp_noise = None -# -# if self.verbose_messaging: -# if not dummy_noise is None: -# print("\nsetup_latent_noise: dummy_noise Shape: {}".format(dummy_noise.shape)) -# -# i = 0 -# for entry in noise: -# print("setup_latent_noise: Batch: {} | noise Shape: {}".format(i, entry.shape)) -# i += 1 -# -# print("\n") -# -# return noise, dummy_noise -# -# def get_latent_window_size(self, preferred_batch_size, frame_count, use_batch_size="next_lowest"): -# latent_size_factor = 4 -# -# if self.verbose_messaging: -# print("get_latent_window_size: preferred_batch_size: {}".format(preferred_batch_size)) -# print("get_latent_window_size: frame_count: {}".format(frame_count)) -# print("get_latent_window_size: use_batch_size: {}".format(use_batch_size)) -# -# num_frames = int(((frame_count - 1) // 4) * 4) + 1 -# -# if num_frames != frame_count: -# print(f"Truncating video from {frame_count} to {num_frames} an because odd number of frames is not allowed.") -# -# if ((num_frames - 1) % (preferred_batch_size - 1)) == 0: -# print("(1) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size))) -# print("(1) batch_count set to: {}".format(int((num_frames - 1) / (preferred_batch_size - 1)))) -# return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames - 1) / (preferred_batch_size - 1)), num_frames -# -# if use_batch_size == "exact": -# num_frames_final = int(((num_frames - 1) // (preferred_batch_size - 1)) + 1) * (preferred_batch_size - 1) -# -# if num_frames_final != frame_count: -# print(f"Truncating video from {num_frames} to {num_frames_final} frames for preferred_batch_size compatibility.") -# -# print("(2) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size + 1))) -# print("(2) batch_count set to: {}".format(int((num_frames_final - 1) / (preferred_batch_size - 1)))) -# return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames_final - 1) / (preferred_batch_size - 1)), num_frames_final -# -# next_lowest_found = False -# next_highest_found = False -# next_lowest = preferred_batch_size - 1 -# next_highest = preferred_batch_size - 1 -# -# if self.verbose_messaging: -# print("get_latent_window_size: Next Lowest Initialized To: {}".format(next_lowest)) -# print("get_latent_window_size: Next Highest Initialized To: {}".format(next_highest)) -# -# num_frames_final = int(((num_frames - 1) // 4) * 4) + 1 -# -# if num_frames != num_frames_final: -# print(f"Truncating video from {num_frames} to {num_frames_final} frames for latent_window_size compatibility.") -# -# if (use_batch_size == "closest") or (use_batch_size == "next_lowest"): -# while next_lowest >= 12: -# next_lowest -= 4 -# -# if (int((num_frames_final - 1) // 4) % next_lowest) == 0: -# next_lowest_found = True -# break -# -# next_lowest += 1 -# -# if next_lowest_found and (use_batch_size == "next_lowest"): -# print("(3) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) -# print("(3) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) -# return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final -# -# while next_highest <= 156: -# next_highest += 4 -# -# if (int((num_frames_final - 1) // 4) % next_highest) == 0: -# next_highest_found = True -# break -# -# if next_highest_found and (use_batch_size == "next_highest"): -# print("(4) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) -# print("(4) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) -# return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final -# -# if next_highest_found and next_lowest_found: -# if (preferred_batch_size - next_lowest) <= (next_highest - preferred_batch_size): -# print("(5) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) -# print("(5) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) -# return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final -# elif (next_highest - preferred_batch_size) < (preferred_batch_size - next_lowest): -# print("(6) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) -# print("(6) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) -# return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final -# -# print("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) -# print("Recalculating Number Of Frames Based On preferred_batch_size of: {}".format(preferred_batch_size)) -# -# return self.calculate_new_number_of_frames(preferred_batch_size, (((frame_count - 1) // 4) * 4) + 1, use_batch_size) -# -# def calculate_new_number_of_frames(self, preferred_batch_size, frame_count, use_batch_size): -# working_batch_size = preferred_batch_size - 1 -# working_frame_count = frame_count - 1 -# -# next_lowest = next_highest = working_frame_count -# next_lowest_found = False -# next_highest_found = False -# -# while next_lowest > 37: -# next_lowest -= 4 -# -# if int(next_lowest % working_batch_size) == 0: -# next_lowest_found = True -# break -# -# if next_lowest_found and (use_batch_size == "next_lowest"): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# while next_highest < 999997: -# next_highest += 4 -# -# if int(next_highest % working_batch_size) == 0: -# next_highest_found = True -# break -# -# if next_highest_found and (use_batch_size == "next_highest"): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# if next_lowest_found and next_highest_found: -# if (working_frame_count - next_lowest) <= (next_highest - working_frame_count): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# if next_lowest_found: -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# if next_highest_found: -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# raise ValueError("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) -# -# def clip_vision_encode(self, image, crop="center"): -# crop_image = False -# if crop != "center": -# crop_image = False -# output = self.clip_vision.encode_image(image, crop=crop_image) -# return output -# -# def encoded_to_decoded_length(self, latent_length): -# if latent_length <= 0: -# return 0 -# -# result_length = ((latent_length - 1) * 4) + 1 -# -# return result_length -# -# def decoded_to_encoded_length(self, image_length): -# if image_length <= 0: -# return 0 -# -# result_length = int(((image_length - 1) / 4) + 1) -# -# return result_length -# -# def apply_flux_guidance(self, conditioning, guidance): -# c = node_helpers.conditioning_set_values(conditioning, {"guidance": guidance}) -# return c -# -# def hunyuan_text_encode(self, clip, clip_vision_output, prompt, image_interleave): -# tokens = clip.tokenize(prompt, llama_template=PROMPT_TEMPLATE_ENCODE_VIDEO_I2V, image_embeds=clip_vision_output.mm_projected, image_interleave=image_interleave) -# return clip.encode_from_tokens_scheduled(tokens) -# -# def hunyuan_encode(self, positive, vae, width, height, length, batch_size, guidance_type, start_image=None): -# latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) -# out_latent = {} -# -# if start_image is not None: -# start_image = comfy.utils.common_upscale(start_image[:length, :, :, :3].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) -# -# concat_latent_image = vae.encode(start_image) -# mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) -# mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 -# -# if guidance_type == "v1 (concat)": -# cond = {"concat_latent_image": concat_latent_image, "concat_mask": mask} -# elif guidance_type == "v2 (replace)": -# cond = {'guiding_frame_index': 0} -# latent[:, :, :concat_latent_image.shape[2]] = concat_latent_image -# out_latent["noise_mask"] = mask -# elif guidance_type == "custom": -# cond = {"ref_latent": concat_latent_image} -# -# positive = node_helpers.conditioning_set_values(positive, cond) -# -# out_latent["samples"] = latent -# return positive, out_latent -# -# def wan_text_encode(self, clip, positive_text="", negative_text=""): -# print("wan_text_encode: Loading clip model to device: {}".format(clip.patcher.load_device)) -# clip.patcher.model.to(device=clip.patcher.load_device) -# -# print("wan_text_encode: Encoding Prompts...") -# positive_conditioning = self.do_text_encode(clip, positive_text) -# negative_conditioning = self.do_text_encode(clip, negative_text) -# print("wan_text_encode: Encoding Prompts...Done.") -# -# print("wan_text_encode: Unloading clip model to device: {}".format(get_offload_device())) -# clip.patcher.model.to(device=get_offload_device()) -# -# if torch.cuda.is_available(): -# torch.cuda.empty_cache() -# -# gc.collect() -# time.sleep(1) -# -# return positive_conditioning, negative_conditioning -# -# def encode(self, clip, text): -# if clip is None: -# raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") -# tokens = clip.tokenize(text) -# return clip.encode_from_tokens_scheduled(tokens) -# -# def do_text_encode(self, clip, text): -# -# if clip is None: -# raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") -# -# tokens = clip.tokenize(text) -# return_encoding = clip.encode_from_tokens_scheduled(tokens) -# -# return return_encoding -# -# def wan_encode(self, positive, negative, vae, width, height, length, batch_size, start_image=None, clip_vision_output=None): -# latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) -# if start_image is not None: -# start_image = comfy.utils.common_upscale(start_image[:length].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) -# image = torch.mul(torch.ones((length, height, width, start_image.shape[-1]), device=start_image.device, dtype=start_image.dtype), 0.5) -# image[:start_image.shape[0]] = start_image -# -# concat_latent_image = vae.encode(image[:, :, :, :3]) -# -# mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) -# mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 -# -# positive = node_helpers.conditioning_set_values(positive, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) -# negative = node_helpers.conditioning_set_values(negative, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) -# -# if clip_vision_output is not None: -# positive = node_helpers.conditioning_set_values(positive, {"clip_vision_output": clip_vision_output}) -# negative = node_helpers.conditioning_set_values(negative, {"clip_vision_output": clip_vision_output}) -# -# out_latent = {} -# out_latent["samples"] = latent -# return positive, negative, out_latent -# -# def process_skip_images(self, frames, skip_count): -# if len(frames.shape) < 4: -# frames = frames.unsqueeze(0) -# -# num_frames = frames.shape[0] -# -# image_batches_tuple = torch.split(frames, 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# -# new_video = None -# i = 0 -# -# while i < len(image_batches_split): -# if i < skip_count: -# i += 1 -# continue -# -# if not new_video is None: -# new_video = torch.cat((new_video, image_batches_split[i]), 0) -# else: -# new_video = image_batches_split[i] -# -# i += 1 -# -# return new_video -# -# def get_blank_image(self, length=1): -# new_image = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) -# return new_image -# -# def get_new_noise(self, length): -# new_noise = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) -# -# new_noise = self.encode_tiled(new_noise) -# -# new_noise = comfy.sample.fix_empty_latent_channels(self.guider.model_patcher, new_noise) -# -# if len(new_noise) < 5: -# new_latent = new_noise.unsqueeze(0) -# -# new_noise = self.generate_noise({"samples": new_noise}) -# -# return new_noise -# -# def pad_noise(self, latent, num_frames=1): -# pad_frames = torch.zeros([1, 16, num_frames, self.height, self.width], dtype=torch.float32, device=self.offload_device) -# pad_frames = torch.cat((latent, pad_frames), 2) -# -# return pad_frames -# -# def setup_callbacks(self): -# callback = latent_preview.prepare_callback(self.guider.model_patcher, self.sigmas.shape[-1] - 1, self.g_output) -# -# return callback -# -# def decode_tiled(self, latents): -# decoded_data = partial_decode_tiled(self.vae, latents, self.dec_tile_size, self.dec_overlap, self.dec_temporal_size, self.dec_temporal_overlap) -# -# if len(decoded_data.shape) < 4: -# decoded_data.unsqueeze(0) -# -# return decoded_data -# -# def initialize_noise(self, frame_count, clear_cache=True): -# noise_latents_full = torch.zeros([1, 16, int(frame_count), self.height, self.width], dtype=torch.float32, device=self.offload_device) -# print("WarpedSamplerCustomBatch: Encoded noise_latents_full Shape: {}".format(noise_latents_full.shape)) -# -# if Decimal(self.noise_scale).compare(Decimal(0.00)) != 0: -# noise_latents_full = warped_prepare_noise(noise_latents_full, self.seed) -# print("WarpedSamplerCustomBatch: noise_latents_full Shape: {}".format(noise_latents_full.shape)) -# -# noise_latents_full = torch.mul(noise_latents_full, self.noise_scale) -# -# if len(noise_latents_full.shape) < 5: -# noise_latents_full.unsqueeze(0) -# -# noise_latents_full = noise_latents_full.to(dtype=torch.float32, device=self.offload_device) -# -# if clear_cache: -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# return noise_latents_full -# -# def initialize_frames(self, latents): -# if len(latents.shape) < 5: -# latents = latents.unsqueeze(0) -# -# print("WarpedSamplerCustomBatch: Encoded latents_full Shape: {}".format(latents.shape)) -# latents_full = latents.clone().detach() -# latents_full = latents_full.to(dtype=torch.float32, device=self.offload_device) -# -# noise_latents_full = self.initialize_noise(latents_full.shape[2]) -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# return noise_latents_full -# -# class WarpedSamplerCustomScripted: -# @classmethod -# def INPUT_TYPES(s): -# return {"required": -# { -# "positive": ("STRING", {"default": None} ), -# "negative": ("STRING", {"default": None}), -# "clip": ("CLIP", ), -# "preferred_frame_count": ("INT", {"default": 81, "min": 17, "max": nodes.MAX_RESOLUTION, "step": 4}), -# "preferred_batch_size": ("INT", {"default": 17, "min": 17, "max": 161, "step": 4}), -# "use_batch_size": (["next_lowest", "next_highest", "closest", "exact"], {"default": "next_lowest", "tooltip": "Number of frames generated may be impacted by choice."}), -# "vae": ("VAE", ), -# "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), -# "model": ("MODEL", ), -# "sampler": ("SAMPLER", ), -# "sigmas": ("SIGMAS", ), -# "dec_tile_size": ("INT", {"default": 256, "min": 64, "max": 4096, "step": 32}), -# "dec_overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}), -# "dec_temporal_size": ("INT", {"default": 64, "min": 8, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to decode at a time."}), -# "dec_temporal_overlap": ("INT", {"default": 8, "min": 4, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to overlap."}), -# "skip_frames": ("INT", {"default": 0, "min": 0, "max": 32, "step": 4}), -# "noise_scale": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 1.00, "step": 0.01}), -# "mode": (["Hunyuan", "Wan"], {"default": "Hunyuan"}), -# "hunyuan_guidance_type": (["v1 (concat)", "v2 (replace)", "custom"], {"default": "v2 (replace)", "tooltip": "Only used if mode is \"Hunyuan\"."}), -# "hunyuan_image_interleave": ("INT", {"default": 1, "min": 1, "max": 512, "tooltip": "How much the image influences things vs the text prompt. Higher number means more influence from the text prompt."}), -# }, -# "optional": -# {"noise_strength": ("FLOAT", {"default": 1.00, "min": 0.10, "max": 1.00, "step": 0.01}), -# "blend_frames": ("INT", {"default":5, "min":0, "max": 16, "step": 1}), -# "t2v_width": ("INT", {"default":480, "min":256, "max": 1280, "step": 16}), -# "t2v_height": ("INT", {"default":720, "min":256, "max": 1280, "step": 16}), -# "scaling_strength": ("FLOAT", {"default": 1.0}), -# "clip_vision_model": ("CLIP_VISION", ), -# "start_image": ("IMAGE", ), -# "flux_guidance": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step": 0.1}), -# "use_flux_guidance": ("BOOLEAN", {"default": False}), -# "dummy_frames": ("INT", {"default":17, "min":17, "max": 121, "step": 4, "tooltip": "Number of frames to generate in dummy batch."}), -# "gen_dummy": ("BOOLEAN", {"default": False, "tooltip": "For t2v or i2v only. Will generate a dummy batch to obtain a starting image for main generation."}), -# "gen_dummy_only": ("BOOLEAN", {"default": False, "tooltip": "Will generate dummy batch only."}), -# "use_dummy_image": (["first", "middle", "last", "random", "all"], {"default": "last", "tooltip": "Which dummy batch image to start main generation."}), -# "output_latents": ("BOOLEAN", {"default": False}), -# "verbose_messaging": ("BOOLEAN", {"default": False}), -# "i2v_sigmas": ("SIGMAS", {"default": None}), -# "i2v_model": ("MODEL", {"default": None}), -# "batches_script": ("STRING", {"default": None}), -# } -# } -# -# RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", "IMAGE", ) -# RETURN_NAMES = ("images", "latents", "seed", "generation_status", "image_used",) -# -# FUNCTION = "sample" -# -# CATEGORY = "Warped/General/Sampling" -# -# def sample(self, positive, negative, clip, preferred_frame_count, preferred_batch_size, use_batch_size, vae, seed, model, sampler, sigmas, dec_tile_size, dec_overlap, dec_temporal_size, dec_temporal_overlap, -# skip_frames, noise_scale, mode="Hunyuan", hunyuan_guidance_type="v2 (replace)", hunyuan_image_interleave=2, noise_strength=1.0, blend_frames=5, t2v_width=480, t2v_height=720, scaling_strength=1.0, -# clip_vision_model=None, start_image=None, flux_guidance=3.5, dummy_frames=17, gen_dummy=False, gen_dummy_only=False, use_dummy_image="last", use_flux_guidance=False, output_latents=False, verbose_messaging=False, -# i2v_sigmas=None, i2v_model=None, batches_script=None): -# -# batch_scripts = None -# -# if (positive is None) and (batches_script is None): -# raise ValueError("positive and batches_script cannot both be None.") -# elif not batches_script is None: -# if verbose_messaging: -# print("\n{}\n".format(batches_script)) -# -# batch_scripts = {} -# temp_strings = batches_script.split("||") -# -# for entry in temp_strings: -# temp_script = entry.strip().split("|") -# batch_scripts[temp_script[0].strip()] = temp_script[1].strip() -# -# if verbose_messaging: -# print("\n{}\n".format(batch_scripts)) -# -# self.device = mm.get_torch_device() -# self.offload_device = get_offload_device() -# mm.unload_all_models() -# gc.collect() -# time.sleep(1) -# -# self.positive = positive -# self.negative = negative -# self.clip = clip -# self.use_clip = clip.clone() -# self.preferred_frame_count = preferred_frame_count -# self.preferred_batch_size = preferred_batch_size -# self.vae = vae -# self.seed = seed -# self.sampler = sampler -# self.sigmas = sigmas -# self.i2v_sigmas = i2v_sigmas -# self.noise_scale = noise_scale -# self.mode = mode -# self.dec_tile_size = dec_tile_size -# self.dec_overlap = dec_overlap -# self.dec_temporal_size = dec_temporal_size -# self.dec_temporal_overlap = dec_temporal_overlap -# self.clip_vision = clip_vision_model -# self.noise_strength = noise_strength -# self.blend_frames = blend_frames -# self.t2v_width = t2v_width -# self.t2v_height = t2v_height -# self.dummy_frames = dummy_frames -# self.dummy_latents = int((dummy_frames - 1) // 4) + 1 -# self.gen_dummy = gen_dummy -# self.gen_dummy_only = gen_dummy_only -# self.use_dummy_image = use_dummy_image -# self.skip_frames = skip_frames -# self.verbose_messaging = verbose_messaging -# self.model = model -# self.i2v_model = i2v_model -# self.batches_script = batches_script -# self.g_output = {} -# -# disable_pbar = not utils.PROGRESS_BAR_ENABLED -# -# self.use_sigmas = self.sigmas -# -# self.guider = WarpedGuider_Basic() -# self.guider.set_model(self.model) -# callback = self.setup_callbacks() -# -# self.latent_window_size, self.batch_count, self.truncated_frame_count = self.get_latent_window_size(preferred_batch_size, self.preferred_frame_count, use_batch_size=use_batch_size) -# self.batch_frame_count = int(((self.truncated_frame_count - 1) // self.batch_count) + 1) -# print("latent_window_size: {} | batch_count: {} | truncated_frame_count: {} | batch_frame_count: {}".format(self.latent_window_size, self.batch_count, self.truncated_frame_count, self.batch_frame_count)) -# -# is_i2v = True -# -# if start_image is None: -# start_image = torch.zeros([1, self.t2v_height, self.t2v_width, 3], dtype=torch.float32, device=self.offload_device) -# is_i2v = False -# -# print("start_image Shape: {}".format(start_image.shape)) -# -# self.width = int(start_image.shape[2] // 8) -# self.height = int(start_image.shape[1] // 8) -# -# noise, dummy_noise = self.setup_latent_noise() -# -# output_images = [] -# output_images_latents = None -# interrupted = False -# generation_status = "" -# total_images_generated = 0 -# is_dummy_section = False -# is_first_section = False -# is_last_section = False -# switch_guider = True -# last_image = None -# positive_prompt = positive -# -# if not self.gen_dummy: -# print("Generating {} Batches".format(self.batch_count)) -# else: -# print("Generating Dummy Batch Plus {} Batches".format(self.batch_count)) -# -# generation_batches = list(range(self.batch_count)) -# -# if self.gen_dummy and (not self.gen_dummy_only): -# generation_batches = [0] + generation_batches -# is_dummy_section = True -# else: -# generation_batches = [0] -# is_dummy_section = True -# -# print("generation_batches: {}".format(generation_batches)) -# -# try: -# for i, generation_batch in enumerate(generation_batches): -# batch_number = generation_batches[i] -# batch_key = "{}".format(batch_number) -# -# if is_dummy_section: -# print("Generating Dummy Batch.") -# is_first_section = False -# -# if not self.gen_dummy_only: -# is_last_section = False -# else: -# is_last_section = True -# -# if not batch_scripts is None: -# positive_prompt = batch_scripts["dummy"] -# print("\nDummy Section Positive Prompt: {}\n".format(positive_prompt)) -# last_prompt = positive_prompt -# else: -# print("Generating Batch {}.".format(batch_number)) -# -# is_first_section = batch_number == min(generation_batches) -# is_last_section = batch_number == max(generation_batches) -# -# if not batch_scripts is None: -# if batch_key in batch_scripts.keys(): -# positive_prompt = batch_scripts[batch_key] -# last_prompt = positive_prompt -# else: -# positive_prompt = last_prompt -# -# print("\nBatch: {} Positive Prompt: {}\n".format(batch_number, positive_prompt)) -# -# print("is_first_section: {} | is_last_section: {} | is_dummy_section: {}".format(is_first_section, is_last_section, is_dummy_section)) -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# image_embeds = None -# -# print("start_image Shape: {}".format(start_image.shape)) -# -# if is_i2v: -# if len(start_image.shape) < 4: -# start_image = start_image.unsqueeze(0) -# -# print("Performing clip_vision_encode.") -# image_embeds = self.clip_vision_encode(start_image.clone().detach()) -# -# if not is_dummy_section: -# noise_latents = noise[batch_number] -# else: -# noise_latents = dummy_noise -# -# print("noise_latents Shape: {}".format(noise_latents.shape)) -# -# noise_mask = None -# -# if mode == "Hunyuan": -# if is_i2v: -# if (not self.i2v_model is None) and switch_guider: -# switch_guider = False -# callback = None -# self.guider = WarpedGuider_Basic() -# self.guider.set_model(self.i2v_model) -# callback = self.setup_callbacks() -# -# self.use_clip = self.clip.clone() -# temp_cond = self.hunyuan_text_encode(self.use_clip, image_embeds, positive_prompt, hunyuan_image_interleave) -# positive_cond, latents = self.hunyuan_encode(temp_cond, self.vae, start_image.shape[2], start_image.shape[1], self.batch_frame_count, 1, hunyuan_guidance_type, start_image=start_image) -# -# if "noise_mask" in latents: -# noise_mask = latents["noise_mask"] * scaling_strength -# -# latents = latents["samples"] -# -# # latents = latents["samples"] * (scaling_strength * vae_scaling_factor) -# else: -# positive_cond = self.do_text_encode(self.use_clip, positive_prompt) -# latents = torch.zeros([1, 16, noise_latents.shape[2], self.height, self.width], dtype=torch.float32, device=self.offload_device) -# -# latents = latents * scaling_strength # scaling_strength -# -# if use_flux_guidance: -# positive_cond = self.apply_flux_guidance(positive_cond, flux_guidance) -# -# self.guider.set_conds_single(positive_cond) -# else: -# # if is_i2v: -# # if (not self.i2v_model is None) and switch_guider: -# # switch_guider = False -# # callback = None -# # self.guider = WarpedGuider_Basic() -# # self.guider.set_model(self.i2v_model) -# # callback = self.setup_callbacks() -# if not is_i2v: -# positive_cond, negative_cond = self.wan_text_encode(self.use_clip, positive_text=positive_prompt, negative_text=negative) -# positive_cond, negative_cond, latents = self.wan_encode(positive_cond, negative_cond, self.vae, start_image.shape[2], start_image.shape[1], ((noise_latents.shape[2] - 1) * 4) + 1, 1, start_image=None, clip_vision_output=None) -# else: -# positive_cond, negative_cond = self.wan_text_encode(self.use_clip, positive_text=positive_prompt, negative_text=negative) -# positive_cond, negative_cond, latents = self.wan_encode(positive_cond, negative_cond, self.vae, start_image.shape[2], start_image.shape[1], ((noise_latents.shape[2] - 1) * 4) + 1, 1, start_image=start_image, clip_vision_output=image_embeds) -# -# latents = latents["samples"] * scaling_strength -# -# self.guider.set_conds_both(positive_cond, negative_cond) -# -# print("latents Shape: {}".format(latents.shape)) -# -# num_frames = int(((latents.shape[2] - 1) * 4) + 1) -# -# print("\nDecoded Width is {} | Decoded Height is {}".format(int(self.width * 8), int(self.height * 8))) -# -# print("-------------------------------------------------------------------------------------------") -# print("WarpedSamplerCustomScripted: Latents Shape: {} | Noise Latents Shape: {}".format(latents.shape, noise_latents.shape)) -# print("-------------------------------------------------------------------------------------------") -# -# print("Noise Shape: {} | Latents Shape: {}".format(noise_latents.shape, latents.shape)) -# print("WarpedSamplerCustomScripted: Generating {} Frames in {} Latents....".format(num_frames, latents.shape[2])) -# -# samples = self.guider.sample(noise_latents, latents, self.sampler, self.use_sigmas, denoise_mask=noise_mask, callback=callback, disable_pbar=disable_pbar, seed=self.seed) -# samples = samples.to(mm.intermediate_device()) -# -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# if len(samples.shape) < 5: -# samples = samples.unsqueeze(0) -# -# samples = samples.clone().detach() / scaling_strength # (scaling_strength * vae_scaling_factor) -# -# print("WarpedSamplerCustomScripted: Decoding Latents...") -# decoded_images = self.decode_tiled(samples) -# -# if not is_dummy_section or (is_dummy_section and ((self.use_dummy_image == "all") or self.gen_dummy_only)): -# output_images.append(decoded_images) -# total_images_generated += decoded_images.shape[0] -# -# samples = None -# -# # output_images = self.process_skip_images(output_images, skip_frames) -# print("WarpedSamplerCustomScripted: Decoded Images Shape: {}".format(decoded_images.shape[0])) -# -# # if output_latents: -# # output_images_latents = self.encode_tiled(output_images) -# -# print("WarpedSamplerCustomScripted: Generating {} frames in {} latents...Done.".format(num_frames, latents.shape[2])) -# -# if not is_i2v: -# self.guider.model_patcher.model.to(get_offload_device()) -# # guider.set_i2v_model() -# -# if not self.i2v_sigmas is None: -# self.use_sigmas = self.i2v_sigmas -# -# if not is_last_section: -# print("HERE 9090000") -# decoded_tuple = torch.split(decoded_images, 1, dim=0) -# decoded_split = [item for item in decoded_tuple] -# decoded_images = decoded_images.to(get_offload_device()) -# decoded_images = None -# -# if (not is_dummy_section) or (is_dummy_section and ((self.use_dummy_image == "last") or (self.use_dummy_image == "all"))): -# print("HERE 9090000a") -# start_image = decoded_split[len(decoded_split) - 1].clone().detach() -# elif is_dummy_section: -# print("HERE 9090000b") -# if self.use_dummy_image == "first": -# print("HERE 9090000c") -# start_image = decoded_split[0].clone().detach() -# elif self.use_dummy_image == "middle": -# print("HERE 9090000d") -# start_image = decoded_split[int(len(decoded_split) // 2)].clone().detach() -# else: -# print("HERE 9090000e") -# random.seed(self.seed) -# start_image = dummy_split[random.randrange(0, len(decoded_split) - 1, 1)].clone().detach() -# -# is_i2v = True -# -# if last_image is None: -# last_image = start_image.clone().detach() -# -# print("HERE 9090001") -# -# samples = None -# latents = None -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# print("*******************************************") -# print("****** WarpedSamplerCustomScripted: Total Images Generated {}".format(total_images_generated)) -# print("*******************************************\n") -# -# generation_status = "****** WarpedSamplerCustomScripted: Total Images Generated {} ******".format(total_images_generated) -# -# interrupted = False -# -# print("HERE 9090002") -# -# if is_dummy_section: -# print("HERE 9090003") -# -# if self.gen_dummy_only: -# print("HERE 9090004") -# break -# -# print("HERE 9090005") -# -# is_dummy_section = False -# -# print("HERE 9090006") -# except mm.InterruptProcessingException as ie: -# interrupted = True -# print(f"\nWarpedSamplerCustomScripted: Processing Interrupted.") -# print("WarpedSamplerCustomScripted: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned.\n") -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# generation_status = f"\nWarpedSamplerCustomScripted: Processing Interrupted." -# -# traceback.print_tb(ie.__traceback__, limit=99, file=sys.stdout) -# -# raise mm.InterruptProcessingException(f"WarpedSamplerCustomScripted: Processing Interrupted.") -# -# except BaseException as e: -# print(f"\nWarpedSamplerCustomScripted: Exception During Processing: {str(e)}") -# print("WarpedSamplerCustomScripted: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned.\n") -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# generation_status = f"WarpedSamplerCustomScripted: Exception During Processing: {str(e)}" -# generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomScripted: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned.") -# -# traceback.print_tb(e.__traceback__, limit=99, file=sys.stdout) -# -# pass -# -# callback = None -# self.guider.model_patcher.model.to(get_offload_device()) -# -# latent = None -# latent_image = None -# noise_mask = None -# samples = None -# -# torch.cuda.empty_cache() -# torch.cuda.ipc_collect() -# gc.collect() -# time.sleep(1) -# -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# image = None -# -# if interrupted and (len(output_images) < 1): -# temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'yellow') -# image = pil2tensorSwap(temp_image) -# final_images = image -# elif (len(output_images) < 1): -# temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'red') -# image = pil2tensorSwap(temp_image) -# final_images = image -# else: -# final_images = self.assemble_final_result(output_images) -# -# if output_images_latents is None: -# output_images_latents = torch.zeros([1, 16, 1, self.height, self.width], dtype=torch.float32, device=self.offload_device) -# -# return (final_images, {"samples": output_images_latents}, self.seed, generation_status, last_image,) -# -# def assemble_final_result(self, image_batches): -# if self.blend_frames < 1: -# resulting_images = None -# for entry in image_batches: -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, entry), 0) -# else: -# resulting_images = entry -# -# entry.to(device=self.offload_device) -# entry = None -# else: -# blend_value = 1.0 / self.blend_frames -# i = 0 -# while i < (len(image_batches) - 1): -# alpha_blend_val = blend_value -# blend_count = self.blend_frames -# -# image_batches_tuple = torch.split(image_batches[i], 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image1 = image_batches_split[len(image_batches_split) - 1] -# # image1 = image_batches_split[len(image_batches_split) - 4] -# image_batches_tuple = None -# image_batches_split = None -# -# image_batches_tuple = torch.split(image_batches[i + 1], 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image2 = image_batches_split[0] -# image_batches_tuple = None -# image_batches_split = None -# -# image1 = tensor2pilSwap(image1)[0] -# image2 = tensor2pilSwap(image2)[0] -# -# blend_latents = None -# -# while blend_count > 0: -# blended_image = Image.blend(image1, image2, alpha_blend_val) -# temp_latent = pil2tensorSwap(blended_image) -# blended_image = None -# -# if len(temp_latent.shape) < 4: -# temp_latent = temp_latent.unsqueeze(0) -# -# if not blend_latents is None: -# blend_latents = torch.cat((blend_latents, temp_latent), 0) -# else: -# blend_latents = temp_latent -# -# alpha_blend_val += blend_value -# blend_count -= 1 -# -# image_batches_tuple = torch.split(image_batches[i], image_batches[i].shape[0] - 3, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image_batches_tuple = None -# -# image_batches[i] = torch.cat((image_batches_split[0], blend_latents), 0) -# blend_latents = None -# image_batches_split = None -# -# self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) -# -# i += 1 -# -# resulting_images = None -# for entry in image_batches: -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, entry), 0) -# else: -# resulting_images = entry -# -# entry.to(device=self.offload_device) -# -# image_batches = None -# -# self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) -# -# -# print("assemble_final_result: Full decoded images count: {}".format(resulting_images.shape[0])) -# -# if self.skip_frames < 1: -# return resulting_images -# -# skipped_frames = 1 -# -# image_batches_tuple = torch.split(resulting_images, 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# -# resulting_images = None -# -# for image in image_batches_split: -# if skipped_frames <= self.skip_frames: -# skipped_frames += 1 -# continue -# -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, image), 0) -# else: -# resulting_images = image -# -# print("assemble_final_result: Final decoded images count: {}".format(resulting_images.shape[0])) -# -# return resulting_images -# -# def cleanup(self, unload_models=False, cleanup_models=False, cleanup_cuda=False): -# if unload_models: -# mm.unload_all_models() -# -# if cleanup_models: -# mm.cleanup_models() -# -# if cleanup_cuda: -# mm.soft_empty_cache() -# -# gc.collect() -# time.sleep(1) -# -# return -# -# def generate_noise(self, input_latent, generator=None): -# latent_image = input_latent["samples"] -# return warped_prepare_noise(latent_image, self.seed, generator=generator) -# -# def setup_latent_noise(self): -# dummy_noise = None -# -# if self.gen_dummy: -# rnd = torch.Generator("cpu").manual_seed(self.seed) -# dummy_noise = torch.randn((1, 16, self.dummy_latents, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) -# -# noise = [] -# -# for i in range(self.batch_count): -# rnd = torch.Generator("cpu").manual_seed(self.seed) -# temp_noise = torch.randn((1, 16, self.latent_window_size, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) -# -# noise.append(temp_noise) -# temp_noise = None -# -# if self.verbose_messaging: -# if not dummy_noise is None: -# print("\nsetup_latent_noise: dummy_noise Shape: {}".format(dummy_noise.shape)) -# -# i = 0 -# for entry in noise: -# print("setup_latent_noise: Batch: {} | noise Shape: {}".format(i, entry.shape)) -# i += 1 -# -# print("\n") -# -# return noise, dummy_noise -# -# def get_latent_window_size(self, preferred_batch_size, frame_count, use_batch_size="next_lowest"): -# latent_size_factor = 4 -# -# if self.verbose_messaging: -# print("get_latent_window_size: preferred_batch_size: {}".format(preferred_batch_size)) -# print("get_latent_window_size: frame_count: {}".format(frame_count)) -# print("get_latent_window_size: use_batch_size: {}".format(use_batch_size)) -# -# num_frames = int(((frame_count - 1) // 4) * 4) + 1 -# -# if num_frames != frame_count: -# print(f"Truncating video from {frame_count} to {num_frames} an because odd number of frames is not allowed.") -# -# if ((num_frames - 1) % (preferred_batch_size - 1)) == 0: -# print("(1) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size))) -# print("(1) batch_count set to: {}".format(int((num_frames - 1) / (preferred_batch_size - 1)))) -# return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames - 1) / (preferred_batch_size - 1)), num_frames -# -# if use_batch_size == "exact": -# num_frames_final = int(((num_frames - 1) // (preferred_batch_size - 1)) + 1) * (preferred_batch_size - 1) -# -# if num_frames_final != frame_count: -# print(f"Truncating video from {num_frames} to {num_frames_final} frames for preferred_batch_size compatibility.") -# -# print("(2) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size + 1))) -# print("(2) batch_count set to: {}".format(int((num_frames_final - 1) / (preferred_batch_size - 1)))) -# return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames_final - 1) / (preferred_batch_size - 1)), num_frames_final -# -# next_lowest_found = False -# next_highest_found = False -# next_lowest = preferred_batch_size - 1 -# next_highest = preferred_batch_size - 1 -# -# if self.verbose_messaging: -# print("get_latent_window_size: Next Lowest Initialized To: {}".format(next_lowest)) -# print("get_latent_window_size: Next Highest Initialized To: {}".format(next_highest)) -# -# num_frames_final = int(((num_frames - 1) // 4) * 4) + 1 -# -# if num_frames != num_frames_final: -# print(f"Truncating video from {num_frames} to {num_frames_final} frames for latent_window_size compatibility.") -# -# if (use_batch_size == "closest") or (use_batch_size == "next_lowest"): -# while next_lowest >= 12: -# next_lowest -= 4 -# -# if (int((num_frames_final - 1) // 4) % next_lowest) == 0: -# next_lowest_found = True -# break -# -# next_lowest += 1 -# -# if next_lowest_found and (use_batch_size == "next_lowest"): -# print("(3) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) -# print("(3) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) -# return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final -# -# while next_highest <= 156: -# next_highest += 4 -# -# if (int((num_frames_final - 1) // 4) % next_highest) == 0: -# next_highest_found = True -# break -# -# if next_highest_found and (use_batch_size == "next_highest"): -# print("(4) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) -# print("(4) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) -# return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final -# -# if next_highest_found and next_lowest_found: -# if (preferred_batch_size - next_lowest) <= (next_highest - preferred_batch_size): -# print("(5) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) -# print("(5) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) -# return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final -# elif (next_highest - preferred_batch_size) < (preferred_batch_size - next_lowest): -# print("(6) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) -# print("(6) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) -# return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final -# -# print("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) -# print("Recalculating Number Of Frames Based On preferred_batch_size of: {}".format(preferred_batch_size)) -# -# return self.calculate_new_number_of_frames(preferred_batch_size, (((frame_count - 1) // 4) * 4) + 1, use_batch_size) -# -# def calculate_new_number_of_frames(self, preferred_batch_size, frame_count, use_batch_size): -# working_batch_size = preferred_batch_size - 1 -# working_frame_count = frame_count - 1 -# -# next_lowest = next_highest = working_frame_count -# next_lowest_found = False -# next_highest_found = False -# -# while next_lowest > 37: -# next_lowest -= 4 -# -# if int(next_lowest % working_batch_size) == 0: -# next_lowest_found = True -# break -# -# if next_lowest_found and (use_batch_size == "next_lowest"): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# while next_highest < 999997: -# next_highest += 4 -# -# if int(next_highest % working_batch_size) == 0: -# next_highest_found = True -# break -# -# if next_highest_found and (use_batch_size == "next_highest"): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# if next_lowest_found and next_highest_found: -# if (working_frame_count - next_lowest) <= (next_highest - working_frame_count): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# if next_lowest_found: -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# if next_highest_found: -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# raise ValueError("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) -# -# def clip_vision_encode(self, image, crop="center"): -# crop_image = False -# if crop != "center": -# crop_image = False -# output = self.clip_vision.encode_image(image, crop=crop_image) -# return output -# -# def encoded_to_decoded_length(self, latent_length): -# if latent_length <= 0: -# return 0 -# -# result_length = ((latent_length - 1) * 4) + 1 -# -# return result_length -# -# def decoded_to_encoded_length(self, image_length): -# if image_length <= 0: -# return 0 -# -# result_length = int(((image_length - 1) / 4) + 1) -# -# return result_length -# -# def apply_flux_guidance(self, conditioning, guidance): -# c = node_helpers.conditioning_set_values(conditioning, {"guidance": guidance}) -# return c -# -# def hunyuan_text_encode(self, clip, clip_vision_output, prompt, image_interleave): -# tokens = clip.tokenize(prompt, llama_template=PROMPT_TEMPLATE_ENCODE_VIDEO_I2V, image_embeds=clip_vision_output.mm_projected, image_interleave=image_interleave) -# return clip.encode_from_tokens_scheduled(tokens) -# -# def hunyuan_encode(self, positive, vae, width, height, length, batch_size, guidance_type, start_image=None): -# latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) -# out_latent = {} -# -# if start_image is not None: -# start_image = comfy.utils.common_upscale(start_image[:length, :, :, :3].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) -# -# concat_latent_image = vae.encode(start_image) -# mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) -# mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 -# -# if guidance_type == "v1 (concat)": -# cond = {"concat_latent_image": concat_latent_image, "concat_mask": mask} -# elif guidance_type == "v2 (replace)": -# cond = {'guiding_frame_index': 0} -# latent[:, :, :concat_latent_image.shape[2]] = concat_latent_image -# out_latent["noise_mask"] = mask -# elif guidance_type == "custom": -# cond = {"ref_latent": concat_latent_image} -# -# positive = node_helpers.conditioning_set_values(positive, cond) -# -# out_latent["samples"] = latent -# return positive, out_latent -# -# def wan_text_encode(self, clip, positive_text="", negative_text=""): -# print("wan_text_encode: Loading clip model to device: {}".format(clip.patcher.load_device)) -# clip.patcher.model.to(device=clip.patcher.load_device) -# -# print("wan_text_encode: Encoding Prompts...") -# positive_conditioning = self.do_text_encode(clip, positive_text) -# negative_conditioning = self.do_text_encode(clip, negative_text) -# print("wan_text_encode: Encoding Prompts...Done.") -# -# print("wan_text_encode: Unloading clip model to device: {}".format(get_offload_device())) -# clip.patcher.model.to(device=get_offload_device()) -# -# if torch.cuda.is_available(): -# torch.cuda.empty_cache() -# -# gc.collect() -# time.sleep(1) -# -# return positive_conditioning, negative_conditioning -# -# def encode(self, clip, text): -# if clip is None: -# raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") -# tokens = clip.tokenize(text) -# return clip.encode_from_tokens_scheduled(tokens) -# -# def do_text_encode(self, clip, text): -# -# if clip is None: -# raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") -# -# tokens = clip.tokenize(text) -# return_encoding = clip.encode_from_tokens_scheduled(tokens) -# -# return return_encoding -# -# def wan_encode(self, positive, negative, vae, width, height, length, batch_size, start_image=None, clip_vision_output=None): -# latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) -# if start_image is not None: -# start_image = comfy.utils.common_upscale(start_image[:length].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) -# image = torch.mul(torch.ones((length, height, width, start_image.shape[-1]), device=start_image.device, dtype=start_image.dtype), 0.5) -# image[:start_image.shape[0]] = start_image -# -# concat_latent_image = vae.encode(image[:, :, :, :3]) -# -# mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) -# mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 -# -# positive = node_helpers.conditioning_set_values(positive, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) -# negative = node_helpers.conditioning_set_values(negative, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) -# -# if clip_vision_output is not None: -# positive = node_helpers.conditioning_set_values(positive, {"clip_vision_output": clip_vision_output}) -# negative = node_helpers.conditioning_set_values(negative, {"clip_vision_output": clip_vision_output}) -# -# out_latent = {} -# out_latent["samples"] = latent -# return positive, negative, out_latent -# -# def process_skip_images(self, frames, skip_count): -# if len(frames.shape) < 4: -# frames = frames.unsqueeze(0) -# -# num_frames = frames.shape[0] -# -# image_batches_tuple = torch.split(frames, 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# -# new_video = None -# i = 0 -# -# while i < len(image_batches_split): -# if i < skip_count: -# i += 1 -# continue -# -# if not new_video is None: -# new_video = torch.cat((new_video, image_batches_split[i]), 0) -# else: -# new_video = image_batches_split[i] -# -# i += 1 -# -# return new_video -# -# def get_blank_image(self, length=1): -# new_image = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) -# return new_image -# -# def get_new_noise(self, length): -# new_noise = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) -# -# new_noise = self.encode_tiled(new_noise) -# -# new_noise = comfy.sample.fix_empty_latent_channels(self.guider.model_patcher, new_noise) -# -# if len(new_noise) < 5: -# new_latent = new_noise.unsqueeze(0) -# -# new_noise = self.generate_noise({"samples": new_noise}) -# -# return new_noise -# -# def pad_noise(self, latent, num_frames=1): -# pad_frames = torch.zeros([1, 16, num_frames, self.height, self.width], dtype=torch.float32, device=self.offload_device) -# pad_frames = torch.cat((latent, pad_frames), 2) -# -# return pad_frames -# -# def setup_callbacks(self): -# callback = latent_preview.prepare_callback(self.guider.model_patcher, self.sigmas.shape[-1] - 1, self.g_output) -# -# return callback -# -# def decode_tiled(self, latents): -# decoded_data = partial_decode_tiled(self.vae, latents, self.dec_tile_size, self.dec_overlap, self.dec_temporal_size, self.dec_temporal_overlap) -# -# if len(decoded_data.shape) < 4: -# decoded_data.unsqueeze(0) -# -# return decoded_data -# -# def initialize_noise(self, frame_count, clear_cache=True): -# noise_latents_full = torch.zeros([1, 16, int(frame_count), self.height, self.width], dtype=torch.float32, device=self.offload_device) -# print("WarpedSamplerCustomScripted: Encoded noise_latents_full Shape: {}".format(noise_latents_full.shape)) -# -# if Decimal(self.noise_scale).compare(Decimal(0.00)) != 0: -# noise_latents_full = warped_prepare_noise(noise_latents_full, self.seed) -# print("WarpedSamplerCustomScripted: noise_latents_full Shape: {}".format(noise_latents_full.shape)) -# -# noise_latents_full = torch.mul(noise_latents_full, self.noise_scale) -# -# if len(noise_latents_full.shape) < 5: -# noise_latents_full.unsqueeze(0) -# -# noise_latents_full = noise_latents_full.to(dtype=torch.float32, device=self.offload_device) -# -# if clear_cache: -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# return noise_latents_full -# -# def initialize_frames(self, latents): -# if len(latents.shape) < 5: -# latents = latents.unsqueeze(0) -# -# print("WarpedSamplerCustomScripted: Encoded latents_full Shape: {}".format(latents.shape)) -# latents_full = latents.clone().detach() -# latents_full = latents_full.to(dtype=torch.float32, device=self.offload_device) -# -# noise_latents_full = self.initialize_noise(latents_full.shape[2]) -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# return noise_latents_full +class WarpedSamplerCustomScripted: + @classmethod + def INPUT_TYPES(s): + return {"required": + { + "positive": ("STRING", {"default": None} ), + "negative": ("STRING", {"default": None}), + "clip": ("CLIP", ), + "preferred_frame_count": ("INT", {"default": 81, "min": 17, "max": nodes.MAX_RESOLUTION, "step": 4}), + "preferred_batch_size": ("INT", {"default": 17, "min": 17, "max": 161, "step": 4}), + "use_batch_size": (["next_lowest", "next_highest", "closest", "exact"], {"default": "next_lowest", "tooltip": "Number of frames generated may be impacted by choice."}), + "vae": ("VAE", ), + "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), + "model": ("MODEL", ), + "sampler": ("SAMPLER", ), + "sigmas": ("SIGMAS", ), + "dec_tile_size": ("INT", {"default": 256, "min": 64, "max": 4096, "step": 32}), + "dec_overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}), + "dec_temporal_size": ("INT", {"default": 64, "min": 8, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to decode at a time."}), + "dec_temporal_overlap": ("INT", {"default": 8, "min": 4, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to overlap."}), + "skip_frames": ("INT", {"default": 0, "min": 0, "max": 32, "step": 4}), + "noise_scale": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 1.00, "step": 0.01}), + "mode": (["Hunyuan", "Wan 2.1", "Wan 2.2 TI2V", "Wan 2.2 Standard"], {"default": "Hunyuan"}), + "hunyuan_guidance_type": (["v1 (concat)", "v2 (replace)", "custom"], {"default": "v2 (replace)", "tooltip": "Only used if mode is \"Hunyuan\"."}), + "hunyuan_image_interleave": ("INT", {"default": 1, "min": 1, "max": 512, "tooltip": "How much the image influences things vs the text prompt. Higher number means more influence from the text prompt."}), + }, + "optional": + {"noise_strength": ("FLOAT", {"default": 1.00, "min": 0.10, "max": 1.00, "step": 0.01}), + "blend_frames": ("INT", {"default":0, "min":0, "max": 16, "step": 1}), + "t2v_width": ("INT", {"default":480, "min":256, "max": 1280, "step": 16}), + "t2v_height": ("INT", {"default":720, "min":256, "max": 1280, "step": 16}), + "scaling_strength": ("FLOAT", {"default": 1.0}), + "clip_vision_model": ("CLIP_VISION", ), + "start_image": ("IMAGE", ), + "flux_guidance": ("FLOAT", {"default": 7, "min": 0.0, "max": 100.0, "step": 0.1}), + "use_flux_guidance": ("BOOLEAN", {"default": False}), + "dummy_frames": ("INT", {"default":17, "min":17, "max": 121, "step": 4, "tooltip": "Number of frames to generate in dummy batch."}), + "gen_dummy": ("BOOLEAN", {"default": False, "tooltip": "For t2v or i2v only. Will generate a dummy batch to obtain a starting image for main generation."}), + "gen_dummy_only": ("BOOLEAN", {"default": False, "tooltip": "Will generate dummy batch only."}), + "use_dummy_image": (["first", "middle", "last", "random", "all"], {"default": "last", "tooltip": "Which dummy batch image to start main generation."}), + "output_latents": ("BOOLEAN", {"default": False}), + "verbose_messaging": ("BOOLEAN", {"default": False}), + "secondary_sigmas": ("SIGMAS", {"default": None}), + "secondary_model": ("MODEL", {"default": None}), + "batches_script": ("WARPEDSCRIPTS", {"default": None}), + } + } + + RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", "IMAGE", "BOOLEAN",) + RETURN_NAMES = ("images", "latents", "seed", "generation_status", "image_used", "valid_output",) + + FUNCTION = "sample" + + CATEGORY = "Warped/General/Sampling" + + def sample(self, positive, negative, clip, preferred_frame_count, preferred_batch_size, use_batch_size, vae, seed, model, sampler, sigmas, dec_tile_size, dec_overlap, dec_temporal_size, dec_temporal_overlap, + skip_frames, noise_scale, mode="Hunyuan", hunyuan_guidance_type="v2 (replace)", hunyuan_image_interleave=2, noise_strength=1.0, blend_frames=5, t2v_width=480, t2v_height=720, scaling_strength=1.0, + clip_vision_model=None, start_image=None, flux_guidance=3.5, dummy_frames=17, gen_dummy=False, gen_dummy_only=False, use_dummy_image="last", use_flux_guidance=False, output_latents=False, verbose_messaging=False, + secondary_sigmas=None, secondary_model=None, batches_script=None): + + batch_scripts = batches_script + + if (positive is None) and (batches_script is None): + raise ValueError("positive and batches_script cannot both be None.") + # elif not batches_script is None: + # if verbose_messaging: + # print("\n{}\n".format(batches_script)) + # + # batch_scripts = {} + # temp_strings = batches_script.split("||") + # + # for entry in temp_strings: + # temp_script = entry.strip().split("|") + # batch_scripts[temp_script[0].strip()] = temp_script[1].strip() + # + # if verbose_messaging: + # print("\n{}\n".format(batch_scripts)) + + self.device = mm.get_torch_device() + self.offload_device = get_offload_device() + mm.unload_all_models() + gc.collect() + time.sleep(1) + + self.positive = positive + self.negative = negative + self.clip = clip + self.use_clip = clip.clone() + self.preferred_frame_count = preferred_frame_count + self.preferred_batch_size = preferred_batch_size + self.vae = vae + self.seed = seed + self.sampler = sampler + self.sigmas = sigmas + self.secondary_sigmas = secondary_sigmas + self.noise_scale = noise_scale + self.mode = mode + self.dec_tile_size = dec_tile_size + self.dec_overlap = dec_overlap + self.dec_temporal_size = dec_temporal_size + self.dec_temporal_overlap = dec_temporal_overlap + self.clip_vision = clip_vision_model + self.noise_strength = noise_strength + self.blend_frames = blend_frames + self.t2v_width = t2v_width + self.t2v_height = t2v_height + self.dummy_frames = dummy_frames + self.dummy_latents = int((dummy_frames - 1) // 4) + 1 + self.gen_dummy = gen_dummy + self.gen_dummy_only = gen_dummy_only + self.use_dummy_image = use_dummy_image + self.skip_frames = skip_frames + self.verbose_messaging = verbose_messaging + self.model = model + self.secondary_model = secondary_model + self.batches_script = batches_script + self.g_output = {} + + disable_pbar = not utils.PROGRESS_BAR_ENABLED + + self.use_sigmas = self.sigmas + + self.guider = WarpedGuider_Basic() + self.guider.set_model(self.model) + callback = self.setup_callbacks() + + self.latent_window_size, self.batch_count, self.truncated_frame_count = self.get_latent_window_size(preferred_batch_size, self.preferred_frame_count, use_batch_size=use_batch_size) + self.batch_frame_count = int(((self.truncated_frame_count - 1) // self.batch_count) + 1) + print("latent_window_size: {} | batch_count: {} | truncated_frame_count: {} | batch_frame_count: {}".format(self.latent_window_size, self.batch_count, self.truncated_frame_count, self.batch_frame_count)) + + is_i2v = True + + if start_image is None: + start_image = torch.zeros([1, self.t2v_height, self.t2v_width, 3], dtype=torch.float32, device=self.offload_device) + is_i2v = False + + if self.mode == "Wan 2.2 TI2V": + self.latent_depth = 48 + else: + self.latent_depth = 16 + + print("start_image Shape: {}".format(start_image.shape)) + + if self.mode != "Wan 2.2 TI2V": + self.width = int(start_image.shape[2] // 8) + self.height = int(start_image.shape[1] // 8) + else: + self.width = int(start_image.shape[2] // 16) + self.height = int(start_image.shape[1] // 16) + + noise, dummy_noise = self.setup_latent_noise() + + output_images = [] + output_images_latents = None + interrupted = False + generation_status = "" + total_images_generated = 0 + is_dummy_section = False + is_first_section = False + is_last_section = False + switch_guider = True + last_image = None + positive_prompt = positive + valid_output = False + + if not self.gen_dummy: + print("Generating {} Batches".format(self.batch_count)) + else: + if not self.gen_dummy_only: + print("Generating Dummy Batch Plus {} Batches".format(self.batch_count)) + else: + print("Generating Dummy Batch Only") + + generation_batches = list(range(self.batch_count)) + + if self.gen_dummy and (not self.gen_dummy_only): + generation_batches = [0] + generation_batches + is_dummy_section = True + else: + generation_batches = [0] + is_dummy_section = True + + print("generation_batches: {}".format(generation_batches)) + + try: + for i, generation_batch in enumerate(generation_batches): + batch_number = generation_batches[i] + batch_key = "{}".format(batch_number) + + if is_dummy_section: + print("Generating Dummy Batch.") + is_first_section = False + + if not self.gen_dummy_only: + is_last_section = False + else: + is_last_section = True + + if not batch_scripts is None: + positive_prompt = batch_scripts["dummy"] + print("\nDummy Section Positive Prompt: {}\n".format(positive_prompt)) + last_prompt = positive_prompt + else: + print("Generating Batch {}.".format(batch_number)) + + is_first_section = batch_number == min(generation_batches) + is_last_section = batch_number == max(generation_batches) + + if not batch_scripts is None: + if batch_key in batch_scripts.keys(): + positive_prompt = batch_scripts[batch_key] + last_prompt = positive_prompt + else: + positive_prompt = last_prompt + + print("\nBatch: {} Positive Prompt: {}\n".format(batch_number, positive_prompt)) + + print("is_first_section: {} | is_last_section: {} | is_dummy_section: {}".format(is_first_section, is_last_section, is_dummy_section)) + + mm.soft_empty_cache() + gc.collect() + time.sleep(0.1) + + image_embeds = None + + print("start_image Shape: {}".format(start_image.shape)) + + if is_i2v: + print("GENERAL HERE 1") + + if len(start_image.shape) < 4: + start_image = start_image.unsqueeze(0) + + if mode != "Wan 2.2 TI2V": + print("Performing clip_vision_encode.") + image_embeds = self.clip_vision_encode(start_image.clone().detach()) + + if not is_dummy_section: + noise_latents = noise[batch_number] + else: + noise_latents = dummy_noise + + print("noise_latents Shape: {}".format(noise_latents.shape)) + + noise_mask = None + + if is_i2v: + if (not self.secondary_model is None) and switch_guider: + switch_guider = False + callback = None + self.guider = WarpedGuider_Basic() + self.guider.set_model(self.secondary_model) + callback = self.setup_callbacks() + self.use_clip = self.clip.clone() + + if mode == "Hunyuan": + if is_i2v: + temp_cond = self.hunyuan_text_encode(self.use_clip, image_embeds, positive_prompt, hunyuan_image_interleave) + positive_cond, latents = self.hunyuan_encode(temp_cond, self.vae, start_image.shape[2], start_image.shape[1], ((noise_latents.shape[2] - 1) * 4) + 1, 1, hunyuan_guidance_type, start_image=start_image) + + if "noise_mask" in latents: + noise_mask = latents["noise_mask"] * scaling_strength + + latents = latents["samples"] * scaling_strength + else: + positive_cond = self.do_text_encode(self.use_clip, positive_prompt) + latents = torch.zeros([1, 16, noise_latents.shape[2], self.height, self.width], dtype=torch.float32, device=self.offload_device) + + latents = latents * scaling_strength + + if use_flux_guidance: + positive_cond = self.apply_flux_guidance(positive_cond, flux_guidance) + + self.guider.set_conds_single(positive_cond) + else: + if not is_i2v: + print("HERE WAN 1") + positive_cond, negative_cond = self.wan_text_encode(self.use_clip, positive_text=positive_prompt, negative_text=negative) + positive_cond, negative_cond, latents = self.wan_encode(positive_cond, negative_cond, self.vae, start_image.shape[2], start_image.shape[1], ((noise_latents.shape[2] - 1) * 4) + 1, 1, start_image=None, clip_vision_output=None) + + if "noise_mask" in latents: + noise_mask = latents["noise_mask"] * scaling_strength + + latents = latents["samples"] * scaling_strength + else: + print("HERE WAN 2") + + temp_cond, negative_cond = self.wan_text_encode(self.use_clip, positive_text=positive_prompt, negative_text=negative) + positive_cond, negative_cond, latents = self.wan_encode(temp_cond, negative_cond, self.vae, start_image.shape[2], start_image.shape[1], ((noise_latents.shape[2] - 1) * 4) + 1, 1, start_image=start_image, clip_vision_output=image_embeds) + + if "noise_mask" in latents: + noise_mask = latents["noise_mask"] * scaling_strength + + latents = latents["samples"] * scaling_strength + + self.guider.set_conds_both(positive_cond, negative_cond) -# class WarpedSamplerCustomBatch: -# @classmethod -# def INPUT_TYPES(s): -# return {"required": -# { -# "positive": ("STRING", ), -# "negative": ("STRING", {"default": None}), -# "clip": ("CLIP", ), -# "preferred_frame_count": ("INT", {"default": 81, "min": 17, "max": nodes.MAX_RESOLUTION, "step": 4}), -# "preferred_batch_size": ("INT", {"default": 17, "min": 17, "max": 161, "step": 4}), -# "use_batch_size": (["next_lowest", "next_highest", "closest", "exact"], {"default": "next_lowest", "tooltip": "Number of frames generated may be impacted by choice."}), -# "vae": ("VAE", ), -# "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), -# "guider": ("GUIDER", ), -# "sampler": ("SAMPLER", ), -# "sigmas": ("SIGMAS", ), -# "dec_tile_size": ("INT", {"default": 256, "min": 64, "max": 4096, "step": 32}), -# "dec_overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}), -# "dec_temporal_size": ("INT", {"default": 64, "min": 8, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to decode at a time."}), -# "dec_temporal_overlap": ("INT", {"default": 8, "min": 4, "max": 4096, "step": 4, "tooltip": "Only used for video VAEs: Amount of frames to overlap."}), -# "skip_frames": ("INT", {"default": 0, "min": 0, "max": 32, "step": 4}), -# "noise_scale": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 1.00, "step": 0.01}), -# "mode": (["Hunyuan", "Wan"], {"default": "Hunyuan"}), -# "hunyuan_guidance_type": (["v1 (concat)", "v2 (replace)", "custom"], {"default": "v2 (replace)", "tooltip": "Only used if mode is \"Hunyuan\"."}), -# "hunyuan_image_interleave": ("INT", {"default": 1, "min": 1, "max": 512, "tooltip": "How much the image influences things vs the text prompt. Higher number means more influence from the text prompt."}), -# }, -# "optional": -# {"noise_strength": ("FLOAT", {"default": 1.00, "min": 0.10, "max": 1.00, "step": 0.01}), -# "blend_frames": ("INT", {"default":5, "min":0, "max": 16, "step": 1}), -# "t2v_width": ("INT", {"default":480, "min":256, "max": 1280, "step": 16}), -# "t2v_height": ("INT", {"default":720, "min":256, "max": 1280, "step": 16}), -# "scaling_strength": ("FLOAT", {"default": 1.0}), -# "clip_vision_model": ("CLIP_VISION", ), -# "start_image": ("IMAGE", ), -# "flux_guidance": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step": 0.1}), -# "use_flux_guidance": ("BOOLEAN", {"default": False}), -# "dummy_frames": ("INT", {"default":17, "min":17, "max": 121, "step": 4, "tooltip": "Number of frames to generate in dummy batch."}), -# "gen_dummy": ("BOOLEAN", {"default": False, "tooltip": "For t2v or i2v only. Will generate a dummy batch to obtain a starting image for main generation."}), -# "gen_dummy_only": ("BOOLEAN", {"default": False, "tooltip": "Will generate dummy batch only."}), -# "use_dummy_image": (["first", "middle", "last", "random", "all"], {"default": "last", "tooltip": "Which dummy batch image to start main generation."}), -# "output_latents": ("BOOLEAN", {"default": False}), -# "verbose_messaging": ("BOOLEAN", {"default": False}), -# "i2v_sigmas": ("SIGMAS", {"default": None}), -# "i2v_model": ("MODEL", {"default": None}), -# "temp_cond": ("CONDITIONING", ), -# "temp_latent": ("LATENT", ), -# } -# } -# -# RETURN_TYPES = ("IMAGE", "LATENT", "INT", "STRING", "IMAGE", ) -# RETURN_NAMES = ("images", "latents", "seed", "generation_status", "last_image",) -# -# FUNCTION = "sample" -# -# CATEGORY = "Warped/General/Sampling" -# -# def sample(self, positive, negative, clip, preferred_frame_count, preferred_batch_size, use_batch_size, vae, seed, guider, sampler, sigmas, dec_tile_size, dec_overlap, dec_temporal_size, dec_temporal_overlap, -# skip_frames, noise_scale, mode="Hunyuan", hunyuan_guidance_type="v2 (replace)", hunyuan_image_interleave=2, noise_strength=1.0, blend_frames=5, t2v_width=480, t2v_height=720, scaling_strength=1.0, -# clip_vision_model=None, start_image=None, flux_guidance=3.5, dummy_frames=17, gen_dummy=False, gen_dummy_only=False, use_dummy_image="last", use_flux_guidance=False, output_latents=False, verbose_messaging=False, -# i2v_sigmas=None, i2v_model=None, temp_cond=None, temp_latent=None): -# self.device = mm.get_torch_device() -# self.offload_device = get_offload_device() -# mm.unload_all_models() -# gc.collect() -# time.sleep(1) -# -# self.positive = positive -# self.negative = negative -# self.clip = clip -# self.use_clip = clip.clone() -# self.preferred_frame_count = preferred_frame_count -# self.preferred_batch_size = preferred_batch_size -# self.vae = vae -# self.seed = seed -# self.sampler = sampler -# self.sigmas = sigmas -# self.i2v_sigmas = i2v_sigmas -# self.noise_scale = noise_scale -# self.mode = mode -# self.dec_tile_size = dec_tile_size -# self.dec_overlap = dec_overlap -# self.dec_temporal_size = dec_temporal_size -# self.dec_temporal_overlap = dec_temporal_overlap -# self.clip_vision = clip_vision_model -# self.noise_strength = noise_strength -# self.blend_frames = blend_frames -# self.t2v_width = t2v_width -# self.t2v_height = t2v_height -# self.dummy_frames = dummy_frames -# self.dummy_latents = int((dummy_frames - 1) // 4) + 1 -# self.gen_dummy = gen_dummy -# self.gen_dummy_only = gen_dummy_only -# self.use_dummy_image = use_dummy_image -# self.skip_frames = skip_frames -# self.verbose_messaging = verbose_messaging -# self.guider = guider -# self.i2v_model = i2v_model -# self.g_output = {} -# -# disable_pbar = not utils.PROGRESS_BAR_ENABLED -# -# self.use_sigmas = self.sigmas -# -# # self.guider = WarpedGuider_Basic() -# # self.guider.set_model(self.model) -# callback = self.setup_callbacks() -# -# self.latent_window_size, self.batch_count, self.truncated_frame_count = self.get_latent_window_size(preferred_batch_size, self.preferred_frame_count, use_batch_size=use_batch_size) -# -# # if not self.start_image is None: -# # start_latent = partial_encode_basic(self.vae, start_image) -# is_i2v = True -# -# if start_image is None: -# start_image = torch.zeros([1, self.t2v_height, self.t2v_width, 3], dtype=torch.float32, device=self.offload_device) -# is_i2v = False -# -# print("start_image Shape: {}".format(start_image.shape)) -# -# self.width = int(start_image.shape[2] // 8) -# self.height = int(start_image.shape[1] // 8) -# -# noise, dummy_noise = self.setup_latent_noise() -# -# output_images = [] -# output_images_latents = None -# interrupted = False -# generation_status = "" -# total_images_generated = 0 -# is_dummy_section = False -# is_first_section = False -# is_last_section = False -# switch_guider = True -# last_image = None -# -# if not self.gen_dummy: -# print("Generating {} Batches".format(self.batch_count)) -# else: -# print("Generating Dummy Batch Plus {} Batches".format(self.batch_count)) -# -# generation_batches = list(range(self.batch_count)) -# -# if self.gen_dummy and (not self.gen_dummy_only): -# generation_batches = [0] + generation_batches -# is_dummy_section = True -# else: -# generation_batches = [0] -# is_dummy_section = True -# -# print("generation_batches: {}".format(generation_batches)) -# -# try: -# # if not self.gen_dummy: -# # i = -1 -# # else: -# # i = -2 -# # is_dummy_section = True -# -# # for batch_number in range(self.batch_count): -# for i, generation_batch in enumerate(generation_batches): -# batch_number = generation_batches[i] -# # batch_key = "{}".format(batch_number) -# -# if is_dummy_section: -# print("Generating Dummy Batch.") -# is_first_section = False -# -# if not self.gen_dummy_only: -# is_last_section = False -# else: -# is_last_section = True -# else: -# print("Generating Batch {}.".format(batch_number)) -# -# is_first_section = batch_number == min(generation_batches) -# is_last_section = batch_number == max(generation_batches) -# -# print("is_first_section: {} | is_last_section: {} | is_dummy_section: {}".format(is_first_section, is_last_section, is_dummy_section)) -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# image_embeds = None -# -# print("start_image Shape: {}".format(start_image.shape)) -# -# if is_i2v: -# if len(start_image.shape) < 4: -# start_image = start_image.unsqueeze(0) -# -# # print("Performing clip_vision_encode.") -# # image_embeds = self.clip_vision_encode(start_image.clone().detach()) -# -# if not is_dummy_section: -# noise_latents = noise[batch_number] -# else: -# noise_latents = dummy_noise -# -# print("noise_latents Shape: {}".format(noise_latents.shape)) -# -# if mode == "Hunyuan": -# if is_i2v: -# # if (not self.i2v_model is None) and switch_guider: -# # switch_guider = False -# # callback = None -# # self.guider = WarpedGuider_Basic() -# # self.guider.set_model(self.i2v_model) -# # callback = self.setup_callbacks() -# # -# # self.use_clip = self.clip.clone() -# # hunyuan_text_encode(self, clip, clip_vision_output, prompt, image_interleave) -# # temp_cond = self.hunyuan_text_encode(self.use_clip, image_embeds, positive, hunyuan_image_interleave) -# # positive_cond, latents = self.hunyuan_encode(temp_cond, self.vae, start_image.shape[2], start_image.shape[1], self.truncated_frame_count, 1, hunyuan_guidance_type, start_image=start_image) -# -# print("HERE 90210") -# positive_cond = temp_cond -# latents = temp_latent -# -# noise_mask = None -# if "noise_mask" in latents: -# noise_mask = latents["noise_mask"] -# -# latents = latents["samples"] # * scaling_strength -# -# if len(latents.shape) < 5: -# latents = latents.unsqueeze(0) -# -# # latents = latents["samples"] * (scaling_strength * vae_scaling_factor) -# # else: -# # positive_cond = self.do_text_encode(self.use_clip, positive) -# # latents = torch.zeros([1, 16, noise_latents.shape[2], self.height, self.width], dtype=torch.float32, device=self.offload_device) -# # -# # latents = latents * scaling_strength # scaling_strength -# # latents = latents * (scaling_strength * vae_scaling_factor) -# # -# # if use_flux_guidance: -# # positive_cond = self.apply_flux_guidance(positive_cond, flux_guidance) -# -# # self.guider.set_conds(positive_cond) -# # else: -# # positive_cond, negative_cond = wan_text_encode(self.use_clip, positive_text=positive, negative_text=negative) -# # positive_cond, negative_cond, latents = self.wan_encode(positive_cond, negative_cond, self.vae, start_image.shape[3], start_image.shape[2], ((noise_latents.shape[2] - 1) * 4) + 1, 1, start_image=start_image, clip_vision_output=image_embeds) -# -# # self.guider.set_conds(positive_cond, negative_cond) -# -# print("latents Shape: {}".format(latents.shape)) -# -# num_frames = int(((latents.shape[2] - 1) * 4) + 1) -# -# print("\nDecoded Width is {} | Decoded Height is {}".format(int(self.width * 8), int(self.height * 8))) -# -# print("-------------------------------------------------------------------------------------------") -# print("WarpedSamplerCustomBatch: Latents Shape: {} | Noise Latents Shape: {}".format(latents.shape, noise_latents.shape)) -# print("-------------------------------------------------------------------------------------------") -# -# print("Noise Shape: {} | Latents Shape: {}".format(noise_latents.shape, latents.shape)) -# print("WarpedSamplerCustomBatch: Generating {} Frames in {} Latents....".format(num_frames, latents.shape[2])) -# -# samples = self.guider.sample(noise_latents, latents, self.sampler, self.sigmas, denoise_mask=noise_mask, callback=callback, disable_pbar=disable_pbar, seed=self.seed) -# samples = samples.to(mm.intermediate_device()) -# -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# if len(samples.shape) < 5: -# samples = samples.unsqueeze(0) -# -# samples = samples.clone().detach() / scaling_strength # (scaling_strength * vae_scaling_factor) -# -# print("WarpedSamplerCustomBatch: Decoding Latents...") -# decoded_images = self.decode_tiled(samples) -# -# if not is_dummy_section or (is_dummy_section and ((self.use_dummy_image == "all")) or self.gen_dummy_only): -# output_images.append(decoded_images) -# total_images_generated += decoded_images.shape[0] -# -# samples = None -# -# # output_images = self.process_skip_images(output_images, skip_frames) -# print("WarpedSamplerCustomBatch: Decoded Images Shape: {}".format(decoded_images.shape[0])) -# -# # if output_latents: -# # output_images_latents = self.encode_tiled(output_images) -# -# print("WarpedSamplerCustomBatch: Generating {} frames in {} latents...Done.".format(num_frames, latents.shape[2])) -# -# # if not is_i2v: -# # self.guider.model_patcher.model.to(get_offload_device()) -# # # guider.set_i2v_model() -# # -# # if not self.i2v_sigmas is None: -# # self.use_sigmas = self.i2v_sigmas -# -# if not is_last_section: -# print("HERE 9090000") -# decoded_tuple = torch.split(decoded_images, 1, dim=0) -# decoded_split = [item for item in decoded_tuple] -# decoded_images = decoded_images.to(get_offload_device()) -# decoded_images = None -# -# if (not is_dummy_section) or (is_dummy_section and ((self.use_dummy_image == "last") or (self.use_dummy_image == "all"))): -# print("HERE 9090000a") -# start_image = decoded_split[len(decoded_split) - 1].clone().detach() -# elif is_dummy_section: -# print("HERE 9090000b") -# if self.use_dummy_image == "first": -# print("HERE 9090000c") -# start_image = decoded_split[0].clone().detach() -# elif self.use_dummy_image == "middle": -# print("HERE 9090000d") -# start_image = decoded_split[int(len(decoded_split) // 2)].clone().detach() -# else: -# print("HERE 9090000e") -# random.seed(self.seed) -# start_image = dummy_split[random.randrange(0, len(decoded_split) - 1, 1)].clone().detach() -# -# is_i2v = True -# -# if last_image is None: -# last_image = start_image.clone().detach() -# -# print("HERE 9090001") -# -# samples = None -# latents = None -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# print("*******************************************") -# print("****** WarpedSamplerCustomBatch: Total Images Generated {}".format(total_images_generated)) -# print("*******************************************\n") -# -# generation_status = "****** WarpedSamplerCustomBatch: Total Images Generated {} ******".format(total_images_generated) -# -# interrupted = False -# -# print("HERE 9090002") -# -# if is_dummy_section: -# print("HERE 9090003") -# -# if self.gen_dummy_only: -# print("HERE 9090004") -# break -# -# print("HERE 9090005") -# -# is_dummy_section = False -# -# print("HERE 9090006") -# except mm.InterruptProcessingException as ie: -# interrupted = True -# print(f"\nWarpedSamplerCustomBatch: Processing Interrupted.") -# print("WarpedSamplerCustomBatch: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned.\n") -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# generation_status = f"\nWarpedSamplerCustomBatch: Processing Interrupted." -# -# traceback.print_tb(ie.__traceback__, limit=99, file=sys.stdout) -# -# raise mm.InterruptProcessingException(f"WarpedSamplerCustomBatch: Processing Interrupted.") -# -# except BaseException as e: -# print(f"\nWarpedSamplerCustomBatch: Exception During Processing: {str(e)}") -# print("WarpedSamplerCustomBatch: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned.\n") -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# generation_status = f"WarpedSamplerCustomBatch: Exception During Processing: {str(e)}" -# generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomBatch: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned.") -# -# traceback.print_tb(e.__traceback__, limit=99, file=sys.stdout) -# -# pass -# -# callback = None -# self.guider.model_patcher.model.to(get_offload_device()) -# -# latent = None -# latent_image = None -# noise_mask = None -# samples = None -# -# torch.cuda.empty_cache() -# torch.cuda.ipc_collect() -# gc.collect() -# time.sleep(1) -# -# mm.unload_all_models() -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(1) -# -# image = None -# -# if interrupted and (len(output_images) < 1): -# temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'yellow') -# image = pil2tensorSwap(temp_image) -# final_images = image -# elif (len(output_images) < 1): -# temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'red') -# image = pil2tensorSwap(temp_image) -# final_images = image -# else: -# final_images = self.assemble_final_result(output_images) -# -# if output_images_latents is None: -# output_images_latents = torch.zeros([1, 16, 1, self.height, self.width], dtype=torch.float32, device=self.offload_device) -# -# return (final_images, {"samples": output_images_latents}, self.seed, generation_status, last_image,) -# -# def assemble_final_result(self, image_batches): -# if self.blend_frames < 1: -# resulting_images = None -# for entry in image_batches: -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, entry), 0) -# else: -# resulting_images = entry -# -# entry.to(device=self.offload_device) -# entry = None -# else: -# blend_value = 1.0 / self.blend_frames -# i = 0 -# while i < (len(image_batches) - 1): -# alpha_blend_val = blend_value -# blend_count = self.blend_frames -# -# image_batches_tuple = torch.split(image_batches[i], 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image1 = image_batches_split[len(image_batches_split) - 1] -# # image1 = image_batches_split[len(image_batches_split) - 4] -# image_batches_tuple = None -# image_batches_split = None -# -# image_batches_tuple = torch.split(image_batches[i + 1], 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image2 = image_batches_split[0] -# image_batches_tuple = None -# image_batches_split = None -# -# image1 = tensor2pilSwap(image1)[0] -# image2 = tensor2pilSwap(image2)[0] -# -# blend_latents = None -# -# while blend_count > 0: -# blended_image = Image.blend(image1, image2, alpha_blend_val) -# temp_latent = pil2tensorSwap(blended_image) -# blended_image = None -# -# if len(temp_latent.shape) < 4: -# temp_latent = temp_latent.unsqueeze(0) -# -# if not blend_latents is None: -# blend_latents = torch.cat((blend_latents, temp_latent), 0) -# else: -# blend_latents = temp_latent -# -# alpha_blend_val += blend_value -# blend_count -= 1 -# -# image_batches_tuple = torch.split(image_batches[i], image_batches[i].shape[0] - 3, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# image_batches_tuple = None -# -# image_batches[i] = torch.cat((image_batches_split[0], blend_latents), 0) -# blend_latents = None -# image_batches_split = None -# -# self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) -# -# i += 1 -# -# resulting_images = None -# for entry in image_batches: -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, entry), 0) -# else: -# resulting_images = entry -# -# entry.to(device=self.offload_device) -# -# image_batches = None -# -# self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) -# -# -# print("assemble_final_result: Full decoded images count: {}".format(resulting_images.shape[0])) -# -# if self.skip_frames < 1: -# return resulting_images -# -# skipped_frames = 1 -# -# image_batches_tuple = torch.split(resulting_images, 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# -# resulting_images = None -# -# for image in image_batches_split: -# if skipped_frames <= self.skip_frames: -# skipped_frames += 1 -# continue -# -# if not resulting_images is None: -# resulting_images = torch.cat((resulting_images, image), 0) -# else: -# resulting_images = image -# -# print("assemble_final_result: Final decoded images count: {}".format(resulting_images.shape[0])) -# -# return resulting_images -# -# def cleanup(self, unload_models=False, cleanup_models=False, cleanup_cuda=False): -# if unload_models: -# mm.unload_all_models() -# -# if cleanup_models: -# mm.cleanup_models() -# -# if cleanup_cuda: -# mm.soft_empty_cache() -# -# gc.collect() -# time.sleep(1) -# -# return -# -# def generate_noise(self, input_latent, generator=None): -# latent_image = input_latent["samples"] -# return warped_prepare_noise(latent_image, self.seed, generator=generator) -# -# def setup_latent_noise(self): -# dummy_noise = None -# -# if self.gen_dummy: -# rnd = torch.Generator("cpu").manual_seed(self.seed) -# dummy_noise = torch.randn((1, 16, self.dummy_latents, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) -# -# noise = [] -# -# for i in range(self.batch_count): -# rnd = torch.Generator("cpu").manual_seed(self.seed) -# temp_noise = torch.randn((1, 16, self.latent_window_size, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) -# -# noise.append(temp_noise) -# temp_noise = None -# -# if self.verbose_messaging: -# if not dummy_noise is None: -# print("\nsetup_latent_noise: dummy_noise Shape: {}".format(dummy_noise.shape)) -# -# i = 0 -# for entry in noise: -# print("setup_latent_noise: Batch: {} | noise Shape: {}".format(i, entry.shape)) -# i += 1 -# -# print("\n") -# -# return noise, dummy_noise -# -# def get_latent_window_size(self, preferred_batch_size, frame_count, use_batch_size="next_lowest"): -# latent_size_factor = 4 -# -# if self.verbose_messaging: -# print("get_latent_window_size: preferred_batch_size: {}".format(preferred_batch_size)) -# print("get_latent_window_size: frame_count: {}".format(frame_count)) -# print("get_latent_window_size: use_batch_size: {}".format(use_batch_size)) -# -# num_frames = int(((frame_count - 1) // 4) * 4) + 1 -# -# if num_frames != frame_count: -# print(f"Truncating video from {frame_count} to {num_frames} an because odd number of frames is not allowed.") -# -# if ((num_frames - 1) % (preferred_batch_size - 1)) == 0: -# print("(1) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size))) -# print("(1) batch_count set to: {}".format(int((num_frames - 1) / (preferred_batch_size - 1)))) -# return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames - 1) / (preferred_batch_size - 1)), num_frames -# -# if use_batch_size == "exact": -# num_frames_final = int(((num_frames - 1) // (preferred_batch_size - 1)) + 1) * (preferred_batch_size - 1) -# -# if num_frames_final != frame_count: -# print(f"Truncating video from {num_frames} to {num_frames_final} frames for preferred_batch_size compatibility.") -# -# print("(2) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size + 1))) -# print("(2) batch_count set to: {}".format(int((num_frames_final - 1) / (preferred_batch_size - 1)))) -# return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames_final - 1) / (preferred_batch_size - 1)), num_frames_final -# -# next_lowest_found = False -# next_highest_found = False -# next_lowest = preferred_batch_size - 1 -# next_highest = preferred_batch_size - 1 -# -# if self.verbose_messaging: -# print("get_latent_window_size: Next Lowest Initialized To: {}".format(next_lowest)) -# print("get_latent_window_size: Next Highest Initialized To: {}".format(next_highest)) -# -# num_frames_final = int(((num_frames - 1) // 4) * 4) + 1 -# -# if num_frames != num_frames_final: -# print(f"Truncating video from {num_frames} to {num_frames_final} frames for latent_window_size compatibility.") -# -# if (use_batch_size == "closest") or (use_batch_size == "next_lowest"): -# while next_lowest >= 12: -# next_lowest -= 4 -# -# if (int((num_frames_final - 1) // 4) % next_lowest) == 0: -# next_lowest_found = True -# break -# -# next_lowest += 1 -# -# if next_lowest_found and (use_batch_size == "next_lowest"): -# print("(3) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) -# print("(3) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) -# return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final -# -# while next_highest <= 156: -# next_highest += 4 -# -# if (int((num_frames_final - 1) // 4) % next_highest) == 0: -# next_highest_found = True -# break -# -# if next_highest_found and (use_batch_size == "next_highest"): -# print("(4) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) -# print("(4) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) -# return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final -# -# if next_highest_found and next_lowest_found: -# if (preferred_batch_size - next_lowest) <= (next_highest - preferred_batch_size): -# print("(5) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) -# print("(5) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) -# return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final -# elif (next_highest - preferred_batch_size) < (preferred_batch_size - next_lowest): -# print("(6) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) -# print("(6) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) -# return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final -# -# print("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) -# print("Recalculating Number Of Frames Based On preferred_batch_size of: {}".format(preferred_batch_size)) -# -# return self.calculate_new_number_of_frames(preferred_batch_size, (((frame_count - 1) // 4) * 4) + 1, use_batch_size) -# -# def calculate_new_number_of_frames(self, preferred_batch_size, frame_count, use_batch_size): -# working_batch_size = preferred_batch_size - 1 -# working_frame_count = frame_count - 1 -# -# next_lowest = next_highest = working_frame_count -# next_lowest_found = False -# next_highest_found = False -# -# while next_lowest > 37: -# next_lowest -= 4 -# -# if int(next_lowest % working_batch_size) == 0: -# next_lowest_found = True -# break -# -# if next_lowest_found and (use_batch_size == "next_lowest"): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# while next_highest < 999997: -# next_highest += 4 -# -# if int(next_highest % working_batch_size) == 0: -# next_highest_found = True -# break -# -# if next_highest_found and (use_batch_size == "next_highest"): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# if next_lowest_found and next_highest_found: -# if (working_frame_count - next_lowest) <= (next_highest - working_frame_count): -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# if next_lowest_found: -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 -# -# if next_highest_found: -# return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 -# -# raise ValueError("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) -# -# def clip_vision_encode(self, image, crop="center"): -# crop_image = False -# if crop != "center": -# crop_image = False -# output = self.clip_vision.encode_image(image, crop=crop_image) -# return output -# -# def encoded_to_decoded_length(self, latent_length): -# if latent_length <= 0: -# return 0 -# -# result_length = ((latent_length - 1) * 4) + 1 -# -# return result_length -# -# def decoded_to_encoded_length(self, image_length): -# if image_length <= 0: -# return 0 -# -# result_length = int(((image_length - 1) / 4) + 1) -# -# return result_length -# -# def apply_flux_guidance(self, conditioning, guidance): -# c = node_helpers.conditioning_set_values(conditioning, {"guidance": guidance}) -# return c -# -# def hunyuan_text_encode(self, clip, clip_vision_output, prompt, image_interleave): -# tokens = clip.tokenize(prompt, llama_template=PROMPT_TEMPLATE_ENCODE_VIDEO_I2V, image_embeds=clip_vision_output.mm_projected, image_interleave=image_interleave) -# return clip.encode_from_tokens_scheduled(tokens) -# -# def hunyuan_encode(self, positive, vae, width, height, length, batch_size, guidance_type, start_image=None): -# latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) -# out_latent = {} -# -# if start_image is not None: -# start_image = comfy.utils.common_upscale(start_image[:length, :, :, :3].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) -# -# concat_latent_image = vae.encode(start_image) -# mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) -# mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 -# -# if guidance_type == "v1 (concat)": -# cond = {"concat_latent_image": concat_latent_image, "concat_mask": mask} -# elif guidance_type == "v2 (replace)": -# cond = {'guiding_frame_index': 0} -# latent[:, :, :concat_latent_image.shape[2]] = concat_latent_image -# out_latent["noise_mask"] = mask -# elif guidance_type == "custom": -# cond = {"ref_latent": concat_latent_image} -# -# positive = node_helpers.conditioning_set_values(positive, cond) -# -# out_latent["samples"] = latent -# return positive, out_latent -# -# def wan_text_encode(self, clip, positive_text="", negative_text=""): -# print("wan_text_encode: Loading clip model to device: {}".format(clip.patcher.load_device)) -# clip.patcher.model.to(device=clip.patcher.load_device) -# -# print("wan_text_encode: Encoding Prompts...") -# positive_conditioning = self.do_text_encode(clip, positive_text) -# negative_conditioning = self.do_text_encode(clip, negative_text) -# print("wan_text_encode: Encoding Prompts...Done.") -# -# print("wan_text_encode: Unloading clip model to device: {}".format(get_offload_device())) -# clip.patcher.model.to(device=get_offload_device()) -# -# if torch.cuda.is_available(): -# torch.cuda.empty_cache() -# -# gc.collect() -# time.sleep(1) -# -# return positive_conditioning, negative_conditioning -# -# def encode(self, clip, text): -# if clip is None: -# raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") -# tokens = clip.tokenize(text) -# return clip.encode_from_tokens_scheduled(tokens) -# -# def do_text_encode(self, clip, text): -# -# if clip is None: -# raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") -# -# tokens = clip.tokenize(text) -# return_encoding = clip.encode_from_tokens_scheduled(tokens) -# -# return return_encoding -# -# def wan_encode(self, positive, negative, vae, width, height, length, batch_size, start_image=None, clip_vision_output=None): -# latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) -# if start_image is not None: -# start_image = comfy.utils.common_upscale(start_image[:length].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) -# image = torch.mul(torch.ones((length, height, width, start_image.shape[-1]), device=start_image.device, dtype=start_image.dtype), 0.5) -# image[:start_image.shape[0]] = start_image -# -# concat_latent_image = vae.encode(image[:, :, :, :3]) -# -# mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) -# mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 -# -# positive = node_helpers.conditioning_set_values(positive, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) -# negative = node_helpers.conditioning_set_values(negative, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) -# -# if clip_vision_output is not None: -# positive = node_helpers.conditioning_set_values(positive, {"clip_vision_output": clip_vision_output}) -# negative = node_helpers.conditioning_set_values(negative, {"clip_vision_output": clip_vision_output}) -# -# out_latent = {} -# out_latent["samples"] = latent -# return positive, negative, out_latent -# -# def process_skip_images(self, frames, skip_count): -# if len(frames.shape) < 4: -# frames = frames.unsqueeze(0) -# -# num_frames = frames.shape[0] -# -# image_batches_tuple = torch.split(frames, 1, dim=0) -# image_batches_split = [item for item in image_batches_tuple] -# -# new_video = None -# i = 0 -# -# while i < len(image_batches_split): -# if i < skip_count: -# i += 1 -# continue -# -# if not new_video is None: -# new_video = torch.cat((new_video, image_batches_split[i]), 0) -# else: -# new_video = image_batches_split[i] -# -# i += 1 -# -# return new_video -# -# def get_blank_image(self, length=1): -# new_image = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) -# return new_image -# -# def get_new_noise(self, length): -# new_noise = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) -# -# new_noise = self.encode_tiled(new_noise) -# -# new_noise = comfy.sample.fix_empty_latent_channels(self.guider.model_patcher, new_noise) -# -# if len(new_noise) < 5: -# new_latent = new_noise.unsqueeze(0) -# -# new_noise = self.generate_noise({"samples": new_noise}) -# -# return new_noise -# -# def pad_noise(self, latent, num_frames=1): -# pad_frames = torch.zeros([1, 16, num_frames, self.height, self.width], dtype=torch.float32, device=self.offload_device) -# pad_frames = torch.cat((latent, pad_frames), 2) -# -# return pad_frames -# -# def setup_callbacks(self): -# callback = latent_preview.prepare_callback(self.guider.model_patcher, self.sigmas.shape[-1] - 1, self.g_output) -# -# return callback -# -# def decode_tiled(self, latents): -# decoded_data = partial_decode_tiled(self.vae, latents, self.dec_tile_size, self.dec_overlap, self.dec_temporal_size, self.dec_temporal_overlap) -# -# if len(decoded_data.shape) < 4: -# decoded_data.unsqueeze(0) -# -# return decoded_data -# -# def initialize_noise(self, frame_count, clear_cache=True): -# noise_latents_full = torch.zeros([1, 16, int(frame_count), self.height, self.width], dtype=torch.float32, device=self.offload_device) -# print("WarpedSamplerCustomBatch: Encoded noise_latents_full Shape: {}".format(noise_latents_full.shape)) -# -# if Decimal(self.noise_scale).compare(Decimal(0.00)) != 0: -# noise_latents_full = warped_prepare_noise(noise_latents_full, self.seed) -# print("WarpedSamplerCustomBatch: noise_latents_full Shape: {}".format(noise_latents_full.shape)) -# -# noise_latents_full = torch.mul(noise_latents_full, self.noise_scale) -# -# if len(noise_latents_full.shape) < 5: -# noise_latents_full.unsqueeze(0) -# -# noise_latents_full = noise_latents_full.to(dtype=torch.float32, device=self.offload_device) -# -# if clear_cache: -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# return noise_latents_full -# -# def initialize_frames(self, latents): -# if len(latents.shape) < 5: -# latents = latents.unsqueeze(0) -# -# print("WarpedSamplerCustomBatch: Encoded latents_full Shape: {}".format(latents.shape)) -# latents_full = latents.clone().detach() -# latents_full = latents_full.to(dtype=torch.float32, device=self.offload_device) -# -# noise_latents_full = self.initialize_noise(latents_full.shape[2]) -# -# mm.soft_empty_cache() -# gc.collect() -# time.sleep(0.1) -# -# return noise_latents_full + print("latents Shape: {}".format(latents.shape)) + + num_frames = int(((latents.shape[2] - 1) * 4) + 1) + + print("\nDecoded Width is {} | Decoded Height is {}".format(int(self.width * 8), int(self.height * 8))) + + print("-------------------------------------------------------------------------------------------") + print("WarpedSamplerCustomScripted: Latents Shape: {} | Noise Latents Shape: {}".format(latents.shape, noise_latents.shape)) + print("-------------------------------------------------------------------------------------------") + + print("Noise Shape: {} | Latents Shape: {}".format(noise_latents.shape, latents.shape)) + print("WarpedSamplerCustomScripted: Generating {} Frames in {} Latents....".format(num_frames, latents.shape[2])) + + samples = self.guider.sample(noise_latents, latents, self.sampler, self.use_sigmas, denoise_mask=noise_mask, callback=callback, disable_pbar=disable_pbar, seed=self.seed) + samples = samples.to(mm.intermediate_device()) + + mm.unload_all_models() + mm.soft_empty_cache() + gc.collect() + time.sleep(1) + + if len(samples.shape) < 5: + samples = samples.unsqueeze(0) + + samples = samples.clone().detach() / scaling_strength # (scaling_strength * vae_scaling_factor) + + print("WarpedSamplerCustomScripted: Decoding Latents...") + decoded_images = self.decode_tiled(samples) + + if not is_dummy_section or (is_dummy_section and ((self.use_dummy_image == "all") or self.gen_dummy_only)): + output_images.append(decoded_images) + total_images_generated += decoded_images.shape[0] + valid_output = True + + samples = None + + # output_images = self.process_skip_images(output_images, skip_frames) + print("WarpedSamplerCustomScripted: Decoded Images Shape: {}".format(decoded_images.shape[0])) + + # if output_latents: + # output_images_latents = self.encode_tiled(output_images) + + print("WarpedSamplerCustomScripted: Generating {} frames in {} latents...Done.".format(num_frames, latents.shape[2])) + + if not is_i2v: + if not self.secondary_model is None: + self.guider.model_patcher.model.to(get_offload_device()) + + if not self.secondary_sigmas is None: + self.use_sigmas = self.secondary_sigmas + + if not is_last_section: + decoded_tuple = torch.split(decoded_images, 1, dim=0) + decoded_split = [item for item in decoded_tuple] + decoded_images = decoded_images.to(get_offload_device()) + decoded_images = None + + if (not is_dummy_section) or (is_dummy_section and ((self.use_dummy_image == "last") or (self.use_dummy_image == "all"))): + start_image = decoded_split[len(decoded_split) - 1].clone().detach() + elif is_dummy_section: + if self.use_dummy_image == "first": + start_image = decoded_split[0].clone().detach() + elif self.use_dummy_image == "middle": + start_image = decoded_split[int(len(decoded_split) // 2)].clone().detach() + else: + random.seed(self.seed) + start_image = dummy_split[random.randrange(0, len(decoded_split) - 1, 1)].clone().detach() + + is_i2v = True + + if last_image is None: + last_image = start_image.clone().detach() + + samples = None + latents = None + + mm.soft_empty_cache() + gc.collect() + time.sleep(0.1) + + print("*******************************************") + print("****** WarpedSamplerCustomScripted: Total Images Generated {}".format(total_images_generated)) + print("*******************************************\n") + + generation_status = "****** WarpedSamplerCustomScripted: Total Images Generated {} ******".format(total_images_generated) + + interrupted = False + + if is_dummy_section: + if self.gen_dummy_only: + break + + is_dummy_section = False + except mm.InterruptProcessingException as ie: + interrupted = True + print(f"\nWarpedSamplerCustomScripted: Processing Interrupted.") + print("WarpedSamplerCustomScripted: Returning only partial results (if any).\n If zero images generated, a blank yellow image will be returned, and valid_output will return False.\n") + mm.unload_all_models() + mm.soft_empty_cache() + gc.collect() + time.sleep(1) + + generation_status = f"\nWarpedSamplerCustomScripted: Processing Interrupted." + + traceback.print_tb(ie.__traceback__, limit=99, file=sys.stdout) + + # raise mm.InterruptProcessingException(f"WarpedSamplerCustomScripted: Processing Interrupted.") + pass + + except BaseException as e: + print(f"\nWarpedSamplerCustomScripted: Exception During Processing: {str(e)}") + print("WarpedSamplerCustomScripted: Returning only partial results (if any).\n If zero images generated, a blank red image will be returned, and valid_output will return False.\n") + mm.unload_all_models() + mm.soft_empty_cache() + gc.collect() + time.sleep(1) + + generation_status = f"WarpedSamplerCustomScripted: Exception During Processing: {str(e)}" + generation_status = "{}{}".format(generation_status, "WarpedSamplerCustomScripted: Returning only partial results (if any).\nIf zero images generated, a blank red image will be returned, and valid_output will return False.") + + traceback.print_tb(e.__traceback__, limit=99, file=sys.stdout) + + pass + + callback = None + self.guider.model_patcher.model.to(get_offload_device()) + + latent = None + latent_image = None + noise_mask = None + samples = None + + torch.cuda.empty_cache() + torch.cuda.ipc_collect() + gc.collect() + time.sleep(1) + + mm.unload_all_models() + mm.soft_empty_cache() + gc.collect() + time.sleep(1) + + image = None + + if interrupted and not valid_output: + temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'yellow') + image = pil2tensorSwap(temp_image) + final_images = image + elif not valid_output: + temp_image = Image.new('RGB', (self.width * 8, self.height * 8), color = 'red') + image = pil2tensorSwap(temp_image) + final_images = image + else: + final_images = self.assemble_final_result(output_images) + + if output_images_latents is None: + output_images_latents = torch.zeros([1, 16, 1, self.height, self.width], dtype=torch.float32, device=self.offload_device) + + return (final_images, {"samples": output_images_latents}, self.seed, generation_status, last_image, valid_output,) + + def assemble_final_result(self, image_batches): + if self.blend_frames < 1: + resulting_images = None + for entry in image_batches: + if not resulting_images is None: + resulting_images = torch.cat((resulting_images, entry), 0) + else: + resulting_images = entry + + entry.to(device=self.offload_device) + entry = None + else: + blend_value = 1.0 / self.blend_frames + i = 0 + while i < (len(image_batches) - 1): + alpha_blend_val = blend_value + blend_count = self.blend_frames + + image_batches_tuple = torch.split(image_batches[i], 1, dim=0) + image_batches_split = [item for item in image_batches_tuple] + image1 = image_batches_split[len(image_batches_split) - 1] + # image1 = image_batches_split[len(image_batches_split) - 4] + image_batches_tuple = None + image_batches_split = None + + image_batches_tuple = torch.split(image_batches[i + 1], 1, dim=0) + image_batches_split = [item for item in image_batches_tuple] + image2 = image_batches_split[0] + image_batches_tuple = None + image_batches_split = None + + image1 = tensor2pilSwap(image1)[0] + image2 = tensor2pilSwap(image2)[0] + + blend_latents = None + + while blend_count > 0: + blended_image = Image.blend(image1, image2, alpha_blend_val) + temp_latent = pil2tensorSwap(blended_image) + blended_image = None + + if len(temp_latent.shape) < 4: + temp_latent = temp_latent.unsqueeze(0) + + if not blend_latents is None: + blend_latents = torch.cat((blend_latents, temp_latent), 0) + else: + blend_latents = temp_latent + + alpha_blend_val += blend_value + blend_count -= 1 + + image_batches_tuple = torch.split(image_batches[i], image_batches[i].shape[0] - 3, dim=0) + image_batches_split = [item for item in image_batches_tuple] + image_batches_tuple = None + + image_batches[i] = torch.cat((image_batches_split[0], blend_latents), 0) + blend_latents = None + image_batches_split = None + + self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) + + i += 1 + + resulting_images = None + for entry in image_batches: + if not resulting_images is None: + resulting_images = torch.cat((resulting_images, entry), 0) + else: + resulting_images = entry + + entry.to(device=self.offload_device) + + image_batches = None + + self.cleanup(unload_models=False, cleanup_models=False, cleanup_cuda=True) + + + print("assemble_final_result: Full decoded images count: {}".format(resulting_images.shape[0])) + + if self.skip_frames < 1: + return resulting_images + + skipped_frames = 1 + + image_batches_tuple = torch.split(resulting_images, 1, dim=0) + image_batches_split = [item for item in image_batches_tuple] + + resulting_images = None + + for image in image_batches_split: + if skipped_frames <= self.skip_frames: + skipped_frames += 1 + continue + + if not resulting_images is None: + resulting_images = torch.cat((resulting_images, image), 0) + else: + resulting_images = image + + print("assemble_final_result: Final decoded images count: {}".format(resulting_images.shape[0])) + + return resulting_images + + def cleanup(self, unload_models=False, cleanup_models=False, cleanup_cuda=False): + if unload_models: + mm.unload_all_models() + + if cleanup_models: + mm.cleanup_models() + + if cleanup_cuda: + mm.soft_empty_cache() + + gc.collect() + time.sleep(1) + + return + + def generate_noise(self, input_latent, generator=None): + latent_image = input_latent["samples"] + return warped_prepare_noise(latent_image, self.seed, generator=generator) + + def setup_latent_noise(self): + dummy_noise = None + + if self.gen_dummy: + rnd = torch.Generator("cpu").manual_seed(self.seed) + dummy_noise = torch.randn((1, self.latent_depth, self.dummy_latents, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) + + noise = [] + + for i in range(self.batch_count): + rnd = torch.Generator("cpu").manual_seed(self.seed) + temp_noise = torch.randn((1, self.latent_depth, self.latent_window_size, self.height, self.width), generator=rnd, device=rnd.device).to(device=rnd.device, dtype=torch.float32) + + noise.append(temp_noise) + temp_noise = None + + if self.verbose_messaging: + if not dummy_noise is None: + print("\nsetup_latent_noise: dummy_noise Shape: {}".format(dummy_noise.shape)) + + i = 0 + for entry in noise: + print("setup_latent_noise: Batch: {} | noise Shape: {}".format(i, entry.shape)) + i += 1 + + print("\n") + + return noise, dummy_noise + + def get_latent_window_size(self, preferred_batch_size, frame_count, use_batch_size="next_lowest"): + latent_size_factor = 4 + + if self.verbose_messaging: + print("get_latent_window_size: preferred_batch_size: {}".format(preferred_batch_size)) + print("get_latent_window_size: frame_count: {}".format(frame_count)) + print("get_latent_window_size: use_batch_size: {}".format(use_batch_size)) + + num_frames = int(((frame_count - 1) // 4) * 4) + 1 + + if num_frames != frame_count: + print(f"Truncating video from {frame_count} to {num_frames} an because odd number of frames is not allowed.") + + if ((num_frames - 1) % (preferred_batch_size - 1)) == 0: + print("(1) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size))) + print("(1) batch_count set to: {}".format(int((num_frames - 1) / (preferred_batch_size - 1)))) + return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames - 1) / (preferred_batch_size - 1)), num_frames + + if use_batch_size == "exact": + num_frames_final = int(((num_frames - 1) // (preferred_batch_size - 1)) + 1) * (preferred_batch_size - 1) + + if num_frames_final != frame_count: + print(f"Truncating video from {num_frames} to {num_frames_final} frames for preferred_batch_size compatibility.") + + print("(2) latent_window_size set to: {}".format(self.decoded_to_encoded_length(preferred_batch_size + 1))) + print("(2) batch_count set to: {}".format(int((num_frames_final - 1) / (preferred_batch_size - 1)))) + return self.decoded_to_encoded_length(preferred_batch_size), int((num_frames_final - 1) / (preferred_batch_size - 1)), num_frames_final + + next_lowest_found = False + next_highest_found = False + next_lowest = preferred_batch_size - 1 + next_highest = preferred_batch_size - 1 + + if self.verbose_messaging: + print("get_latent_window_size: Next Lowest Initialized To: {}".format(next_lowest)) + print("get_latent_window_size: Next Highest Initialized To: {}".format(next_highest)) + + num_frames_final = int(((num_frames - 1) // 4) * 4) + 1 + + if num_frames != num_frames_final: + print(f"Truncating video from {num_frames} to {num_frames_final} frames for latent_window_size compatibility.") + + if (use_batch_size == "closest") or (use_batch_size == "next_lowest"): + while next_lowest >= 12: + next_lowest -= 4 + + if (int((num_frames_final - 1) // 4) % next_lowest) == 0: + next_lowest_found = True + break + + next_lowest += 1 + + if next_lowest_found and (use_batch_size == "next_lowest"): + print("(3) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) + print("(3) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) + return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final + + while next_highest <= 156: + next_highest += 4 + + if (int((num_frames_final - 1) // 4) % next_highest) == 0: + next_highest_found = True + break + + if next_highest_found and (use_batch_size == "next_highest"): + print("(4) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) + print("(4) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) + return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final + + if next_highest_found and next_lowest_found: + if (preferred_batch_size - next_lowest) <= (next_highest - preferred_batch_size): + print("(5) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_lowest + 1))) + print("(5) batch_count set to: {}".format(int((num_frames_final - 1) / next_lowest))) + return self.decoded_to_encoded_length(next_lowest + 1), int((num_frames_final - 1) / next_lowest), num_frames_final + elif (next_highest - preferred_batch_size) < (preferred_batch_size - next_lowest): + print("(6) latent_window_size set to: {}".format(self.decoded_to_encoded_length(next_highest + 1))) + print("(6) batch_count set to: {}".format(int((num_frames_final - 1) / next_highest))) + return self.decoded_to_encoded_length(next_highest + 1), int((num_frames_final - 1) / next_highest), num_frames_final + + print("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) + print("Recalculating Number Of Frames Based On preferred_batch_size of: {}".format(preferred_batch_size)) + + return self.calculate_new_number_of_frames(preferred_batch_size, (((frame_count - 1) // 4) * 4) + 1, use_batch_size) + + def calculate_new_number_of_frames(self, preferred_batch_size, frame_count, use_batch_size): + working_batch_size = preferred_batch_size - 1 + working_frame_count = frame_count - 1 + + next_lowest = next_highest = working_frame_count + next_lowest_found = False + next_highest_found = False + + while next_lowest > 37: + next_lowest -= 4 + + if int(next_lowest % working_batch_size) == 0: + next_lowest_found = True + break + + if next_lowest_found and (use_batch_size == "next_lowest"): + return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 + + while next_highest < 999997: + next_highest += 4 + + if int(next_highest % working_batch_size) == 0: + next_highest_found = True + break + + if next_highest_found and (use_batch_size == "next_highest"): + return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 + + if next_lowest_found and next_highest_found: + if (working_frame_count - next_lowest) <= (next_highest - working_frame_count): + return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 + + return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 + + if next_lowest_found: + return self.decoded_to_encoded_length(preferred_batch_size), int(next_lowest // working_batch_size), next_lowest + 1 + + if next_highest_found: + return self.decoded_to_encoded_length(preferred_batch_size), int(next_highest // working_batch_size), next_highest + 1 + + raise ValueError("Unable to find a compatible latent_window_size for number of frames = {} and preferred_batch_size = {}.".format(frame_count, preferred_batch_size)) + + def clip_vision_encode(self, image, crop="center"): + crop_image = False + if crop != "center": + crop_image = False + output = self.clip_vision.encode_image(image, crop=crop_image) + return output + + def encoded_to_decoded_length(self, latent_length): + if latent_length <= 0: + return 0 + + result_length = ((latent_length - 1) * 4) + 1 + + return result_length + + def decoded_to_encoded_length(self, image_length): + if image_length <= 0: + return 0 + + result_length = int(((image_length - 1) / 4) + 1) + + return result_length + + def apply_flux_guidance(self, conditioning, guidance): + c = node_helpers.conditioning_set_values(conditioning, {"guidance": guidance}) + return c + + def hunyuan_text_encode(self, clip, clip_vision_output, prompt, image_interleave): + tokens = clip.tokenize(prompt, llama_template=PROMPT_TEMPLATE_ENCODE_VIDEO_I2V, image_embeds=clip_vision_output.mm_projected, image_interleave=image_interleave) + return clip.encode_from_tokens_scheduled(tokens) + + def hunyuan_encode(self, positive, vae, width, height, length, batch_size, guidance_type, start_image=None): + latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) + out_latent = {} + + if start_image is not None: + start_image = comfy.utils.common_upscale(start_image[:length, :, :, :3].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) + + concat_latent_image = vae.encode(start_image) + mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) + mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 + + if guidance_type == "v1 (concat)": + cond = {"concat_latent_image": concat_latent_image, "concat_mask": mask} + elif guidance_type == "v2 (replace)": + cond = {'guiding_frame_index': 0} + latent[:, :, :concat_latent_image.shape[2]] = concat_latent_image + out_latent["noise_mask"] = mask + elif guidance_type == "custom": + cond = {"ref_latent": concat_latent_image} + + positive = node_helpers.conditioning_set_values(positive, cond) + + out_latent["samples"] = latent + return positive, out_latent + + def wan_text_encode(self, clip, positive_text="", negative_text=""): + print("wan_text_encode: Loading clip model to device: {}".format(clip.patcher.load_device)) + clip.patcher.model.to(device=clip.patcher.load_device) + + print("wan_text_encode: Encoding Prompts...") + positive_conditioning = self.do_text_encode(clip, positive_text) + negative_conditioning = self.do_text_encode(clip, negative_text) + print("wan_text_encode: Encoding Prompts...Done.") + + print("wan_text_encode: Unloading clip model to device: {}".format(get_offload_device())) + clip.patcher.model.to(device=get_offload_device()) + + if torch.cuda.is_available(): + torch.cuda.empty_cache() + + gc.collect() + time.sleep(1) + + return positive_conditioning, negative_conditioning + + def wan_encode_image(self, vae, width, height, length, batch_size, start_image=None): + latent = torch.zeros([1, self.latent_depth, ((length - 1) // 4) + 1, height // 16, width // 16], device=comfy.model_management.intermediate_device()) + + if start_image is None: + out_latent = {} + out_latent["samples"] = latent + return out_latent + + mask = torch.ones([latent.shape[0], 1, ((length - 1) // 4) + 1, latent.shape[-2], latent.shape[-1]], device=comfy.model_management.intermediate_device()) + + if start_image is not None: + start_image = comfy.utils.common_upscale(start_image[:length].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) + latent_temp = vae.encode(start_image) + latent[:, :, :latent_temp.shape[-3]] = latent_temp + mask[:, :, :latent_temp.shape[-3]] *= 0.0 + + out_latent = {} + latent_format = comfy.latent_formats.Wan22() + latent = latent_format.process_out(latent) * mask + latent * (1.0 - mask) + out_latent["samples"] = latent.repeat((batch_size, ) + (1,) * (latent.ndim - 1)) + out_latent["noise_mask"] = mask.repeat((batch_size, ) + (1,) * (mask.ndim - 1)) + + return out_latent + + + def encode(self, clip, text): + if clip is None: + raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") + tokens = clip.tokenize(text) + return clip.encode_from_tokens_scheduled(tokens) + + def do_text_encode(self, clip, text): + + if clip is None: + raise RuntimeError("ERROR: clip input is invalid: None\n\nIf the clip is from a checkpoint loader node your checkpoint does not contain a valid clip or text encoder model.") + + tokens = clip.tokenize(text) + return_encoding = clip.encode_from_tokens_scheduled(tokens) + + return return_encoding + + def wan_encode(self, positive, negative, vae, width, height, length, batch_size, start_image=None, clip_vision_output=None): + if self.mode == "Wan 2.1" or self.mode == "Wan 2.2 Standard": + latent = torch.zeros([batch_size, 16, ((length - 1) // 4) + 1, height // 8, width // 8], device=comfy.model_management.intermediate_device()) + if start_image is not None: + start_image = comfy.utils.common_upscale(start_image[:length].movedim(-1, 1), width, height, "bilinear", "center").movedim(1, -1) + image = torch.mul(torch.ones((length, height, width, start_image.shape[-1]), device=start_image.device, dtype=start_image.dtype), 0.5) + image[:start_image.shape[0]] = start_image + + concat_latent_image = vae.encode(image[:, :, :, :3]) + + mask = torch.ones((1, 1, latent.shape[2], concat_latent_image.shape[-2], concat_latent_image.shape[-1]), device=start_image.device, dtype=start_image.dtype) + mask[:, :, :((start_image.shape[0] - 1) // 4) + 1] = 0.0 + + positive = node_helpers.conditioning_set_values(positive, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) + negative = node_helpers.conditioning_set_values(negative, {"concat_latent_image": concat_latent_image, "concat_mask": mask}) + + if clip_vision_output is not None: + positive = node_helpers.conditioning_set_values(positive, {"clip_vision_output": clip_vision_output}) + negative = node_helpers.conditioning_set_values(negative, {"clip_vision_output": clip_vision_output}) + + out_latent = {} + out_latent["samples"] = latent + else: + out_latent = self.wan_encode_image(vae, width, height, length, batch_size, start_image) + + return positive, negative, out_latent + + def process_skip_images(self, frames, skip_count): + if len(frames.shape) < 4: + frames = frames.unsqueeze(0) + + num_frames = frames.shape[0] + + image_batches_tuple = torch.split(frames, 1, dim=0) + image_batches_split = [item for item in image_batches_tuple] + + new_video = None + i = 0 + + while i < len(image_batches_split): + if i < skip_count: + i += 1 + continue + + if not new_video is None: + new_video = torch.cat((new_video, image_batches_split[i]), 0) + else: + new_video = image_batches_split[i] + + i += 1 + + return new_video + + def get_blank_image(self, length=1): + new_image = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) + return new_image + + def get_new_noise(self, length): + new_noise = torch.zeros([length, self.height, self.width, 3], dtype=torch.float32, device=self.offload_device) + + new_noise = self.encode_tiled(new_noise) + + new_noise = comfy.sample.fix_empty_latent_channels(self.guider.model_patcher, new_noise) + + if len(new_noise) < 5: + new_latent = new_noise.unsqueeze(0) + + new_noise = self.generate_noise({"samples": new_noise}) + + return new_noise + + def pad_noise(self, latent, num_frames=1): + pad_frames = torch.zeros([1, 16, num_frames, self.height, self.width], dtype=torch.float32, device=self.offload_device) + pad_frames = torch.cat((latent, pad_frames), 2) + + return pad_frames + + def setup_callbacks(self): + callback = latent_preview.prepare_callback(self.guider.model_patcher, self.sigmas.shape[-1] - 1, self.g_output) + + return callback + + def decode_tiled(self, latents): + decoded_data = partial_decode_tiled(self.vae, latents, self.dec_tile_size, self.dec_overlap, self.dec_temporal_size, self.dec_temporal_overlap) + + if len(decoded_data.shape) < 4: + decoded_data.unsqueeze(0) + + return decoded_data + + def initialize_noise(self, frame_count, clear_cache=True): + noise_latents_full = torch.zeros([1, 16, int(frame_count), self.height, self.width], dtype=torch.float32, device=self.offload_device) + print("WarpedSamplerCustomScripted: Encoded noise_latents_full Shape: {}".format(noise_latents_full.shape)) + + if Decimal(self.noise_scale).compare(Decimal(0.00)) != 0: + noise_latents_full = warped_prepare_noise(noise_latents_full, self.seed) + print("WarpedSamplerCustomScripted: noise_latents_full Shape: {}".format(noise_latents_full.shape)) + + noise_latents_full = torch.mul(noise_latents_full, self.noise_scale) + + if len(noise_latents_full.shape) < 5: + noise_latents_full.unsqueeze(0) + + noise_latents_full = noise_latents_full.to(dtype=torch.float32, device=self.offload_device) + + if clear_cache: + mm.soft_empty_cache() + gc.collect() + time.sleep(0.1) + + return noise_latents_full + + def initialize_frames(self, latents): + if len(latents.shape) < 5: + latents = latents.unsqueeze(0) + + print("WarpedSamplerCustomScripted: Encoded latents_full Shape: {}".format(latents.shape)) + latents_full = latents.clone().detach() + latents_full = latents_full.to(dtype=torch.float32, device=self.offload_device) + + noise_latents_full = self.initialize_noise(latents_full.shape[2]) + + mm.soft_empty_cache() + gc.collect() + time.sleep(0.1) + + return noise_latents_full def sd3_patch(model, shift, multiplier=1000): m = model.clone() @@ -7863,7 +6100,6 @@ class WarpedHunyuanMultiLoraLoader: # Load the LoRA weights lora_weights = utils.load_torch_file(lora_path) - lora_weights = convert_lora(lora_weights, convert_to="diffusion_model") # Filter the LoRA weights based on the block type @@ -7906,6 +6142,12 @@ class WarpedHunyuanMultiLoraLoader: if filtered_lora: model, _ = load_lora_for_models(model, None, filtered_lora, temp_strength, 0) + # print("\n\nmodel.model:") + # print(model.model) + # print("\n\nmodel:") + # print(model) + # print("\n\n") + return (model, lora_metadata, ) @classmethod @@ -8247,6 +6489,70 @@ class WarpedHunyuanLoraConvertKeys: return {"ui": {"tags": [save_message]}} +# class WarpedHunyuanLoraConvertKeys2: +# def __init__(self): +# self.base_output_dir = get_default_output_folder() +# os.makedirs(self.base_output_dir, exist_ok = True) +# +# @classmethod +# def INPUT_TYPES(s): +# return { +# "required": { +# "save_path": ("STRING", {"default": get_default_output_path()}), +# "lora": (get_lora_list(),), +# "convert_to": (["diffusion_model", "transformer", "framepack"], {"default": "diffusion_model"}), +# "save_metadata": ("BOOLEAN", {"default": True}), +# }, +# } +# +# RETURN_TYPES = () +# OUTPUT_NODE = True +# OUTPUT_IS_LIST = (True,) +# FUNCTION = "convert_lora" +# CATEGORY = "Warped/Hunyuan/Lora" +# DESCRIPTION = "Convert Keys For Hunyuan LORA and Save Modified LORA." +# +# def load_lora(self, lora_name: str) -> Tuple[Dict[str, torch.Tensor],]: +# """Load and filter a single LoRA model.""" +# if not lora_name: +# return {} +# +# # Get the full path to the LoRA file +# lora_path = folder_paths.get_full_path("loras", lora_name) +# if not os.path.exists(lora_path): +# raise ValueError(f"LoRA file not found: {lora_path}") +# +# # Load the LoRA weights +# lora_weights = utils.load_torch_file(lora_path) +# +# return lora_weights +# +# def convert_lora(self, save_path, lora, convert_to, save_metadata=True): +# metadata = {"original_lora": "{}".format(lora)} +# +# # Load the LoRA weights +# temp_lora = self.load_lora(lora) +# +# if convert_to != "framepack": +# new_lora = convert_lora(temp_lora, convert_to=convert_to) +# else: +# new_lora = convert_lora(temp_lora, convert_to="diffusion_model") +# +# for key in new_lora.keys(): +# print("LORA Key: {}".format(key)) +# +# if not save_metadata: +# metadata = None +# +# if len(new_lora) < 1: +# utils.save_torch_file(temp_lora, save_path, metadata=metadata) +# else: +# utils.save_torch_file(new_lora, save_path, metadata=metadata) +# +# save_message = "Weights Saved To: {}".format(save_path) +# +# return {"ui": {"tags": [save_message]}} + class WarpedLoraKeysAndMetadataReader: def __init__(self): pass @@ -8486,8 +6792,8 @@ class WarpedFramepackSampler: } } - RETURN_TYPES = ("IMAGE", "STRING", "INT", ) - RETURN_NAMES = ("images", "generation_status", "seed", ) + RETURN_TYPES = ("IMAGE", "STRING", "INT", "BOOLEAN",) + RETURN_NAMES = ("images", "generation_status", "seed", "valid_output",) FUNCTION = "process" CATEGORY = "Warped/Framepack/Sampling" @@ -8723,6 +7029,7 @@ class WarpedFramepackSampler: dummy_images = None dummy_gen_latents = None generated_image_batches = [] + valid_output = False self.cleanup(unload_models=True, cleanup_models=False, cleanup_cuda=True) @@ -8843,6 +7150,7 @@ class WarpedFramepackSampler: decoded_images = partial_decode_tiled(self.vae, generated_latents.clone().detach() / vae_scaling_factor, self.dec_tile_size, self.dec_overlap, self.dec_temporal_size, self.dec_temporal_overlap) generated_image_batches.append(decoded_images.clone().detach()) + valid_output = True decoded_tuple = torch.split(decoded_images, 1, dim=0) decoded_split = [item for item in decoded_tuple] @@ -8888,8 +7196,9 @@ class WarpedFramepackSampler: dummy_images = dummy_decoded.clone().detach() - if self.use_dummy_image == "all": + if (self.use_dummy_image == "all") or self.gen_dummy_only: generated_image_batches.append(dummy_images) + valid_output = True if not self.gen_dummy_only: dummy_tuple = torch.split(dummy_decoded, 1, dim=0) @@ -9000,7 +7309,7 @@ class WarpedFramepackSampler: if self.verbose_messaging: print("output_images Shape: {}".format(output_images.shape)) - return (output_images, generation_status, self.seed, ) + return (output_images, generation_status, self.seed, valid_output,) def process_v2v(self, video_image_batch): if len(video_image_batch.shape) < 4: @@ -9059,6 +7368,7 @@ class WarpedFramepackSampler: generation_status = "" temp_history_latents = None original_history_latents = None + valid_output = False self.cleanup(unload_models=True, cleanup_models=False, cleanup_cuda=True) @@ -9153,6 +7463,7 @@ class WarpedFramepackSampler: print("generated_latents for batch {}: Shape: {}\n".format(latent_padding, generated_latents.shape)) latent_batches_gend.append(generated_latents.clone().detach() / vae_scaling_factor) + valid_output = True total_generated_latent_frames += int(generated_latents.shape[2]) generated_latents.to(dtype=torch.float32, device=self.offload_device) @@ -9248,7 +7559,7 @@ class WarpedFramepackSampler: if self.verbose_messaging: print("output_images Shape: {}".format(output_images.shape)) - return (output_images, generation_status, self.seed, ) + return (output_images, generation_status, self.seed, valid_output,) def generate_video(self, width, height, num_frames, seed_generator, noise_latent, llama_vec, llama_attention_mask, clip_l_pooler, llama_vec_n, llama_attention_mask_n, clip_l_pooler_n, image_encoder_last_hidden_state, latent_indices, clean_latents, clean_latent_indices, clean_latents_2x, clean_latent_2x_indices, clean_latents_4x, clean_latent_4x_indices, callback): @@ -10182,33 +8493,6 @@ class WarpedDualEncoder(ComfyNodeABC): return return_encoding -# class CLIPLoader: -# @classmethod -# def INPUT_TYPES(s): -# return {"required": { "clip_name": (folder_paths.get_filename_list("text_encoders"), ), -# "type": (["stable_diffusion", "stable_cascade", "sd3", "stable_audio", "mochi", "ltxv", "pixart", "cosmos", "lumina2", "wan", "hidream", "chroma", "ace"], ), -# }, -# "optional": { -# "device": (["default", "cpu"], {"advanced": True}), -# }} -# RETURN_TYPES = ("CLIP",) -# FUNCTION = "load_clip" -# -# CATEGORY = "advanced/loaders" -# -# DESCRIPTION = "[Recipes]\n\nstable_diffusion: clip-l\nstable_cascade: clip-g\nsd3: t5 xxl/ clip-g / clip-l\nstable_audio: t5 base\nmochi: t5 xxl\ncosmos: old t5 xxl\nlumina2: gemma 2 2B\nwan: umt5 xxl\n hidream: llama-3.1 (Recommend) or t5" -# -# def load_clip(self, clip_name, type="stable_diffusion", device="default"): -# clip_type = getattr(comfy.sd.CLIPType, type.upper(), comfy.sd.CLIPType.STABLE_DIFFUSION) -# -# model_options = {} -# if device == "cpu": -# model_options["load_device"] = model_options["offload_device"] = torch.device("cpu") -# -# clip_path = folder_paths.get_full_path_or_raise("text_encoders", clip_name) -# clip = comfy.sd.load_clip(ckpt_paths=[clip_path], embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=clip_type, model_options=model_options) -# return (clip,) - class WarpedCLIPLoader: @classmethod def INPUT_TYPES(s): @@ -10377,7 +8661,7 @@ class WarpedLoadFramePackModel: "base_precision": (["fp32", "bf16", "fp16"], {"default": "bf16"}), "quantization": (['disabled', 'fp8_e4m3fn', 'fp8_e4m3fn_fast', 'fp8_e5m2'], {"default": 'disabled', "tooltip": "optional quantization method"}), - "load_device": (get_available_devices(), {"default": "cpu", "tooltip": "set load device."}), + "load_device": (get_available_devices(), {"default": "cuda", "tooltip": "set load device."}), }, "optional": { "attention_mode": ([ @@ -10438,6 +8722,9 @@ class WarpedLoadFramePackModel: gc.collect() time.sleep(1) + # for key in sd.keys(): + # print("Framepack Model Key: {}".format(key)) + # sd = load_torch_file(model_path, device=offload_device, safe_load=True) model_weight_dtype = sd['single_transformer_blocks.0.attn.to_k.weight'].dtype @@ -10907,3 +9194,698 @@ class WarpedCheckpointLoader: raise RuntimeError("ERROR: Could not detect model type of: {}".format(ckpt_path)) return out + +class WarpedDatabase: + def __init__(self, the_dictionary): + self.data = the_dictionary + + def catExists(self, category): + return category in self.data + + def keyExists(self, category, key): + return category in self.data and key in self.data[category] + + def insert(self, category, key, value): + if not isinstance(category, str) or not isinstance(key, str): + cstr("Category and key must be strings").error.print() + return + + if category not in self.data: + self.data[category] = {} + self.data[category][key] = value + self._save() + + def update(self, category, key, value): + if category in self.data and key in self.data[category]: + self.data[category][key] = value + self._save() + + def updateCat(self, category, dictionary): + self.data[category].update(dictionary) + self._save() + + def get(self, category, key): + return self.data.get(category, {}).get(key, None) + + def getDB(self): + return self.data + + def insertCat(self, category): + if not isinstance(category, str): + cstr("Category must be a string").error.print() + return + + if category in self.data: + cstr(f"The database category '{category}' already exists!").error.print() + return + self.data[category] = {} + self._save() + + def getDict(self, category): + if category not in self.data: + cstr(f"The database category '{category}' does not exist!").error.print() + return {} + return self.data[category] + +warped_DB = WarpedDatabase({"custom_tokens": {}}) + +class TextTokens: + def __init__(self): + self.WDB = warped_DB + if not self.WDB.getDB().__contains__('custom_tokens'): + self.WDB.insertCat('custom_tokens') + self.custom_tokens = self.WDB.getDict('custom_tokens') + + self.tokens = { + '[time]': str(time.time()).replace('.','_'), + '[hostname]': socket.gethostname(), + '[cuda_device]': str(comfy.model_management.get_torch_device()), + '[cuda_name]': str(comfy.model_management.get_torch_device_name(device=comfy.model_management.get_torch_device())), + } + + if '.' in self.tokens['[time]']: + self.tokens['[time]'] = self.tokens['[time]'].split('.')[0] + + try: + self.tokens['[user]'] = os.getlogin() if os.getlogin() else 'null' + except Exception: + self.tokens['[user]'] = 'null' + + def addToken(self, name, value): + self.custom_tokens.update({name: value}) + self._update() + + def removeToken(self, name): + self.custom_tokens.pop(name) + self._update() + + def format_time(self, format_code): + return time.strftime(format_code, time.localtime(time.time())) + + def parseTokens(self, text): + tokens = self.tokens.copy() + if self.custom_tokens: + tokens.update(self.custom_tokens) + + # Update time + tokens['[time]'] = str(time.time()) + if '.' in tokens['[time]']: + tokens['[time]'] = tokens['[time]'].split('.')[0] + + for token, value in tokens.items(): + if token.startswith('[time('): + continue + pattern = re.compile(re.escape(token)) + text = pattern.sub(value, text) + + def replace_custom_time(match): + format_code = match.group(1) + return self.format_time(format_code) + + text = re.sub(r'\[time\((.*?)\)\]', replace_custom_time, text) + + return text + + def _update(self): + self.WDB.updateCat('custom_tokens', self.custom_tokens) + +class WarpedSamplerScriptsBase: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(self.num_batchs): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + RETURN_TYPES = ("WARPEDSCRIPTS",) + RETURN_NAMES = ("scripts", ) + FUNCTION = "do_scripts" + + CATEGORY = "Warped/General/Scripts" + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(12): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + + def get_tokens(self, text): + new_text = [] + for line in io.StringIO(text): + if not line.strip().startswith('#'): + new_text.append(line.replace("\n", '')) + new_text = "\n".join(new_text) + + tokens = TextTokens() + new_text = tokens.parseTokens(new_text) + + return new_text + +class WarpedSamplerScripts5(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(5): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(5): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedSamplerScripts8(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(8): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(8): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedSamplerScripts12(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(12): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(12): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedSamplerScripts16(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(16): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(16): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedSamplerScripts20(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(20): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(20): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedSamplerScripts30(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(30): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(30): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedSamplerScripts40(WarpedSamplerScriptsBase): + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + arg_dict = { + "required": { + }, + "optional": { + } + } + + arg_dict["optional"]["dummy"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + for i in range(40): + arg_dict["optional"][f"batch_{i}"] = ("STRING", {"default": "", "multiline": True, "dynamicPrompts": True}) + + return arg_dict + + def do_scripts(self, **kwargs): + scripts = {} + + temp_text = kwargs.get(f"dummy") + + if len(temp_text) > 0: + scripts["dummy"] = self.get_tokens(temp_text) + + for i in range(40): + temp_text = kwargs.get(f"batch_{i}") + + if len(temp_text) > 0: + scripts["{}".format(i)] = self.get_tokens(temp_text) + + return (scripts, ) + +class WarpedLoadImages: + def __init__(self, index=0): + self.index = index + self.output_dir = folder_paths.get_output_directory() + self.previous_path = "" + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "mode": (["incremental_image", "random"], {"default": "incremental_image"}), + "index": ("INT", {"default": 0, "min": 0, "max": 150000, "step": 1}), + "label": ("STRING", {"default": 'Batch 001', "multiline": False}), + "path": ("STRING", {"default": '', "multiline": False}), + }, + "optional": { + "suffix": ("STRING", {"default": '', "multiline": False}) + } + } + + RETURN_TYPES = ("STRING", "INT", "STRING", "STRING", "STRING") + RETURN_NAMES = ("filename", "index", "prefixorg", "prefixseg", "prefixmsk") + + FUNCTION = "load_batch_images" + + CATEGORY = "Warped/General/Image" + + def load_batch_images(self, path, index=0, mode="incremental_image", label='Batch 001', suffix=""): + if not os.path.exists(path): + return (None, ) + + if path != self.previous_path: + self.index = index + self.previous_path = path + + fl = self.BatchImageLoader(path, label, '*', index) + new_paths = fl.image_paths + + retry = True + + try: + filename = fl.image_paths[self.index] + except: + if retry: + retry = False + self.index = 0 + filename = fl.image_paths[self.index] + + print("Filename: {}".format(filename)) + + temp_strings = filename.split(".") + temp_fileend = temp_strings[len(temp_strings) - 1] + + temp_filename = "" + + i = 0 + while i < (len(temp_strings) - 1): + temp_filename = "{}{}".format(temp_filename, temp_strings[i]) + i += 1 + + tempFilename = "{}/{}_{}.{}" + tempFilenamesuffix = "{}/{}_{}_{}.{}" + + tempStrings1 = temp_filename.split("\\") + temp_filename = tempStrings1[len(tempStrings1) - 1] + + if len(suffix) < 1: + prefixorg = tempFilename.format(self.output_dir, temp_filename, "org", temp_fileend) + prefixseg = tempFilename.format(self.output_dir, temp_filename, "seg", temp_fileend) + prefixmsk = tempFilename.format(self.output_dir, temp_filename, "msk", temp_fileend) + else: + prefixorg = tempFilenamesuffix.format(self.output_dir, temp_filename, "org", suffix, temp_fileend) + prefixseg = tempFilenamesuffix.format(self.output_dir, temp_filename, "seg", suffix, temp_fileend) + prefixmsk = tempFilenamesuffix.format(self.output_dir, temp_filename, "msk", suffix, temp_fileend) + + self.index += 1 + + if self.index >= len(fl.image_paths): + self.index = 0 + + return filename, self.index - 1, prefixorg, prefixseg, prefixmsk, + + class BatchImageLoader: + def __init__(self, directory_path, label, pattern, index): + self.image_paths = [] + self.load_images(directory_path, pattern) + self.image_paths.sort() + + self.index = index + self.label = label + + def load_images(self, directory_path, pattern): + for file_name in glob.glob(os.path.join(directory_path, pattern), recursive=True): + if file_name.lower().endswith(ALLOWED_EXT): + abs_file_path = os.path.abspath(file_name) + self.image_paths.append(abs_file_path) + + def get_image_by_id(self, image_id): + if image_id < 0 or image_id >= len(self.image_paths): + cstr(f"Invalid image index `{image_id}`").error.print() + return + + return self.image_paths[image_id] + + def get_next_image(self): + if self.index >= len(self.image_paths): + self.index = 0 + + image_path = self.image_paths[self.index] + self.index += 1 + + if self.index == len(self.image_paths): + self.index = 0 + + cstr(f'{cstr.color.YELLOW}{self.label}{cstr.color.END} Index: {self.index}').msg.print() + + return image_path + + def get_current_image(self): + if self.index >= len(self.image_paths): + self.index = 0 + image_path = self.image_paths[self.index] + + return image_path + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float("NaN") + +class WarpedSaveImageCaption: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {"required": + {"image_path": ("STRING", {"forceInput": True}), + "caption": ("STRING", {"forceInput": True}), + }, + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("caption",) + OUTPUT_NODE = True + FUNCTION = "save_caption" + + CATEGORY = "Warped/General/Captioning" + + def save_caption(self, image_path, caption): + tempStrings = image_path.split('.') + caption_path = tempStrings[0] + + i = 1 + + while i < (len(tempStrings) - 1): + caption_path = "{}.{}".format(caption_path, tempStrings[i]) + i += 1 + + caption_path = "{}.txt".format(caption_path) + + with open(caption_path, 'w') as fp: + fp.write(caption) + + return {"ui": {"string": [caption,]}, "result": (caption,)} + +class WarpedModifyCaptionFile: + def __init__(self, index=0): + self.index = index + self.previous_path = "" + + @classmethod + def INPUT_TYPES(s): + return {"required": + {"mode": (["incremental_caption", "random"], {"default": "incremental_caption"}), + "index": ("INT", {"default": 0, "min": 0, "max": 150000, "step": 1}), + "caption_path": ("STRING", {"forceInput": False}), + "find_text": ("STRING", {"forceInput": False}), + "replace_text": ("STRING", {"forceInput": False}), + }, + } + + RETURN_TYPES = ("STRING", "STRING", "STRING", ) + RETURN_NAMES = ("filename", "original", "modified", ) + OUTPUT_NODE = True + FUNCTION = "load_batch_captions" + + CATEGORY = "Warped/General/Captioning" + + def load_batch_captions(self, mode="incremental_caption", index=0, caption_path="", find_text="", replace_text=""): + if (len(caption_path) == 0) or (len(find_text) == 0) or (not os.path.exists(caption_path)): + return ("None", "None", "None") + + if caption_path != self.previous_path: + self.index = index + self.previous_path = caption_path + + fl = self.BatchCaptionLoader(caption_path, '*', index) + + retry = True + + try: + filename = fl.caption_paths[self.index] + except: + if retry: + retry = False + self.index = 0 + filename = fl.caption_paths[self.index] + + print("Filename: {}".format(filename)) + + original, modified = self.find_replace(filename, find_text, replace_text) + + self.index += 1 + + if self.index >= len(fl.caption_paths): + self.index = 0 + + return {"ui": {"string": [filename, original, modified]}, "result": (filename, original, modified)} + + def find_replace(self, filename, find_text, replace_text): + with open(filename, "r") as fp: + original = fp.read() + + modified = original.replace(find_text, replace_text) + + with open(filename, "w") as fp: + fp.write(modified) + + return (original, modified) + + class BatchCaptionLoader: + def __init__(self, directory_path, pattern, index): + self.caption_paths = [] + self.load_captions(directory_path, pattern) + self.caption_paths.sort() + self.index = index + + def load_captions(self, directory_path, pattern): + for file_name in glob.glob(os.path.join(directory_path, pattern), recursive=True): + if file_name.lower().endswith(ALLOWED_CAPTION_EXT): + abs_file_path = os.path.abspath(file_name) + self.caption_paths.append(abs_file_path) + + def get_caption_by_id(self, caption_id): + if caption_id < 0 or caption_id >= len(self.caption_paths): + cstr(f"Invalid caption index `{caption_id}`").error.print() + return + + return self.caption_paths[caption_id] + + def get_next_caption(self): + if self.index >= len(self.caption_paths): + self.index = 0 + + caption_path = self.caption_paths[self.index] + self.index += 1 + + if self.index == len(self.caption_paths): + self.index = 0 + + cstr(f'{cstr.color.YELLOW}{self.label}{cstr.color.END} Index: {self.index}').msg.print() + + return caption_path + + def get_current_caption(self): + if self.index >= len(self.caption_paths): + self.index = 0 + caption_path = self.caption_paths[self.index] + + return caption_path + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float("NaN") diff --git a/pyproject.toml b/pyproject.toml index 90f42ee..29e4f18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "ComfyUI-WarpedToolset" description = "A toolset for Hunyuan Video (mainly), with some additional nodes applicable to Framepack Video and WAN Video." -version = "1.7.1" +version = "1.7.2" license = { file = "LICENSE" } [project.urls] @@ -12,3 +12,4 @@ PublisherId = "warpedanimation" DisplayName = "Warped Toolset" Icon = "" Models = [] +