高级对口型视频生成。先识别人脸,再同步自定义音频。
在所有请求中添加 Bearer Token 认证头:
Authorization: Bearer YOUR_API_KEY
| 模型 | API 名称 | 特性 | 价格 (最多省60%) |
|---|---|---|---|
| 人脸识别 | kling-identify-face | 检测视频人脸,返回 sessionId + faceId | $0.0100/次 |
| 对口型视频生成 | kling-lip-sync-video | 用 sessionId + faceId + 音频生成对口型视频 | $0.0650/5秒 |
| 操作 | 价格 |
|---|---|
| 人脸识别 (kling-identify-face) | $0.0100/次 |
| 对口型视频生成 (kling-lip-sync-video) | $0.0650/5秒 |
/api/v1/video/generations创建人脸识别或对口型任务。将 model 设为 "kling-identify-face" 或 "kling-lip-sync-video"。
/api/v1/video/generations?task_id=xxx查询任务状态并获取结果
对口型需要两次 API 调用。首先,将视频提交给 "kling-identify-face",返回 session_id 和检测到的人脸列表(含 face_id)。然后,向 "kling-lip-sync-video" 提交第二次请求,传入 session_id、要同步的 face_id 及对应音频来源。
提交一段视频识别人脸,返回 sessionId 和 faceId(在 resultJson 里),供第二步使用。$0.01/次。
用第一步的 sessionId 和 faceId,配合音频(kling-lip-sync-tts 产出的 audioId,或直接 audioUrl)完成对口型。
用预设音色把文本合成为语音(可用于驱动对口型),返回音频结果。
# Step 1: Identify faces in the video
curl -X POST https://apimodels.app/api/v1/video/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-identify-face",
"video_url": "https://example.com/video.mp4"
}'{
"code": 200,
"msg": "success",
"data": {
"taskId": "clxxx...",
"state": "pending",
"model": "kling-identify-face"
}
}{
"code": 200,
"msg": "success",
"data": {
"taskId": "clxxx...",
"state": "completed",
"model": "kling-identify-face",
"resultUrls": [],
"resultJson": "{ \"resultUrls\": [], \"sessionId\": \"891032747618619461\", \"faceId\": \"0\", \"faces\": [{ \"face_id\": \"0\", \"start_time\": 0, \"end_time\": 13500 }] }"
}
}对 data.resultJson 做 JSON.parse,取 sessionId 和 faceId 传给 kling-lip-sync-video。faces[] 还带每个人脸的 start_time / end_time 可对口型区间。
{
"code": 200,
"msg": "success",
"data": {
"taskId": "clxxx...",
"state": "completed",
"model": "kling-lip-sync-video",
"resultUrls": ["https://...lip_synced_video.mp4"]
}
}{
"code": 200,
"msg": "success",
"data": {
"taskId": "clxxx...",
"state": "failed",
"failMsg": "Face detection failed: no faces found"
}
}在创建请求中传入 callback_url 后,任务进入 completed 或 failed 终态时,我们会向该地址发起一次 HTTP POST。请求头仅包含 Content-Type: application/json,无签名头。失败会自动重试 3 次(指数退避 1s/2s/4s,单次超时 10s);如果仍未成功,后台会在 30 分钟内继续补偿重发,直到接收端返回 2xx。
POST {your callback_url}
Content-Type: application/json
{
"code": 200,
"msg": "success",
"data": {
"taskId": "clxxx...",
"model": "rh-lip-sync-video/kling-lip-sync-video",
"state": "completed" | "failed",
"param": "<JSON string>", // request params, JSON.parse once
"resultJson": "<JSON string> | null", // result object, JSON.parse once
"failCode": null | "CONTENT_MODERATION | INVALID_INPUT | INSUFFICIENT_BALANCE | UPSTREAM_BUSY | UPSTREAM_FAILED | TIMEOUT | INTERNAL_ERROR | OTHER",
"failMsg": null | "string",
"retryable": true | false, // present when state=failed: safe to retry/fallback
"costTime": 12345, // duration in ms
"completeTime": 1705123500000, // ms epoch
"createTime": 1705123450000 // ms epoch
}
}注意:data.param 与 data.resultJson 都是 JSON 字符串,使用前必须 JSON.parse 一次。
{
"resultUrls": ["https://r2.apimodels.app/videos/lip_synced.mp4"],
"videoDuration": 8 // optional, seconds
}对口型最终产物是视频。resultUrls 始终存在(成功时长度为 1,失败时为空数组);部分上游会带 videoDuration。state=failed 时 resultJson 通常为 null 或 {"resultUrls":[]}。
app.post('/webhook/kling-lip-sync', express.json(), (req, res) => {
const { taskId, state, resultJson, failMsg } = req.body.data
if (state === 'completed') {
const r = JSON.parse(resultJson)
console.log('lip-sync ready', taskId, r.resultUrls[0])
} else {
console.warn('lip-sync failed', taskId, failMsg)
}
res.status(200).end() // must be 2xx, otherwise we retry
})pending任务已排队,等待处理processing任务执行中completed任务成功完成failed任务失败400请求错误 - 参数缺失或无效401未授权 - API 密钥无效402余额不足 - 积分不够404未找到 - 任务 ID 不存在500服务器内部错误