AIMoCap Docs
API 接口说明
AIMoCap 异步视频动捕 API 的上行字段、下行字段与 Python 调用示例。
异步流程
1. 创建任务
POST /api/v1/mocap/jobs
请求体:
{
"title": "tennis-02",
"sourceType": "upload",
"sourceFilename": "tennis_02.mp4",
"sourceBytes": 24500812,
"sourceDurationSec": 18.4,
"trimStartSec": 1.2,
"trimEndSec": 13.8,
"targetId": "default"
}
字段说明:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
title |
string | 否 | 可选任务标题 |
sourceType |
string | 是 | 首版固定为 upload |
sourceFilename |
string | 是 | 原始文件名 |
sourceBytes |
number | 是 | 文件大小,单位字节 |
sourceDurationSec |
number | 是 | 原始视频总时长 |
trimStartSec |
number | 是 | 选中的起始时间 |
trimEndSec |
number | 是 | 选中的结束时间 |
targetId |
string | 是 | default、unitree_g1 或 avatar:{avatarId} |
返回:
{
"jobId": "mocap_xxx",
"status": "draft",
"uploadUrl": "https://...",
"sourceKey": "..."
}
2. 上传源文件
对返回的 uploadUrl 发起 PUT,上传视频二进制内容。
3. 完成准入
POST /api/v1/mocap/jobs/{jobId}/complete-upload
如果 admission 成功:
- 任务进入队列
- API v-credit 在这一刻扣减
4. 轮询任务状态
GET /api/v1/mocap/jobs/{jobId}
示例返回:
{
"job": {
"id": "mocap_xxx",
"status": "processing",
"targetIds": ["default"]
},
"events": [],
"result": null
}
5. 获取最终结果
GET /api/v1/mocap/jobs/{jobId}/result
公共字段:
| 字段 | 说明 |
|---|---|
jobId |
任务 ID |
status |
最终状态 |
targetId |
输出目标 |
previewVideoUrl |
预览视频链接 |
manifestUrl |
结果 manifest 链接 |
createdAt |
创建时间 |
updatedAt |
更新时间 |
completedAt |
完成时间 |
按目标区分的结果字段:
| 目标 | resultType |
返回字段 |
|---|---|---|
default |
fbx |
fbxUrl |
avatar:{avatarId} |
fbx |
fbxUrl |
unitree_g1 |
robot_motion_json |
motionJsonUrl |
Python 调用示例
import time
import requests
BASE_URL = "https://aimocap.net"
API_KEY = "sk-your-api-key"
VIDEO_PATH = "tennis_02.mp4"
headers = {
"Authorization": f"Bearer {API_KEY}",
}
with open(VIDEO_PATH, "rb") as f:
video_bytes = f.read()
create_payload = {
"title": "tennis-02",
"sourceType": "upload",
"sourceFilename": "tennis_02.mp4",
"sourceBytes": len(video_bytes),
"sourceDurationSec": 18.4,
"trimStartSec": 1.2,
"trimEndSec": 13.8,
"targetId": "default",
}
create_resp = requests.post(
f"{BASE_URL}/api/v1/mocap/jobs",
json=create_payload,
headers=headers,
)
create_resp.raise_for_status()
create_data = create_resp.json()["data"]
upload_resp = requests.put(
create_data["uploadUrl"],
data=video_bytes,
headers={"Content-Type": "video/mp4"},
)
upload_resp.raise_for_status()
complete_resp = requests.post(
f"{BASE_URL}/api/v1/mocap/jobs/{create_data['jobId']}/complete-upload",
headers=headers,
)
complete_resp.raise_for_status()
while True:
job_resp = requests.get(
f"{BASE_URL}/api/v1/mocap/jobs/{create_data['jobId']}",
headers=headers,
)
job_resp.raise_for_status()
job_data = job_resp.json()["data"]
status = job_data["job"]["status"]
if status in {"completed", "failed", "canceled"}:
break
time.sleep(5)
result_resp = requests.get(
f"{BASE_URL}/api/v1/mocap/jobs/{create_data['jobId']}/result",
headers=headers,
)
result_resp.raise_for_status()
result = result_resp.json()["data"]
print("result type:", result["resultType"])
print("preview:", result.get("previewVideoUrl"))
print("fbx:", result.get("fbxUrl"))
print("motion json:", result.get("motionJsonUrl"))
