
    +j9                     b   d dl mZ d dlmZ d dlmZmZmZmZm	Z	 d dl
mZmZ d dlmZmZmZmZmZmZmZmZmZmZmZmZmZmZ dZdZdZd	ed
z  dej         d
z  ded
z  fdZ!de"ej#                 dej         dedefdZ$de"ej#                 dej         dede%dedefdZ&de'dej(        j        fdZ)dej        de'de*ej                 fdZ+de"ej#                 dedefdZ,dededefdZ-dededed
z  fdZ. G d  d!ej#                  Z/ G d" d#ej#                  Z0 G d$ d%e          Z1de1fd&Z2d
S )'    )Fraction)override)IOComfyExtensionInput	InputImplTypes)CreateSwitchXRequestSwitchXStatusResponse)ApiEndpointbytesio_to_image_tensorconvert_mask_to_imagedownload_url_as_bytesiodownload_url_to_image_tensordownload_url_to_video_outputdownscale_image_tensordownscale_video_to_max_pixelspoll_opsync_opupload_image_to_comfyapiupload_video_to_comfyapivalidate_stringvalidate_video_frame_countiPD*    i  promptNreference_imagereturnc                     | r|                                  nd}|s|t          d          |rt          |dt                     |pdS )zVBeeble requires at least one of prompt or reference_image. Returns the cleaned prompt. Nz?At least one of 'prompt' or 'reference_image' must be provided.F)strip_whitespace
max_length)strip
ValueErrorr   _MAX_PROMPT_LEN)r   r   cleaneds      </home/wildlama/comfy/ComfyUI/comfy_api_nodes/nodes_beeble.py_validate_inputsr'       s]     &.fllnnnBG \.Z[[[ U%OTTTT?d    clsmask
wait_labelc                   K   |                                 dk    r|                    d          }t          |dd                   }t          | |d|t                     d{V S )zCEncode a single-frame MASK (H, W) or (1, H, W) as a PNG and upload.   r   N   	image/png	mime_typer+   total_pixels)dim	unsqueezer   r   _MAX_PIXELS)r)   r*   r+   images       r&   _upload_mask_as_imager7   *   s       xxzzQ~~a  !$rr(++E)          r(   
frame_ratesource_frame_countc                  K   |                                 dk    r|                    d          }|j        d         |k    r!t          d|j        d          d| d          t	          t          |          t                    }t          j        t          j
        |d|                    }t          | ||           d{V S )	ut  Encode a MASK batch (N, H, W) as a grayscale H.264 MP4 at frame_rate and upload.

    The matte is always downscaled to the pixel budget so it stays within Beeble's limit and
    keeps the same dimensions as the (similarly downscaled) source — both use the same algorithm
    from the same starting dimensions, and downscaling is a no-op when already within budget.
    r-   r   z Custom alpha video frame count (z/) does not match the source video frame count (z5). The Beeble API requires one mask per source frame.N)imagesaudior8   r+   )r3   r4   shaper#   r   r   r5   r   VideoFromComponentsr	   VideoComponentsr   )r)   r*   r8   r9   r+   r;   alpha_videos          r&   _upload_mask_batch_as_videorB   =   s       xxzzQ~~a  z!}***)tz!} ) ));) ) )
 
 	

 $$9$$?$?MMF/0EV[_lv0w0w0wxxK)#{zRRRRRRRRRRr(   videoc                    | rdnd}| rdnd}t           j                            ddt           j                            dg           t           j                            dg           t           j                            d	t           j                            d
|          g          t           j                            dt           j                            d|          g          g          S )zBBuild the alpha_mode DynamicCombo with mode-specific extra inputs.zCFirst-frame keyframe mask. Beeble propagates this across the video.zGrayscale keyframe mask.zPer-frame grayscale mask covering the entire video. Must have the same frame count as the source. Connect a MASK output from SAM3_TrackToMask or similar.zGrayscale mask to apply.
alpha_modea  Controls how SwitchX decides what to keep vs. regenerate. 'auto' isolates the main subject automatically. 'fill' regenerates the entire frame while preserving geometry. 'select' propagates a first-frame keyframe across the clip. 'custom' uses a per-frame alpha matte you provide.autofillselectalpha_keyframe)tooltipcustom
alpha_mask)rJ   options)r   DynamicCombor   OptionMask)rC   select_keyframe_tooltipcustom_tooltips      r&   _alpha_mode_inputrS   X   s     RWvMM\v  	( 	B 	B (  ?  A O""62..O""62..O""/9PQQR  O""|^DDE 
 !   r(   sourcec                 <   | t           j                            dddd          t           j                            ddd          t	          |	          t           j                            d
ddgdd          t           j                            dddddd          gS )Nr   Tr   zsText description of the desired output (max 2000 chars). At least one of 'prompt' or 'reference_image' is required.)	multilinedefaultrJ   r   zReference image whose look (background, lighting, costume) the result should adopt. At least one of 'reference_image' or 'prompt' is required.)optionalrJ   )rC   max_resolution1080p720pzMaximum output resolution.)rM   rW   rJ   seedr   iz_Seed controls whether the node should re-run; results are non-deterministic regardless of seed.)rW   minmaxcontrol_after_generaterJ   )r   Stringr   ImagerS   ComboIntrT   rC   s     r&   _common_inputsre   |   s    
	M 	 	
 	
 	[	 	 	
 	
 	&&&
f%0	 	 	
 	
 	#'t 	 		
 		
5$ $r(   requestc                    K   t          | t          dd          t          |           d {V }t          | t          d|j                   t          d d 	           d {V S )
Nz$/proxy/beeble/v1/switchx/generationsPOST)pathmethod)response_modeldataz%/proxy/beeble/v1/switchx/generations/)ri   c                     | j         S N)statusrs    r&   <lambda>z"_submit_and_poll.<locals>.<lambda>   s    18 r(   c                     | j         S rn   )progressrp   s    r&   rr   z"_submit_and_poll.<locals>.<lambda>   s    QZ r(   )rk   status_extractorprogress_extractor)r   r   r   r   id)r)   rf   initials      r&   _submit_and_pollry      s       ?OOO,	        G MMMNNN,++//         r(   responsenamec                     | j         t          | j         |          t          d| j         d|d          t          | j         |          S )NzBeeble job z completed without a z output URL.)outputgetattrRuntimeErrorrw   )rz   r{   s     r&   _require_output_urlr      sQ    '(/4"@"@"H___4___```8?D)))r(   modec                 8    |dk    s| j         dS | j         j        S )ur  URL of the alpha matte, or None when the mode produces no separate matte.

    'fill' selects the whole frame, so Beeble writes no alpha asset even though the status
    response still returns a (dangling) signed URL for it — fetching it 403s with S3
    AccessDenied. The other three modes ('auto', 'custom', 'select') all produce a real,
    downloadable matte.
    rG   N)r}   alpha)rz   r   s     r&   
_alpha_urlr      s$     v~~0t?  r(   c                       e Zd Zedej        fd            Ze	 ddej        de	de
de	ded	ej        dz  dej        fd
            ZdS )BeebleSwitchXVideoEditr   c                    t          j        ddddt          t           j                            d          d          t           j                            d          t           j                            d	d
          gt           j        j        t           j        j        t           j        j	        gdt          j
        t          j        dg          d          	  	        S )Nr   zBeeble SwitchX Video Editzpartner/video/Beeblea	  Edit a video with Beeble SwitchX. Switches anything in the scene (background, lighting, costume) while preserving the original subject's pixels and motion. Provide a reference image and/or text prompt to describe the new look. Max 240 frames, max ~2.77MP per frame.rC   Trd   display_namer   PThe alpha matte Beeble used. Empty for 'fill' mode, which has no separate matte.r   rJ   rY   widgetsz
                (
                  $rate := widgets.max_resolution = "1080p" ? 0.429 : 0.143;
                  {"type":"usd","usd": $rate, "format":{"suffix":"/30 frames"}}
                )
                
depends_onexpr	node_idr   categorydescriptioninputsoutputshiddenis_api_nodeprice_badge)r   Schemare   Videor   OutputHiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgePriceBadgeDependsr)   s    r&   define_schemaz$BeebleSwitchXVideoEdit.define_schema   s    y,4+9
 ")@)@MMMW55!(n     	.	+	#
 /9I8JKKK  1!
 !
 !
 !	
r(   NrC   r   rE   rY   r\   r   c           
        K   t          ||          }t          |t                     t          |t                    }|d         }d }	|dk    rt          | |d         d           d {V }	nJ|dk    rDt          | |d         |                                |                                d	
           d {V }	t          | |d           d {V }
d }|t          | |ddt                     d {V }t          d|
||||	|dk    rdnd          }t          | |           d {V }t          t          |d                     d {V }d }t          ||          x}t          |           d {V }t!          j        ||          S )N)max_frame_countrE   rH   rI   Uploading keyframer=   rK   rL   zUploading alpha video)r8   r9   r+   Uploading sourcer/   Uploading referencer0   rC   rZ   8    generation_type
source_urirE   r   reference_image_uri	alpha_urirY   render)r'   r   _MAX_FRAMESr   r5   r7   rB   get_frame_rateget_frame_countr   r   r
   ry   r   r   r   r   
NodeOutput)r)   rC   r   rE   rY   r\   r   cleaned_promptr   r   r   reference_urirf   rz   r   r   	alpha_urls                    r&   executezBeebleSwitchXVideoEdit.execute   s2      *&/BB"5+FFFF-e[AA,' $	83CDT9UbvwwwwwwwwwIIX9<( //11#(#8#8#:#:2        I 4CK]^^^^^^^^^
$(&":%0(# # #      M '#!! -#1W#<#<44#
 
 
 *#w7777777734GRZ4[4[\\\\\\\\#Hd333I@6yAAAAAAAAE}VU+++r(   rn   )__name__
__module____qualname__classmethodr   r   r   r   r   strdictintra   r   r    r(   r&   r   r      s        "
bi "
 "
 "
 ["
H  /35, 5,{5, 5, 	5,
 5, 5, t+5, 
5, 5, 5, [5, 5, 5,r(   r   c                       e Zd Zedej        fd            Ze	 ddej        de	de
de	ded	ej        dz  dej        fd
            ZdS )BeebleSwitchXImageEditr   c                    t          j        ddddt          t           j                            d          d          t           j                            d          t           j                            d	d
          gt           j        j        t           j        j	        t           j        j
        gdt          j        t          j        dg          d          	  	        S )Nr   zBeeble SwitchX Image Editzpartner/image/BeeblezEdit a single image with Beeble SwitchX. Switches anything in the scene (background, lighting, costume) while preserving the original subject's pixels. Provide a reference image and/or text prompt to describe the new look. Max ~2.77MP.r6   Frd   r   r   r   r   TrY   r   z
                (
                  $rate := widgets.max_resolution = "1080p" ? 0.429 : 0.143;
                  {"type":"usd","usd": $rate}
                )
                r   r   )r   r   re   ra   r   r   rP   r   r   r   r   r   r   r   s    r&   r   z$BeebleSwitchXImageEdit.define_schema,  s    y,4+
 ")@)@NNNW55!(n    	.	+	#
 /9I8JKKK  1!
 !
 !
 !	
r(   Nr6   r   rE   rY   r\   r   c           
        K   t          ||          }t          |t                    }|d         }d }	|dk    rt          | |d         d           d {V }	n$|dk    rt          | |d         d           d {V }	t	          | |d	d
d            d {V }
d }|t	          | |d	dt                     d {V }t          d|
||||	|dk    rdnd          }t          | |           d {V }t          t          |d                     d {V }d }t          ||          x}St          t          |           d {V d          }|                                dk    r|                    d          n|}t          j        ||          S )NrE   rH   rI   r   r=   rK   rL   zUploading alphar/   r   r0   r   r6   rZ   r   r   r   r   L)r      )r'   r   r5   r7   r   r
   ry   r   r   r   r   r   r3   squeezer   r   )r)   r6   r   rE   rY   r\   r   r   r   r   r   r   rf   rz   r   rL   r   alpha_images                     r&   r   zBeebleSwitchXImageEdit.executeQ  sD      *&/BB&uk::,' $	83CDT9UbvwwwwwwwwwIIX3CL9Q^opppppppppI3!)
 
 
 
 
 
 
 
 

 %)&":%0(# # #      M '#!! -#1W#<#<44#
 
 
 *#w7777777734GRZ4[4[\\\\\\\\
#Hd333I@18OPY8Z8Z2Z2Z2Z2Z2Z2ZadeeeK4?OO4E4E4J4J,,R000P[J}VZ000r(   rn   )r   r   r   r   r   r   r   r   ra   r   r   r   r   r   r   r(   r&   r   r   *  s        "
bi "
 "
 "
 ["
H  /351 51{51 51 	51
 51 51 t+51 
51 51 51 [51 51 51r(   r   c                   L    e Zd Zedeeej                          fd            ZdS )BeebleExtensionr   c                 "   K   t           t          gS rn   )r   r   )selfs    r&   get_node_listzBeebleExtension.get_node_list  s       #"
 	
r(   N)	r   r   r   r   listtyper   	ComfyNoder   r   r(   r&   r   r     sE        
T$r|*<%= 
 
 
 X
 
 
r(   r   c                  "   K   t                      S rn   )r   r   r(   r&   comfy_entrypointr     s      r(   )3	fractionsr   typing_extensionsr   comfy_api.latestr   r   r   r   r	   comfy_api_nodes.apis.beebler
   r   comfy_api_nodes.utilr   r   r   r   r   r   r   r   r   r   r   r   r   r   r5   r   r$   r   ra   r'   r   r   r7   r   rB   boolrN   rS   r   re   ry   r   r   r   r   r   r   r   r(   r&   <module>r      s         & & & & & & H H H H H H H H H H H H H H                                      " S4Z %+:L QTW[Q[    	bl	
+ 	
 	   &S	bl	S
+S 	S
 S S 	S S S S6! !)> ! ! ! !H%bh %t %RX % % % %P	bl	!    &*"7 *s *s * * * *
!. 
!c 
!cDj 
! 
! 
! 
!], ], ], ], ],R\ ], ], ],@]1 ]1 ]1 ]1 ]1R\ ]1 ]1 ]1@
 
 
 
 
n 
 
 
      r(   