mirror of
https://git.datalinker.icu/comfyanonymous/ComfyUI
synced 2026-09-07 18:47:05 +08:00
[Kling] Add Duration and Video ID outputs (#105)
This commit is contained in:
parent
1178022a7a
commit
99a6b59cbb
@ -103,7 +103,42 @@ def get_camera_control_input_config(
|
|||||||
return IO.FLOAT, input_config
|
return IO.FLOAT, input_config
|
||||||
|
|
||||||
|
|
||||||
class KlingCameraControls(ComfyNodeABC):
|
class KlingNodeBase(ComfyNodeABC):
|
||||||
|
"""
|
||||||
|
Base class for Kling nodes.
|
||||||
|
|
||||||
|
Compatibility Table
|
||||||
|
===================
|
||||||
|
| Mode | Duration | Model Name | Camera Control | Image Tail |
|
||||||
|
|------|----------|------------------|----------------|------------|
|
||||||
|
| std | 5 | kling-v1 | No | Yes |
|
||||||
|
| std | 5 | kling-v1-5 | No | Yes |
|
||||||
|
| std | 5 | kling-v1-6 | No | No |
|
||||||
|
| std | 5 | kling-v2-master | No | No |
|
||||||
|
| std | 10 | kling-v1 | No | No |
|
||||||
|
| std | 10 | kling-v1-5 | No | No |
|
||||||
|
| std | 10 | kling-v1-6 | No | No |
|
||||||
|
| std | 10 | kling-v2-master | No | No |
|
||||||
|
| pro | 5 | kling-v1 | No | Yes |
|
||||||
|
| pro | 5 | kling-v1-5 | Yes | Yes |
|
||||||
|
| pro | 5 | kling-v1-6 | No | Yes |
|
||||||
|
| pro | 5 | kling-v2-master | No | No |
|
||||||
|
| pro | 10 | kling-v1 | No | No |
|
||||||
|
| pro | 10 | kling-v1-5 | No | Yes |
|
||||||
|
| pro | 10 | kling-v1-6 | No | Yes |
|
||||||
|
| pro | 10 | kling-v2-master | No | No |
|
||||||
|
|
||||||
|
**Note**: Although the combo of pro mode, kling-v1-5 model, and 5s duration
|
||||||
|
supports both camera_control and image_tail, you can only use one feature
|
||||||
|
at a time.
|
||||||
|
"""
|
||||||
|
|
||||||
|
FUNCTION = "api_call"
|
||||||
|
CATEGORY = "api node/video/Kling"
|
||||||
|
API_NODE = True
|
||||||
|
|
||||||
|
|
||||||
|
class KlingCameraControls(KlingNodeBase):
|
||||||
"""Kling Camera Controls Node"""
|
"""Kling Camera Controls Node"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -148,16 +183,16 @@ class KlingCameraControls(ComfyNodeABC):
|
|||||||
RETURN_NAMES = ("camera_control",)
|
RETURN_NAMES = ("camera_control",)
|
||||||
FUNCTION = "main"
|
FUNCTION = "main"
|
||||||
|
|
||||||
def main(
|
@classmethod
|
||||||
self,
|
def VALIDATE_INPUTS(
|
||||||
camera_control_type: str,
|
cls,
|
||||||
horizontal_movement: float,
|
horizontal_movement: float,
|
||||||
vertical_movement: float,
|
vertical_movement: float,
|
||||||
pan: float,
|
pan: float,
|
||||||
tilt: float,
|
tilt: float,
|
||||||
roll: float,
|
roll: float,
|
||||||
zoom: float,
|
zoom: float,
|
||||||
):
|
) -> bool | str:
|
||||||
if not is_valid_camera_control_configs(
|
if not is_valid_camera_control_configs(
|
||||||
[
|
[
|
||||||
horizontal_movement,
|
horizontal_movement,
|
||||||
@ -169,7 +204,18 @@ class KlingCameraControls(ComfyNodeABC):
|
|||||||
]
|
]
|
||||||
):
|
):
|
||||||
return "Invalid camera control configs: at least one of the values must be non-zero"
|
return "Invalid camera control configs: at least one of the values must be non-zero"
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main(
|
||||||
|
self,
|
||||||
|
camera_control_type: str,
|
||||||
|
horizontal_movement: float,
|
||||||
|
vertical_movement: float,
|
||||||
|
pan: float,
|
||||||
|
tilt: float,
|
||||||
|
roll: float,
|
||||||
|
zoom: float,
|
||||||
|
) -> tuple[CameraControl]:
|
||||||
return (
|
return (
|
||||||
CameraControl(
|
CameraControl(
|
||||||
type=CameraType(camera_control_type),
|
type=CameraType(camera_control_type),
|
||||||
@ -185,18 +231,8 @@ class KlingCameraControls(ComfyNodeABC):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class KlingNodeBase(ComfyNodeABC):
|
|
||||||
"""Base class for Kling nodes."""
|
|
||||||
|
|
||||||
FUNCTION = "api_call"
|
|
||||||
CATEGORY = "api node/video/Kling"
|
|
||||||
API_NODE = True
|
|
||||||
|
|
||||||
|
|
||||||
class KlingTextToVideoNode(KlingNodeBase):
|
class KlingTextToVideoNode(KlingNodeBase):
|
||||||
"""
|
"""Kling Text to Video Node"""
|
||||||
Kling Text to Video Node.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def poll_for_task_status(task_id: str, auth_token: str) -> KlingText2VideoResponse:
|
def poll_for_task_status(task_id: str, auth_token: str) -> KlingText2VideoResponse:
|
||||||
@ -254,13 +290,11 @@ class KlingTextToVideoNode(KlingNodeBase):
|
|||||||
enum_type=AspectRatio,
|
enum_type=AspectRatio,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"optional": {
|
|
||||||
"camera_control": ("CAMERA_CONTROL", {}),
|
|
||||||
},
|
|
||||||
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("VIDEO",)
|
RETURN_TYPES = ("VIDEO", "STRING", "STRING")
|
||||||
|
RETURN_NAMES = ("VIDEO", "Kling ID", "Duration (sec)")
|
||||||
DESCRIPTION = "Kling Text to Video Node"
|
DESCRIPTION = "Kling Text to Video Node"
|
||||||
|
|
||||||
def api_call(
|
def api_call(
|
||||||
@ -274,7 +308,7 @@ class KlingTextToVideoNode(KlingNodeBase):
|
|||||||
aspect_ratio: str,
|
aspect_ratio: str,
|
||||||
camera_control: Optional[CameraControl] = None,
|
camera_control: Optional[CameraControl] = None,
|
||||||
auth_token: Optional[str] = None,
|
auth_token: Optional[str] = None,
|
||||||
) -> tuple[VideoFromFile]:
|
) -> tuple[VideoFromFile, str, str]:
|
||||||
validate_prompts(prompt, negative_prompt, MAX_PROMPT_LENGTH_T2V)
|
validate_prompts(prompt, negative_prompt, MAX_PROMPT_LENGTH_T2V)
|
||||||
initial_operation = SynchronousOperation(
|
initial_operation = SynchronousOperation(
|
||||||
endpoint=ApiEndpoint(
|
endpoint=ApiEndpoint(
|
||||||
@ -311,16 +345,79 @@ class KlingTextToVideoNode(KlingNodeBase):
|
|||||||
logging.error(error_msg)
|
logging.error(error_msg)
|
||||||
raise KlingApiError(error_msg)
|
raise KlingApiError(error_msg)
|
||||||
|
|
||||||
video_url = str(final_response.data.task_result.videos[0].url)
|
video = final_response.data.task_result.videos[0]
|
||||||
logging.debug("Kling task %s succeeded. Video URL: %s", task_id, video_url)
|
logging.debug("Kling task %s succeeded. Video URL: %s", task_id, video.url)
|
||||||
|
return (
|
||||||
|
download_url_to_video_output(video.url),
|
||||||
|
str(video.id),
|
||||||
|
str(video.duration),
|
||||||
|
)
|
||||||
|
|
||||||
return (download_url_to_video_output(video_url),)
|
|
||||||
|
class KlingCameraControlT2VNode(KlingTextToVideoNode):
|
||||||
|
"""
|
||||||
|
Kling Text to Video Camera Control Node. This node is a text to video node, but it supports controlling the camera.
|
||||||
|
Duration, mode, and model_name request fields are hard-coded because camera control is only supported in pro mode with the kling-v1-5 model at 5s duration as of 2025-05-02.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"prompt": model_field_to_node_input(
|
||||||
|
IO.STRING, KlingText2VideoRequest, "prompt", multiline=True
|
||||||
|
),
|
||||||
|
"negative_prompt": model_field_to_node_input(
|
||||||
|
IO.STRING,
|
||||||
|
KlingText2VideoRequest,
|
||||||
|
"negative_prompt",
|
||||||
|
multiline=True,
|
||||||
|
),
|
||||||
|
"cfg_scale": model_field_to_node_input(
|
||||||
|
IO.FLOAT, KlingText2VideoRequest, "cfg_scale"
|
||||||
|
),
|
||||||
|
"aspect_ratio": model_field_to_node_input(
|
||||||
|
IO.COMBO,
|
||||||
|
KlingText2VideoRequest,
|
||||||
|
"aspect_ratio",
|
||||||
|
enum_type=AspectRatio,
|
||||||
|
),
|
||||||
|
"camera_control": (
|
||||||
|
"CAMERA_CONTROL",
|
||||||
|
{
|
||||||
|
"tooltip": "Can be created using the Kling Camera Controls node. Controls the camera movement and motion during the video generation.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
||||||
|
}
|
||||||
|
|
||||||
|
DESCRIPTION = "Transform text into cinematic videos with professional camera movements that simulate real-world cinematography. Control virtual camera actions including zoom, rotation, pan, tilt, and first-person view, while maintaining focus on your original text."
|
||||||
|
|
||||||
|
def api_call(
|
||||||
|
self,
|
||||||
|
prompt: str,
|
||||||
|
negative_prompt: str,
|
||||||
|
cfg_scale: float,
|
||||||
|
aspect_ratio: str,
|
||||||
|
camera_control: Optional[CameraControl] = None,
|
||||||
|
auth_token: Optional[str] = None,
|
||||||
|
):
|
||||||
|
return super().api_call(
|
||||||
|
model_name="kling-v1-5",
|
||||||
|
cfg_scale=cfg_scale,
|
||||||
|
mode="pro",
|
||||||
|
aspect_ratio=aspect_ratio,
|
||||||
|
duration="5",
|
||||||
|
prompt=prompt,
|
||||||
|
negative_prompt=negative_prompt,
|
||||||
|
camera_control=camera_control,
|
||||||
|
auth_token=auth_token,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class KlingImage2VideoNode(KlingNodeBase):
|
class KlingImage2VideoNode(KlingNodeBase):
|
||||||
"""
|
"""Kling Image to Video Node"""
|
||||||
Kling Image to Video Node.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def poll_for_task_status(task_id: str, auth_token: str) -> KlingImage2VideoResponse:
|
def poll_for_task_status(task_id: str, auth_token: str) -> KlingImage2VideoResponse:
|
||||||
@ -347,6 +444,9 @@ class KlingImage2VideoNode(KlingNodeBase):
|
|||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
|
"start_frame": model_field_to_node_input(
|
||||||
|
IO.IMAGE, KlingImage2VideoRequest, "image"
|
||||||
|
),
|
||||||
"prompt": model_field_to_node_input(
|
"prompt": model_field_to_node_input(
|
||||||
IO.STRING, KlingImage2VideoRequest, "prompt", multiline=True
|
IO.STRING, KlingImage2VideoRequest, "prompt", multiline=True
|
||||||
),
|
),
|
||||||
@ -363,9 +463,6 @@ class KlingImage2VideoNode(KlingNodeBase):
|
|||||||
enum_type=ModelName,
|
enum_type=ModelName,
|
||||||
default="kling-v2-master",
|
default="kling-v2-master",
|
||||||
),
|
),
|
||||||
"start_frame": model_field_to_node_input(
|
|
||||||
IO.IMAGE, KlingImage2VideoRequest, "image"
|
|
||||||
),
|
|
||||||
"cfg_scale": model_field_to_node_input(
|
"cfg_scale": model_field_to_node_input(
|
||||||
IO.FLOAT, KlingImage2VideoRequest, "cfg_scale"
|
IO.FLOAT, KlingImage2VideoRequest, "cfg_scale"
|
||||||
),
|
),
|
||||||
@ -382,24 +479,19 @@ class KlingImage2VideoNode(KlingNodeBase):
|
|||||||
IO.COMBO, KlingImage2VideoRequest, "duration", enum_type=Duration
|
IO.COMBO, KlingImage2VideoRequest, "duration", enum_type=Duration
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"optional": {
|
|
||||||
"camera_control": ("CAMERA_CONTROL", {}),
|
|
||||||
"end_frame": model_field_to_node_input(
|
|
||||||
IO.IMAGE, KlingImage2VideoRequest, "image_tail"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("VIDEO",)
|
RETURN_TYPES = ("VIDEO", "STRING", "STRING")
|
||||||
|
RETURN_NAMES = ("VIDEO", "Kling ID", "Duration (sec)")
|
||||||
DESCRIPTION = "Kling Image to Video Node"
|
DESCRIPTION = "Kling Image to Video Node"
|
||||||
|
|
||||||
def api_call(
|
def api_call(
|
||||||
self,
|
self,
|
||||||
|
start_frame: torch.Tensor,
|
||||||
prompt: str,
|
prompt: str,
|
||||||
negative_prompt: str,
|
negative_prompt: str,
|
||||||
model_name: str,
|
model_name: str,
|
||||||
start_frame: torch.Tensor,
|
|
||||||
cfg_scale: float,
|
cfg_scale: float,
|
||||||
mode: str,
|
mode: str,
|
||||||
aspect_ratio: str,
|
aspect_ratio: str,
|
||||||
@ -449,20 +541,190 @@ class KlingImage2VideoNode(KlingNodeBase):
|
|||||||
logging.error(error_msg)
|
logging.error(error_msg)
|
||||||
raise KlingApiError(error_msg)
|
raise KlingApiError(error_msg)
|
||||||
|
|
||||||
video_url = str(final_response.data.task_result.videos[0].url)
|
video = final_response.data.task_result.videos[0]
|
||||||
logging.info("Attempting to download video from URL: %s", video_url)
|
logging.info("Kling task %s succeeded. Video URL: %s", task_id, video.url)
|
||||||
|
|
||||||
return (download_url_to_video_output(video_url),)
|
return (
|
||||||
|
download_url_to_video_output(video.url),
|
||||||
|
str(video.id),
|
||||||
|
str(video.duration),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KlingCameraControlI2VNode(KlingImage2VideoNode):
|
||||||
|
"""
|
||||||
|
Kling Image to Video Camera Control Node. This node is a image to video node, but it supports controlling the camera.
|
||||||
|
Duration, mode, and model_name request fields are hard-coded because camera control is only supported in pro mode with the kling-v1-5 model at 5s duration as of 2025-05-02.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"start_frame": model_field_to_node_input(
|
||||||
|
IO.IMAGE, KlingImage2VideoRequest, "image"
|
||||||
|
),
|
||||||
|
"prompt": model_field_to_node_input(
|
||||||
|
IO.STRING, KlingImage2VideoRequest, "prompt", multiline=True
|
||||||
|
),
|
||||||
|
"negative_prompt": model_field_to_node_input(
|
||||||
|
IO.STRING,
|
||||||
|
KlingImage2VideoRequest,
|
||||||
|
"negative_prompt",
|
||||||
|
multiline=True,
|
||||||
|
),
|
||||||
|
"cfg_scale": model_field_to_node_input(
|
||||||
|
IO.FLOAT, KlingImage2VideoRequest, "cfg_scale"
|
||||||
|
),
|
||||||
|
"aspect_ratio": model_field_to_node_input(
|
||||||
|
IO.COMBO,
|
||||||
|
KlingImage2VideoRequest,
|
||||||
|
"aspect_ratio",
|
||||||
|
enum_type=AspectRatio,
|
||||||
|
),
|
||||||
|
"camera_control": (
|
||||||
|
"CAMERA_CONTROL",
|
||||||
|
{
|
||||||
|
"tooltip": "Can be created using the Kling Camera Controls node. Controls the camera movement and motion during the video generation.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
||||||
|
}
|
||||||
|
|
||||||
|
DESCRIPTION = "Transform still images into cinematic videos with professional camera movements that simulate real-world cinematography. Control virtual camera actions including zoom, rotation, pan, tilt, and first-person view, while maintaining focus on your original image."
|
||||||
|
|
||||||
|
def api_call(
|
||||||
|
self,
|
||||||
|
start_frame: torch.Tensor,
|
||||||
|
prompt: str,
|
||||||
|
negative_prompt: str,
|
||||||
|
cfg_scale: float,
|
||||||
|
aspect_ratio: str,
|
||||||
|
camera_control: CameraControl,
|
||||||
|
auth_token: Optional[str] = None,
|
||||||
|
):
|
||||||
|
return super().api_call(
|
||||||
|
model_name="kling-v1-5",
|
||||||
|
start_frame=start_frame,
|
||||||
|
cfg_scale=cfg_scale,
|
||||||
|
mode="pro",
|
||||||
|
aspect_ratio=aspect_ratio,
|
||||||
|
duration="5",
|
||||||
|
prompt=prompt,
|
||||||
|
negative_prompt=negative_prompt,
|
||||||
|
camera_control=camera_control,
|
||||||
|
auth_token=auth_token,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KlingStartEndFrameNode(KlingImage2VideoNode):
|
||||||
|
"""
|
||||||
|
Kling First Last Frame Node. This node allows creation of a video from a first and last frame. It calls the normal image to video endpoint, but only allows the subset of input options that support the `image_tail` request field.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_mode_string_mapping() -> dict[str, tuple[str, str, str]]:
|
||||||
|
"""
|
||||||
|
Returns a mapping of mode strings to their corresponding (mode, duration, model_name) tuples.
|
||||||
|
Only includes config combos that support the `image_tail` request field.
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"standard mode / 5s duration / kling-v1": ("std", "5", "kling-v1"),
|
||||||
|
"standard mode / 5s duration / kling-v1-5": ("std", "5", "kling-v1-5"),
|
||||||
|
"pro mode / 5s duration / kling-v1": ("pro", "5", "kling-v1"),
|
||||||
|
"pro mode / 5s duration / kling-v1-5": ("pro", "5", "kling-v1-5"),
|
||||||
|
"pro mode / 5s duration / kling-v1-6": ("pro", "5", "kling-v1-6"),
|
||||||
|
"pro mode / 10s duration / kling-v1-5": ("pro", "10", "kling-v1-5"),
|
||||||
|
"pro mode / 10s duration / kling-v1-6": ("pro", "10", "kling-v1-6"),
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
modes = list(KlingStartEndFrameNode.get_mode_string_mapping().keys())
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"start_frame": model_field_to_node_input(
|
||||||
|
IO.IMAGE, KlingImage2VideoRequest, "image"
|
||||||
|
),
|
||||||
|
"end_frame": model_field_to_node_input(
|
||||||
|
IO.IMAGE, KlingImage2VideoRequest, "image_tail"
|
||||||
|
),
|
||||||
|
"prompt": model_field_to_node_input(
|
||||||
|
IO.STRING, KlingImage2VideoRequest, "prompt", multiline=True
|
||||||
|
),
|
||||||
|
"negative_prompt": model_field_to_node_input(
|
||||||
|
IO.STRING,
|
||||||
|
KlingImage2VideoRequest,
|
||||||
|
"negative_prompt",
|
||||||
|
multiline=True,
|
||||||
|
),
|
||||||
|
"cfg_scale": model_field_to_node_input(
|
||||||
|
IO.FLOAT, KlingImage2VideoRequest, "cfg_scale"
|
||||||
|
),
|
||||||
|
"aspect_ratio": model_field_to_node_input(
|
||||||
|
IO.COMBO,
|
||||||
|
KlingImage2VideoRequest,
|
||||||
|
"aspect_ratio",
|
||||||
|
enum_type=AspectRatio,
|
||||||
|
),
|
||||||
|
"mode": (
|
||||||
|
modes,
|
||||||
|
{
|
||||||
|
"default": modes[2],
|
||||||
|
"tooltip": "The configuration to use for the video generation following the format: mode / duration / model_name.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
|
||||||
|
}
|
||||||
|
|
||||||
|
DESCRIPTION = "Generate a video sequence that transitions between your provided start and end images. The node creates all frames in between, producing a smooth transformation from the first frame to the last."
|
||||||
|
|
||||||
|
def parse_inputs_from_mode(self, mode: str) -> tuple[str, str, str]:
|
||||||
|
"""Parses the mode input into a tuple of (model_name, duration, mode)."""
|
||||||
|
return KlingStartEndFrameNode.get_mode_string_mapping()[mode]
|
||||||
|
|
||||||
|
def api_call(
|
||||||
|
self,
|
||||||
|
start_frame: torch.Tensor,
|
||||||
|
end_frame: torch.Tensor,
|
||||||
|
prompt: str,
|
||||||
|
negative_prompt: str,
|
||||||
|
cfg_scale: float,
|
||||||
|
aspect_ratio: str,
|
||||||
|
mode: str,
|
||||||
|
auth_token: Optional[str] = None,
|
||||||
|
):
|
||||||
|
mode, duration, model_name = self.parse_inputs_from_mode(mode)
|
||||||
|
return super().api_call(
|
||||||
|
prompt=prompt,
|
||||||
|
negative_prompt=negative_prompt,
|
||||||
|
model_name=model_name,
|
||||||
|
start_frame=start_frame,
|
||||||
|
cfg_scale=cfg_scale,
|
||||||
|
mode=mode,
|
||||||
|
aspect_ratio=aspect_ratio,
|
||||||
|
duration=duration,
|
||||||
|
end_frame=end_frame,
|
||||||
|
auth_token=auth_token,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"KlingCameraControls": KlingCameraControls,
|
"KlingCameraControls": KlingCameraControls,
|
||||||
"KlingTextToVideoNode": KlingTextToVideoNode,
|
"KlingTextToVideoNode": KlingTextToVideoNode,
|
||||||
"KlingImage2VideoNode": KlingImage2VideoNode,
|
"KlingImage2VideoNode": KlingImage2VideoNode,
|
||||||
|
"KlingCameraControlI2VNode": KlingCameraControlI2VNode,
|
||||||
|
"KlingCameraControlT2VNode": KlingCameraControlT2VNode,
|
||||||
|
"KlingStartEndFrameNode": KlingStartEndFrameNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
"KlingCameraControls": "Kling Camera Controls",
|
"KlingCameraControls": "Kling Camera Controls",
|
||||||
"KlingTextToVideoNode": "Kling Text to Video",
|
"KlingTextToVideoNode": "Kling Text to Video",
|
||||||
"KlingImage2VideoNode": "Kling Image to Video",
|
"KlingImage2VideoNode": "Kling Image to Video",
|
||||||
|
"KlingCameraControlI2VNode": "Kling Image to Video (Camera Control)",
|
||||||
|
"KlingCameraControlT2VNode": "Kling Text to Video (Camera Control)",
|
||||||
|
"KlingStartEndFrameNode": "Kling Start-End Frame to Video",
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user