mirror of
https://github.com/Hommy-master/capcut-mate.git
synced 2026-08-29 07:31:26 +08:00
解决缩放关键帧不生效的问题。
This commit is contained in:
+17
-6
@@ -19,7 +19,7 @@ POST /openapi/capcut-mate/v1/add_keyframes
|
||||
```json
|
||||
{
|
||||
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
|
||||
"keyframes": "[{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":0.5,\"value\":-0.1}]"
|
||||
"keyframes": "[{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":5000000,\"value\":-0.1}]"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -39,9 +39,15 @@ keyframes 是一个JSON字符串,包含关键帧数组,每个关键帧对象
|
||||
|--------|------|------|------|
|
||||
| segment_id | string | ✅ | 目标片段的唯一标识ID |
|
||||
| property | string | ✅ | 动画属性类型,支持的类型见下表 |
|
||||
| offset | number | ✅ | 关键帧在片段中的时间偏移(0-1范围,0表示开始,1表示结束) |
|
||||
| offset | number | ✅ | 关键帧在片段中的时间偏移(微秒绝对时间) |
|
||||
| value | number | ✅ | 属性在该时间点的值 |
|
||||
|
||||
#### offset 参数说明
|
||||
|
||||
offset 参数只支持微秒绝对时间格式:
|
||||
- 以微秒为单位的整数,如 5000000 表示片段开始后5秒的位置
|
||||
- 系统会自动将微秒值转换为相对时间比例
|
||||
|
||||
#### 支持的动画属性类型
|
||||
|
||||
| 属性类型 | 描述 | 值范围 | 示例 |
|
||||
@@ -52,6 +58,11 @@ keyframes 是一个JSON字符串,包含关键帧数组,每个关键帧对象
|
||||
| KFTypeScaleY | Y轴缩放 | 0.1 到 10.0 | 1.0 (原始), 0.5 (缩小), 2.0 (放大) |
|
||||
| KFTypeRotation | 旋转角度 | -360 到 360 | 0 (无旋转), 90 (顺时针90度) |
|
||||
| KFTypeAlpha | 透明度 | 0.0 到 1.0 | 1.0 (不透明), 0.5 (半透明), 0.0 (透明) |
|
||||
| UNIFORM_SCALE | 统一缩放 | 0.1 到 10.0 | 1.0 (原始), 0.5 (缩小), 2.0 (放大) |
|
||||
| KFTypeSaturation | 饱和度 | -1.0 到 1.0 | 0.0 (原始), -0.5 (降低), 0.5 (增强) |
|
||||
| KFTypeContrast | 对比度 | -1.0 到 1.0 | 0.0 (原始), -0.5 (降低), 0.5 (增强) |
|
||||
| KFTypeBrightness | 亮度 | -1.0 到 1.0 | 0.0 (原始), -0.5 (变暗), 0.5 (变亮) |
|
||||
| KFTypeVolume | 音量 | 0.0 到 2.0 | 1.0 (原始), 0.5 (降低), 2.0 (增强) |
|
||||
|
||||
## 响应格式
|
||||
|
||||
@@ -85,14 +96,14 @@ keyframes 是一个JSON字符串,包含关键帧数组,每个关键帧对象
|
||||
|
||||
### cURL 示例
|
||||
|
||||
#### 1. 基本关键帧添加
|
||||
#### 1. 基本关键帧添加(使用微秒时间)
|
||||
|
||||
```bash
|
||||
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_keyframes \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"draft_url": "YOUR_DRAFT_URL",
|
||||
"keyframes": "[{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":0,\"value\":0},{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":1,\"value\":-0.5}]"
|
||||
"keyframes": "[{\"segment_id\":\"segment-id\",\"property\":\"UNIFORM_SCALE\",\"offset\":0,\"value\":1},{\"segment_id\":\"segment-id\",\"property\":\"UNIFORM_SCALE\",\"offset\":5000000,\"value\":1.3}]"
|
||||
}'
|
||||
```
|
||||
|
||||
@@ -103,7 +114,7 @@ curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_keyframes
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"draft_url": "YOUR_DRAFT_URL",
|
||||
"keyframes": "[{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypePositionX\",\"offset\":0,\"value\":0},{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypePositionY\",\"offset\":0,\"value\":0},{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypeRotation\",\"offset\":0.5,\"value\":90},{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypeAlpha\",\"offset\":1,\"value\":0}]"
|
||||
"keyframes": "[{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypePositionX\",\"offset\":0,\"value\":0},{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypePositionY\",\"offset\":0,\"value\":0},{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypeRotation\",\"offset\":2500000,\"value\":90},{\"segment_id\":\"segment-uuid\",\"property\":\"KFTypeAlpha\",\"offset\":5000000,\"value\":0}]"
|
||||
}'
|
||||
```
|
||||
|
||||
@@ -124,7 +135,7 @@ curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_keyframes
|
||||
|
||||
1. **片段ID验证**: segment_id 必须是草稿中存在的有效片段ID
|
||||
2. **片段类型限制**: 只有视觉片段(视频、图片、贴纸、文本)支持关键帧
|
||||
3. **时间偏移范围**: offset 值必须在 0.0-1.0 范围内
|
||||
3. **时间偏移范围**: offset 值必须是非负整数(微秒)
|
||||
4. **属性值范围**: 不同的属性类型有不同的值范围限制
|
||||
5. **重复关键帧**: 相同片段相同属性的关键帧会被累加,不会覆盖
|
||||
6. **性能考虑**: 单次请求建议不超过100个关键帧
|
||||
|
||||
@@ -70,7 +70,7 @@ def add_keyframes(
|
||||
if segment is None:
|
||||
logger.error(f"Segment not found: {keyframe_item['segment_id']}, skipping this keyframe")
|
||||
failed_keyframes += 1
|
||||
continue # 继续处理下一个关键帧,而不是抛出异常
|
||||
continue # 继续处理下一个关键帧
|
||||
|
||||
# 验证片段类型
|
||||
if not isinstance(segment, VisualSegment):
|
||||
@@ -86,9 +86,18 @@ def add_keyframes(
|
||||
failed_keyframes += 1
|
||||
continue # 继续处理下一个关键帧
|
||||
|
||||
# 计算时间偏移(将相对位置转换为微秒)
|
||||
# 处理offset值:只支持微秒绝对时间,需要转换为相对时间
|
||||
segment_duration = segment.duration
|
||||
time_offset = int(keyframe_item['offset'] * segment_duration)
|
||||
offset_value = keyframe_item['offset']
|
||||
|
||||
# 将微秒绝对时间转换为相对时间(0-1范围)
|
||||
relative_offset = offset_value / segment_duration
|
||||
# 确保相对时间在有效范围内
|
||||
relative_offset = max(0.0, min(1.0, relative_offset))
|
||||
logger.info(f"Converting absolute offset {offset_value} microseconds to relative offset {relative_offset} for segment duration {segment_duration}")
|
||||
|
||||
# 计算时间偏移(将相对位置转换为微秒)
|
||||
time_offset = int(relative_offset * segment_duration)
|
||||
|
||||
logger.info(f"Adding keyframe to segment {keyframe_item['segment_id']}: property={property_enum.value}, time_offset={time_offset}, value={keyframe_item['value']}")
|
||||
|
||||
@@ -156,7 +165,7 @@ def parse_keyframes_data(json_str: str) -> List[Dict[str, Any]]:
|
||||
{
|
||||
"segment_id": "d62994b4-25fe-422a-a123-87ef05038558", # [必选] 目标片段的唯一标识ID
|
||||
"property": "KFTypePositionX", # [必选] 动画属性类型
|
||||
"offset": 0.5, # [必选] 关键帧在片段中的时间偏移(0-1范围)
|
||||
"offset": 5000000, # [必选] 关键帧在片段中的时间偏移(微秒绝对时间)
|
||||
"value": -0.1 # [必选] 属性在该时间点的值
|
||||
}
|
||||
]
|
||||
@@ -206,10 +215,10 @@ def parse_keyframes_data(json_str: str) -> List[Dict[str, Any]]:
|
||||
logger.error(f"the {i}th item has unsupported property type: {item['property']}")
|
||||
raise CustomException(CustomError.INVALID_KEYFRAME_INFO, f"the {i}th item has unsupported property type: {item['property']}")
|
||||
|
||||
# 验证offset范围(0-1)
|
||||
if not isinstance(item["offset"], (int, float)) or item["offset"] < 0.0 or item["offset"] > 1.0:
|
||||
logger.error(f"the {i}th item has invalid offset value: {item['offset']}, must be between 0.0 and 1.0")
|
||||
raise CustomException(CustomError.INVALID_KEYFRAME_INFO, f"the {i}th item has invalid offset value: {item['offset']}")
|
||||
# 验证offset是数字类型且为非负数
|
||||
if not isinstance(item["offset"], (int, float)) or item["offset"] < 0:
|
||||
logger.error(f"the {i}th item has invalid offset type or value: {item['offset']}, must be a non-negative number")
|
||||
raise CustomException(CustomError.INVALID_KEYFRAME_INFO, f"the {i}th item has invalid offset type or value: {item['offset']}")
|
||||
|
||||
# 验证value是数字类型
|
||||
if not isinstance(item["value"], (int, float)):
|
||||
@@ -220,11 +229,11 @@ def parse_keyframes_data(json_str: str) -> List[Dict[str, Any]]:
|
||||
processed_item = {
|
||||
"segment_id": str(item["segment_id"]),
|
||||
"property": item["property"],
|
||||
"offset": float(item["offset"]),
|
||||
"offset": float(item["offset"]), # 保持原始微秒值,在主函数中转换为相对时间
|
||||
"value": float(item["value"])
|
||||
}
|
||||
|
||||
result.append(processed_item)
|
||||
|
||||
logger.info(f"Successfully parsed {len(result)} keyframe items")
|
||||
return result
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user