@ -41,6 +41,7 @@ WORKFLOW_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "workfl
KEYS_FILE = os . path . join ( os . path . dirname ( os . path . abspath ( __file__ ) ) , " keys.json " )
KEYS_FILE = os . path . join ( os . path . dirname ( os . path . abspath ( __file__ ) ) , " keys.json " )
COMFY_OUTPUT_DIR = os . getenv ( " COMFY_OUTPUT_DIR " , " /ComfyUI/output " )
COMFY_OUTPUT_DIR = os . getenv ( " COMFY_OUTPUT_DIR " , " /ComfyUI/output " )
COMFY_INPUT_DIR = os . getenv ( " COMFY_INPUT_DIR " , " /ComfyUI/input " )
# ============================================================================
# ============================================================================
# Инициализация
# Инициализация
@ -99,10 +100,12 @@ def to_nearest_multiple_of_16(value):
def save_base64_to_file ( base64_data , temp_dir , filename ) :
def save_base64_to_file ( base64_data , temp_dir , filename ) :
""" Сохраняет base64 данные в файл. """
""" Сохраняет base64 данные в файл. """
decoded = base64 . b64decode ( base64_data )
decoded = base64 . b64decode ( base64_data )
logger . info ( f " 📦 Base64 decoded: { len ( base64_data ) } chars → { len ( decoded ) } bytes " )
os . makedirs ( temp_dir , exist_ok = True )
os . makedirs ( temp_dir , exist_ok = True )
file_path = os . path . abspath ( os . path . join ( temp_dir , filename ) )
file_path = os . path . abspath ( os . path . join ( temp_dir , filename ) )
with open ( file_path , " wb " ) as f :
with open ( file_path , " wb " ) as f :
f . write ( decoded )
f . write ( decoded )
logger . info ( f " 💾 Saved to: { file_path } ( { os . path . getsize ( file_path ) } bytes) " )
return file_path
return file_path
@ -119,22 +122,41 @@ def download_file(url, temp_dir, filename):
return file_path
return file_path
def copy_to_comfy_input ( src_path , filename ) :
"""
Копирует файл в ComfyUI input / директорию .
ComfyUI LoadImage ищет файлы только в своей input / папке .
Возвращает имя файла ( не полный путь ) .
"""
os . makedirs ( COMFY_INPUT_DIR , exist_ok = True )
dst_path = os . path . join ( COMFY_INPUT_DIR , filename )
shutil . copy2 ( src_path , dst_path )
logger . info ( f " 📋 Copied to ComfyUI input: { dst_path } ( { os . path . getsize ( dst_path ) } bytes) " )
return filename
def process_image_input ( job_input , prefix , temp_dir ) :
def process_image_input ( job_input , prefix , temp_dir ) :
"""
"""
Обрабатывает входные данные изображения .
Обрабатывает входные данные изображения .
prefix : " image " или " last_image "
prefix : " image " или " last_image "
Возвращает ( file_path , True ) или ( None , False )
Возвращает ( comfy_filename , True ) или ( None , False )
Файл копируется в ComfyUI input / директорию .
"""
"""
path_key = f " { prefix } _path "
path_key = f " { prefix } _path "
url_key = f " { prefix } _url "
url_key = f " { prefix } _url "
b64_key = f " { prefix } _base64 "
b64_key = f " { prefix } _base64 "
src_path = None
if path_key in job_input and job_input [ path_key ] :
if path_key in job_input and job_input [ path_key ] :
return job_input [ path_key ] , True
src_path = job_input [ path_key ]
elif url_key in job_input and job_input [ url_key ] :
elif url_key in job_input and job_input [ url_key ] :
return download_file ( job_input [ url_key ] , temp_dir , f " { prefix } .png " ) , True
src_path = download_file ( job_input [ url_key ] , temp_dir , f " { prefix } .png " )
elif b64_key in job_input and job_input [ b64_key ] :
elif b64_key in job_input and job_input [ b64_key ] :
return save_base64_to_file ( job_input [ b64_key ] , temp_dir , f " { prefix } .png " ) , True
src_path = save_base64_to_file ( job_input [ b64_key ] , temp_dir , f " { prefix } .png " )
if src_path :
comfy_filename = copy_to_comfy_input ( src_path , f " { prefix } .png " )
return comfy_filename , True
return None , False
return None , False
@ -288,8 +310,9 @@ def build_prompt(job_input, image_path, last_image_path, use_flf2v):
negative_prompt = job_input . get ( " negative_prompt " , prompt [ " 6 " ] [ " inputs " ] [ " text " ] )
negative_prompt = job_input . get ( " negative_prompt " , prompt [ " 6 " ] [ " inputs " ] [ " text " ] )
prompt [ " 6 " ] [ " inputs " ] [ " text " ] = negative_prompt
prompt [ " 6 " ] [ " inputs " ] [ " text " ] = negative_prompt
# Node 7: Load first frame image
# Node 7: Load first frame image (filename in ComfyUI input/ dir)
prompt [ " 7 " ] [ " inputs " ] [ " image " ] = image_path
prompt [ " 7 " ] [ " inputs " ] [ " image " ] = image_path
logger . info ( f " 🖼️ Node 7 image: ' { image_path } ' (resolved: { COMFY_INPUT_DIR } / { image_path } ) " )
# Node 15: Load last frame image (for FLF2V mode)
# Node 15: Load last frame image (for FLF2V mode)
if use_flf2v and last_image_path :
if use_flf2v and last_image_path :
@ -331,18 +354,19 @@ def build_prompt(job_input, image_path, last_image_path, use_flf2v):
return prompt , seed , width , height
return prompt , seed , width , height
def cleanup_comfy_output ( ) :
def cleanup_comfy_dirs ( ) :
""" Очистка output директории ComfyUI. """
""" Очистка output и input директорий ComfyUI. """
try :
for dir_path in ( COMFY_OUTPUT_DIR , COMFY_INPUT_DIR ) :
if os . path . exists ( COMFY_OUTPUT_DIR ) :
try :
for fname in os . listdir ( COMFY_OUTPUT_DIR ) :
if os . path . exists ( dir_path ) :
fpath = os . path . join ( COMFY_OUTPUT_DIR , fname )
for fname in os . listdir ( dir_path ) :
if os . path . isfile ( fpath ) :
fpath = os . path . join ( dir_path , fname )
os . unlink ( fpath )
if os . path . isfile ( fpath ) :
elif os . path . isdir ( fpath ) :
os . unlink ( fpath )
shutil . rmtree ( fpath )
elif os . path . isdir ( fpath ) :
except Exception :
shutil . rmtree ( fpath )
pass
except Exception :
pass
def worker_loop ( ) :
def worker_loop ( ) :
@ -415,7 +439,7 @@ def worker_loop():
# Очистка
# Очистка
if os . path . exists ( temp_dir ) :
if os . path . exists ( temp_dir ) :
shutil . rmtree ( temp_dir , ignore_errors = True )
shutil . rmtree ( temp_dir , ignore_errors = True )
cleanup_comfy_output ( )
cleanup_comfy_dirs ( )
job_queue . task_done ( )
job_queue . task_done ( )