Kling 3.0 Motion Control
The character from your photo copies the motion, gestures and expressions from a video. 3–30 second clips, 720p or 1080p.
Kling 3.0 Motion Control takes one character photo and a motion video and brings the character to life: it repeats the motion, gestures and expressions from the clip.
Orientation «Like the video» — pose and turns as in the clip, video 3–30 seconds. «Like the photo» — the character keeps the angle from the photo, video 3–10 seconds. Longer is trimmed. The clip's sound can be kept. Quality Standard (720p) or Pro (1080p). You pay per second of your video.
One model, kling-3.0-motion-control · ~5 min. Send your video video_url and photos image_urls.
Price
| Resolution | Price per second of your video |
|---|---|
| 720p | $0.134 |
| 1080p | $0.179 |
- Price = per-second price × clip length, rounded up to $0.001. Charged when the task is created and fully refunded if it fails.
character_orientation: "image"— video up to 10 s (longer is trimmed to 10).- You pay per second of your video (3 to 30 s). A clip longer than 30 s is trimmed to 30; the result has the same length.
promptmay be omitted.
Media limits
| Type | Limits |
|---|---|
| Images | 1 (character); JPG / PNG / WebP; public https link or files/upload — up to 30 MB per file |
| Video | one clip, video_url; 3 s to 30 s (longer is trimmed to 30); MP4 / MOV → MP4 on the server; upload ≤ 200 MB |
Photos — public https or upload; video and audio — files/upload only.
Parameters (field input)
| Parameter | Description | Values (default in bold) |
|---|---|---|
prompt | What happens in the clip: scene, motion, camera, light, style | text, up to 2500 chars (optional, default empty) |
video_url | Motion video (MP4): one clip, 3–30 s with character_orientation: "video", 3–10 s with "image" (longer is trimmed). Upload it via files/upload first | "https://…" |
image_urls | Character photos (https): look, face, clothes | ["https://…"], 1–1 |
character_orientation | video — pose and turns follow the video (clip up to 30 s), image — the angle follows the photo (clip up to 10 s) | video image |
resolution | Quality = the Kling mode: 720p — Standard (std), 1080p — Pro (pro). You can also send mode: std / pro | 720p · 1080p |
keep_original_sound | Keep the sound of your video in the result | true false (default true) |
Examples
Video + photo
curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"kling-3.0-motion-control","input":{"prompt":"The character from the photo repeats the dance from the video","video_url":"https://mixmedia.tech/files/<id>.mp4","image_urls":["https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"],"character_orientation":"video","resolution":"720p","keep_original_sound":true}}'
import os, requests
r = requests.post(
"https://mixmedia.tech/api/v1/jobs/createTask",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
json={
"model": "kling-3.0-motion-control",
"input": {
"prompt": "The character from the photo repeats the dance from the video",
"video_url": "https://mixmedia.tech/files/<id>.mp4",
"image_urls": [
"https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"
],
"character_orientation": "video",
"resolution": "720p",
"keep_original_sound": True
}
},
)
print(r.json()) # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"model": "kling-3.0-motion-control",
"input": {
"prompt": "The character from the photo repeats the dance from the video",
"video_url": "https://mixmedia.tech/files/<id>.mp4",
"image_urls": [
"https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"
],
"character_orientation": "video",
"resolution": "720p",
"keep_original_sound": true
}
}),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }
Create and result
POST /api/v1/jobs/createTaskwithmodelandinput.- Poll
GET /api/v1/jobs/recordInfo?taskId=…every 3–5 s (or a callback).
Successful createTask (HTTP 200)
{
"code": 200,
"msg": "success",
"data": {
"taskId": "task_...",
"task_id": "task_...",
"status": "submitted"
}
}
Completed task (recordInfo)
{
"code": 200,
"msg": "success",
"data": {
"taskId": "task_...",
"task_id": "task_...",
"state": "success",
"status": "completed",
"costUsd": "0.384",
"refunded": false,
"resultJson": {
"videos": [
{
"url": "https://…/out.mp4"
}
],
"duration": 8
}
}
}
Aliases: task_id = taskId; status: pending / processing / completed / failed alongside state. Clip URL is in resultJson. size is an alias of aspect_ratio in input.
Photos can be any public https links or uploads via files/upload. Videos and audio — via files/upload only.
Error handling
API responses are JSON {"code", "msg", "data"}; errors also have a string error field (type). On /api/v1/* the HTTP status matches body code.
Example response bodies
400
{
"code": 400,
"msg": "input.duration: must be between 4 and 30, or \"auto\" / -1",
"data": null,
"error": "invalid_request_error"
}
401
{
"code": 401,
"msg": "Authentication failed. Please check your API key",
"data": null,
"error": "authentication_error"
}
402
{
"code": 402,
"msg": "Insufficient balance. Please top up and try again. Available: $0.01, required: $0.015. Top up at https://mixmedia.tech/cabinet/billing",
"data": {
"balance": "0.0100",
"required": "0.0150",
"currency": "USD",
"topUpUrl": "https://mixmedia.tech/cabinet/billing"
},
"error": "payment_required"
}
429
{
"code": 429,
"msg": "Rate limit exceeded: 10 createTask/upload requests per 10 s per key. Retry after 8s",
"data": null,
"error": "rate_limit_error"
}
500
{
"code": 500,
"msg": "Internal server error",
"data": null,
"error": "server_error"
}
Codes on createTask / upload
| code | error | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_request_error | Invalid parameter or body | See msg |
| 400 | unsupported_model | Unknown model | Model list |
| 400 | nsfw_content_detected | Moderation / content policy — msg / failMsg is the upstream text verbatim | Read the refusal text, change the prompt or files |
| 401 | authentication_error | Missing or invalid key | Check the key |
| 402 | payment_required | Not enough balance | Top up |
| 403 | permission_error | No access | Contact support |
| 429 | rate_limit_error | Too many requests | Wait for Retry-After |
| 505 | model_disabled | Model temporarily disabled | Pick another |
| 500 | server_error | Our failure | Retry later |
Example msg values: Authentication failed. Please check your API key (401); Insufficient balance. Please top up and try again… (402).
Task errors (recordInfo)
If the task was created and then failed: state: "fail" (alias status: "failed"), failCode / failMsg, and error: { code, message, type }. Money is refunded (refunded: true).
| failCode | error.type | Meaning |
|---|---|---|
| 400 | nsfw_content_detected / invalid_request_error | Moderation — failMsg is upstream text verbatim |
| 422 | invalid_request_error | The model rejected the parameters (length, mode, resolution, file) |
| 501 | server_error | The model could not generate (failMsg) |
| 504 | timeout_error | Timed out — retry |
| 500 / 503 | server_error | Service temporarily unavailable |
Rate limits
| What | Limit |
|---|---|
| createTask and upload | 20 per 10 s per key |
| recordInfo / list / balance | 100 per 10 s per key |
Over the limit — HTTP 429 and Retry-After.