# cutsdk API 速查

从 `cutsdk` 导入：

```ts
import {
  createDraftFromSpec,
  validateDraftSpec,
  createAndRenderDraft,
  createDraft,
  getDraftInfo,
  addCaptions,
  addImages,
  addVideos,
  addAudios,
  addEffects,
  addSticker,
  addKeyframes,
  addMasks,
  getTextEffects,
  getTextEffect,
  renderDraft,
  isCutSdkError,
} from 'cutsdk';
```

## 优先选择：AI Draft Spec + createAndRenderDraft

```ts
const result = await createAndRenderDraft({
  draft: {
    version: '1.0',
    canvas: { width: 1080, height: 1920 },
    duration: '5s',
    tracks: [
      { type: 'text', clips: [{ type: 'caption', text: 'Hello', start: '0s', duration: '5s' }] },
    ],
  },
  output: {
    draftsDir: process.env.CUT_DRAFTS_DIR,
    name: 'demo-draft',
  },
  render: false,
});
```

用于一次性生成完整时间线，并控制输出目录和草稿名。`createDraftFromSpec(spec)` 只能按当前配置创建草稿，不能直接传 `draftsDir` 和 `name`。

## 创建并渲染

```ts
const result = await createAndRenderDraft({
  draft: spec,
  output: {
    draftsDir: process.env.CUT_DRAFTS_DIR,
    name: 'demo-draft',
  },
  render: {
    cloud: true,
    apiToken: process.env.CUT_API_TOKEN,
  },
});

console.log(result.render?.videoUrl);
```

## 当前 Draft Spec 限制

- 同一个 Spec 内，图片/视频 `transform` 会整批应用，不能每段素材独立设置不同 scale/position。
- 同一个 Spec 内，字幕 `style` 和 `position` 会整批应用，不能每条字幕完全不同位置样式。
- 需要逐片段差异化时，先用 Spec 创建主体，再用 `afterCreate` 或低层 SDK API 后处理。
- 转场名先从 `material-browser.html` 挑选；当前 CLI 还没有 `cutcli query transitions`。

## 低层草稿流程

```ts
const draft = await createDraft({ width: 1080, height: 1920 });

await addImages({
  draftId: draft.draftId,
  imageInfos: [
    { imageUrl: '/absolute/path/bg.png', width: 1080, height: 1920, start: 0, end: 5000000 },
  ],
});

await addCaptions({
  draftId: draft.draftId,
  captions: [{ text: 'Hello', start: 0, end: 5000000 }],
  fontSize: 8,
  textColor: '#ffffff',
  textEffect: '红黄火焰综艺花字',
  hasShadow: true,
});
```

需要逐步添加素材或操作时使用这种方式。

## 时间

低层 API 使用微秒：

| 人类时间 | 数值 |
|------------|-------|
| 0.5s | `500000` |
| 1s | `1000000` |
| 3s | `3000000` |
| 10s | `10000000` |

Draft Spec 可以使用字符串：

```ts
'1.5s'
'500ms'
'300000us'
```

## 错误处理

```ts
try {
  await createDraftFromSpec(spec);
} catch (error) {
  if (isCutSdkError(error)) {
    console.error(error.code, error.operation, error.details);
  } else {
    console.error(error);
  }
}
```

常见错误码：

| code | 含义 |
|------|---------|
| `INVALID_INPUT` | SDK 参数不合法 |
| `DRAFT_NOT_FOUND` | 草稿 ID 或草稿文件夹不存在 |
| `MEDIA_NOT_FOUND` | 本地媒体文件不存在 |
| `MEDIA_DOWNLOAD_FAILED` | 远程媒体下载失败 |
| `MISSING_API_TOKEN` | 缺少云渲染 token |
| `DRAFT_SPEC_VALIDATION_FAILED` | Draft Spec 校验失败 |
| `DRAFT_SPEC_RESOLVE_FAILED` | Draft Spec 无法归一化 |

## 对应 CLI 命令

```bash
cutcli draft create --width 1080 --height 1920
cutcli query text-effects --keyword 火焰 --limit 5
cutcli text add <draftId> --text "Hello" --start 0s --duration 3s
cutcli image add <draftId> --src ./素材/bg.png --start 0s --duration 5s --width 1080 --height 1920
cutcli cloud render <draftId> --wait
```

云渲染状态：

| status | 含义 |
|--------|------|
| `0` | 初始创建，尚未正式入队 |
| `1` | 已提交/排队中 |
| `2` | 处理中 |
| `3` | 草稿 ID 异常或不存在 |
| `5` | 处理超时 |
| `6` | 处理失败 |
| `7` | 成功完成，读取 `video_url` |

## 花字查询

```ts
const effects = await getTextEffects({ keyword: '火焰', limit: 5 });
const exact = await getTextEffect({ name: effects.effects[0].title });
```
