From 6cc08e4c4419b2efa1278739b75b8a8c79f6f758 Mon Sep 17 00:00:00 2001 From: nofunstudio Date: Thu, 16 Oct 2025 00:53:46 -0600 Subject: [PATCH] seedance video - image batch custom and reset on queue counter --- __init__.py | 7 +- __pycache__/__init__.cpython-312.pyc | Bin 1022 -> 1778 bytes .../custom_name_selector.cpython-312.pyc | Bin 1395 -> 1405 bytes __pycache__/fal_kling_video.cpython-312.pyc | Bin 0 -> 12935 bytes .../fal_recraft_upscale.cpython-312.pyc | Bin 0 -> 13875 bytes .../fal_seedance_video.cpython-312.pyc | Bin 0 -> 14196 bytes ...ntext_inpaint_conditioning.cpython-312.pyc | Bin 0 -> 3733 bytes __pycache__/iframe_view.cpython-312.pyc | Bin 11424 -> 11434 bytes __pycache__/ksampler_fun.cpython-312.pyc | Bin 9699 -> 9709 bytes .../layered_infinite_zoom.cpython-312.pyc | Bin 6790 -> 6800 bytes .../load_image_batch_fun.cpython-312.pyc | Bin 0 -> 9313 bytes .../multi_alpha_composite.cpython-312.pyc | Bin 0 -> 4480 bytes .../queue_counter_reset.cpython-312.pyc | Bin 2728 -> 3102 bytes .../replicate_Flux_Fill.cpython-312.pyc | Bin 11014 -> 11024 bytes .../replicate_Flux_Pro_Ultra.cpython-312.pyc | Bin 12472 -> 12482 bytes __pycache__/string_lower.cpython-312.pyc | Bin 0 -> 829 bytes fal_seedance_video.py | 106 ++++---- load_image_batch_fun.py | 229 ++++++++++++++++++ queue_counter_reset.py | 13 +- 19 files changed, 292 insertions(+), 63 deletions(-) create mode 100644 __pycache__/fal_kling_video.cpython-312.pyc create mode 100644 __pycache__/fal_recraft_upscale.cpython-312.pyc create mode 100644 __pycache__/fal_seedance_video.cpython-312.pyc create mode 100644 __pycache__/flux_kontext_inpaint_conditioning.cpython-312.pyc create mode 100644 __pycache__/load_image_batch_fun.cpython-312.pyc create mode 100644 __pycache__/multi_alpha_composite.cpython-312.pyc create mode 100644 __pycache__/string_lower.cpython-312.pyc create mode 100644 load_image_batch_fun.py diff --git a/__init__.py b/__init__.py index 3515384..4a7facb 100644 --- a/__init__.py +++ b/__init__.py @@ -12,6 +12,7 @@ from .fal_seedance_video import FalAPI_seedance_video from .string_lower import StringLower from .multi_alpha_composite import MultiAlphaComposite from .flux_kontext_inpaint_conditioning import FluxKontextInpaintingConditioning +from .load_image_batch_fun import LoadImageBatchFun WEB_DIRECTORY = "./js" NODE_CLASS_MAPPINGS = { @@ -27,7 +28,8 @@ NODE_CLASS_MAPPINGS = { "FalAPI_seedance_video": FalAPI_seedance_video, "StringLower": StringLower, "MultiAlphaComposite": MultiAlphaComposite, - "FluxKontextInpaintingConditioning": FluxKontextInpaintingConditioning + "FluxKontextInpaintingConditioning": FluxKontextInpaintingConditioning, + "LoadImageBatchFun": LoadImageBatchFun } NODE_DISPLAY_NAME_MAPPINGS = { "LayeredInfiniteZoom": "Layered Infinite Zoom", @@ -42,7 +44,8 @@ NODE_DISPLAY_NAME_MAPPINGS = { "FalAPI_seedance_video": "Fal API Seedance Video", "StringLower": "String to Lowercase", "MultiAlphaComposite": "Multi Alpha Composite", - "FluxKontextInpaintingConditioning": "No Fun Flux Kontext Inpaint Conditioning" + "FluxKontextInpaintingConditioning": "No Fun Flux Kontext Inpaint Conditioning", + "LoadImageBatchFun": "Load Image Batch (Fun)" } __all__ = [ diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc index 166e8703dcabd4140edb19395a13230107ae5a83..b54ecaff0a9e062a7cc73b3b96b80a367461a383 100644 GIT binary patch delta 1068 zcmZ9J%}*0S7{+HQra);+yDg=k3?&3=kVZaZFeb={sh|=F9yT$XwKFXXv%AgiRT%sc${pqC*vLAW{h!WT14HXZ=QWWw(swKeg!YW)1SlPA;6yW;Q8U+ zAOK(a%heO@iOZj-(@Gnl0TMByN>l;}pg}TX#FUuOLnLmTGa45d*9Wl;|0Q9-m6>Hv+ula%pSurzV{=|j6Dd81nzS=+6sHm=%Q%~hKXr>YUm zD)Cz2{59Npy~ zo!BDHlWog%@rhfRHyfI6x@>CQGLi1;mdP~hitSh$su)@w-`Cvg;a1aZ_0N@$oKmDy zmu4qz?u8xVVVH+74-p=?74`@VosRUT9b=-EVhck?2=}^#@SscBlCKKe91uR`fGvIw z(Y@c}>*eJx9ds=y2&tP1tk1K*_wH5LAEly!&zYu7FN2jtnV7NHOfJuAcX=I z&alZ+XR>cYf}O*@v$iMKH1fYY;s9QhSN?KGT*Qm>?7!}aD|y3?Fi0ibA#pP=X>gNN zjk}~)uWS;h^d@R-d$oPs^-9&d>$9%w^~Jfp1Yr!S&fQXW*4n>b_2H_cmsD03pEM8 zXHT;^iT#}SESv`w|^PSs?d}78Yq{ zmgeWFT%g%GT6##+H^1kjslG2jJ}-jY0-fHZ#Z?*~r`dU$U#5v7Ev(Q?ndXQUX&Q$JH z-W1L`>{0wFTq)csJSn^>d@1}X0$?$LbcPhcMT}8`l|q`rlQkHZb5ybD>1P#dvQKVc z(wTgosfPt*>11IR7e=AU5iIMCi+F+jB5n}D10-&-$Hyn;GY4=qkD zD%Q_R%uOvW&dklt&zt<8)mZcwhfQvNN@-52U6CYE9U~AIr%ZNdlbu}2CS&}OpF^DK w0)y}e5e6CK8|tn%l&o(E$={GRx*=Vd&cI>Jo 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 AE&u=k literal 0 HcmV?d00001 diff --git a/__pycache__/fal_recraft_upscale.cpython-312.pyc b/__pycache__/fal_recraft_upscale.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6789c44aed970ceeac6bc9f6200dae7fb086487 GIT binary patch literal 13875 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 literal 0 HcmV?d00001 diff --git a/__pycache__/fal_seedance_video.cpython-312.pyc b/__pycache__/fal_seedance_video.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74e92012abe0f94f583fc495fca48975d4011344 GIT binary patch literal 14196 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 literal 0 HcmV?d00001 diff --git a/__pycache__/flux_kontext_inpaint_conditioning.cpython-312.pyc b/__pycache__/flux_kontext_inpaint_conditioning.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afb0d836cf6634f03f7d85111b0606ad3db1a3e6 GIT binary patch literal 3733 zcmb_fTTC0-89sCIh4C1B051fy#5m#NEWt^aq+7x+b+{yS!DIv3CRV$nk!K8MePd?4 zo48|%N?FN~DlKfKLaRt6Ps=8GV4uok`c|ngp7OwSnyN_c3vW(|)T$3{|KnRAB#Kn^ zSpLs{&VSA~|84$r=J!q~gP{FI`eLEK5uv~0L9NkM=3oq%H6$XDNT3Mr$pn!kBP3Co zqaqZEt{{=Ri$wYnS=kk#MT11eW`R@k$h^}r!Gjoq@aB2lcjl3bs#{RHc^TR*@SA^ z)O0$b#xnt{$wm(uV^W_9l4;GvZ%YZqr15r>lcks>OR1>DCj?bWsfx*zAHrktHwg40 z6a{<1_pgQE4Mmcb;G&R}6eXTarc+9AEFH}z@xI__IvKljV=@@cDr!2(r_!RN1j9i2 ziEN6mNn_x0{?m%j`FO?Y{9!EzGIvbJWcb>RIezZewei{9**8XM;LvhAsH(gNWEqvL z$k}Rif7j?9FuKnf-9e-KywMXh2H!IVZ$7h7-{~zOs;BRnlR42?qF6UmLTm$b0DDn@ zlrfOZR(LmbrnTZA(+b`Kt8y)ewGLKIiQ)vQH7hXXgqZ+l4Qb?0JJotZE!Oh5wi9Oo&Qn>ml@2G{pIFShoSW1@KIp zA|x{jNtwerCX_KCYgim7enCoPAhc%d;eEU!sr+X`A}c8Y%A^%35tGZFVBm?hbivyB zd_K7iKcbDV;PQ2qs>^aiZw}(?_P!0s%0(c{XwTs(I=Y^Edw0Dfx_88IcNpC1joem1 z?;S4oykB&GV6=Ll+vtwQ!c>Vt?vA3}E4Rbes0~Q1H2_l%%RhmxA+elndukkx1bnzeYx2S&V*EO%{!OB|K?NHpKxiw zWe?%f;H_7Cm4N?zxM=L-bHTJhflEkH zH9*Myc-$aMnM6DaC+Iv3p_N9e%-#qfHA7hiVYL|Y@uV;>nU3ltK4|4m*dyb>2Hd7a zP0P^*lT4*dCYDV_@m)knm=3s}NOC5Pi#%39Sr9UkX{mP6L^=i2P{os3kW(2!G%a#E zn-Zb$FJ&bOOtHv9YF?7Dk7XYwU6`B(67a}=%;WMdH(`Qb7a3<_`S2*KW;)Vxe4ek~ zADBwdM;AUf3Em{Gn#2!H3p|!zsC1vpmtea|Buye}I*)juic~qS@*XK3h~F~$o2%u^+xKqoy8OD!zv~*%T>}Q|{&MQx)VhCN z*l78>{XzTYL(kajit@5&5w3G!2)A= zPVRcTbx-#_ra%e+FP7U(_ByUU%@xl?tuxnRKx_o+s1WpHh1b?E2Ay7S~N z+o!XAo7@ijPJwvJy|uFRi?%|@@b^9B9)=z+ZFOz7>;AzlMfVSF3wqbclT&)vcwyqJ z^Ir+S;?_eeLw{g9OB8BqFWJ$Fj$bpsWHv7Dw4Et9jW%z2bZMt82>xsf6qx65mpie` zp3~WL2HR$wK5umRo>7F;e_)}V;KdS)+B$Yy2ldv$t&g^uoz~F;3;MSDHoQg8*#h%N zhsWrBr|^RnO=nN^S?9w^@q;45P;;4tkxpMt9`&zlU-!&{$CV4mgqrL2&s zN*vLIpeRX6T}X>EE`BC^eSGf5^>F2~S|5c&)8n(Ied0!V6yNww`zT!MugqM(Res$n zui#s-z5M)2T0_}IGA1_oD}zApBE#Z-MmjCb0fnqw33H`R)N*!t%4o*K)w+DuaCI+V z{X1>9bUbefTFz7eF--1c_0z`p;@ieIdgyx~V3Xg4btV_ZH}`=u<<&bGNs)1-tCR?g zWHyIq#>V;4snF~!KOMSu4L)FI&Gz!-*yQZBsn9JR8(f#kM@=*B!xeXaAb$*SxZ*1B z11V7iK^#~S;rui5{RuVygPtLXGtUsFC6Ppyo?`FS5=FL>Mbr%Ux!Sms)KPoc(EkEV Co}G07 literal 0 HcmV?d00001 diff --git a/__pycache__/iframe_view.cpython-312.pyc b/__pycache__/iframe_view.cpython-312.pyc index 1a5c4eab4b252333a9e571e756d8ceed78b61686..e4aa9895f42de74085e0cb8df9780769bfaf57eb 100644 GIT binary patch delta 101 zcmZ1wxhj(9G%qg~0}$L#ZOz!oW6mTSq#s(GT2!o`m6)4aT%4Jko1a&#?~YikI=$=8OCXm{@Ny##ZT1uICfqyjDn)gY6chdX-D`OFG%0WW6mV(p&weDT2!o`m6)4aT%4Jko1eEifvJj@^%tW~ qmGb0=LgJgh@h@d!{>2zO*+D>Z^L8Ok4#r=bA4(k)08%TonHT}^9Uesh diff --git a/__pycache__/ksampler_fun.cpython-312.pyc b/__pycache__/ksampler_fun.cpython-312.pyc index e816d6a71056c409fa90d9e39cd9d220302dbf9f..964e01ede79ca1153a5a8edd5fe0f8388fcc3884 100644 GIT binary patch delta 63 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 bfnu2`-wpYFkZ;Da zyJKPz$3!h$lmZMmZh@Lf9FzfyR*C~e0SZKUbDx@`Kuel#L|jzVK>gx3*$z;&FYWC8 zkhG#SOLBH^cXoDmZ@+JbfA)Bs2+BW%pUo;>g#L*i%wjbfk6(et4a6g!NTL)mMG&}c zNm`~zt+q~CdGZRHvhh}slm(qYyzL6&saqD^!jyg960$$Q4tLL^4$gPNp3 zlJI-{7wEl#P3`x0<;n@eMDLLs)=18?nwDaH=A%YJiyB4D`i+=xHiqxKeO<TJ^D4zj@;nS$(plA(i>KuwQM2Kg7BeYM6uEiT9@AY4SyW2* zMy1o)XdGWn39rqv|9NxpoFs_SV1i2tk`zy+GHGdWG!x6EgtROT8k-r6?sjdM^}lv;|Ml2+H1^Ug&w?bPWgoRWYD- zCjNCSe%ino0T?TwH2Xc?TIOCfSjV%;6?klA9hou56F#%mtd$0jCAKwt&6eEYlti1^ z*Q`x^@l+o6Rj|lA%&|m=*=p8GlL<+MOzdoqm@VFJS_H(>O~f|viNX3Ld_@{2i#U9Q zND;r57J=UZP`x$9NpmyMM(AGV6%E}XFZ2RPbVQPA;ce9_#R0&!ET9%DDVvPTA|@3P zGofnJ04rjCRPEEr3@5*EK()ykF*d6@F`%P5=pDJV!380!>HtXTU{;+Mx!Bx{n8~Gi z5g(Gc9fX9h7Yjwir=@zZIsj3Jq!@xeO=}q%3kUc2-?GOW~TUr(*39yTIER{2IlKoR9ZI*9|0~DS}5+7M_?Q z1uJj4g3S95p_`ndcbq<(>iV8DfrlLl3I=1_(R{Mc*ji(jua71_pntl*Z%F8})$@Wwc%}>Vrmo$fyq+ z^@~P51Yv;|g-f}(DDWzs$;$CenoBO@J55Lu_R6?9u2YdS=O&|*=g*8yMS4?SL= za|3xDPVIGz2f>=^Xatr>OiSmW6Bmp^?QQ%DZo&t_9*MrMRwJt~#u!;4ZjYax%Bc6~NnIS#&jdyUBh(CFDj< z#*__pHrW*$=T zE1tv_Y_0fB8w6_cmr}gEJrApZkF?_7D!+pf2aIgN>mQCkm_yLUtPRMe~}+(=++NsBkeiGt8b5GclZc9lC%Jjyi78sV%6p7? zr?p{m5IoE~*a3C|V$d*~r=MlVAvz7STCmFRGqfjUPL%N)Z^z|X_97<~78<1icYi1@FC>U@Js=7cd(%!m*k zMMz{-hX6Duh@32F8KV{_A>Ykr1qg3Jm?U=NnKqG2&loY5*_3>0;Vsk#3@Rk2#lv_G zq%%ky!r~Z|x)FH-fr150yD`Rd-`+KvdwGPxT2GV=jh**jcxS9V11ySzoE=6b4h z>5hwC4?I=r9BfAd0FsqH>k={;0AbhhH1xJyq$ZV+fIQtRD)W##Mc zgNx(Ea52BWeRuiQ+V;WXiF=*wuY>OgAR8_@`jyTm8JZ@5s;p$#8`4H4HnVJYm&&|P{M z{vrf+ym#s5?$Y#!&wTCgD~7>lrEOq|TOpQXOXpVhRszF!-AC5jyVlzKtL^<*!wMw9Nvm=U}^fZx#hW~3#|>Pm11pFS712t_q0-T48vZgxqpC9+g&Unq z;3v`Ktt*WaRt>GcH!hboA058u{j@;i1KgX)sdHmXSxM1^rTbRZ)$mnZ5xxPw|=o@@ljDj9c45Zy4Hb{aX h{*KzeL4j|O`;nC)#)wC~9wPX!o*{yLgg|Jk{}0ce02}}S literal 0 HcmV?d00001 diff --git a/__pycache__/queue_counter_reset.cpython-312.pyc b/__pycache__/queue_counter_reset.cpython-312.pyc index 31b7bce14547c011595ce0b21f328e55fbc1e6f0..695d3c5af780d91e62fa90ed379d3554a72aae88 100644 GIT binary patch delta 1312 zcma)5-D@0G6u);qcV}k561Pb=Hl4VH?G)1xtc}(fYDr5H(*_!fv=qydnPj)wk9hAy z>2inmL9n1g!WFF8XdjinDEp3#v{4yT>gIft88;{w0ZcYomA{_vLzd7qlFCaNO}AW zzaY8UG^7l*rFV*Cky1(Iw@HToC=HMGfkBf1x6xA#rL(J--)GHOAL$0yyb2J>UaQBU z;g6Av1C@`+*(+)TW)f(=sJbmoda%1@oju(bBkJrSS9&1$LFgdU7`nb|A;c80_D=e7 zz9t`^tc?lx4XqQhAD2cEB18Y4B0BFX{14@j{V8%)2v8f~hqbn@MwMd3WLM|k%16$% zcY~N4V=*`rUzdaUzTRR{gl|U4*`ANZ7vwnv3_2fB@*@T_n7(uk%FHo6Fqs)x5qpq; z{1)UlSOU;oSA#gy_=++(U_#XXshFL518XwGGQ4a|b$$wXlj&|5`z;>j=7RCJs z=Zot9HSBs?&$vOvVIB9?%J0H{R^`o*2M4+zPK-5!8OFVtzBsMTH129rK7@jH6qmUtjN ztNz_9k5YxrKIhKF2Q!=fc~G-kR;JlC{+;rZ^}Y3*b)h9*(p}~A)F-K5Q-$rLL#xV1 z*5-2sP^qnSw%L2}p})a?W)Ex4Ym3d&+by8PlhO`CWl&(1@RU$f(zH-LuS-u6%1ATP zHyiqU7gR}GRH#2bAuvDj3}tXp z9vGz*11r6CKHEq0gl4bh3VBM03x)A9zKE~mPM(t5;v1G$n<&Xf$}Ay+UzVD16`ztk zHv!zDHgYpZhA5SUP?{w9Zz+4R778k^r_oOhrQF%R8Mb2769#s+-fq}Q$|`4 zA_w^wW$#I45-XEY@S%)KYG8at{c4Wp ze4mhgqEaWw@R(ne0Wxve$o%La5gSb`0XF}t2MuvZ)0IJz;?f0}teJbhhtC?Sz8@;O zjQPCLoc@-qp7kGIT1_^8tk2x(xp#KWc2=soUMX+w*Y>J??nO`RHpUKrXZGL}cdWyw zV1kh#5oY0XMkZoIi2(7?(*U>7y5mltSyxjVQcN{BWu!SJk(H|XjMbtYQ@b&7_)Dwt s#BQxE<9K1*yD^&YB1b?+>@yV;Dajb)b*E}N@k{B&xEudK;VbOo4@zLvmjD0& diff --git a/__pycache__/replicate_Flux_Fill.cpython-312.pyc b/__pycache__/replicate_Flux_Fill.cpython-312.pyc index 5ee81f81dd78baa6a5791c23698ec1155b5d28f5..719f3412403d85a7a326324a44827633e50180fb 100644 GIT binary patch delta 62 zcmZn*n-IoxnwOW00SNA=wq|VPxyB+Jr5{?HT2!o`m6)4aT%4Jko1a&#?~D={~D={~%ML6#-ibT?2A+slM>2A2(`?o5fYF_8l% zUX2I*7dHE+c=1T);wJtBRSqVeoM|B;zNBB@} zWc^SkOVFSV1QtNht?X3c!Az^^etJl8Q-O6|o|izuLj*jHAWx?T(H3yK>Gn*bdl_PQ zSz<20vu2rER^)mS8%%`9JdujWN^AYiOyoMwS>MI(`B|%XeXz4geW#!-<&P!I zA2qx(Ep?ND7hf zw%mT#N!=6HQQv90ol_^##MB>}OiFdC)tLgdHGd{y0juKu`SG1u`lXqsz1AUfFIHK+ y59P}IWK}$zAFmC~tfVyRvUDUN`Hx*#&r|s?*rV+TwSKH4g#KtHRQU}O5}toWkiazn literal 0 HcmV?d00001 diff --git a/fal_seedance_video.py b/fal_seedance_video.py index ad1185e..8bc6b78 100644 --- a/fal_seedance_video.py +++ b/fal_seedance_video.py @@ -3,11 +3,15 @@ import time import requests import tempfile import json +import random import numpy as np import torch +import asyncio +import folder_paths from io import BytesIO from PIL import Image import fal_client +from comfy_api.input_impl import VideoFromFile class FalAPI_seedance_video: @classmethod @@ -85,62 +89,37 @@ class FalAPI_seedance_video: } } - RETURN_TYPES = ("STRING", "STRING",) - RETURN_NAMES = ("video_path", "generation_info",) + RETURN_TYPES = ("VIDEO", "STRING", "STRING",) + RETURN_NAMES = ("video", "video_path", "generation_info",) FUNCTION = "generate_video" CATEGORY = "FAL" def __init__(self): - # Directory structure for saving generated videos - self.output_dir = "output/API/FAL/seedance-video" - self.metadata_dir = os.path.join(self.output_dir, "metadata") - - os.makedirs(self.output_dir, exist_ok=True) + # Use ComfyUI's temp directory for temporary video storage + self.temp_dir = folder_paths.get_temp_directory() + self.metadata_dir = os.path.join(self.temp_dir, "seedance_metadata") os.makedirs(self.metadata_dir, exist_ok=True) - def get_next_number(self): + def get_temp_filename(self): """ - Looks at existing .mp4/.mov files and picks the next integer - filename index (e.g. 001, 002, etc.). + Generate a unique temporary filename using timestamp and random component. """ - valid_exts = {".mp4", ".mov", ".avi"} - files = [f for f in os.listdir(self.output_dir) - if os.path.splitext(f)[1].lower() in valid_exts] - if not files: - return 1 + timestamp = int(time.time() * 1000) + random_id = random.randint(1000, 9999) + return f"seedance_{timestamp}_{random_id}.mp4" - numbers = [] - for file_name in files: - base, _ = os.path.splitext(file_name) - try: - numbers.append(int(base)) - except ValueError: - pass - - if numbers: - return max(numbers) + 1 - else: - return 1 + def save_video_and_metadata(self, video_content, generation_info, filename): + """ + Saves the generated video to temp directory, plus metadata as a .json. + """ + filepath = os.path.join(self.temp_dir, filename) - def create_filename(self, number): - """ - Zero-padded filenames ending in .mp4 (e.g., '001.mp4'). - """ - return f"{number:03d}.mp4" - - def save_video_and_metadata(self, video_content, generation_info, number): - """ - Saves the generated video as .mp4, plus metadata as a .json. - """ - filename = self.create_filename(number) - filepath = os.path.join(self.output_dir, filename) - - # Save video content + # Save video content to temp directory with open(filepath, 'wb') as f: f.write(video_content) - # Create metadata filename (001_metadata.json) - metadata_filename = f"{number:03d}_metadata.json" + # Create metadata filename based on video filename + metadata_filename = f"{os.path.splitext(filename)[0]}_metadata.json" metadata_filepath = os.path.join(self.metadata_dir, metadata_filename) # Write out metadata @@ -158,10 +137,11 @@ class FalAPI_seedance_video: except Exception as e: print(f"[Seedance Video] Error in queue update: {e}") - def generate_video(self, api_token, image, prompt, aspect_ratio, resolution, + async def generate_video(self, api_token, image, prompt, aspect_ratio, resolution, duration, camera_fixed, enable_safety_checker, seed=-1): """ Generate video using fal-ai/bytedance/seedance/v1/pro/image-to-video + (Async execution for parallel processing) """ print(f"[Seedance Video] Starting video generation process...") @@ -201,18 +181,18 @@ class FalAPI_seedance_video: except Exception as e: print(f"[Seedance Video] fal_client check failed: {str(e)}") - # 2) Convert ComfyUI image tensor to temporary file + # 2) Convert ComfyUI image tensor to temporary file (run in thread pool) try: - temp_file_path = self.tensor_to_tempfile(image) + temp_file_path = await asyncio.to_thread(self.tensor_to_tempfile, image) print(f"[Seedance Video] Created temp file: {temp_file_path}") except Exception as e: print(f"[Seedance Video] Error creating temp file: {str(e)}") raise - # 3) Upload image to FAL storage and get URL + # 3) Upload image to FAL storage and get URL (run in thread pool) try: print(f"[Seedance Video] Uploading image to FAL storage...") - image_url = fal_client.upload_file(temp_file_path) + image_url = await asyncio.to_thread(fal_client.upload_file, temp_file_path) print(f"[Seedance Video] Image uploaded successfully: {image_url}") except Exception as e: print(f"[Seedance Video] Error uploading file: {str(e)}") @@ -240,9 +220,10 @@ class FalAPI_seedance_video: print(f"[Seedance Video] Starting video generation...") - # 5) Call fal_client.subscribe() + # 5) Call fal_client.subscribe() (run in thread pool for async execution) try: - result = fal_client.subscribe( + result = await asyncio.to_thread( + fal_client.subscribe, "fal-ai/bytedance/seedance/v1/pro/image-to-video", arguments=arguments, with_logs=True, @@ -270,14 +251,14 @@ class FalAPI_seedance_video: video_url = video_data["url"] seed_used = result.get("seed", "unknown") - # 8) Download the generated video + # 8) Download the generated video (run in thread pool) print(f"[Seedance Video] Downloading video from: {video_url}") - resp = requests.get(video_url) + resp = await asyncio.to_thread(requests.get, video_url) if resp.status_code != 200: raise ConnectionError(f"Failed to download video. HTTP {resp.status_code}") - # 9) Save the video & metadata - number = self.get_next_number() + # 9) Save the video to temp directory & metadata (run in thread pool) + temp_filename = self.get_temp_filename() generation_info = { "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), @@ -297,22 +278,27 @@ class FalAPI_seedance_video: "fal_result": result } - video_path, metadata_path = self.save_video_and_metadata(resp.content, generation_info, number) - print(f"[Seedance Video] Saved video -> {video_path}") + video_path, metadata_path = await asyncio.to_thread( + self.save_video_and_metadata, resp.content, generation_info, temp_filename + ) + print(f"[Seedance Video] Saved temp video -> {video_path}") print(f"[Seedance Video] Saved metadata -> {metadata_path}") - # 10) Return the video path & metadata JSON string - return (video_path, json.dumps(generation_info, indent=2)) + # 10) Create VideoFromFile object for ComfyUI's VIDEO type + video_output = VideoFromFile(video_path) + + # 11) Return the video object, video path string & metadata JSON string + return (video_output, video_path, json.dumps(generation_info, indent=2)) except Exception as e: - # Return empty path and an error message in JSON + # Return None for video, empty path and an error message in JSON error_info = { "error": f"Seedance video generation failed: {str(e)}", "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "model": "fal-ai/bytedance/seedance/v1/pro/image-to-video" } print(f"[Seedance Video] Error: {str(e)}") - return (empty_path, json.dumps(error_info, indent=2)) + return (None, empty_path, json.dumps(error_info, indent=2)) def tensor_to_tempfile(self, tensor): """ diff --git a/load_image_batch_fun.py b/load_image_batch_fun.py new file mode 100644 index 0000000..0b514a8 --- /dev/null +++ b/load_image_batch_fun.py @@ -0,0 +1,229 @@ +import os +import numpy as np +import torch +from PIL import Image, ImageOps, ImageSequence +import hashlib +import folder_paths + +class LoadImageBatchFun: + """ + A fixed version of Load Image Batch that supports multiple instances in the same workflow. + Each instance maintains its own state to prevent conflicts. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "mode": (["single_image", "incremental_image", "random"],), + "index": ("INT", {"default": 0, "min": 0, "max": 150000, "step": 1}), + "label": ("STRING", {"default": "Batch"}), + "path": ("STRING", {"default": "", "multiline": False}), + "pattern": ("STRING", {"default": "*", "multiline": False}), + "allow_RGBA_output": (["false", "true"],), + }, + } + + RETURN_TYPES = ("IMAGE", "STRING", "INT") + RETURN_NAMES = ("image", "filename", "count") + FUNCTION = "load_batch_images" + CATEGORY = "image" + + def __init__(self): + """ + Initialize instance-specific variables to prevent shared state issues. + This is the key fix for supporting multiple instances. + """ + self.current_images = [] + self.current_filenames = [] + self.current_index = 0 + self.last_hash = None + self.cached_images = [] + self.cached_filenames = [] + + def load_batch_images(self, mode, index, label, path, pattern, allow_RGBA_output): + """ + Load images from a directory path based on the specified mode. + """ + # Validate path + if not path or path.strip() == "": + raise ValueError("Path cannot be empty") + + # Expand path and validate + path = os.path.expanduser(path) + if not os.path.exists(path): + raise ValueError(f"Path does not exist: {path}") + + if not os.path.isdir(path): + raise ValueError(f"Path is not a directory: {path}") + + # Generate a hash for path/pattern to determine if we need to reload images + # Don't include index/mode in this hash so we can reuse cached images + cache_hash = hashlib.md5( + f"{path}_{pattern}_{allow_RGBA_output}".encode() + ).hexdigest() + + # Load images if cache is invalid or parameters changed + if self.last_hash != cache_hash or not self.cached_images: + print(f"[Load Image Batch Fun] Loading images from: {path}") + self.cached_images, self.cached_filenames = self._load_images_from_path( + path, pattern, allow_RGBA_output + ) + self.last_hash = cache_hash + self.current_index = 0 + + if not self.cached_images: + raise ValueError(f"No images found in path: {path} with pattern: {pattern}") + + total_images = len(self.cached_images) + print(f"[Load Image Batch Fun] Total images found: {total_images}") + + # Select image based on mode + if mode == "single_image": + # Use the specified index, wrap around if needed + selected_index = index % total_images + selected_image = self.cached_images[selected_index] + selected_filename = self.cached_filenames[selected_index] + print(f"[Load Image Batch Fun] Single image mode - selected index: {selected_index}") + + elif mode == "incremental_image": + # Use current index and increment + selected_index = self.current_index % total_images + selected_image = self.cached_images[selected_index] + selected_filename = self.cached_filenames[selected_index] + self.current_index += 1 + print(f"[Load Image Batch Fun] Incremental mode - selected index: {selected_index}, next: {self.current_index}") + + elif mode == "random": + # Random selection + import random + selected_index = random.randint(0, total_images - 1) + selected_image = self.cached_images[selected_index] + selected_filename = self.cached_filenames[selected_index] + print(f"[Load Image Batch Fun] Random mode - selected index: {selected_index}") + + else: + raise ValueError(f"Invalid mode: {mode}") + + return (selected_image, selected_filename, total_images) + + def _load_images_from_path(self, path, pattern, allow_RGBA_output): + """ + Load all images from the specified path matching the pattern. + Returns lists of image tensors and filenames. + """ + import glob + + # Get all files matching pattern + if pattern == "*": + search_pattern = os.path.join(path, "*") + else: + search_pattern = os.path.join(path, pattern) + + files = glob.glob(search_pattern) + + # Filter for image extensions + image_extensions = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.tiff', '.tif'} + image_files = [ + f for f in files + if os.path.isfile(f) and os.path.splitext(f.lower())[1] in image_extensions + ] + + # Sort files for consistent ordering + image_files.sort() + + if not image_files: + return [], [] + + print(f"[Load Image Batch Fun] Found {len(image_files)} image files") + + images = [] + filenames = [] + + for img_path in image_files: + try: + img = self._load_image(img_path, allow_RGBA_output) + images.append(img) + filenames.append(os.path.basename(img_path)) + except Exception as e: + print(f"[Load Image Batch Fun] Error loading {img_path}: {str(e)}") + continue + + return images, filenames + + def _load_image(self, image_path, allow_RGBA_output): + """ + Load a single image and convert it to the ComfyUI tensor format. + """ + img = Image.open(image_path) + + # Handle animated images (take first frame) + if hasattr(img, 'is_animated') and img.is_animated: + img = ImageSequence.Iterator(img)[0] + + # Handle EXIF orientation + img = ImageOps.exif_transpose(img) + + # Convert to RGB or RGBA based on settings + if allow_RGBA_output == "true" and img.mode == "RGBA": + # Keep RGBA + img_array = np.array(img).astype(np.float32) / 255.0 + else: + # Convert to RGB + if img.mode != "RGB": + img = img.convert("RGB") + img_array = np.array(img).astype(np.float32) / 255.0 + + # Convert to tensor with shape (1, H, W, C) + img_tensor = torch.from_numpy(img_array).unsqueeze(0) + + return img_tensor + + @classmethod + def IS_CHANGED(cls, mode, index, label, path, pattern, allow_RGBA_output): + """ + This tells ComfyUI when to re-execute the node. + We return a hash of the parameters to detect changes. + """ + # For single_image mode, include index in the hash so changing index triggers re-execution + # For incremental_image mode, always return a new value so it increments each time + # For random mode, always return a new value so it randomizes each time + + if mode == "incremental_image" or mode == "random": + # Always execute for these modes + import time + return str(time.time()) + else: + # For single_image mode, return hash of all parameters including index + param_string = f"{mode}_{index}_{label}_{path}_{pattern}_{allow_RGBA_output}" + return hashlib.md5(param_string.encode()).hexdigest() + + @classmethod + def VALIDATE_INPUTS(cls, mode, index, label, path, pattern, allow_RGBA_output): + """ + Validate inputs before execution. + """ + if not path or path.strip() == "": + return "Path cannot be empty" + + expanded_path = os.path.expanduser(path) + if not os.path.exists(expanded_path): + return f"Path does not exist: {path}" + + if not os.path.isdir(expanded_path): + return f"Path is not a directory: {path}" + + return True + + +# Register with ComfyUI +NODE_CLASS_MAPPINGS = { + "LoadImageBatchFun": LoadImageBatchFun +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "LoadImageBatchFun": "Load Image Batch (Fun)" +} + +__all__ = ["LoadImageBatchFun"] + diff --git a/queue_counter_reset.py b/queue_counter_reset.py index c7fcd43..dae465b 100644 --- a/queue_counter_reset.py +++ b/queue_counter_reset.py @@ -14,6 +14,8 @@ class DynamicQueueCounter: # Widget shows stop as 8 "stop": ("FLOAT", {"default": 8.0}), "step": ("FLOAT", {"default": 1.0}), + # Toggle to reset counter to start + "reset": ("BOOLEAN", {"default": False}), } } @@ -27,16 +29,25 @@ class DynamicQueueCounter: # Always return NaN so that ComfyUI re-runs this node each prompt. return float("NaN") - def node(self, start, stop, step): + def node(self, start, stop, step, reset): display_offset = 1.0 # Adjust widget values for internal calculation. # (The displayed value is normally calculated as internal_value + display_offset.) internal_start = float(start) - display_offset internal_stop = float(stop) - display_offset + # Initialize counter if this is the first run if not hasattr(self, "counter"): self.counter = internal_start + self.last_reset = reset print("DynamicQueueCounter: Initialized counter =", self.counter) + else: + # Check if user toggled the reset button + if reset != self.last_reset: + # Reset toggle state changed, reset counter to start + self.counter = internal_start + self.last_reset = reset + print(f"DynamicQueueCounter: Reset toggled - counter reset to {self.counter} (display: {internal_start + display_offset})") if step == 0: display_current = self.counter + display_offset