o
    i                     @   sR  d dl Z d dlmZmZ d dlmZ d dlmZ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 G dd deZG dd	 d	eZG d
d deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZ G dd deZ!G dd deZ"G d d! d!eZ#G d"d# d#eZ$G d$d% d%eZ%G d&d' d'eZ&G d(d) d)eZ'G d*d+ d+e%Z(G d,d- d-e%Z)G d.d/ d/eZ*G d0d1 d1eZ+e ,d2Z-G d3d4 d4ej.Z/G d5d6 d6ej.Z0G d7d8 d8ej.Z1G d9d: d:ej.Z2G d;d< d<ej.Z3G d=d> d>eZ4d?e4fd@dAZ5dS )B    N)	BaseModelField)override)IOComfyExtensionInput)ApiEndpointaudio_to_base64_stringdownload_url_to_image_tensordownload_url_to_video_outputget_number_of_imagespoll_opsync_optensor_to_base64_stringupload_video_to_comfyapivalidate_audio_durationvalidate_video_durationc                   @   s2   e Zd ZU edZeed< edZedB ed< dS )Text2ImageInputField.promptNnegative_prompt)__name__
__module____qualname__r   r   str__annotations__r    r   r   7/mnt/c/Users/fbmor/ComfyUI/comfy_api_nodes/nodes_wan.pyr      s   
 r   c                   @   sL   e Zd ZU edZeed< edZedB ed< eddddZe	e ed< dS )	Image2ImageInputField.r   Nr         )
min_length
max_lengthimages)
r   r   r   r   r   r   r   r   r"   listr   r   r   r   r      s   
 r   c                   @   sF   e Zd ZU edZeed< edZedB ed< edZedB ed< dS )Text2VideoInputField.r   Nr   	audio_url)	r   r   r   r   r   r   r   r   r%   r   r   r   r   r$   !      
 r$   c                   @   sV   e Zd ZU edZeed< edZedB ed< edZeed< edZ	edB ed< dS )Image2VideoInputField.r   Nr   img_urlr%   )
r   r   r   r   r   r   r   r   r(   r%   r   r   r   r   r'   '   s
   
 r'   c                   @   sF   e Zd ZU edZeed< edZedB ed< edZe	e ed< dS )Reference2VideoInputField.r   Nr   reference_video_urls)
r   r   r   r   r   r   r   r   r*   r#   r   r   r   r   r)   .   r&   r)   c                   @   sh   e Zd ZU edZeed< edddZeed< edddd	Z	eed
< edZ
eed< edZeed< dS )Txt2ImageParametersField.sizer   Number of images to generate.descriptionnr   geleseedTprompt_extendF	watermarkN)r   r   r   r   r,   r   r   r0   intr5   r6   boolr7   r   r   r   r   r+   4   s   
 r+   c                   @   s\   e Zd ZU edZedB ed< edddZeed< eddd	d
Z	eed< edZ
eed< dS )Image2ImageParametersFieldNr,   r   r-   r.   r0   .r   r1   r2   r5   Fr7   )r   r   r   r   r,   r   r   r0   r8   r5   r7   r9   r   r   r   r   r:   <   s
   
 r:   c                   @      e Zd ZU edZeed< eddddZeed< eddddZ	eed	< ed
Z
eed< edZeed< edddZeed< edZeed< dS )Text2VideoParametersField.r,   r   r1   r2   r5         durationTr6   Fr7   (Whether to generate audio automatically.r.   audiosingle	shot_typeN)r   r   r   r   r,   r   r   r5   r8   r?   r6   r9   r7   rA   rC   r   r   r   r   r<   C      
 r<   c                   @   r;   )Image2VideoParametersField.
resolutionr   r1   r2   r5   r=   r>   r?   Tr6   Fr7   r@   r.   rA   rB   rC   N)r   r   r   r   rF   r   r   r5   r8   r?   r6   r9   r7   rA   rC   r   r   r   r   rE   M   rD   rE   c                   @   sj   e Zd ZU edZeed< eddddZeed< edZ	eed< edd	d
dZ
eed< edZeed< dS )Reference2VideoParametersField.r,   r=   r>   r2   r?   rB   rC   r   r1   r5   Fr7   N)r   r   r   r   r,   r   r   r?   r8   rC   r5   r7   r9   r   r   r   r   rG   W   s   
 rG   c                   @   >   e Zd ZU edZeed< edZeed< edZ	e
ed< dS )Text2ImageTaskCreationRequest.modelinput
parametersN)r   r   r   r   rJ   r   r   rK   r   rL   r+   r   r   r   r   rI   _      
 rI   c                   @   rH   )Image2ImageTaskCreationRequest.rJ   rK   rL   N)r   r   r   r   rJ   r   r   rK   r   rL   r:   r   r   r   r   rN   e   rM   rN   c                   @   rH   )Text2VideoTaskCreationRequest.rJ   rK   rL   N)r   r   r   r   rJ   r   r   rK   r$   rL   r<   r   r   r   r   rO   k   rM   rO   c                   @   rH   )Image2VideoTaskCreationRequest.rJ   rK   rL   N)r   r   r   r   rJ   r   r   rK   r'   rL   rE   r   r   r   r   rP   q   rM   rP   c                   @   rH   )"Reference2VideoTaskCreationRequest.rJ   rK   rL   N)r   r   r   r   rJ   r   r   rK   r)   rL   rG   r   r   r   r   rQ   w   rM   rQ   c                   @   s.   e Zd ZU edZeed< edZeed< dS )TaskCreationOutputField.task_idtask_statusN)r   r   r   r   rS   r   r   rT   r   r   r   r   rR   }   s   
 rR   c                   @   sb   e Zd ZU edZedB ed< edZeed< edddZ	edB ed< edddZ
edB ed	< dS )
TaskCreationResponseNoutput.
request_idz"Error code for the failed request.r.   codez!Details about the failed request.message)r   r   r   r   rV   rR   r   rW   r   rX   rY   r   r   r   r   rU      s
   
 rU   c                   @   sJ   e Zd ZU edZedB ed< edZedB ed< edZedB ed< dS )
TaskResultNurlrX   rY   )	r   r   r   r   r[   r   r   rX   rY   r   r   r   r   rZ      s   
 rZ   c                   @   sF   e Zd ZU edZeed< edZeed< edZe	e
 dB ed< dS )ImageTaskStatusOutputField.rS   rT   Nresults)r   r   r   r   rS   r   r   rT   r]   r#   rZ   r   r   r   r   r\      s   
 r\   c                   @   sj   e Zd ZU edZeed< edZeed< edZedB ed< edZ	edB ed< edZ
edB ed< dS )VideoTaskStatusOutputField.rS   rT   N	video_urlrX   rY   )r   r   r   r   rS   r   r   rT   r_   rX   rY   r   r   r   r   r^      s   
 r^   c                   @   2   e Zd ZU edZedB ed< edZeed< dS )ImageTaskStatusResponseNrV   .rW   )	r   r   r   r   rV   r\   r   rW   r   r   r   r   r   ra         
 ra   c                   @   r`   )VideoTaskStatusResponseNrV   .rW   )	r   r   r   r   rV   r^   r   rW   r   r   r   r   r   rc      rb   rc   u   \((\d+)\s*[x×]\s*(\d+)\)c                   @   sT   e Zd Zedd Ze						dded	ed
edededededefddZdS )WanTextToImageApic                 C   s   t jddddt jjddgdddt jjd	d
dddt jjdd
ddd
dt jjdddddd
dt jjdddddd
dt jjdddddt jjd
dd
d	t jjdd
dd
d
d t jjd!d"d#d
d
d gt j	
 gt jjt jjt jjgd
t jd$d%d&	S )'Nrd   zWan Text to Imageapi node/image/Wanz*Generates an image based on a text prompt.rJ   zwan2.5-t2i-previewModel to use.optionsdefaulttooltipr   T QPrompt describing the elements and visual features. Supports English and Chinese.	multilineri   rj   r   )Negative prompt describing what to avoid.rn   ri   rj   optionalwidth   i   i      )ri   minmaxsteprq   heightr5   r   r1   r   Seed to use for generation.ri   ru   rv   rw   display_modecontrol_after_generaterj   rq   r6   1Whether to enhance the prompt with AI assistance.ri   rj   rq   advancedr7   F7Whether to add an AI-generated watermark to the result.{"type":"usd","usd":0.03}expr	node_iddisplay_namecategoryr/   inputsoutputshiddenis_api_nodeprice_badge)r   SchemaCombor   StringIntNumberDisplaynumberBooleanImageOutputHiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgeclsr   r   r   define_schema   s   ?zWanTextToImageApi.define_schemark   rs   r   TFrJ   r   r   rr   rx   r5   r6   r7   c	                    s   t | tdddtt|t||dt| d| |||dddI d H }	|	js3td	|	j d
|	j	 t
| td|	jj dtdd dddI d H }
ttt|
jjd jI d H S )Nz:/proxy/wan/api/v1/services/aigc/text2image/image-synthesisPOSTpathmethod)r   r   *)r,   r5   r6   r7   rJ   rK   rL   response_modeldataAn unknown error occurred:  - /proxy/wan/api/v1/tasks/r   c                 S      | j jS NrV   rT   xr   r   r   <lambda>      z+WanTextToImageApi.execute.<locals>.<lambda>	      r   status_extractorestimated_durationpoll_intervalr   )r   r   rU   rI   r   r+   rV   	ExceptionrX   rY   r   rS   ra   r   
NodeOutputr
   r   r]   r[   )r   rJ   r   r   rr   rx   r5   r6   r7   initial_responseresponser   r   r   execute   s6   

"zWanTextToImageApi.executeN)rk   rs   rs   r   TF)	r   r   r   classmethodr   r   r8   r9   r   r   r   r   r   rd      s6    
R	rd   c                   @   sH   e Zd Zedd Ze			ddedejded	ed
ede	fddZ
dS )WanImageToImageApic                 C   s   t jddddt jjddgdddt jjd	d
dt jjdddddt jjddddddt jjdddddt jjdddd	t j	jddddddgt j
 gt jjt jjt jjgdt jddd 	S )!Nr   zWan Image to Imagere   zGenerates an image from one or two input images and a text prompt. The output image is currently fixed at 1.6 MP, and its aspect ratio matches the input image(s).rJ   zwan2.5-i2i-previewrf   rg   imagez=Single-image editing or multi-image fusion. Maximum 2 images.)rj   r   Trk   rl   rm   r   ro   rp   r5   r   r1   r   ry   rz   r7   Fr   r~   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   '  st   =z WanImageToImageApi.define_schemark   r   FrJ   r   r   r   r5   r7   c                    s   t |}|dvrtd| dg }|D ]}	|dt|	dd  qt| tddd	tt|t|||d
t	||dddI d H }
|
j
sOtd|
j d|
j t| td|
j
j dtdd dddI d H }ttt|j
jd jI d H S )N)r   r   z&Expected 1 or 2 input images, but got .data:image/png;base64,i   total_pixelsz;/proxy/wan/api/v1/services/aigc/image2image/image-synthesisr   r   )r   r   r"   )r5   r7   r   r   r   r   r   r   c                 S   r   r   r   r   r   r   r   r     r   z,WanImageToImageApi.execute.<locals>.<lambda>*      r   r   )r   
ValueErrorappendr   r   r   rU   rN   r   r:   rV   r   rX   rY   r   rS   ra   r   r   r
   r   r]   r[   )r   rJ   r   r   r   r5   r7   n_imagesr"   ir   r   r   r   r   r   y  s>   
"zWanImageToImageApi.executeN)rk   r   F)r   r   r   r   r   r   r   r   r8   r9   r   r   r   r   r   r   &  s(    
Q	r   c                   @   sl   e Zd Zedd Ze										
ddedededededejdB dede	de	de	defddZ
dS )WanTextToVideoApic                 C   s@  t jddddt jjdddgddd	t jjd
ddddt jjddddddt jjdg ddddt jjdddddt jjdddt jjddddt jjdddd d!t jjdd"dd#	t j	jd$d%dd&dd't j	jd(dd)ddd*t j	jd+d%d,ddd*t jjd-d.d/gd0ddd1gt j
 gt jjt jjt jjgdt jt jddgd2d3d4d5	S )6Nr   zWan Text to Videoapi node/video/Wanz)Generates a video based on a text prompt.rJ   wan2.5-t2v-preview
wan2.6-t2vrf   rg   r   Trk   rl   rm   r   ro   rp   r,   )z480p: 1:1 (624x624)z480p: 16:9 (832x480)z480p: 9:16 (480x832)720p: 1:1 (960x960)720p: 16:9 (1280x720)720p: 9:16 (720x1280)720p: 4:3 (1088x832)720p: 3:4 (832x1088)1080p: 1:1 (1440x1440)1080p: 16:9 (1920x1080)1080p: 9:16 (1080x1920)1080p: 4:3 (1632x1248)1080p: 3:4 (1248x1632)r   rh   ri   rq   r?   r=   r>   z=A 15-second duration is available only for the Wan 2.6 model.ri   ru   rv   rw   r{   rj   rq   rA   UAudio must contain a clear, loud voice, without extraneous noise or background music.rq   rj   r5   r   r1   r   ry   rz   generate_audioF<If no audio input is provided, generate audio automatically.ri   rq   rj   r   r6   r}   r~   r7   r   rC   rB   multiSpecifies the shot type for the generated video, that is, whether the video is a single continuous shot or multiple shots with cuts. This parameter takes effect only when prompt_extend is True.rh   rj   rq   r   widgetsaJ  
                (
                  $ppsTable := { "480p": 0.05, "720p": 0.1, "1080p": 0.15 };
                  $resKey := $substringBefore(widgets.size, ":");
                  $pps := $lookup($ppsTable, $resKey);
                  { "type": "usd", "usd": $round($pps * widgets.duration, 2) }
                )
                
depends_onr   r   )r   r   r   r   r   r   r   r   Audior   Videor   r   r   r   r   r   PriceBadgeDependsr   r   r   r   r     s   
bzWanTextToVideoApi.define_schemark   r   r=   Nr   FTrB   rJ   r   r   r,   r?   rA   r5   r   r6   r7   rC   c                    s*  d|v r|dkrt d|dkr|dkrt dt| \}}d }|d ur6t|dd d	t|d
d }t| tdddtt	|t
|||dt| d| ||||	|
|dddI d H }|jsltd|j d|j t| td|jj dtdd dt|d  ddI d H }tt|jjI d H S )N480pr   z(The Wan 2.6 model does not support 480p.r>   r   <A 15-second duration is supported only by the Wan 2.6 model.      @      =@data:audio/mp3;base64,mp3
libmp3lame@/proxy/wan/api/v1/services/aigc/video-generation/video-synthesisr   r   )r   r   r%   r   )r,   r?   r5   rA   r6   r7   rC   r   r   r   r   r   r   c                 S   r   r   r   r   r   r   r   r   V  r   z+WanTextToVideoApi.execute.<locals>.<lambda>x   r=      r   )r   RES_IN_PARENSsearchgroupsr   r	   r   r   rU   rO   r$   r<   rV   r   rX   rY   r   rS   rc   r8   r   r   r   r_   )r   rJ   r   r   r,   r?   rA   r5   r   r6   r7   rC   rr   rx   r%   r   r   r   r   r   r   %  sN   
zWanTextToVideoApi.execute)	rk   r   r=   Nr   FTFrB   )r   r   r   r   r   r   r8   r   r   r9   r   r   r   r   r   r     sH    
}	
r   c                   @   sr   e Zd Zedd Ze										
ddedejdededededej	dB dede
de
de
defddZdS )WanImageToVideoApic                 C   sJ  t jddddt jjdddgddd	t jd
t jjdddddt jjddddddt jjdg ddddt jjdddddt jjdddt j	jddddt jjdd d d!d"t jjdd#dd$	t j
jd%d&dd'dd(t j
jd)dd*ddd+t j
jd,d&d-ddd+t jjd.d/d0gd1ddd2gt j gt jjt jjt jjgdt jt jddgd3d4d5d6	S )7Nr   zWan Image to Videor   z9Generates a video from the first frame and a text prompt.rJ   wan2.5-i2v-preview
wan2.6-i2vrf   rg   r   r   Trk   rl   rm   r   ro   rp   rF   )480P720P1080Pr   r   r?   r=   r>   z,Duration 15 available only for WAN2.6 model.r   rA   r   r   r5   r   r1   r   ry   rz   r   Fr   r   r6   r}   r~   r7   r   rC   rB   r   r   r   r   a  
                (
                  $ppsTable := { "480p": 0.05, "720p": 0.1, "1080p": 0.15 };
                  $pps := $lookup($ppsTable, widgets.resolution);
                  { "type": "usd", "usd": $round($pps * widgets.duration, 2) }
                )
                r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ^  s   

[z WanImageToVideoApi.define_schemark   r   r=   Nr   FTrB   rJ   r   r   r   rF   r?   rA   r5   r   r6   r7   rC   c                    s4  t |dkrtdd|v r|dkrtd|dkr#|dkr#tdd	t|d
d }d }|d ur?t|dd dt|dd }t| tdddtt|t	||||dt
||||	|
||dddI d H }|jsqtd|j d|j t| td|jj dtdd dt|d  d d!I d H }tt|jjI d H S )"Nr   z$Exactly one input image is required.r   r   z(The Wan 2.6 model does not support 480P.r>   r   r   r   i 	= r   r   r   r   r   r   r   r   r   )r   r   r(   r%   )rF   r?   r5   rA   r6   r7   rC   r   r   r   r   r   r   c                 S   r   r   r   r   r   r   r   r   	  r   z,WanImageToVideoApi.execute.<locals>.<lambda>r   r=   r   r   )r   r   r   r   r	   r   r   rU   rP   r'   rE   rV   r   rX   rY   r   rS   rc   r8   r   r   r   r_   )r   rJ   r   r   r   rF   r?   rA   r5   r   r6   r7   rC   	image_urlr%   r   r   r   r   r   r     sV   
zWanImageToVideoApi.execute)	rk   r   r=   Nr   FTFrB   )r   r   r   r   r   r   r   r   r8   r   r9   r   r   r   r   r   r   ]  sL    
u	
r   c                   @   sN   e Zd Zedd Zededededejjdede	d	e	d
ede
fddZdS )WanReferenceVideoApic                 C   s  t jddddt jjddgdt jjdd	d
ddt jjdd	d
ddt jjdt jjt jdg ddddt jjdg ddt jjdddddt j	j
dt jjdddddt j	jd	dt jjdd d!gd"d	d#t jjd$d%d&d	d'g	t j gt jjt jjt jjgd	t jt jddgd(d)d*d+	S ),Nr   zWan Reference to Videor   zUse the character and voice from input videos, combined with a prompt, to generate a new video that maintains character consistency.rJ   z
wan2.6-r2v)rh   r   Trk   zPrompt describing the elements and visual features. Supports English and Chinese. Use identifiers such as `character1` and `character2` to refer to the reference characters.rm   r   ro   reference_videosreference_video)
character1
character2
character3r   )namesru   )templater,   )
r   r   r   r   r   r   r   r   r   r   r?   r=   
   )ri   ru   rv   rw   r{   r5   r   r1   )ri   ru   rv   rw   r{   r|   rC   rB   r   zSpecifies the shot type for the generated video, that is, whether the video is a single continuous shot or multiple shots with cuts.)rh   rj   r   r7   Fr   )ri   rj   r   r   a  
                (
                  $rate := $contains(widgets.size, "1080p") ? 0.15 : 0.10;
                  $inputMin := 2 * $rate;
                  $inputMax := 5 * $rate;
                  $outputPrice := widgets.duration * $rate;
                  {
                    "type": "range_usd",
                    "min_usd": $inputMin + $outputPrice,
                    "max_usd": $inputMax + $outputPrice
                  }
                )
                r   r   )r   r   r   r   r   AutogrowTemplateNamesr   r   r   sliderr   r   r   r   r   r   r   r   r   r   r   r   r   r     s   
	Fz"WanReferenceVideoApi.define_schemarJ   r   r   r   r,   r?   r5   rC   r7   c
                    s  g }
|D ]}t || ddd q|D ]}|
t| || I d H  qt| \}}t| tdddtt	|t
|||
dt| d| |||	|d	d
dI d H }|js`td|j d|j t| td|jj dtdd dddI d H }tt|jjI d H S )Nr      )min_durationmax_durationr   r   r   )r   r   r*   r   )r,   r?   rC   r7   r5   r   r   r   r   r   r   c                 S   r   r   r   r   r   r   r   r     r   z.WanReferenceVideoApi.execute.<locals>.<lambda>r   i  )r   r   r   max_poll_attempts)r   r   r   r   r   r   r   r   rU   rQ   r)   rG   rV   r   rX   rY   r   rS   rc   r   r   r   r_   )r   rJ   r   r   r   r,   r?   r5   rC   r7   r*   r   rr   rx   r   r   r   r   r   r   y  sH   
zWanReferenceVideoApi.executeN)r   r   r   r   r   r   r   r  Typer8   r9   r   r   r   r   r   r     s.    
g	
r   c                   @   s(   e Zd Zedeeej  fddZdS )WanApiExtensionreturnc                    s   t ttttgS r   )rd   r   r   r   r   )selfr   r   r   get_node_list  s   zWanApiExtension.get_node_listN)	r   r   r   r   r#   typer   	ComfyNoder  r   r   r   r   r    s    r  r  c                      s   t  S r   )r  r   r   r   r   comfy_entrypoint  s   r  )6repydanticr   r   typing_extensionsr   comfy_api.latestr   r   r   comfy_api_nodes.utilr   r	   r
   r   r   r   r   r   r   r   r   r   r   r$   r'   r)   r+   r:   r<   rE   rG   rI   rN   rO   rP   rQ   rR   rU   rZ   r\   r^   ra   rc   compiler   r  rd   r   r   r   r   r  r  r   r   r   r   <module>   sN    4


|  8 4 