Add new nodes CogViewImageGenerateNode, CogVideoXGenerateNode
This commit is contained in:
@@ -156,7 +156,9 @@ Optional: You can also set initial language values when creating nodes in
|
||||
"from_translate": "ru",
|
||||
"to_translate": "en",
|
||||
"default_language_model": "glm-4.5-flash",
|
||||
"default_multimodal_model": "glm-4v-flash",
|
||||
"default_multimodal_model": "glm-4.6v-flash",
|
||||
"default_image_generate_model": "cogview-3-flash",
|
||||
"default_video_generate_model": "cogvideox-flash",
|
||||
"ZHIPUAI_API_KEY": "your_api_key"
|
||||
}
|
||||
```
|
||||
@@ -170,6 +172,10 @@ Optional: You can also set initial language values when creating nodes in
|
||||
> **ChatGLM4InstructNode** - Generate prompt from instruct
|
||||
>
|
||||
> **ChatGLM4InstructMediaNode** - Generate prompt from instruct to describe what is shown in the media
|
||||
>
|
||||
> **CogViewImageGenerateNode** - Generate prompt from instruct to describe what is shown in the media
|
||||
>
|
||||
> **CogVideoXGenerateNode** - Generate prompt from instruct to describe what is shown in the media
|
||||
|
||||
## Image:
|
||||
|
||||
|
||||
+260
-16
@@ -1,17 +1,26 @@
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
|
||||
import base64
|
||||
from io import BytesIO
|
||||
import numpy as np
|
||||
from server import PromptServer
|
||||
from PIL import Image
|
||||
from PIL import Image, ImageOps, ImageSequence
|
||||
import time
|
||||
import torch
|
||||
import node_helpers
|
||||
from comfy_api_nodes.util import (
|
||||
download_url_to_video_output,
|
||||
)
|
||||
|
||||
|
||||
ALL_CODES_LANGS = ['af', 'sq', 'am', 'ar', 'hy', 'as', 'ay', 'az', 'bm', 'eu', 'be', 'bn', 'bho', 'bs', 'bg', 'ca', 'ceb', 'ny', 'zh-CN', 'zh-TW', 'co', 'hr', 'cs', 'da', 'dv', 'doi', 'nl', 'en', 'eo', 'et', 'ee', 'tl', 'fi', 'fr', 'fy', 'gl', 'ka', 'de', 'el', 'gn', 'gu', 'ht', 'ha', 'haw', 'iw', 'hi', 'hmn', 'hu', 'is', 'ig', 'ilo', 'id', 'ga', 'it', 'ja', 'jw', 'kn', 'kk', 'km', 'rw', 'gom', 'ko', 'kri', 'ku', 'ckb', 'ky', 'lo', 'la', 'lv', 'ln', 'lt', 'lg', 'lb', 'mk', 'mai', 'mg', 'ms', 'ml', 'mt', 'mi', 'mr', 'mni-Mtei', 'lus', 'mn', 'my', 'ne', 'no', 'or', 'om', 'ps', 'fa', 'pl', 'pt', 'pa', 'qu', 'ro', 'ru', 'sm', 'sa', 'gd', 'nso', 'sr', 'st', 'sn', 'sd', 'si', 'sk', 'sl', 'so', 'es', 'su', 'sw', 'sv', 'tg', 'ta', 'tt', 'te', 'th', 'ti', 'ts', 'tr', 'tk', 'ak', 'uk', 'ur', 'ug', 'uz', 'vi', 'cy', 'xh', 'yi', 'yo', 'zu']
|
||||
|
||||
|
||||
# Endpoints
|
||||
ENDPOINT_URL = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
|
||||
ENDPOINT_IMAGE_URL = "https://open.bigmodel.cn/api/paas/v4/images/generations"
|
||||
ENDPOINT_VIDEO_URL = "https://open.bigmodel.cn/api/paas/v4/videos/generations"
|
||||
ENDPOINT_VIDEO_CHECK_URL = "https://open.bigmodel.cn/api/paas/v4/async-result/"
|
||||
|
||||
# Language models: https://docs.bigmodel.cn/api-reference/%E6%A8%A1%E5%9E%8B-api/%E5%AF%B9%E8%AF%9D%E8%A1%A5%E5%85%A8#%E6%96%87%E6%9C%AC%E6%A8%A1%E5%9E%8B
|
||||
LIST_LANGUAGE_MODELS = [
|
||||
@@ -57,13 +66,6 @@ LIST_MULTIMODAL_MODELS = [
|
||||
"autoglm-phone",
|
||||
]
|
||||
|
||||
# Multimodal models: https://docs.bigmodel.cn/api-reference/%E6%A8%A1%E5%9E%8B-api/%E5%AF%B9%E8%AF%9D%E8%A1%A5%E5%85%A8#%E8%A7%86%E8%A7%89%E6%A8%A1%E5%9E%8B
|
||||
LIST_IMAGE_GENERATION_MODELS = [
|
||||
"cogview-4-250304",
|
||||
"cogview-4",
|
||||
"cogview-3-flash"
|
||||
]
|
||||
|
||||
# CogView: https://docs.bigmodel.cn/api-reference/%E6%A8%A1%E5%9E%8B-api/%E5%9B%BE%E5%83%8F%E7%94%9F%E6%88%90
|
||||
LIST_IMAGE_GENERATION_MODELS = [
|
||||
"cogview-4-250304",
|
||||
@@ -74,7 +76,6 @@ LIST_IMAGE_GENERATION_MODELS = [
|
||||
# CogVideo: https://docs.bigmodel.cn/api-reference/%E6%A8%A1%E5%9E%8B-api/%E7%94%9F%E6%88%90%E8%A7%86%E9%A2%91%E5%BC%82%E6%AD%A5
|
||||
LIST_VIDEO_GENERATION_MODELS = [
|
||||
"cogvideox-3",
|
||||
"cogvideox3-flash",
|
||||
"cogvideox-2",
|
||||
"cogvideox-flash",
|
||||
]
|
||||
@@ -89,6 +90,8 @@ def getConfigData():
|
||||
"to_translate": "en",
|
||||
"default_language_model": "glm-4.5-flash",
|
||||
"default_multimodal_model": "glm-4.6v-flash",
|
||||
"default_image_generate_model": "cogview-3-flash",
|
||||
"default_video_generate_model": "cogvideox-flash",
|
||||
"ZHIPUAI_API_KEY": "your_api_key"
|
||||
}
|
||||
|
||||
@@ -119,7 +122,7 @@ def checkPropValue(obj, key, not_include = []):
|
||||
|
||||
CONFIG = getConfigData()
|
||||
|
||||
def createRequest(payload):
|
||||
def createRequest(payload, generate = "text", method = "POST", params = {}):
|
||||
global CONFIG
|
||||
|
||||
if checkPropValue(CONFIG, "ZHIPUAI_API_KEY", ["your_api_key"]):
|
||||
@@ -133,15 +136,30 @@ def createRequest(payload):
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
if generate == "image":
|
||||
endpoint = ENDPOINT_IMAGE_URL
|
||||
elif generate == "video":
|
||||
endpoint = ENDPOINT_VIDEO_URL
|
||||
headers.update({'Accept-Language': "en-US,en"})
|
||||
elif generate == "video-check":
|
||||
endpoint = ENDPOINT_VIDEO_CHECK_URL + params["id"]
|
||||
headers.update({'Accept-Language': "en-US,en"})
|
||||
else:
|
||||
endpoint = ENDPOINT_URL
|
||||
|
||||
try:
|
||||
response = requests.post(ENDPOINT_URL, headers=headers, json=payload)
|
||||
response = requests.post(endpoint, headers=headers, json=payload) if method == "POST" else requests.get(endpoint, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
if response.status_code == 200:
|
||||
json_data = response.json()
|
||||
response_text = json_data.get("choices")[0]["message"]["content"].strip()
|
||||
|
||||
return response_text
|
||||
|
||||
if generate == "text":
|
||||
return json_data.get("choices")[0]["message"]["content"].strip()
|
||||
elif generate == "image":
|
||||
return json_data.get("data")[0]["url"]
|
||||
elif generate == "video" or generate == "video-check":
|
||||
return json_data
|
||||
|
||||
except requests.HTTPError as e:
|
||||
print(f"Error request ChatGLM: {response.status_code}, {response.text}")
|
||||
@@ -512,3 +530,229 @@ class ChatGLM4InstructMediaNode:
|
||||
answer = createRequest(payload)
|
||||
|
||||
return (answer,)
|
||||
|
||||
# Generate Image & Video nodes
|
||||
IMAGE_SUPPORTS_RESOLUTIONS = ["768x1344", "864x1152", "1024x1024", "1344x768", "1152x864", "1440x720", "720x1440"]
|
||||
VIDEO_SUPPORTS_RESOLUTIONS = ["720x1280", "1024x1024", "1080x1920", "1280x720", "1920x1080", "2048x1080", "3840x2160"]
|
||||
|
||||
|
||||
# List sizes to str
|
||||
def getStrListSizes(list_values, indexVal):
|
||||
return ", ".join(map(str, sorted(int(w.split("x")[indexVal]) for w in list_values)))
|
||||
|
||||
|
||||
# Function set correct size value
|
||||
def setCorrectSize(value, minMax, nodeName):
|
||||
if type(value) == str:
|
||||
value = int(value)
|
||||
|
||||
if value < minMax[0]:
|
||||
value = minMax[0]
|
||||
print(f"[{nodeName}] The value is less than {minMax[0]}, we set it to the correct value {minMax[0]}.")
|
||||
elif value > minMax[1]:
|
||||
value = minMax[1]
|
||||
print(f"[{nodeName}] The value is greater than {minMax[1]}, we set it to the correct value {minMax[1]}.")
|
||||
|
||||
return value
|
||||
|
||||
class CogViewImageGenerateNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"model": (
|
||||
LIST_IMAGE_GENERATION_MODELS,
|
||||
{
|
||||
"default": CONFIG.get("default_image_generate_model", "cogvideox-flash"),
|
||||
"tooltip": "The model code to be called. Models with text 'flash' should be free!",
|
||||
},
|
||||
),
|
||||
"prompt": (
|
||||
"STRING",
|
||||
{
|
||||
"multiline": True,
|
||||
"placeholder": "Input prompt text",
|
||||
"default": "",
|
||||
"tooltip": "Enter the prompt for generated image",
|
||||
},
|
||||
),
|
||||
},
|
||||
"optional": {
|
||||
"quality": (
|
||||
["standard", "hd"],
|
||||
{
|
||||
"default": "standard",
|
||||
"tooltip": "Image generation quality, default is 'standard'. This parameter is only supported by cogview-4-250304.",
|
||||
},
|
||||
),
|
||||
"width": ("INT", {"default": 1024, "tooltip":f"Image width, default value 1024. Recommended width values: {getStrListSizes(IMAGE_SUPPORTS_RESOLUTIONS, 0)}."}),
|
||||
"height": ("INT", {"default": 1024, "tooltip":f"Image height, default value 1024. Recommended height values: {getStrListSizes(IMAGE_SUPPORTS_RESOLUTIONS, 1)}."}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "image_generate"
|
||||
DESCRIPTION = (
|
||||
"This is a node that generates an image based on a text prompt."
|
||||
)
|
||||
CATEGORY = "AlekPet Nodes/image"
|
||||
|
||||
def image_generate(self, model, prompt, quality="standard", width=1024, height=1024):
|
||||
if prompt is None and not prompt.strip():
|
||||
raise ValueError("Prompt value is empty!")
|
||||
|
||||
width = setCorrectSize(width, [512, 2048], "CogViewImageGenerateNode")
|
||||
height = setCorrectSize(height, [512, 2048], "CogViewImageGenerateNode")
|
||||
|
||||
size = f"{width}x{height}"
|
||||
|
||||
# Create body request
|
||||
payload = {
|
||||
"model": model,
|
||||
"prompt": prompt,
|
||||
"quality": quality,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
image_url = createRequest(payload, "image")
|
||||
response = requests.get(image_url)
|
||||
img = node_helpers.pillow(Image.open, BytesIO(response.content))
|
||||
|
||||
output_images = []
|
||||
w, h = None, None
|
||||
|
||||
excluded_formats = ['MPO']
|
||||
|
||||
for i in ImageSequence.Iterator(img):
|
||||
i = node_helpers.pillow(ImageOps.exif_transpose, i)
|
||||
|
||||
if i.mode == 'I':
|
||||
i = i.point(lambda i: i * (1 / 255))
|
||||
image = i.convert("RGB")
|
||||
|
||||
if len(output_images) == 0:
|
||||
w = image.size[0]
|
||||
h = image.size[1]
|
||||
|
||||
if image.size[0] != w or image.size[1] != h:
|
||||
continue
|
||||
|
||||
image = np.array(image).astype(np.float32) / 255.0
|
||||
image = torch.from_numpy(image)[None,]
|
||||
output_images.append(image)
|
||||
|
||||
if len(output_images) > 1 and img.format not in excluded_formats:
|
||||
output_image = torch.cat(output_images, dim=0)
|
||||
else:
|
||||
output_image = output_images[0]
|
||||
|
||||
return (output_image,)
|
||||
|
||||
# Video generate
|
||||
async def execute_gen_video(model, prompt, image, quality, with_audio, watermark, width, height, fps, duration):
|
||||
|
||||
width = setCorrectSize(width, [512, 2048], "CogVideoXGenerateNode")
|
||||
height = setCorrectSize(height, [512, 2048], "CogVideoXGenerateNode")
|
||||
|
||||
size = f"{width}x{height}"
|
||||
|
||||
# Create body request
|
||||
payload = {
|
||||
"model": model,
|
||||
"prompt": prompt,
|
||||
"quality": quality,
|
||||
"watermark_enabled": watermark,
|
||||
"with_audio": with_audio,
|
||||
"size": size,
|
||||
"fps": int(fps),
|
||||
"duration": int(duration),
|
||||
}
|
||||
|
||||
if image is not None:
|
||||
img = 255.0 * image.cpu().numpy()
|
||||
img = np.squeeze(img)
|
||||
img = Image.fromarray(np.clip(img, 0, 255).astype(np.uint8))
|
||||
img = toBase64ImgUrl(img)
|
||||
# Add to payload
|
||||
payload.update({"image_url": img})
|
||||
|
||||
|
||||
video_task = createRequest(payload, "video")
|
||||
|
||||
# Data task generate video
|
||||
idTask = video_task.get("id")
|
||||
|
||||
if not idTask or not idTask.strip():
|
||||
raise ValueError("Video get result task fail! Video generate task ID is not valid!")
|
||||
|
||||
video_generated = None
|
||||
for _ in range(400):
|
||||
check_video_task = createRequest(payload, "video-check", "GET", {"id": idTask})
|
||||
task_status = check_video_task.get("task_status")
|
||||
|
||||
if task_status == "SUCCESS":
|
||||
video_generated = check_video_task.get("video_result")
|
||||
break
|
||||
|
||||
elif task_status == "FAIL":
|
||||
raise ValueError("The video generation task failed!")
|
||||
|
||||
time.sleep(0.3)
|
||||
|
||||
if video_generated is None or not len(video_generated):
|
||||
raise ValueError("Genereated video is not valid!")
|
||||
|
||||
return await download_url_to_video_output(str(video_generated[0]["url"]))
|
||||
|
||||
class CogVideoXGenerateNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"model": (
|
||||
LIST_VIDEO_GENERATION_MODELS,
|
||||
{
|
||||
"default": CONFIG.get("default_video_generate_model", "cogvideox-3"),
|
||||
"tooltip": "The model code to be called. Models with text 'flash' should be free!",
|
||||
},
|
||||
),
|
||||
"prompt": (
|
||||
"STRING",
|
||||
{
|
||||
"multiline": True,
|
||||
"placeholder": "Input prompt text",
|
||||
"default": "",
|
||||
"tooltip": "Enter the prompt for generated image",
|
||||
},
|
||||
),
|
||||
},
|
||||
"optional": {
|
||||
"image": ("IMAGE",),
|
||||
"quality": (
|
||||
["speed", "quality"],
|
||||
{
|
||||
"default": "speed",
|
||||
"tooltip": "Output mode, defaults to speed. quality: Quality priority, generates higher quality output. speed: Speed priority, generates faster output, but with slightly lower quality.",
|
||||
},
|
||||
),
|
||||
"with_audio": ("BOOLEAN", {"default": False, "tooltip": "Whether to generate AI sound effects. Default: False (do not generate sound effects)."},),
|
||||
"watermark": ("BOOLEAN", {"default": True, "tooltip": "Add watermark, default: True. Watermark off allow only customers who have signed a disclaimer to use the service. Signature path: Personal Center>Security Management>Remove Watermark Management"},),
|
||||
"width": ("INT", {"default": 1920, "tooltip":f"Video width, default value 1920. Recommended width values: {getStrListSizes(VIDEO_SUPPORTS_RESOLUTIONS, 0)}"}),
|
||||
"height": ("INT", {"default": 1080, "tooltip":f"Video height, default value 1080. Recommended height values: {getStrListSizes(VIDEO_SUPPORTS_RESOLUTIONS, 1)}"}),
|
||||
"fps": ([30, 60], {"default": 30, "tooltip":"Video frame rate (FPS), default value is 30 frame rate"}),
|
||||
"duration": ([5, 10], {"default": 5, "tooltip":"Video duration, default is 5 seconds"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VIDEO",)
|
||||
FUNCTION = "video_generate"
|
||||
DESCRIPTION = (
|
||||
"This is a node that generates an video based on a text prompt or image."
|
||||
)
|
||||
CATEGORY = "AlekPet Nodes/video"
|
||||
|
||||
async def video_generate(self, model, prompt, image=None, quality="speed", with_audio=False, watermark=True, width=1920, height=1080, fps=30, duration=5):
|
||||
if prompt is None and not prompt.strip():
|
||||
raise ValueError("Prompt value is empty!")
|
||||
|
||||
return (await execute_gen_video(model, prompt, image, quality, with_audio, watermark, width, height, fps, duration),)
|
||||
@@ -4,5 +4,7 @@
|
||||
"to_translate": "en",
|
||||
"default_language_model": "glm-4.5-flash",
|
||||
"default_multimodal_model": "glm-4.6v-flash",
|
||||
"default_image_generate_model": "cogview-3-flash",
|
||||
"default_video_generate_model": "cogvideox-flash",
|
||||
"ZHIPUAI_API_KEY": "your_api_key"
|
||||
}
|
||||
|
||||
@@ -364,6 +364,8 @@ try:
|
||||
ChatGLM4TranslateTextNode,
|
||||
ChatGLM4InstructNode,
|
||||
ChatGLM4InstructMediaNode,
|
||||
CogViewImageGenerateNode,
|
||||
CogVideoXGenerateNode
|
||||
)
|
||||
|
||||
NODE_CLASS_MAPPINGS.update(
|
||||
@@ -372,6 +374,9 @@ try:
|
||||
"ChatGLM4TranslateTextNode": ChatGLM4TranslateTextNode,
|
||||
"ChatGLM4InstructNode": ChatGLM4InstructNode,
|
||||
"ChatGLM4InstructMediaNode": ChatGLM4InstructMediaNode,
|
||||
# Generate
|
||||
"CogViewImageGenerateNode": CogViewImageGenerateNode,
|
||||
"CogVideoXGenerateNode": CogVideoXGenerateNode,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -381,6 +386,9 @@ try:
|
||||
"ChatGLM4TranslateTextNode": "ChatGLM-4 Translate Text Node",
|
||||
"ChatGLM4InstructNode": "ChatGLM-4 Instruct Node",
|
||||
"ChatGLM4InstructMediaNode": "ChatGLM-4 Instruct Media Node",
|
||||
# Generate
|
||||
"CogViewImageGenerateNode": "CogView Image Generate Node",
|
||||
"CogVideoXGenerateNode": "CogVideoX Video Generate Node",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui_custom_nodes_alekpet"
|
||||
description = "Nodes: PoseNode, PainterNode, TranslateTextNode, TranslateCLIPTextEncodeNode, DeepTranslatorTextNode, DeepTranslatorCLIPTextEncodeNode, ArgosTranslateTextNode, ArgosTranslateCLIPTextEncodeNode, ChatGLM4TranslateCLIPTextEncodeNode, ChatGLM4TranslateTextNode, ChatGLM4InstructNode, ChatGLM4InstructMediaNode, PreviewTextNode, HexToHueNode, ColorsCorrectNode, IDENode."
|
||||
version = "1.0.90"
|
||||
description = "Nodes: PoseNode, PainterNode, TranslateTextNode, TranslateCLIPTextEncodeNode, DeepTranslatorTextNode, DeepTranslatorCLIPTextEncodeNode, ArgosTranslateTextNode, ArgosTranslateCLIPTextEncodeNode, ChatGLM4TranslateCLIPTextEncodeNode, ChatGLM4TranslateTextNode, ChatGLM4InstructNode, ChatGLM4InstructMediaNode, CogViewImageGenerateNode, CogVideoXGenerateNode, PreviewTextNode, HexToHueNode, ColorsCorrectNode, IDENode."
|
||||
version = "1.0.91"
|
||||
license = { file = "LICENSE" }
|
||||
|
||||
[project.urls]
|
||||
|
||||
Reference in New Issue
Block a user