o
    ih                     @   s  d dl Z d dlZd dl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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# dZ$ddd	d
Z%dZ&dZ'ddhZ(e )e*Z+dede,fddZ-G dd dej.Z/G dd dej.Z0G dd dej.Z1G dd dej.Z2G dd dej.Z3G dd dej.Z4de5ej. deeB d e6dB dej7fd!d"Z8d#e,d$e9e, ddfd%d&Z:ej;ej<g d'd(d)d*Z=G d+d, d,eZ>de>fd-d.Z?dS )/    N)override)IOComfyExtensionInput)RECOMMENDED_PRESETSRECOMMENDED_PRESETS_SEEDREAM_4VIDEO_TASKS_EXECUTION_TIMEImage2VideoTaskCreationRequestImageTaskCreationResponseSeedream4OptionsSeedream4TaskCreationRequestTaskCreationResponseTaskImageContentTaskImageContentUrlTaskStatusResponseTaskTextContentText2ImageTaskCreationRequestText2VideoTaskCreationRequest)ApiEndpointdownload_url_to_image_tensordownload_url_to_video_outputget_number_of_imagesimage_tensor_pair_to_batchpoll_opsync_opupload_images_to_comfyapivalidate_image_aspect_ratiovalidate_image_dimensionsvalidate_stringz)/proxy/byteplus/api/v3/images/generationsseedream-5-0-260128seedream-4-5-251128seedream-4-0-250828)zseedream 5.0 liter    r!   z1/proxy/byteplus/api/v3/contents/generations/tasksseedance-1-0-lite-t2v-250428seedance-1-0-lite-i2v-250428responsereturnc                 C   sX   | j rd| j d  d| j d  }t| t|td| jd d  | jd d S )Nz ByteDance request failed. Code: codez, message: messagez'ByteDance task succeeded, image URL: %sr   url)errorlogginginfoRuntimeErrordata)r$   	error_msg r/   =/mnt/c/Users/fbmor/ComfyUI/comfy_api_nodes/nodes_bytedance.pyget_image_url_from_response7   s   
r1   c                   @   sL   e Zd Zedd Zededededededed	ed
ede	j
fddZdS )ByteDanceImageNodec                 C   s   t jddddt jjddgdt jjdd	d
dt jjddd t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$t jj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	d-
S ).Nr2   zByteDance Imageapi node/image/ByteDancez>Generate images using ByteDance models via api based on promptmodelzseedream-3-0-t2i-250415optionspromptTz*The text prompt used to generate the image	multilinetooltipsize_presetc                 S      g | ]\}}}|qS r/   r/   .0label_r/   r/   r0   
<listcomp>R       z4ByteDanceImageNode.define_schema.<locals>.<listcomp>zHPick a recommended size. Select Custom to use the width and height belowr6   r:   width         @   QCustom width for image. Value is working only if `size_preset` is set to `Custom`)defaultminmaxstepr:   heightRCustom height for image. Value is working only if `size_preset` is set to `Custom`seedr      zSeed to use for generationrJ   rK   rL   rM   display_modecontrol_after_generater:   optionalguidance_scaleg      @g      ?      $@g{Gz?z;Higher value makes the image follow the prompt more closelyrJ   rK   rL   rM   rT   r:   rV   	watermarkFz7Whether to add an "AI generated" watermark to the imagerJ   r:   rV   advancedz{"type":"usd","usd":0.03})expr)
node_iddisplay_namecategorydescriptioninputsoutputshiddenis_api_nodeprice_badgeis_deprecated)r   SchemaCombor   Stringr   IntNumberDisplaynumberFloatBooleanImageOutputHiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgeclsr/   r/   r0   define_schemaB   s   
:z ByteDanceImageNode.define_schemar4   r7   r;   rD   rN   rP   rW   rZ   r%   c	                    s   t |ddd d  }	}
tD ]\}}}||kr||}	}
 nq|	d u s'|
d u rN||}	}
d|	  kr6dkrCn nd|
  krBdksNn td|	 d|
 dt|||	 d|
 |||d	}t| ttd
d|tdI d H }t	t
t|I d H S )NTrR   strip_whitespace
min_lengthrF   rG   zCustom size out of range: xz<. Both width and height must be between 512 and 2048 pixels.)r4   r7   sizerP   rW   rZ   POSTpathmethodr-   response_model)r   r   
ValueErrorr   r   r   BYTEPLUS_IMAGE_ENDPOINTr
   r   
NodeOutputr   r1   )rx   r4   r7   r;   rD   rN   rP   rW   rZ   whr?   twthpayloadr$   r/   r/   r0   execute   s:   

.
zByteDanceImageNode.executeN)__name__
__module____qualname__classmethodry   strintfloatboolr   r   r   r/   r/   r/   r0   r2   @   s.    
N	
r2   c                   @   sz   e Zd Zedd Zeded d ddddddd	f	d
ededejdB dede	de	dede	de	de
de
dejfddZdS )ByteDanceSeedreamNodec                 C   sH  t jddddt jjdtt dt jjddd	d
dt jjddddt jjddd t	D ddt j
jddddddddt j
jdddd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't j
jd(d)d)d*d$t jjdd+dd,	t jjd-d.d/ddd0t jjd1dd2ddd0gt j gt jjt jjt jjgdt jt jdgd3d4d5d6	S )7Nr   zByteDance Seedream 4.5 & 5.0r3   z\Unified text-to-image generation and precise single-sentence editing at up to 4K resolution.r4   r5   r7   T z-Text prompt for creating or editing an image.)r9   rJ   r:   imagezjInput image(s) for image-to-image generation. Reference image(s) for single or multi-reference generation.)r:   rV   r;   c                 S   r<   r/   r/   r=   r/   r/   r0   rA      rB   z7ByteDanceSeedreamNode.define_schema.<locals>.<listcomp>zIPick a recommended size. Select Custom to use the width and height below.rC   rD   rG   rE   i`     rI   )rJ   rK   rL   rM   r:   rV   rN   i  rO   sequential_image_generationdisabledautozGroup image generation mode. 'disabled' generates a single image. 'auto' lets the model decide whether to generate multiple related images (e.g., story scenes, character variations).)r6   r:   rV   
max_imagesrR      zMaximum number of images to generate when sequential_image_generation='auto'. Total images (input + generated) cannot exceed 15.rY   rP   r   rQ   Seed to use for generation.rS   rZ   Fz8Whether to add an "AI generated" watermark to the image.r[   fail_on_partialzSIf enabled, abort execution if any requested images are missing or return an error.widgetsa  
                (
                  $price := $contains(widgets.model, "5.0 lite") ? 0.035 :
                            $contains(widgets.model, "4-5") ? 0.04 : 0.03;
                  {
                    "type":"usd",
                    "usd": $price,
                    "format": { "suffix":" x images/Run", "approximate": true }
                  }
                )
                
depends_onr]   	r^   r_   r`   ra   rb   rc   rd   re   rf   )r   rh   ri   r   listSEEDREAM_MODELSkeysrj   rp   r   rk   rl   rm   ro   rq   rr   rs   rt   ru   rv   PriceBadgeDependsrw   r/   r/   r0   ry      s   
			Wz#ByteDanceSeedreamNode.define_schemaNr   rG   r   rR   FTr4   r7   r   r;   rD   rN   r   r   rP   rZ   r   r%   c                    sd  t | }t|ddd d  }}tD ]\}}}||kr"||}} nq|d u s+|d u r0||}}|| }|d }d|v s@d|v rM|dk rMtd|d	d
d|v r^|dk r^td|d	d
d|v rddnd}||krytd|d d	d|d	d
|d urt|nd}|dkrdnd}||krtd| d| d|dkr|| dkrtdg }|r|D ]}t|dd qt| ||dd I d H }t| tt	d!d"t
t|||| d#| |	|t|d$|
|dkrd%nd d&	d'I d H }t|jdkrttt|I d H S d(d) |jD }|r"t|t|jk r"td*t| d+t|j d,ttd-d) |D I d H S ).NTrR   rz   g    .Azseedream-4-5zseedream-5-0i @8 z?Minimum image resolution for the selected model is 3.68MP, but z.2fzMP provided.zseedream-4-0i  zMMinimum image resolution that the selected model can generate is 0.92MP, but i i   z3Maximum image resolution for the selected model is i@B zMP, but r   r      
   zMaximum of z% reference images are supported, but z
 received.r   r   z\The maximum number of generated images plus the number of reference images cannot exceed 15.)rR      )r   rR   	image/pngr   	mime_typer   r   r}   r   png)	r4   r7   r   r~   rP   r   #sequential_image_generation_optionsrZ   output_format)r   r-   c                 S   s*   g | ]}t |trd |v rt|d  qS r(   )
isinstancedictr   )r>   dr/   r/   r0   rA     s   * z1ByteDanceSeedreamNode.execute.<locals>.<listcomp>zOnly z of z$ images were generated before error.c                    s   g | ]	}t |I d H qS N)r   r>   ir/   r/   r0   rA     s    )r   r   r   r   r   r   r   r   r   r   r
   r   r   lenr-   r   r   r   r1   r,   torchcat)rx   r4   r7   r   r;   rD   rN   r   r   rP   rZ   r   r   r   r?   r   r   out_num_pixelsmp_provided
max_pixelsn_input_imagesmax_num_of_imagesreference_images_urlsr   r$   urlsr/   r/   r0   r   4  s   


  zByteDanceSeedreamNode.execute)r   r   r   r   ry   r   r   r   rp   r   r   r   r   r   r/   r/   r/   r0   r      sL    
u
	
r   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dedej	fddZ
dS )ByteDanceTextToVideoNodec                 C   s   t jddddt jjdg dddt jjd	d
ddt jjdg dddt jjdg dddt jjddddddt jj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#g	t j
 gt jjt jjt jjgd
td(	S ))Nr   zByteDance Text to Videoapi node/video/ByteDancez=Generate video using ByteDance models via api based on promptr4   )seedance-1-5-pro-251215seedance-1-0-pro-250528r"   seedance-1-0-pro-fast-251015r   r6   rJ   r7   T+The text prompt used to generate the video.r8   
resolution480p720p1080p#The resolution of the output video.rC   aspect_ratio)16:94:31:13:49:1621:9%The aspect ratio of the output video.duration   r      rR   ,The duration of the output video in seconds.rJ   rK   rL   rM   r:   rT   rP   r   rQ   r   rS   camera_fixedFSpecifies whether to fix the camera. The platform appends an instruction to fix the camera to your prompt, but does not guarantee the actual effect.r[   rZ   8Whether to add an "AI generated" watermark to the video.generate_audio@This parameter is ignored for any model except seedance-1-5-pro.r   )r   rh   ri   r   rj   rk   rl   sliderrm   ro   Videorq   rr   rs   rt   ru   PRICE_BADGE_VIDEOrw   r/   r/   r0   ry     s   
	Fz&ByteDanceTextToVideoNode.define_schemaFr4   r7   r   r   r   rP   r   rZ   r   r%   c
           
         s   |dkr|dk rt dt|ddd t|g d | d| d	| d
| d| dt|  dt|  }t| t|t|dg|dkrH|	nd dtdt	
t| | |d  dI d H S )Nr      =Minimum supported duration for Seedance 1.5 Pro is 4 seconds.TrR   rz   r   ratior   rP   camerafixedrZ    --resolution 	 --ratio  --duration  --seed  --camerafixed  --watermark textr4   contentr   rX   r   estimated_duration)r   r   raise_if_text_paramsr   lowerprocess_video_taskr   r   rL   mathceilr   )
rx   r4   r7   r   r   r   rP   r   rZ   r   r/   r/   r0   r     s8   

	
z ByteDanceTextToVideoNode.executeNF)r   r   r   r   ry   r   r   r   r   r   r   r/   r/   r/   r0   r     s4    
W	
r   c                   @   sZ   e Zd Zedd Ze	ddededejdeded	ed
ede	de	de	de
jfddZdS )ByteDanceImageToVideoNodec                 C   s  t jddddt jjdg dddt jjd	d
ddt jjdddt jjdg dddt jjdg dddt jjddddddt jj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&g
t j gt jjt jjt jjgd
td+	S ),Nr   zByteDance Image to Videor   zGGenerate video using ByteDance models via api based on image and promptr4   )r   r   r#   r   r   r   r7   Tr   r8   r   %First frame to be used for the video.r:   r   r   r   rC   r   adaptiver   r   r   r   r   r   r   r   r   r   r   rR   r   r   rP   r   rQ   r   rS   r   Fr   r[   rZ   r   r   r   r   r   rh   ri   r   rj   rp   rk   rl   r   rm   ro   r   rq   rr   rs   rt   ru   r   rw   r/   r/   r0   ry     s   
	Jz'ByteDanceImageToVideoNode.define_schemaFr4   r7   r   r   r   r   rP   r   rZ   r   r%   c                    s  |dkr|dk rt dt|ddd t|g d t|ddd	d	d
 t|dddd t| |ddI d H d }| d| d| d| d| dt|  dt|	  }t| t	|t
|dtt|ddg|dkrl|
nd dtdtt| | |d  dI d H S )Nr   r   r   TrR   rz   r   ,  p  	min_width
min_height	max_width
max_heightr   r   r   r   Fstrictr   r   r   r   r   r   r   r   r   r   )	image_urlr   rX   r   )r   r   r   r   r   r   r   r   r   r	   r   r   r   rL   r   r   r   )rx   r4   r7   r   r   r   r   rP   r   rZ   r   r  r/   r/   r0   r   j  s>   


z!ByteDanceImageToVideoNode.executeNr   r   r   r   r   ry   r   r   rp   r   r   r   r   r   r/   r/   r/   r0   r     s8    
[	
r   c                   @   s`   e Zd Zedd Ze	ddededejdejded	ed
edede	de	de	de
jfddZdS )ByteDanceFirstLastFrameNodec                 C   s  t jddddt jjdg dddt jjd	d
ddt jjdddt jjdddt jjdg dddt jjdg dddt jjddddddt jj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(gt j gt jjt jjt jjgd
td-	S ).Nr  z#ByteDance First-Last-Frame to Videor   z6Generate video using prompt and first and last frames.r4   )r   r   r#   r#   r   r7   Tr   r8   first_framer   r   
last_framez$Last frame to be used for the video.r   r   r   rC   r   r  r   r   r   r   r   rR   r   r   rP   r   rQ   r   rS   r   Fr   r[   rZ   r   r   r   r   r  rw   r/   r/   r0   ry     s   	Iz)ByteDanceFirstLastFrameNode.define_schemaFr4   r7   r  r  r   r   r   rP   r   rZ   r   r%   c                    s<  |dkr|dk rt dt|ddd t|g d ||fD ]}t|ddd	d	d
 t|dddd qt| t||dddI d H }| d| d| d| d| dt|	  dt|
  }t	| t
|t|dttt|d dddttt|d dddg|dkr|nd dtdtt| | |d  d I d H S )!Nr   r   r   TrR   rz   r   r  r  r  r  r  Fr  r   r   r   r   r   r   r   r   r   r   r   r   r  r  roler  r   rX   r   )r   r   r   r   r   r   r   r   r   r   r	   r   r   r   rL   r   r   r   )rx   r4   r7   r  r  r   r   r   rP   r   rZ   r   r   download_urlsr/   r/   r0   r     sP   


	z#ByteDanceFirstLastFrameNode.executeNr   r  r/   r/   r/   r0   r    s<    
Z	
r  c                   @   sN   e Zd Zedd Zedededejdededed	ed
e	de
jfddZdS )ByteDanceImageReferenceNodec                 C   s   t jddddt jjdddgddt jjd	d
ddt jjdddt jjdddgddt jjdg dddt jjddddddt jj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t jg d(d)d*d+d,	S )-Nr  z#ByteDance Reference Images to Videor   z1Generate video using prompt and reference images.r4   r   r#   r   r7   Tr   r8   imageszOne to four images.r   r   r   r   r   rC   r   r  r   r   r   r   r   rR   r   r   rP   r   rQ   r   rS   rZ   Fr   r[   )r4   r   r   r   a(  
                (
                  $priceByModel := {
                    "seedance-1-0-pro": {
                      "480p":[0.23,0.24],
                      "720p":[0.51,0.56]
                    },
                    "seedance-1-0-lite": {
                      "480p":[0.17,0.18],
                      "720p":[0.37,0.41]
                    }
                  };
                  $model := widgets.model;
                  $modelKey :=
                    $contains($model, "seedance-1-0-pro")  ? "seedance-1-0-pro" :
                    "seedance-1-0-lite";
                  $resolution := widgets.resolution;
                  $resKey :=
                    $contains($resolution, "720") ? "720p" :
                    "480p";
                  $modelPrices := $lookup($priceByModel, $modelKey);
                  $baseRange := $lookup($modelPrices, $resKey);
                  $min10s := $baseRange[0];
                  $max10s := $baseRange[1];
                  $scale := widgets.duration / 10;
                  $minCost := $min10s * $scale;
                  $maxCost := $max10s * $scale;
                  ($minCost = $maxCost)
                    ? {"type":"usd","usd": $minCost}
                    : {"type":"range_usd","min_usd": $minCost, "max_usd": $maxCost}
                )
                r   r   )r   rh   ri   r   rj   rp   rk   rl   r   rm   ro   r   rq   rr   rs   rt   ru   rv   r   rw   r/   r/   r0   ry   +  s   	6z)ByteDanceImageReferenceNode.define_schemar4   r7   r  r   r   r   rP   rZ   r%   c	                    s   t |ddd t|g d |D ]}	t|	ddddd t|	dd	d
d qt| |dddI d H }
| d| d| d| d| dt|  }t|dgdd |
D }t| t	||d dt
dtt| | |d  dI d H S )NTrR   rz   )r   r   r   rP   rZ   r  r  r  r  r  Fr  r   r   r   r   r   r   r   r   r   c                 S   s"   g | ]}t tt|d ddqS )r   reference_imager  )r   r   r   r   r/   r/   r0   rA     s   " z7ByteDanceImageReferenceNode.execute.<locals>.<listcomp>r   rX   r   )r   r   r   r   r   r   r   r   r   r	   rL   r   r   r   )rx   r4   r7   r  r   r   r   rP   rZ   r   
image_urlsr}   r/   r/   r0   r     s8   
	z#ByteDanceImageReferenceNode.executeNr  r/   r/   r/   r0   r  )  s.    
i	
r  rx   r   r   c                    s~   |j tv rtd|j  t| ttdd|tdI d H }t| tt	 d|j
 ddd |td	I d H }tt|jjI d H S )
NzModel '%s' is deprecated and will be deactivated on May 13, 2026. Please switch to a newer model. Recommended: seedance-1-0-pro-fast-251015.r   r   r   /)r   c                 S   s   | j S r   )status)rr/   r/   r0   <lambda>  s    z$process_video_task.<locals>.<lambda>)status_extractorr   r   )r4   DEPRECATED_MODELSloggerwarningr   r   BYTEPLUS_TASK_ENDPOINTr   r   BYTEPLUS_TASK_STATUS_ENDPOINTidr   r   r   r   r   	video_url)rx   r   r   initial_responser$   r/   r/   r0   r     s(   

r   r7   text_paramsc                 C   s.   |D ]}d| d| v rt d| dqd S )Nz-- zV is not allowed in the prompt, use the appropriated widget input to change this value.)r   )r7   r(  r   r/   r/   r0   r     s   
r   )r4   r   r   r   r   a  
    (
      $priceByModel := {
        "seedance-1-5-pro": {
          "480p":[0.12,0.12],
          "720p":[0.26,0.26],
          "1080p":[0.58,0.59]
        },
        "seedance-1-0-pro": {
          "480p":[0.23,0.24],
          "720p":[0.51,0.56],
          "1080p":[1.18,1.22]
        },
        "seedance-1-0-pro-fast": {
          "480p":[0.09,0.1],
          "720p":[0.21,0.23],
          "1080p":[0.47,0.49]
        },
        "seedance-1-0-lite": {
          "480p":[0.17,0.18],
          "720p":[0.37,0.41],
          "1080p":[0.85,0.88]
        }
      };
      $model := widgets.model;
      $modelKey :=
        $contains($model, "seedance-1-5-pro")      ? "seedance-1-5-pro" :
        $contains($model, "seedance-1-0-pro-fast") ? "seedance-1-0-pro-fast" :
        $contains($model, "seedance-1-0-pro")      ? "seedance-1-0-pro" :
        "seedance-1-0-lite";
      $resolution := widgets.resolution;
      $resKey :=
        $contains($resolution, "1080") ? "1080p" :
        $contains($resolution, "720")  ? "720p" :
        "480p";
      $modelPrices := $lookup($priceByModel, $modelKey);
      $baseRange := $lookup($modelPrices, $resKey);
      $min10s := $baseRange[0];
      $max10s := $baseRange[1];
      $scale := widgets.duration / 10;
      $audioMultiplier := ($modelKey = "seedance-1-5-pro" and widgets.generate_audio) ? 2 : 1;
      $minCost := $min10s * $scale * $audioMultiplier;
      $maxCost := $max10s * $scale * $audioMultiplier;
      ($minCost = $maxCost)
        ? {"type":"usd","usd": $minCost, "format": { "approximate": true }}
        : {"type":"range_usd","min_usd": $minCost, "max_usd": $maxCost, "format": { "approximate": true }}
    )
    r   c                   @   s(   e Zd Zedeeej  fddZdS )ByteDanceExtensionr%   c                    s   t tttttgS r   )r2   r   r   r   r  r  )selfr/   r/   r0   get_node_list  s   z ByteDanceExtension.get_node_listN)	r   r   r   r   r   typer   	ComfyNoder,  r/   r/   r/   r0   r*    s    r*  c                      s   t  S r   )r*  r/   r/   r/   r0   comfy_entrypoint   s   r/  )@r*   r   r   typing_extensionsr   comfy_api.latestr   r   r   comfy_api_nodes.apis.bytedancer   r   r   r	   r
   r   r   r   r   r   r   r   r   r   comfy_api_nodes.utilr   r   r   r   r   r   r   r   r   r   r   r   r   r#  r$  r   	getLoggerr   r!  r   r1   r.  r2   r   r   r   r  r  r-  r   r   r   r   r   rv   r   r   r*  r/  r/   r/   r/   r0   <module>   sX    @4
	| Q  
  
5