From 63e84c2aa1644a1d2e3bed6b75fa5403468eb552 Mon Sep 17 00:00:00 2001 From: Meisoftcoltd <38667978+Meisoftcoltd@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:22:08 +0000 Subject: [PATCH] Fix Micro-Cycle Death Loops in frame calculation This commit patches the `SessionImageSender`, `AutoLoopCalculatorWan`, and `AutoLoopCalculatorLTX` nodes to prevent infinite loops caused by extreme truncation at the end of video sequences. - `image.py`: Ensures `SessionImageSender` accepts the entire batch if no faces are detected, rather than defaulting to frame 0, which previously trapped the workflow in a 1-frame micro-cycle loop. - `video.py`: Updates `AutoLoopCalculatorWan` to always round the final chunk size up to the nearest multiple of 4, removing the strict cropping logic that broke the 3D VAE rule. - `loop.py`: Updates `AutoLoopCalculatorLTX` to always round the final chunk size up to the nearest `8n + 1` value, removing the strict cropping logic that broke the DiT rule. --- __pycache__/__init__.cpython-312.pyc | Bin 2100 -> 0 bytes __pycache__/loop.cpython-312.pyc | Bin 12844 -> 12972 bytes __pycache__/video.cpython-312.pyc | Bin 20822 -> 21445 bytes __pycache__/vram_node.cpython-312.pyc | Bin 2484 -> 0 bytes image.py | 4 ++-- loop.py | 10 ++++++---- video.py | 11 ++++++++--- 7 files changed, 16 insertions(+), 9 deletions(-) delete mode 100644 __pycache__/__init__.cpython-312.pyc delete mode 100644 __pycache__/vram_node.cpython-312.pyc diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index bc51c7a80424c75cbfa16683bf573e235a7f3430..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2100 zcmaJ>&2JM&6rZ)dPW%-T$8o^i|r$PQVoF0!*`Rz`blAV21So_Od>}el`F|*&yJ4HUxNp z9RxhY4g+SHqzO-&>S4p|$b6ubSQ4a>WpQlu_~_V7Ij~bd3Bnk^TUCIE_o}p2`zW-jQ;k{4iN!Ib_LlVz={S+YF3u*4IF zIV71wM;}KwLPMJ)r+yf@@a)oerRSv=q5em= z)|VeIZ-j<7WAT-XTM$8h!#`URxu{i?d6kFsT5W-gw>75LxMEIt4>YTM!$?A~jo_|-yh446`Wo+^RyDJB-MTWDo1Rjy8_Ik|twN}s_WWNyr>M|o ziKmLHX==4<9*db%%c^!80(!iFwI{T$QctE0ohO^4ifR?wV&my{*Vn%ISB$Unz4>a{ zP_Z6Gzk+)$TDTvG8}#DtfByTkRoY~tIoqm@G+aFG1?8%WzO<|wS2gQK&SqN8KI%n( z@-0St7TWO8^GaEzOtsXqRWs-jNC*KuiFpgq^GQW7+qwc;qx6rwH7Sa8N9A4rjku~* z?O}hvy9d!MSp0e>*p=KlX}2te%h&9o|IY#zIzBof@y?=p%ZBc0ijMUaEyb|xZZCNC zu3xe@N3(hOHx^;NHv=vk+Wb6pyWb1>bj1&;&(f^d>`S(4s}gTRa(=d0&?*|99$e*@ z)o-xFs8En-UE`5C)w~R6_T*x{n6(FRO1vq0a*<|>Q}AX;JX)U{JF)Fs-S)vG8m|?0 zd=uk~^-BG7(MSpNJDuIJpE$N?XS|Kw|9U$uOw#N{ySij6Rf#9+DPR`c?z`{Zd(*w$ z?et`=$}|h^g`#`MX0B#qDY{8>KOx%D84r4c|bQP2*PGt*GlYFdapw|H~R)0lGzFcg~Xq6B24^9#(yRUUy;t2 zB(p&>o1x@`f*TC<240hZ5OiCK(DRZEZjeEjq=o_@JE^Q2gyE}DpEK~bE5gtX6S2qX zJ>|9_X(i%5Cv)75Ac+!jz@d|F3`v}beNKPDO(1Ej+x8%7Ct|PDmv=jmBt3H0?L?9y zV#et?=5`@Td&)a*HbkBquQ pNDdG&<#dg?2az1|YRms|7|3gqf~_AV@j++*87KPg-4?IU{{TP^Xp8^= diff --git a/__pycache__/loop.cpython-312.pyc b/__pycache__/loop.cpython-312.pyc index cc73119a6d180e0416e8b1ad453618a1b16114fa..aa556aaa8979744674931969092da2ae3761f557 100644 GIT binary patch delta 605 zcmZ3JvL==HG%qg~0}wbLxt950Bd;YB8;^csL4p2eccydPjITC}@!2smD^xK|4&)P^ zoFk}UAH%><#9zV<(gOl1iZvp$8B&zyGOuQYh%hqL@YjkWsZg$A0jf{|t5co4SJ0AC zZS!}*Da`RN*?>AqjevxLf`YD{!iV|&jS9{grFq#3X_-sl^HfiA9MDxruotsd=eI3Pq{uIf)7udD@10le>i)npDSRU;saNBn}6!3AUIi&D-Pxm_-J#9!i$zr!PV zLB#EXd+Y_bxC?Rh9~c;f9htr`Fz`AtO%9fN${4oUQaX^4ap&Z2nRARMHb=?ob24Ua z?oumeWNQZcqo`#wv&K0_#_Y|PGz}QVrvrsFMT;CjGW8$=qGqzBc9=mAh@TE5ZZQ@V zO#yKnL4*^CSOg*#1BqKqxw%DafsA6&$${b$>_uWAnYPLMwAC5UY<{LalSQr#Bq9tV zBtQgMK`n>{BDPPSYY@r-Vga2ock(X-Ig9xqIk*KyOF-PEAYvDY$N~{8Ai@?z*nx;_ v5Rp4Mz)*s*c5S&WSCj2{@l)MsV}CjJjh5TS_4JVputl?$OJ delta 461 zcmZ3Jx+aD9G%qg~0}$+DyOx=`k=K%mk$tld(>ZR&JDa8X?3kIEs<Q%WQ@e#TpSHsWkb5pe3X7W-g&A%#;6$ z9%szhd{oSXk&$;ZpF}1T^8;ne$u&}{Y7e-@E=U<%Fm}Eu<$RIb<$`T+lQ?$qdBvS_>AZjMh)DF|`2JzE@#4W~xqRAkRBZzPU5eq@Y zA|P>#DL1!h&15MZWyaRYb~@^er#7eQ%w&;k1t|~)5fUIm3`Eqxh^>=l4MRCVT%g@^ zCRZ8CSU5j#OdCWv4G5w;-04n$;uh@8n63?&$ACciY4W!y8F-6&fs bgOSml@dE>x`pnG0#Q%W_A`~*Y$4CJHX5@JX diff --git a/__pycache__/video.cpython-312.pyc b/__pycache__/video.cpython-312.pyc index 28eaaddad9767f0c5a9f8a89c59fca1e6aaef0b8..32938746d0d192a5939b8be509942745af53c7e9 100644 GIT binary patch delta 2879 zcmb7`X>e256@cG;@_X7B+wvmgMe-sngI5d~<4tym*Vtw-#b5{X&=X+LmMaMx#|h4K z+8H`#TykbYrU_}2;Kd+s@RJNKTeYu_e6`3^Dt+-THs?A!Y8wds-ZH%)asDUG%B8s2D-jj}jRj_`8s zt0MGey-h?=35P7^XuubgXb3WtR?(O55qLiI2zc92|H64y4aRMvi9`&M(j zzAIkgzHL<7Oz9jh+a7l`r&YYobUW8z(WN;<>?QS|iDeU;0NsqJMY!Osw$8B)#Zrc( zcw$DPN5iy-Rl->ecJ|RWNNJl$JD7DI(g9&zO^)I*iblL*#7w@YYs=|JjhbPBON*Sv zN;}|lT@gQS0!gzgc2Hks;OEtFXs2~j-X=RQqA&aCGZB48;y8KxMUs&TH!r?Go);rU z>uuC1w?xjb*Dl@{PI8nyUn~nU=j(p1dcOMjSs*z@kjQT*rC=^-gD)4fmgtvfxLMVHZicv8W5L2=LJq_hZMS$5g4yC_HLYMH zMtk6Tagoj+l)b*7odN1MrfS3*OdL}?tc zpCL)SN&OKj`PuNnXdps&!K8h^coy3a!jJ5mb7%z3vOs5VS%8(t;*>}}2 zzG5zpo2yr>jt|YYmjgc#W12*1%Zk;$YRFqLn3e|43@i?%%+{s3Gjku9oe8t^s<}F4 z$vdw*r~AO-Ojw*(E!D8>tmXG+0ogcldcwjb97U7Gd}60z(kv{i4U@cjIX8b|t9IF? zLAgXG@)41A-rYT;SH0V=mbV!+nNt-rh)iAGA zv3AlWq^b#{iys?y8Izi+sQ~UDtZsC%lP*-di+1C-j46AA*n{Xmw85e360=Rv-BEF3 zcA95WdK)ZOcN-^oVU}c!v>e3Ud!WwsMNKa{xe-nTcJu~Gl5iMLI=fw{Y-gA&1=5@g z$7}Rt4NlgaV0Z0CO;h&oSW{BVPJ$=ulOkR^5Ubkc%py<2Q2lSjFQM~3*wnB_hQQWX zPTHWYvE8Kq$*lv5uLmu;rJgzo7CnhHxGONDix}E3=rJ@Yxmz&yiSJ^CCa4 z?AZ`Ac|%8kg+A{i;)nzSmrj=vR}jBOTtnPMJhbgtU0KI14(3O;7`utkdw<7QaK{T_ zV*A$yH!>?1q1~CH3w^AJd<144mx>-@MN*KW@^mn>K4qleGwmaBfrb_rc@hq^G#YUs z%n^H~UGQ>CD;bDgX?aIQZo${v=15jd-(EpZXEqmYlq>H-X&#|u-3FAF7?K*lbiyl7 z(=dGzb>BkFV1p1oCWX97^-*s`ibN^{coqw~QdikM7zt&jt&7;n|u}*wr)Gpp5uO?D9_txwqxwoJe$y~p)ySpNj^H2C{U@;*iJ?+7LC|GwXi@YB9N@((cgpDV`8MDHT*F=U?L zh0N9a9Ny{QmiHd^|4%ef*8c^QqIK|EV>!46j>^$GR%h>eZHGPm&7~LYJ;$Pf6ZRw1 z0m;W+H2kX}$-z3i`*<`QkpgniF4?11=%PF^VS7lTlHD%_BHnlNX^OuD!B0@mmVW*WSJxD*c|0(^TqXr$d2pvL?Ffb%d!BAw{ zFZre-&^1_)XT$~*!i=yWvcWgFDK`hj2T9DvdSywh(72w&SbeUH9j`KRiCKmNu}=pt z^ZVFKSlRlPJ5kYo$&o1Ux%5oJ(HGa0Ue`NbcQ5O!R;rwFLwQ=q84BV>4e>2KiK3o_ z{)u?s)UtjGA5Cj_yk~#B`#}7_=`_dXx_K6GV>b`Gw`~CHNN2SYFeSjbIKRj4QzPmS zbMWj)bIE}R*$6eu3 z^@mQ;*HLjA75aXEC`co_C=F7I*CdmHm3ysB=FtfzHEry#QPk({pj~W21dfkBRWza^ pvn0(a1$#1ibDGbn4ntzJt2jVNFKbo`rTI3m$am9&dZ^v)`WKfS&h-EQ delta 2398 zcmb7_drVtZ7{Kqj?d`jzj8P~$Sc~9p2SXl?XL&gk>|hg^v-p5(TU;Hbc-qQVVOumY zCeBwrO-v*{|1gUtMw=Mp6QeUT69v>ou5-hzuZ#9j>M5k>z+iW+b1#{{x{Yhf?usP{^L>XcoylmXyx)jAi z235CnT%k9`XgeFkv3JZ|!=;t^ZWN#st<<*2D?RVQln4Euz% zPOz`0UhtR;#9k}hYv@SbZ7#9Ei}~ebBb>-@v`YJDg2JR_k7b;U3ozu&(~$j#|9H>- z@%|W+&NbOv#)VxPzc5bZ+8&jd&Q`(mP8p`1Mo^t6h(Gm4!8am_!ZT~;OJz|N6Jb?H zL$Sn2T=voP6K0E}o8i~Ov*ddCv8akvK-t=N3oDsg)sBQ?an&9S#Y2I3HwzE<1(cBx zt%e-eo$!RqT~UnDm^R-a+JVw`#5D{m3905`szgGAfoNhhPB+16mtS``+OLPJ++`Q2 zmSH8ptV%4P1VgHJ>_&yEns9Iz9ftedo5=w<>aI06VgT-BvJmW|!?8gbRYrCvL)}aj zo04#IPnfOXGZm*I#izCK+PZRaQUj;fUAxzB73N$815R=JghTi+(=G;jc2z z%LbGy4XCegt6)wGR-?Z{v*57#J(>lNgmRVSZ?Z1bqU%D7G+;EVS`1Jv(tyLLW*b

NF0NN@@vVl*RrY*{T`_2S+h&ct@65nWW{mf~}ZD-=CS#UX;9uM(}yoWaUey6^)?F zPK!)R*TA@^UB5+?b`k1LO?$2(C6}XbE20E}@dt=XVll!bR*|S|0&iI{Sp=nQCo9XD zva0OkOsyK(p#>5nN<2inQugvvEx8VAD;IRzFy?A-R4ox7Xsg|%5iYLwI!oD%D>i03 zvrl-tcv?9mzZvH`bJp1l(0qcL`Ps&0~;r=?f@-hB$`6uhT^Y zUp-+Hv(R+SjO|NQo@I#TGQhHXwV^eW!$~-KsY_fDQl^dj#qE5De9Yy5iN1$1Gl=&Q zA0V0#vxqswhlr05ClUYHWE>v(6UShwu0hA=J_6vJz2WCK-F z62WjZlLMdabEZ9a%P(k2$LHG+5II+T(KehF2ebPt1Sh$uTl!7z={`%(88B7p`ewnG^Usrs8jaU~w7RKjh2 z7|r|!t43)Y_O=$(@Z-QdXfFCJqVz9c#sUfK2o182(e*IXI-Kb^CyPlI!P*9=J{Awh z13NlXH?)07eE;hlaFX-SAqRDcT9~-3PS4LFhrovVd^qN51ly*EIv4n&5jw=D2o-S@ z!K`e4t^paI6j5A4zYyz7V#Y-jaWvUMyw$C*=|D#`?L}cUfD^$ z2b=GK3$ZEa4~R1inZM4yObh)4ulP3FU&ZhKj1D~AUw~}BS5JRKg#as?J$rdO4&j*B zgoyrHga(17M%^g=-Qdpu)ZiGX!$3X4fG{FV45}?U77s_1k-<1jb?4=p(O^MX5jI2? z9O_2d8%OaQ0q;E07RG<7i{?J-3 diff --git a/__pycache__/vram_node.cpython-312.pyc b/__pycache__/vram_node.cpython-312.pyc deleted file mode 100644 index 097015015496f1e1f2c144e1aa8ce7d46e942424..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 zcmb7FO=ufO6rNq}uGZ4}FNqUUC+*^-sa2@brfnc;e(;at*o|dl%PCPQ%XoKWui4cq zvnzw#P+agKAqBg%;6PJyC^QMaw3m{ed+fyl(U^$?q3tE7%Gglosc%-2tr(KhIlOuA z&3td(yf^R7ug%Rd1mmXioBf%B&>vi=54px{7Jyks7P15fWvjE06+&5bBUwp6mS{yB z*;TTNfJ8KaENKB*GKsE4sy4E!h=^(_D?&|fB1*U~3j5R*v8r9EPAD5I35lj>TuMLV zh=jnJDVehUfKVgvS;VaE3@523Y#st;84<*N%ZipjB9=&`oMc57q^w+$5;BYS&ec8Y{4lmtbZH*3CZAHZ+0$&Xk@;FXxZa33W^Ci%q4(I}{W4$$>~v{{PX z(79xx#1zBG6T_HmshyIn${~Qqbsnv??%M;0c|HoB63d1DwddyT9K@3N!cb#Uf@Yn5>a+wnApCT3oeiK4EK{9 z#ZxZHL)y$*=D{*TJOW`{yMTe0B?Md>j-0^Xk|o(fPPF9PqAiT0gpy_|C0C0!B^HbJ zj*MJN^`u$UA~{@if(wuj73WLAw4I+~dvYE%36COijAGvLum#VDuNwg*9(cj`xifkg zH5MOCk4|Ka%$3p9_}q~fc%N+8!~^bk1DQt^1vMX7Km7Ww57*v!`-f8x$m)sy)nlm* zIdZV25|P_t6(l#s!hk0P+6fpI1E*_2DINwz<<8fi>*H`Yh?0#Ry%z`OG@-{ckY(TG zL8=e_2E(BJ1l}*BU^}1|gzOvitynKEp>Zv;qrE25*BVgL&PuR-&I~_g*QjUyIlFQL zn!oCB%&2v4XKp};t%k46@b|iF%(U)OfLO=Ufd;>~n+W*xa*ORRw)mgey)VV?#6H>( zhaD~C!x9=Za!ttbhpeWV5Su%3_J5D!aqy>d=kCw?$Nj0^iGfe_^hp26X`Ppu-dJaP z_bB!;B@Rv$djX^C`djDp%AK#i*E1CR4z_UK^7ODgJYTo-*bMAh;IQss-6gI^ZLD*v z-F>4IiDWWaJlkMq`OCi^Eb1x8b^*x^1tjl#l=%8|@t6BFhx1^{A`P~f`;?m*u}e-B5V+D86<`(E|7ULkfoHMp z;7NzDIB^R>$uKdLCX3qz)2M+G5gG>%!_ubw`|)`tLCmWiSqEXR>qR|frxS$8?_l#h zT34Hw#HEu<-Phf+dI+S|w)17RXG1~StLs|(>YmGG?W1+A<&ma8)bz5}wWXk@merQw zvYK93V~epHu`e{xY3+-rZ=8MljiEMtmUYJPtWd=u}yZ7~EQUfDnSE$aByFRx4T*nD-8~!^$7SL0< zZ9`P#*k%MN?G?^d+EB;gr4QyWt?ku;w06#4Tx(6vU)+=q$eqSy8NJf0%_yJBs-HS{Rojwo-BEaC^W`rGm=hMw(mnW<;M0(|4==t{S>*f}MX+uTY-lcbMo|#vl3N3$&$Ar!b0s>bQTQ|5E G-r`?zL_Pli diff --git a/image.py b/image.py index 06db9dc..992ca49 100644 --- a/image.py +++ b/image.py @@ -129,8 +129,8 @@ class SessionImageSender: break if not found: - print(f" -> ⚠️ ALERTA: No se detectó rostro frontal en NINGÚN frame. Salvando el ciclo usando el frame 0 por defecto.") - best_idx = 0 + print(f" -> ⚠️ ALERTA: No se detectó rostro frontal en NINGÚN frame. Aceptando todo el lote para evitar bucles infinitos.") + best_idx = batch_size - 1 except Exception as e: print(f" -> ⚠️ Error en OpenCV al validar: {e}") else: diff --git a/loop.py b/loop.py index c13bf7c..230c74d 100644 --- a/loop.py +++ b/loop.py @@ -162,14 +162,16 @@ class AutoLoopCalculatorLTX: print(f" -> ⚖️ Sin caras detectadas. Forzando corte equitativo: {ideal_cut}") effective_chunk_frames = math.ceil((best_cut - current_pos) / select_every_nth) - # Forzar a 8n + 1 - effective_chunk_frames = ((effective_chunk_frames - 1) // 8) * 8 + 1 + + # Redondear siempre hacia ARRIBA al (8n + 1) más cercano + effective_chunk_frames = ((effective_chunk_frames + 6) // 8) * 8 + 1 if effective_chunk_frames < 9: effective_chunk_frames = 9 # Mínimo vital LTX - if current_pos + (effective_chunk_frames * select_every_nth) > safe_source_frame_count: - effective_chunk_frames = (safe_source_frame_count - current_pos) // select_every_nth + # ELIMINAMOS el recorte final que rompe la regla 8n + 1 + if current_pos + (effective_chunk_frames * select_every_nth) >= safe_source_frame_count: + print(f" -> 🏁 Chunk final LTX detectado. Ajustando a {effective_chunk_frames} frames para mantener regla 8n+1.") skip_frames = current_pos diff --git a/video.py b/video.py index 5a22473..07338ec 100644 --- a/video.py +++ b/video.py @@ -468,13 +468,18 @@ class AutoLoopCalculatorWan: # 4. Cálculo final del chunk consolidado effective_chunk_frames = math.ceil((best_cut - current_pos) / select_every_nth) - effective_chunk_frames = (effective_chunk_frames // 4) * 4 + + # Redondear siempre hacia ARRIBA al múltiplo de 4 más cercano para evitar chunks inválidos + effective_chunk_frames = ((effective_chunk_frames + 3) // 4) * 4 if effective_chunk_frames < 4: effective_chunk_frames = 4 - if current_pos + (effective_chunk_frames * select_every_nth) > safe_source_frame_count: - effective_chunk_frames = (safe_source_frame_count - current_pos) // select_every_nth + # ELIMINAMOS el recorte final que rompe el múltiplo de 4. + # Si pedimos más frames de los que quedan, VHS duplicará el último frame automáticamente, + # salvando así el renderizado sin crashear el 3D VAE. + if current_pos + (effective_chunk_frames * select_every_nth) >= safe_source_frame_count: + print(f" -> 🏁 Chunk final detectado. Ajustando a {effective_chunk_frames} frames para mantener múltiplo de 4.") skip_frames = current_pos