adding kling motion 2.6

This commit is contained in:
Steve Tietze
2026-01-08 09:59:02 +07:00
parent 47d77aa048
commit de946d248b
4 changed files with 514 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
Kling 26 Motion I2V
inputs
- Ref Image (Single Image)
- Motion video (Single mp4)
These files are uploaded to Kie AI similar to how we upload the images in kling26_i2v.py how its done in their.
KIE API Documents:
POST
/api/v1/jobs/createTask
Create Task
Create a new generation task
Request Parameters
The API accepts a JSON payload with the following structure:
Request Body Structure
{
"model": "string",
"callBackUrl": "string (optional)",
"input": {
// Input parameters based on form configuration
}
}
Root Level Parameters
model
Required
string
The model name to use for generation
Example:
"kling-2.6/motion-control"
callBackUrl
Optional
string
Callback URL for task completion notifications. Optional parameter. If provided, the system will send POST requests to this URL when the task completes (success or failure). If not provided, no callback notifications will be sent.
Example:
"https://your-domain.com/api/callback"
Input Object Parameters
The input object contains the following parameters based on the form configuration:
input.prompt
Required
string
A text description of the desired output. Maximum length is 2500 characters.
Max length: 2500 characters
Example:
"The cartoon character is dancing."
input.input_urls
Required
array(URL)
An array containing a single image URL. The photo must clearly show the subject's head, shoulders, and torso.
Please provide the URL of the uploaded file; Accepted types: image/jpeg, image/png, image/webp; Max size: 10.0MB
Example:
["https://static.aiquickdraw.com/tools/example/1767694885407_pObJoMcy.png"]
input.video_urls
Required
array(URL)
An array containing a single video URL. The duration must be between 3 to 30 seconds, and the video must clearly show the subject's head, shoulders, and torso.The minimum width and height for videos must be 720 pixels, and only jpeg/jpg/png image formats are supported.
Please provide the URL of the uploaded file; Accepted types: video/mp4, video/quicktime, video/x-matroska; Max size: 100.0MB
Example:
["https://static.aiquickdraw.com/tools/example/1767525918769_QyvTNib2.mp4"]
input.character_orientation
Required
string
Generate the orientation of the characters in the video. 'image': same orientation as the person in the picture (max 10s video). 'video': consistent with the orientation of the characters in the video (max 30s video).
Available options:
image
-
Image
video
-
Video
Example:
"video"
input.mode
Required
string
Output resolution mode. Use 'std' for 720p or 'pro' for 1080p.
Available options:
720p
-
720p
1080p
-
1080p
Example:
"720p"
Request Example
cURL
JavaScript
Python
import requests
import json
url = "https://api.kie.ai/api/v1/jobs/createTask"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY"
}
payload = {
"model": "kling-2.6/motion-control",
"callBackUrl": "https://your-domain.com/api/callback",
"input": {
"prompt": "The cartoon character is dancing.",
"input_urls": [
"https://static.aiquickdraw.com/tools/example/1767694885407_pObJoMcy.png"
],
"video_urls": [
"https://static.aiquickdraw.com/tools/example/1767525918769_QyvTNib2.mp4"
],
"character_orientation": "video",
"mode": "720p"
}
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()
print(result)
Response Example
{
"code": 200,
"message": "success",
"data": {
"taskId": "task_12345678"
}
}
Response Fields
code
Status code, 200 for success, others for failure
message
Response message, error description when failed
data.taskId
Task ID for querying task status
Callback Notifications
When you provide the callBackUrl parameter when creating a task, the system will send POST requests to the specified URL upon task completion (success or failure).
Success Callback Example
{
"code": 200,
"data": {
"completeTime": 1755599644000,
"costTime": 8,
"createTime": 1755599634000,
"model": "kling-2.6/motion-control",
"param": "{\"callBackUrl\":\"https://your-domain.com/api/callback\",\"model\":\"kling-2.6/motion-control\",\"input\":{\"prompt\":\"The cartoon character is dancing.\",\"input_urls\":[\"https://static.aiquickdraw.com/tools/example/1767694885407_pObJoMcy.png\"],\"video_urls\":[\"https://static.aiquickdraw.com/tools/example/1767525918769_QyvTNib2.mp4\"],\"character_orientation\":\"video\",\"mode\":\"720p\"}}",
"resultJson": "{\"resultUrls\":[\"https://example.com/generated-image.jpg\"]}",
"state": "success",
"taskId": "e989621f54392584b05867f87b160672",
"failCode": null,
"failMsg": null,
},
"msg": "Playground task completed successfully."
}
Failure Callback Example
{
"code": 501,
"data": {
"completeTime": 1755597081000,
"costTime": 0,
"createTime": 1755596341000,
"failCode": "500",
"failMsg": "Internal server error",
"model": "kling-2.6/motion-control",
"param": "{\"callBackUrl\":\"https://your-domain.com/api/callback\",\"model\":\"kling-2.6/motion-control\",\"input\":{\"prompt\":\"The cartoon character is dancing.\",\"input_urls\":[\"https://static.aiquickdraw.com/tools/example/1767694885407_pObJoMcy.png\"],\"video_urls\":[\"https://static.aiquickdraw.com/tools/example/1767525918769_QyvTNib2.mp4\"],\"character_orientation\":\"video\",\"mode\":\"720p\"}}",
"state": "fail",
"taskId": "bd3a37c523149e4adf45a3ddb5faf1a8",
"resultJson": null,
},
"msg": "Playground task failed."
}
Important Notes
The callback content structure is identical to the Query Task API response
The param field contains the complete Create Task request parameters, not just the input section
If callBackUrl is not provided, no callback notifications will be sent
+201
View File
@@ -0,0 +1,201 @@
"""Kling 2.6 motion-control image-to-video helper."""
import json
import time
from pathlib import Path
from typing import Any
import torch
from .auth import _load_api_key
from .credits import _log_remaining_credits
from .http import TransientKieError, requests
from .jobs import _poll_task_until_complete
from .log import _log
from .results import _extract_result_urls
from .upload import _image_tensor_to_png_bytes, _truncate_url, _upload_image
from .validation import _validate_prompt
from .video import _download_video, _video_path_to_comfy_video_output, _write_video_to_temp_file
CREATE_TASK_URL = "https://api.kie.ai/api/v1/jobs/createTask"
MODEL_NAME = "kling-2.6/motion-control"
PROMPT_MAX_LENGTH = 2500
CHARACTER_ORIENTATION_OPTIONS = ["image", "video"]
MODE_OPTIONS = ["720p", "1080p"]
def _validate_options(character_orientation: str, mode: str) -> None:
if character_orientation not in CHARACTER_ORIENTATION_OPTIONS:
raise RuntimeError("Invalid character_orientation. Use the pinned enum options.")
if mode not in MODE_OPTIONS:
raise RuntimeError("Invalid mode. Use the pinned enum options.")
def _validate_image_input(images: torch.Tensor | None) -> torch.Tensor:
if images is None:
raise RuntimeError("images input is required.")
if not isinstance(images, torch.Tensor):
raise RuntimeError("images input must be a tensor batch.")
if images.dim() != 4 or images.shape[-1] != 3:
raise RuntimeError("images input must have shape [B, H, W, 3].")
if images.shape[0] < 1:
raise RuntimeError("images input batch is empty.")
return images
def _validate_video_input(video: Any) -> Any:
if video is None:
raise RuntimeError("video input is required.")
return video
def _create_kling_task(api_key: str, payload: dict[str, Any]) -> tuple[str, str]:
try:
response = requests.post(
CREATE_TASK_URL,
headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
json=payload,
timeout=30,
)
except requests.RequestException as exc:
raise RuntimeError(f"Failed to call createTask endpoint: {exc}") from exc
if response.status_code == 429 or response.status_code >= 500:
raise TransientKieError(
f"createTask returned HTTP {response.status_code}: {response.text}", status_code=response.status_code
)
try:
payload_json: Any = response.json()
except json.JSONDecodeError as exc:
raise RuntimeError("createTask endpoint did not return valid JSON.") from exc
if payload_json.get("code") != 200:
message = payload_json.get("message") or payload_json.get("msg")
raise RuntimeError(f"createTask endpoint returned error code {payload_json.get('code')}: {message}")
task_id = (payload_json.get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError("createTask endpoint did not return a taskId.")
return task_id, response.text
def run_kling26motion_i2v_video(
prompt: str,
images: torch.Tensor,
video: Any,
character_orientation: str = "video",
mode: str = "720p",
poll_interval_s: float = 10.0,
timeout_s: int = 900,
log: bool = True,
) -> Any:
# Validate prompt length and required inputs.
_validate_prompt(prompt, max_length=PROMPT_MAX_LENGTH)
_validate_options(character_orientation, mode)
images = _validate_image_input(images)
video = _validate_video_input(video)
# Load the API key once for uploads and task creation.
api_key = _load_api_key()
if images.shape[0] > 1:
_log(log, f"More than 1 image provided ({images.shape[0]}); only the first will be used.")
# Upload the reference image using the shared upload helper.
_log(log, "Uploading reference image for Kling 2.6 Motion I2V...")
png_bytes = _image_tensor_to_png_bytes(images[0])
image_url = _upload_image(api_key, png_bytes)
_log(log, f"Image upload success: {_truncate_url(image_url)}")
# Resolve the input video into bytes so it can be uploaded.
video_bytes: bytes
if isinstance(video, (bytes, bytearray)):
video_bytes = bytes(video)
elif isinstance(video, str):
try:
video_bytes = Path(video).read_bytes()
except OSError as exc:
raise RuntimeError(f"Failed to read video file: {exc}") from exc
elif isinstance(video, dict):
video_path = video.get("path") or video.get("filename")
if not video_path:
raise RuntimeError("video input dict must include a 'path' or 'filename'.")
try:
video_bytes = Path(video_path).read_bytes()
except OSError as exc:
raise RuntimeError(f"Failed to read video file: {exc}") from exc
else:
raise RuntimeError("video input must be bytes, a file path string, or a dict with a path.")
# Upload the motion reference video using the shared upload helper.
_log(log, "Uploading motion reference video for Kling 2.6 Motion I2V...")
video_url = _upload_image(api_key, video_bytes)
_log(log, f"Video upload success: {_truncate_url(video_url)}")
# Build the createTask payload exactly as required by the KIE API spec.
payload = {
"model": MODEL_NAME,
"input": {
"prompt": prompt,
"input_urls": [image_url],
"video_urls": [video_url],
"character_orientation": character_orientation,
"mode": mode,
},
}
# Create the task and log the raw response for troubleshooting.
_log(log, "Creating Kling 2.6 Motion I2V task...")
start_time = time.time()
task_id, create_response_text = _create_kling_task(api_key, payload)
_log(log, f"createTask response (elapsed={time.time() - start_time:.1f}s): {create_response_text}")
_log(log, f"Task created with ID {task_id}. Polling for completion...")
# Poll until the job finishes or times out.
record_data = _poll_task_until_complete(
api_key,
task_id,
poll_interval_s,
timeout_s,
log,
start_time,
)
# Extract the final video URL from the result payload.
result_urls = _extract_result_urls(record_data)
result_video_url = result_urls[0]
_log(log, f"Final video URL: {result_video_url}")
# Download the video bytes, write to a temp file, and return a VIDEO-compatible object.
result_video_bytes = _download_video(result_video_url)
video_path = _write_video_to_temp_file(result_video_bytes)
video_output = _video_path_to_comfy_video_output(video_path)
_log_remaining_credits(log, record_data, api_key, _log)
return video_output
def run_kling26motion_i2v(
prompt: str,
images: torch.Tensor,
video: Any,
character_orientation: str = "video",
mode: str = "720p",
poll_interval_s: float = 10.0,
timeout_s: int = 900,
log: bool = True,
) -> Any:
"""Backward-compatible alias for existing imports."""
return run_kling26motion_i2v_video(
prompt=prompt,
images=images,
video=video,
character_orientation=character_orientation,
mode=mode,
poll_interval_s=poll_interval_s,
timeout_s=timeout_s,
log=log,
)
+87
View File
@@ -27,6 +27,11 @@ from .kie_api.kling26_i2v import (
DURATION_OPTIONS as KLING26_DURATION_OPTIONS,
run_kling26_i2v_video,
)
from .kie_api.kling26motion_i2v import (
CHARACTER_ORIENTATION_OPTIONS as KLING26MOTION_CHARACTER_ORIENTATION_OPTIONS,
MODE_OPTIONS as KLING26MOTION_MODE_OPTIONS,
run_kling26motion_i2v_video,
)
from .kie_api.grid import slice_grid_tensor
from .kie_api.http import TransientKieError
@@ -312,6 +317,86 @@ Outputs:
time.sleep(backoff)
class KIE_Kling26Motion_I2V:
HELP = """
KIE Kling 2.6 Motion-Control (I2V)
Generate a short video clip from a prompt, a reference image, and a motion reference video.
Inputs:
- prompt: Text prompt (required)
- images: Source image batch (first image used)
- video: Motion reference video input (single clip)
- character_orientation: Match character orientation to image or video
- mode: 720p or 1080p output resolution
- poll_interval_s / timeout_s / log
- retry_on_fail / max_retries / retry_backoff_s
Outputs:
- VIDEO: ComfyUI video output referencing a temporary .mp4 file
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"prompt": ("STRING", {"multiline": True}),
"images": ("IMAGE",),
"video": ("VIDEO",),
},
"optional": {
"character_orientation": (
"COMBO",
{"options": KLING26MOTION_CHARACTER_ORIENTATION_OPTIONS, "default": "video"},
),
"mode": ("COMBO", {"options": KLING26MOTION_MODE_OPTIONS, "default": "720p"}),
"log": ("BOOLEAN", {"default": True}),
},
}
RETURN_TYPES = ("VIDEO",)
RETURN_NAMES = ("video",)
FUNCTION = "generate"
CATEGORY = "kie/api"
def generate(
self,
prompt: str,
images: torch.Tensor,
video: object,
character_orientation: str = "video",
mode: str = "720p",
log: bool = True,
poll_interval_s: float = 10.0,
timeout_s: int = 900,
retry_on_fail: bool = True,
max_retries: int = 2,
retry_backoff_s: float = 3.0,
):
attempts = max_retries + 1 if retry_on_fail else 1
attempts = max(attempts, 1)
backoff = retry_backoff_s if retry_backoff_s >= 0 else 0.0
for attempt in range(1, attempts + 1):
try:
video_output = run_kling26motion_i2v_video(
prompt=prompt,
images=images,
video=video,
character_orientation=character_orientation,
mode=mode,
poll_interval_s=poll_interval_s,
timeout_s=timeout_s,
log=log,
)
return (video_output,)
except TransientKieError:
if not retry_on_fail or attempt >= attempts:
raise
_log(log, f"Retrying (attempt {attempt + 1}/{attempts}) after {backoff}s")
time.sleep(backoff)
class KIE_GridSlice:
HELP = """
KIE Grid Slice
@@ -382,6 +467,7 @@ NODE_CLASS_MAPPINGS = {
"KIE_SeedanceV1Pro_Fast_I2V": KIE_SeedanceV1Pro_Fast_I2V,
"KIE_Seedance15Pro_I2V": KIE_Seedance15Pro_I2V,
"KIE_Kling26_I2V": KIE_Kling26_I2V,
"KIE_Kling26Motion_I2V": KIE_Kling26Motion_I2V,
"KIE_GridSlice": KIE_GridSlice,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -392,5 +478,6 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"KIE_SeedanceV1Pro_Fast_I2V": "KIE Seedance V1 Pro Fast (I2V)",
"KIE_Seedance15Pro_I2V": "KIE Seedance 1.5 Pro (I2V/T2V)",
"KIE_Kling26_I2V": "KIE Kling 2.6 (I2V/T2V)",
"KIE_Kling26Motion_I2V": "KIE Kling 2.6 Motion-Control (I2V)",
"KIE_GridSlice": "KIE Grid Slice",
}
+30
View File
@@ -0,0 +1,30 @@
# KIE Kling 2.6 Motion-Control (I2V)
## Overview
Generate a short video clip from a prompt, a single reference image, and a motion reference video using the Kling 2.6 motion-control model.
## Inputs
- prompt (STRING, multiline, required): The text prompt for the video.
- images (IMAGE, required): Source image batch; the first image is used.
- video (VIDEO, required): Motion reference video clip used for motion control.
- character_orientation (COMBO, default: video): Match character orientation to the image or the video. Options: image, video.
- mode (COMBO, default: 720p): Output resolution. Options: 720p, 1080p.
- poll_interval_s (FLOAT, seconds, default: 10.0): How often to poll job status.
- timeout_s (INT, seconds, default: 900): Max wait time before timing out.
- log (BOOLEAN, default: true): Enable KIE console logs.
- retry_on_fail (BOOLEAN, default: true): Retry on transient API failures.
- max_retries (INT, default: 2): Number of retry attempts.
- retry_backoff_s (FLOAT, seconds, default: 3.0): Delay between retries.
## Outputs
- video (VIDEO): ComfyUI VIDEO output referencing a temporary .mp4 file.
## Examples
Prompt: "The character dances in sync with the reference motion video."
Character orientation: video
Mode: 720p
## Troubleshooting
- Timeouts: Increase timeout_s or use a shorter motion reference clip.
- Internal error / try later: Enable retries and increase retry_backoff_s.
- Insufficient credits: Check remaining credits and top up your KIE account.