Files
magicwang1111-Comfyui-Kling…/examples/generate_examples.py

944 lines
29 KiB
Python

import json
from pathlib import Path
ROOT = Path(__file__).resolve().parent
NODE_PREFIX = "Comfyui-Kling-Wrapper"
CLIENT_TYPE = "COMFYUI_KLING_WRAPPER_API_CLIENT"
ELEMENT_TYPE = "COMFYUI_KLING_WRAPPER_ELEMENT"
ELEMENT_LIST_TYPE = "COMFYUI_KLING_WRAPPER_ELEMENT_LIST"
LIPSYNC_INPUT_TYPE = "COMFYUI_KLING_WRAPPER_LIPSYNC_INPUT"
def input_slot(name, type_name, link=None, shape=7):
slot = {"name": name, "type": type_name, "link": link}
if type_name in {"IMAGE", "MASK"}:
slot["shape"] = shape
return slot
def output_slot(name, type_name, links=None, slot_index=None):
slot = {"name": name, "type": type_name, "links": links}
if slot_index is not None:
slot["slot_index"] = slot_index
return slot
def node(node_id, type_name, pos, size, order, widgets_values, inputs=None, outputs=None):
return {
"id": node_id,
"type": type_name,
"pos": pos,
"size": size,
"flags": {},
"order": order,
"mode": 0,
"inputs": inputs or [],
"outputs": outputs or [],
"properties": {"Node name for S&R": type_name},
"widgets_values": widgets_values,
}
def workflow(nodes, links):
return {
"id": "Comfyui-Kling-Wrapper-example",
"revision": 0,
"last_node_id": max(node["id"] for node in nodes),
"last_link_id": max((link[0] for link in links), default=0),
"nodes": nodes,
"links": links,
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.9,
"offset": [0, 0],
},
"frontendVersion": "1.42.8",
},
"version": 0.4,
}
def client_node(node_id=1, order=0, area="china"):
type_name = f"{NODE_PREFIX} Client"
return node(
node_id,
type_name,
[40, 60],
[320, 210],
order,
["", "", 1, area],
outputs=[output_slot("client", CLIENT_TYPE, slot_index=0)],
)
def load_image_node(node_id, filename, pos, order):
return node(
node_id,
"LoadImage",
pos,
[290, 340],
order,
[filename, "image"],
outputs=[
output_slot("IMAGE", "IMAGE", slot_index=0),
output_slot("MASK", "MASK", slot_index=1),
],
)
def save_image_node(node_id, filename_prefix, pos, order, link_id):
return node(
node_id,
"SaveImage",
pos,
[320, 100],
order,
[filename_prefix],
inputs=[input_slot("images", "IMAGE", link_id)],
)
def preview_video_node(node_id, pos, order, link_id):
type_name = f"{NODE_PREFIX} Preview Video"
return node(
node_id,
type_name,
pos,
[430, 820],
order,
[NODE_PREFIX, True],
inputs=[input_slot("video_url", "STRING", link_id)],
outputs=[output_slot("file_path", "STRING", slot_index=0)],
)
def preview_audio_node(node_id, pos, order, link_id):
type_name = f"{NODE_PREFIX} Preview Audio"
return node(
node_id,
type_name,
pos,
[360, 180],
order,
[NODE_PREFIX + "-audio", True],
inputs=[input_slot("audio_url", "STRING", link_id)],
outputs=[
output_slot("audio", "AUDIO", slot_index=0),
output_slot("file_path", "STRING", slot_index=1),
],
)
def image_generator_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Image Generator"
return node(
node_id,
type_name,
pos,
[430, 370],
order,
[
"kling-v3",
"A fashion editorial portrait of a young woman in soft morning light, realistic skin texture, elegant framing, filmic color grading.",
"",
"None",
0.5,
0.45,
1,
"16:9",
"1k",
],
inputs=[input_slot("client", CLIENT_TYPE)],
outputs=[output_slot("image", "IMAGE", slot_index=0)],
)
def text2video_node(node_id, pos, order, model, prompt, mode="pro", aspect_ratio="16:9", duration="5",
sound="off", voice_preset="None", shot_type="single", reference_video=""):
type_name = f"{NODE_PREFIX} Text2Video"
return node(
node_id,
type_name,
pos,
[430, 520],
order,
[
model,
prompt,
"",
0.5,
mode,
aspect_ratio,
duration,
"None",
"horizontal",
0.5,
sound,
voice_preset,
shot_type,
reference_video,
],
inputs=[input_slot("client", CLIENT_TYPE)],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def image2video_node(node_id, pos, order, model, prompt="", mode="pro", duration="5", shot_type="single",
reference_video=""):
type_name = f"{NODE_PREFIX} Image2Video"
return node(
node_id,
type_name,
pos,
[430, 520],
order,
[
model,
prompt,
"",
0.5,
mode,
duration,
"None",
"horizontal",
0.5,
"off",
"None",
shot_type,
reference_video,
],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("image", "IMAGE"),
input_slot("image_tail", "IMAGE", None),
],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def multi_images_to_video_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Multi Images To Video"
return node(
node_id,
type_name,
pos,
[430, 360],
order,
[
"kling-v3",
"Keep the same person identity across the shot while the subject turns toward camera and smiles naturally.",
"",
"pro",
"5",
"16:9",
],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("image_list", "IMAGE"),
input_slot("image_tail", "IMAGE", None),
],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def image_batch_node(node_id, pos, order):
return node(
node_id,
"ImageBatch",
pos,
[320, 120],
order,
[],
inputs=[
input_slot("image1", "IMAGE"),
input_slot("image2", "IMAGE"),
],
outputs=[output_slot("IMAGE", "IMAGE", slot_index=0)],
)
def virtual_try_on_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Virtual Try On"
return node(
node_id,
type_name,
pos,
[360, 180],
order,
["kolors-virtual-try-on-v1-5"],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("human_image", "IMAGE"),
input_slot("cloth_image", "IMAGE"),
],
outputs=[output_slot("image", "IMAGE", slot_index=0)],
)
def image_expander_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Image Expander"
return node(
node_id,
type_name,
pos,
[360, 260],
order,
[0.25, 0.0, 0.0, 0.0, "Extend the background naturally with coherent lighting and scene details.", 1],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("image", "IMAGE"),
],
outputs=[output_slot("image", "IMAGE", slot_index=0)],
)
def video_extender_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Video Extender"
return node(
node_id,
type_name,
pos,
[360, 180],
order,
["", "Continue the shot naturally for a few more moments, keeping the same scene and motion direction."],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("video_id", "STRING"),
],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def text_to_audio_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} TextToAudio"
return node(
node_id,
type_name,
pos,
[360, 180],
order,
["Generate a calm cinematic ambient track with gentle piano and soft pads.", 6.0],
inputs=[input_slot("client", CLIENT_TYPE)],
outputs=[
output_slot("id", "STRING", slot_index=0),
output_slot("url", "STRING", slot_index=1),
],
)
def video_to_audio_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Video2Audio"
return node(
node_id,
type_name,
pos,
[390, 220],
order,
["", "", "Footsteps on stone floor and distant city ambience.", "Cinematic ambient soundtrack with low strings.", False],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("video_id", "STRING"),
],
outputs=[
output_slot("videos_id", "STRING", slot_index=0),
output_slot("videos_url", "STRING", slot_index=1),
output_slot("audio_id", "STRING", slot_index=2),
output_slot("audio_url_mp3", "STRING", slot_index=3),
],
)
def lip_sync_text_input_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Lip Sync Text Input"
return node(
node_id,
type_name,
pos,
[360, 220],
order,
["Welcome to Comfyui Kling Wrapper demo. This is a lip sync example generated from text.", "The Reader", "en", 1.0],
outputs=[output_slot("input", LIPSYNC_INPUT_TYPE, slot_index=0)],
)
def lip_sync_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Lip Sync"
return node(
node_id,
type_name,
pos,
[390, 220],
order,
["", "", ""],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("input", LIPSYNC_INPUT_TYPE),
input_slot("video_id", "STRING"),
],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def effects_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Effects"
return node(
node_id,
type_name,
pos,
[390, 220],
order,
["yearbook", "kling-v1-6", "std", "5"],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("image0", "IMAGE"),
input_slot("image1", "IMAGE", None),
],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def advanced_element_create_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Advanced Element Create"
return node(
node_id,
type_name,
pos,
[390, 260],
order,
[
"image_subject",
"demo_subject",
"A clear portrait of the subject with consistent identity traits for reuse in video generation.",
"",
"",
"",
],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("image", "IMAGE"),
input_slot("image_list", "IMAGE", None),
],
outputs=[
output_slot("element", ELEMENT_TYPE, slot_index=0),
output_slot("element_id", "STRING", slot_index=1),
output_slot("element_json", "STRING", slot_index=2),
],
)
def element_list_builder_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Element List Builder"
return node(
node_id,
type_name,
pos,
[340, 180],
order,
[""],
inputs=[input_slot("element_1", ELEMENT_TYPE)],
outputs=[
output_slot("element_list", ELEMENT_LIST_TYPE, slot_index=0),
output_slot("element_json", "STRING", slot_index=1),
],
)
def motion_control_node(node_id, pos, order):
type_name = f"{NODE_PREFIX} Motion Control"
return node(
node_id,
type_name,
pos,
[420, 320],
order,
[
"kling-v2-6",
"https://example.com/reference-motion.mp4",
"Transfer the body motion naturally while keeping the subject stable and realistic.",
"",
"pro",
"5",
"",
],
inputs=[
input_slot("client", CLIENT_TYPE),
input_slot("reference_image", "IMAGE"),
],
outputs=[
output_slot("url", "STRING", slot_index=0),
output_slot("video_id", "STRING", slot_index=1),
],
)
def link(link_id, src_node, src_slot, dst_node, dst_slot, type_name):
return [link_id, src_node, src_slot, dst_node, dst_slot, type_name]
def write_json(name, data):
(ROOT / name).write_text(json.dumps(data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
def write_examples_readme():
content = """# Comfyui-Kling-Wrapper Examples
This directory contains refreshed ComfyUI workflow JSON examples for the upgraded `Comfyui-Kling-Wrapper` node pack.
Before running the workflows:
- Fill in `access_key` and `secret_key` in the `Comfyui-Kling-Wrapper Client` node, or keep them empty and use `config.ini`.
- Replace placeholder image filenames such as `example_portrait.png`, `example_subject_a.png`, `example_cloth.png`, and `example_scene.png` with files that exist in your ComfyUI input directory.
- Replace placeholder URLs such as `https://example.com/reference-motion.mp4` with real URLs when needed.
- If `kling-v3-omni`, `kling-video-o1`, or `kling-image-o1` return `1201 model is not supported`, verify the model is enabled for your key on the active endpoint. The official docs list newer models, but the live service can lag behind rollout on some accounts.
Included files:
- `01_comfyui_kling_wrapper_image_generation_v3.json`: basic image generation using a live-tested `kling-v3` image model preset.
- `02_comfyui_kling_wrapper_text2video_v3_intelligence.json`: text-to-video using `kling-v3` intelligent multi-shot mode.
- `03_comfyui_kling_wrapper_image2video_v3.json`: single-image to video with the 3.0 video family.
- `04_comfyui_kling_wrapper_multi_images_to_video_v3.json`: multi-image identity-consistent video generation.
- `05_comfyui_kling_wrapper_text2video_v26_sound.json`: `kling-v2-6` talking-head example using the node's built-in `voice_preset` dropdown.
- `06_comfyui_kling_wrapper_advanced_element_subject_to_image2video.json`: create an advanced element and bind it into image-to-video.
- `07_comfyui_kling_wrapper_motion_control_v26.json`: motion-control workflow with reference image and reference video.
- `08_comfyui_kling_wrapper_virtual_try_on.json`: virtual try-on image workflow.
- `09_comfyui_kling_wrapper_image_expand.json`: image expansion workflow.
- `10_comfyui_kling_wrapper_video_extend_chain.json`: generate a clip and extend it.
- `11_comfyui_kling_wrapper_text_to_audio.json`: text-to-audio workflow.
- `12_comfyui_kling_wrapper_video_to_audio.json`: extract or generate audio from a video clip.
- `13_comfyui_kling_wrapper_lip_sync_from_text.json`: lip-sync workflow driven by text input.
- `14_comfyui_kling_wrapper_effects_single_image.json`: single-image effect example.
- `api_examples.py`: small Python snippets for the same upgraded API wrappers.
"""
(ROOT / "README.md").write_text(content, encoding="utf-8")
def write_api_examples():
content = '''import base64
import os
from pathlib import Path
from py.api import AdvancedCustomElements, Client, Image2Video, ImageGenerator, MotionControl, MultiImages2Video, Text2Video
def image_to_base64(path: str) -> str:
return base64.b64encode(Path(path).read_bytes()).decode("utf-8")
def build_client(in_china: bool = True) -> Client:
access_key = os.environ["KLING_ACCESS_KEY"]
secret_key = os.environ["KLING_SECRET_KEY"]
return Client(access_key, secret_key, in_china=in_china, timeout=30, poll_interval=2.0)
def example_image_generation(client: Client):
task = ImageGenerator()
task.model_name = "kling-v3"
task.prompt = "A cinematic editorial portrait with elegant framing and realistic skin texture."
task.aspect_ratio = "16:9"
task.resolution = "1k"
return task.run(client)
def example_text2video_v3(client: Client):
task = Text2Video()
task.model_name = "kling-v3"
task.prompt = "A traveler walks through an old alley at dusk with cinematic multi-shot storytelling."
task.mode = "pro"
task.aspect_ratio = "16:9"
task.duration = "5"
task.shot_type = "intelligence"
return task.run(client)
def example_text2video_v26_sound(client: Client):
task = Text2Video()
task.model_name = "kling-v2-6"
task.prompt = "A presenter speaks directly to camera in a clean studio."
task.mode = "pro"
task.aspect_ratio = "16:9"
task.duration = "5"
task.sound = "on"
task.voice_list = [{"voice_id": "reader_en_m-v1"}]
return task.run(client)
def example_create_advanced_element(client: Client, image_path: str):
task = AdvancedCustomElements()
task.type = "image_subject"
task.name = "demo_subject"
task.image = image_to_base64(image_path)
task.image_list = [task.image]
return task.run(client)
def example_image2video_with_element(client: Client, image_path: str, element_id: str):
task = Image2Video()
task.model_name = "kling-v3"
task.image = image_to_base64(image_path)
task.prompt = "Keep the same subject identity while the camera slowly pushes in."
task.mode = "pro"
task.duration = "5"
task.element_list = [{"element_id": element_id}]
return task.run(client)
def example_multi_images_to_video(client: Client, image_paths: list[str]):
if len(image_paths) < 2:
raise ValueError("Provide at least two image paths.")
task = MultiImages2Video()
task.model_name = "kling-v3"
encoded = [image_to_base64(path) for path in image_paths]
task.image = encoded[0]
task.image_list = encoded[1:]
task.prompt = "Maintain the same identity across the shot with natural motion."
task.mode = "pro"
task.duration = "5"
task.aspect_ratio = "16:9"
return task.run(client)
def example_motion_control(client: Client, image_path: str, reference_video_url: str):
task = MotionControl()
task.model_name = "kling-v2-6"
task.reference_image = image_to_base64(image_path)
task.reference_video = reference_video_url
task.prompt = "Transfer the motion naturally while keeping the subject stable and realistic."
task.mode = "pro"
task.duration = "5"
return task.run(client)
if __name__ == "__main__":
print("Set KLING_ACCESS_KEY and KLING_SECRET_KEY before running these examples.")
print("Import this file and call the helper that matches the workflow you want to test.")
'''
(ROOT / "api_examples.py").write_text(content, encoding="utf-8")
def generate_workflows():
examples = {}
nodes = [
client_node(1, 0),
image_generator_node(2, [430, 40], 1),
save_image_node(3, "Comfyui-Kling-Wrapper-image-generation", [900, 60], 2, 2),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 0, "IMAGE"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[1]["outputs"][0]["links"] = [2]
examples["01_comfyui_kling_wrapper_image_generation_v3.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
text2video_node(
2,
[430, 20],
1,
"kling-v3",
"A traveler moves through an old alley at dusk, cinematic atmosphere, natural motion, evolving composition with coherent multi-shot storytelling.",
mode="pro",
shot_type="intelligence",
),
preview_video_node(3, [910, 20], 2, 2),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 0, "STRING"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[1]["outputs"][0]["links"] = [2]
examples["02_comfyui_kling_wrapper_text2video_v3_intelligence.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_portrait.png", [60, 340], 1),
image2video_node(
3,
[430, 200],
2,
"kling-v3",
"A cinematic close-up portrait. The subject breathes naturally, hair and clothing move subtly in the wind, and the camera slowly pushes in.",
mode="pro",
),
preview_video_node(4, [920, 200], 3, 3),
]
links = [
link(1, 1, 0, 3, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 1, "IMAGE"),
link(3, 3, 0, 4, 0, "STRING"),
]
nodes[2]["inputs"][0]["link"] = 1
nodes[2]["inputs"][1]["link"] = 2
nodes[2]["outputs"][0]["links"] = [3]
examples["03_comfyui_kling_wrapper_image2video_v3.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_subject_a.png", [40, 330], 1),
load_image_node(3, "example_subject_b.png", [40, 700], 2),
image_batch_node(4, [370, 510], 3),
multi_images_to_video_node(5, [700, 420], 4),
preview_video_node(6, [1180, 420], 5, 5),
]
links = [
link(1, 1, 0, 5, 0, CLIENT_TYPE),
link(2, 2, 0, 4, 0, "IMAGE"),
link(3, 3, 0, 4, 1, "IMAGE"),
link(4, 4, 0, 5, 1, "IMAGE"),
link(5, 5, 0, 6, 0, "STRING"),
]
nodes[3]["inputs"][0]["link"] = 2
nodes[3]["inputs"][1]["link"] = 3
nodes[4]["inputs"][0]["link"] = 1
nodes[4]["inputs"][1]["link"] = 4
nodes[4]["outputs"][0]["links"] = [5]
examples["04_comfyui_kling_wrapper_multi_images_to_video_v3.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
text2video_node(
2,
[430, 20],
1,
"kling-v2-6",
"A presenter speaks directly to camera in a clean studio, natural gestures, subtle head motion, clear talking-head composition.",
mode="pro",
sound="on",
voice_preset="The Reader | reader_en_m-v1",
),
preview_video_node(3, [910, 20], 2, 2),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 0, "STRING"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[1]["outputs"][0]["links"] = [2]
examples["05_comfyui_kling_wrapper_text2video_v26_sound.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_subject.png", [30, 140], 1),
load_image_node(3, "example_scene.png", [30, 520], 2),
advanced_element_create_node(4, [390, 100], 3),
element_list_builder_node(5, [820, 120], 4),
image2video_node(
6,
[820, 420],
5,
"kling-v3",
"Keep the same subject identity while the camera slowly moves and the background remains coherent.",
mode="pro",
),
preview_video_node(7, [1290, 420], 6, 7),
]
links = [
link(1, 1, 0, 4, 0, CLIENT_TYPE),
link(2, 2, 0, 4, 1, "IMAGE"),
link(3, 4, 0, 5, 0, ELEMENT_TYPE),
link(4, 1, 0, 6, 0, CLIENT_TYPE),
link(5, 3, 0, 6, 1, "IMAGE"),
link(6, 5, 0, 6, 4, ELEMENT_LIST_TYPE),
link(7, 6, 0, 7, 0, "STRING"),
]
nodes[3]["inputs"][0]["link"] = 1
nodes[3]["inputs"][1]["link"] = 2
nodes[4]["inputs"][0]["link"] = 3
nodes[5]["inputs"][0]["link"] = 4
nodes[5]["inputs"][1]["link"] = 5
nodes[5]["inputs"].append(input_slot("element_list", ELEMENT_LIST_TYPE, 6))
nodes[5]["outputs"][0]["links"] = [7]
examples["06_comfyui_kling_wrapper_advanced_element_subject_to_image2video.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_motion_subject.png", [40, 330], 1),
motion_control_node(3, [430, 190], 2),
preview_video_node(4, [930, 190], 3, 3),
]
links = [
link(1, 1, 0, 3, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 1, "IMAGE"),
link(3, 3, 0, 4, 0, "STRING"),
]
nodes[2]["inputs"][0]["link"] = 1
nodes[2]["inputs"][1]["link"] = 2
nodes[2]["outputs"][0]["links"] = [3]
examples["07_comfyui_kling_wrapper_motion_control_v26.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_model.png", [40, 150], 1),
load_image_node(3, "example_cloth.png", [40, 520], 2),
virtual_try_on_node(4, [420, 310], 3),
save_image_node(5, "Comfyui-Kling-Wrapper-virtual-try-on", [860, 320], 4, 4),
]
links = [
link(1, 1, 0, 4, 0, CLIENT_TYPE),
link(2, 2, 0, 4, 1, "IMAGE"),
link(3, 3, 0, 4, 2, "IMAGE"),
link(4, 4, 0, 5, 0, "IMAGE"),
]
nodes[3]["inputs"][0]["link"] = 1
nodes[3]["inputs"][1]["link"] = 2
nodes[3]["inputs"][2]["link"] = 3
nodes[3]["outputs"][0]["links"] = [4]
examples["08_comfyui_kling_wrapper_virtual_try_on.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_expand.png", [40, 220], 1),
image_expander_node(3, [430, 180], 2),
save_image_node(4, "Comfyui-Kling-Wrapper-image-expand", [860, 190], 3, 3),
]
links = [
link(1, 1, 0, 3, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 1, "IMAGE"),
link(3, 3, 0, 4, 0, "IMAGE"),
]
nodes[2]["inputs"][0]["link"] = 1
nodes[2]["inputs"][1]["link"] = 2
nodes[2]["outputs"][0]["links"] = [3]
examples["09_comfyui_kling_wrapper_image_expand.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
text2video_node(
2,
[420, 20],
1,
"kling-v3",
"A quiet street scene at sunrise with subtle camera drift and natural environmental motion.",
mode="pro",
),
video_extender_node(3, [870, 40], 2),
preview_video_node(4, [1290, 40], 3, 4),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 1, 0, 3, 0, CLIENT_TYPE),
link(3, 2, 1, 3, 1, "STRING"),
link(4, 3, 0, 4, 0, "STRING"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[2]["inputs"][0]["link"] = 2
nodes[2]["inputs"][1]["link"] = 3
nodes[2]["outputs"][0]["links"] = [4]
examples["10_comfyui_kling_wrapper_video_extend_chain.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
text_to_audio_node(2, [430, 80], 1),
preview_audio_node(3, [870, 80], 2, 2),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 2, 1, 3, 0, "STRING"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[1]["outputs"][1]["links"] = [2]
examples["11_comfyui_kling_wrapper_text_to_audio.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
text2video_node(
2,
[420, 20],
1,
"kling-v3",
"A person walks through an empty hall with slow cinematic movement.",
mode="pro",
),
video_to_audio_node(3, [880, 30], 2),
preview_audio_node(4, [1330, 30], 3, 4),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 1, 0, 3, 0, CLIENT_TYPE),
link(3, 2, 1, 3, 1, "STRING"),
link(4, 3, 3, 4, 0, "STRING"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[2]["inputs"][0]["link"] = 2
nodes[2]["inputs"][1]["link"] = 3
nodes[2]["outputs"][3]["links"] = [4]
examples["12_comfyui_kling_wrapper_video_to_audio.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
text2video_node(
2,
[420, 20],
1,
"kling-v3",
"A portrait subject looks at camera with subtle idle motion.",
mode="pro",
),
lip_sync_text_input_node(3, [420, 420], 2),
lip_sync_node(4, [880, 240], 3),
preview_video_node(5, [1320, 240], 4, 5),
]
links = [
link(1, 1, 0, 2, 0, CLIENT_TYPE),
link(2, 1, 0, 4, 0, CLIENT_TYPE),
link(3, 3, 0, 4, 1, LIPSYNC_INPUT_TYPE),
link(4, 2, 1, 4, 3, "STRING"),
link(5, 4, 0, 5, 0, "STRING"),
]
nodes[1]["inputs"][0]["link"] = 1
nodes[3]["inputs"][0]["link"] = 2
nodes[3]["inputs"][1]["link"] = 3
nodes[3]["inputs"][2]["link"] = 4
nodes[3]["outputs"][0]["links"] = [5]
examples["13_comfyui_kling_wrapper_lip_sync_from_text.json"] = workflow(nodes, links)
nodes = [
client_node(1, 0),
load_image_node(2, "example_effect_input.png", [40, 220], 1),
effects_node(3, [430, 180], 2),
preview_video_node(4, [900, 180], 3, 3),
]
links = [
link(1, 1, 0, 3, 0, CLIENT_TYPE),
link(2, 2, 0, 3, 1, "IMAGE"),
link(3, 3, 0, 4, 0, "STRING"),
]
nodes[2]["inputs"][0]["link"] = 1
nodes[2]["inputs"][1]["link"] = 2
nodes[2]["outputs"][0]["links"] = [3]
examples["14_comfyui_kling_wrapper_effects_single_image.json"] = workflow(nodes, links)
for name, data in examples.items():
write_json(name, data)
if __name__ == "__main__":
write_examples_readme()
write_api_examples()
generate_workflows()
print(f"Wrote refreshed examples into {ROOT}")