---
title: Timeline 1.0
description: 오디오 스파인 하나와 순서 있는 video[] 슬롯을 긴 MP4로 조립합니다. 공개 조립 표면은 여기뿐입니다.
---

> **현재 SoT.** Timeline 1.0 렌더(`sume/timeline-1.0`). dest와 prod.
> 이것은 **조립**입니다 — 시퀀스, 트랜지션, 오디오 스파인.
> 소재 준비는 [비디오 트림](/models/video-trim),
> [오디오 분리](/models/audio-detach), [비디오 필터](/models/video-filter),
> [타임라인 합성](/models/timeline-compose)에 남습니다.

Timeline 1.0은 선언적 문서(오디오 스파인 하나 + 순서 있는 `video[]`)를
받아 **하나의** MP4를 반환합니다. 서버가 워커 미디어 런타임에서
ffmpeg를 컴파일합니다(`apps/api/src/routes.ts` `renderTimelineV1` /
`submitSumeTimelineRenderJob`). 호출자는 필터그래프, 코덱, 셸 조각을
보내지 않습니다.

```text
POST /v1/timeline-1.0/render
POST /v1/timeline-1.0/plan                 # 무료 컴파일 프리플라이트
POST /v1/models/sume/timeline-1.0/runs     # 렌더와 같은 본문, 추가 `model` 필드 없음
POST /v1/models/sume/timeline/v1.0/runs    # 레거시 model-run 별칭
```

**`GET /v1/timeline-1.0/:id`는 없습니다.** Job 봉투로 폴링하세요:

```text
GET /v1/jobs/:id/status
GET /v1/jobs/:id/result
```

호스티드 MCP: `timeline_create` → `jobs_wait` → `timeline_get`
(`packages/mcp-server/src/mcp.ts`). `timeline_get`은
`GET /v1/jobs/:id/result`입니다. 쓰기는 `idempotency_key`가
필요합니다(OAuth에서는 `mcp:write`).

## Plan (무료)

`POST /v1/timeline-1.0/plan`(`planTimelineV1`)은 스키마 + Sume 호스트
URL 검사 + 순수 컴파일러를 돌리고 `object: timeline_plan`에
`duration_seconds`, `segment_count`, `billable_minutes`,
`estimated_cost_usd_micros`, `filtergraph_summary`를 돌려줍니다. Job을
만들지 않고, 크레딧을 예약하지 않으며, 미디어를 다운로드하지 않습니다.
`Idempotency-Key`는 필요 없습니다. Plan은 짧은 소스 pad/loop 경고를
예측하지 않습니다.

## 렌더

필수: `audio.duration_seconds`(1–**1800**)와 `audio.url` 또는
`audio.parts[]`(`audio.mode`가 `"silence"`가 아니면), 그리고 `video[]`
(1–**200** 슬롯). 모든 URL은 이 워크스페이스의 `media.sume.com`
아티팩트 또는 에셋이어야 합니다. 먼저 가져오세요
(`POST /v1/media-imports`). `Idempotency-Key`는 필수입니다.

기본 `mode`는 **`async`**입니다. `mode: "sync"`를 주면 최대 **30초**
기다리고 끝난 Job을 `200`으로 주거나, `202`로 폴링합니다.

```bash
curl -X POST https://api.sume.com/v1/timeline-1.0/render \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: timeline-001" \
  -d '{
    "audio": {
      "url": "https://media.sume.com/artifacts/artf_demo/voice.wav",
      "duration_seconds": 24
    },
    "video": [
      {
        "source_url": "https://media.sume.com/artifacts/artf_demo/intro.mp4",
        "start": 0,
        "duration": 8
      },
      {
        "source_url": "https://media.sume.com/artifacts/artf_demo/talk.mp4",
        "start": 8,
        "duration": 16,
        "transition": { "type": "fade", "duration": 0.25 }
      }
    ]
  }'
```

성공한 submit은 Job을 반환합니다(`type: timeline_render`,
`model: sume/timeline-1.0`). `result_ready`이면
`GET /v1/jobs/:id/result`는 `kind: timeline_render`이고 `video_url`,
`duration_seconds`, `segment_count`, `billable_minutes`, 선택적
`warnings[]`를 줍니다. 짧은 소스 pad/loop, 스냅된 트랜지션, 무시된
스틸 모션 같은 소프트 경고는 **실패가 아닙니다**.

공개 요금: **출력 분(ceil)당 $0.10**(`TIMELINE_PUBLIC_PRICING`;
`GET /v1/catalog`에서 확인). 예약은
`ceil(audio.duration_seconds / 60)`분입니다. 프로바이더 추론 없음 —
워커 ffmpeg만.

기본 출력은 **1080×1920** MP4입니다. `output.fps`를 생략하면 소스가
이미 쓰는 프레임레이트로 렌더합니다(가장 긴 비디오 소스가 결정, 스틸은
레이트가 없음, 아무것도 없을 때만 30). 소스와 다른 레이트는 몇 프레임마다
한 프레임을 반복하거나 버려서 — 움직임에서 떨림(judder) — 소스가 원한
레이트와 함께 `output_fps_resamples_sources`로 보고됩니다.

## 프로그램

| 필드 | 효과 |
|---|---|
| `audio.duration_seconds` | 출력 길이. 필수. 1–1800초. |
| `audio.url` | Sume 호스트 스파인 하나. `parts`와 배타. |
| `audio.parts[]` | ≤20개의 갭리스 조각(`url` + 선택 `source_in` / `duration`). 샘플 도메인 조인, 재 TTS 없음. `url`과 배타. |
| `audio.mode` | `"silence"` — 스파인 파일 없이 선언된 길이. 그때는 `url` / `parts` / `gain_db` / `source_in` 없음. |
| `audio.source_in` | **단일** `url` 스파인의 인포인트. `parts`와 함께 쓰면 거부. 출력 길이는 여전히 `duration_seconds`. |
| `audio.gain_db` | −60…12. silence와 함께 쓰면 거부. |
| `video[].source_url` | Sume 호스트 클립 또는 스틸. 스틸은 정적 홀드(`motion`은 받고 `motion_ignored`로 무시). |
| `video[].start` | 스파인 위 시작. `video[0].start`는 **0**. 이후 start는 증가해야 함. 선언된 start가 권위 — 컴파일러가 xfade를 보정하고 미리 당기지 않음. |
| `video[].duration` | 화면 길이, ≥ 0.2초. 커버리지는 스파인보다 최대 0.5초 뒤일 수 있음. |
| `video[].source_in` | 파일 인포인트. |
| `video[].fit` | `cover`(기본) \| `contain` \| `stretch` \| `blur`. |
| `video[].transition` | **첫 슬롯 이후**. `type` ∈ `fade` \| `wipeleft` \| `wiperight` \| `slideup` \| `slidedown` \| `dissolve`. 길이 ≤ 1초, 더 짧은 이웃의 50% 이하, 출력 프레임 최소 1장. |
| `output.width` / `height` | 짝수 정수 256–2160. |
| `output.fps` | `24` \| `25` \| `30` \| `60`. 생략하면 소스에 맞춤. |
| `output.fade_in_seconds` / `fade_out_seconds` | 0–5초; 합 ≤ 출력 길이. |
| `soundtrack` | 선택 배드: `url`, `gain_db`, `loop`, `fade_out_seconds` ≤ 10, `duck_db` 0–20(진짜 스파인 필요, silence 불가). |
| `render.strategy` | `auto`(기본; 12슬롯 넘으면 청크) \| `chunked` \| `single`(12슬롯 초과는 `render_strategy_unsafe`). |

**이 렌더 안에서만** 필요한 잘린 VO는 `audio.parts[]`에 둡니다.
재사용 가능한 병합 파일은 [타임라인 오디오](/models/timeline-audio)입니다.
한 프레임에 소스 두 개가 동시에 필요하면
[타임라인 합성](/models/timeline-compose) 후 그 MP4를 `video[]`에 넣습니다.

## 거부 (안정 코드)

| 코드 | 언제 |
|---|---|
| `audio_url_required` | `url` / `parts` 없고 silence도 아님. |
| `audio_url_and_parts_exclusive` | `url`과 `parts`를 같이 보냄. |
| `silent_audio_takes_no_url` / `_parts` / `_gain` / `_source_in` | silence에 스파인 필드. |
| `audio_source_in_requires_single_spine` | `parts`와 함께 `source_in`. |
| `audio_parts_shorter_than_duration` | 선언된 part 길이 합이 `duration_seconds`보다 짧음. |
| `timeline_must_start_at_zero` | `video[0].start` ≠ 0. |
| `transition_on_first_segment` | `video[0].transition`. |
| `invalid_segment_timing` / `segment_overlap` | start가 증가하지 않거나 xfade를 넘어 겹침. |
| `transition_too_long` / `transition_not_frame_aligned` | 이웃 / fps 대비 길이. |
| `too_many_chained_transitions` | 인접 페이드 8개 초과. 하드 컷을 넣으세요. |
| `edge_fades_exceed_output` / `soundtrack_fade_exceeds_output` | 페이드가 스파인보다 김. |
| `duck_requires_audio_spine` | silence에 `soundtrack.duck_db`. |
| `render_strategy_unsafe` | 슬롯 12개 초과에 `strategy: "single"`. |
| `unsupported_media_source` / `source_not_found` | 호스트 밖 또는 죽은 URL. |
| 프로바이더 / ffmpeg 키 | 400 — `model`, `filtergraph`, `ffmpeg_args`, `codec`, `crf` 등 (`TIMELINE_REJECTED_PROVIDER_KEYS`). |

호스트 밖 URL(`https://example.com/…`)은 admit에서 거부됩니다. 먼저
가져오세요.

dim / crop / 픽셀 패스는 렌더 옵션이 **아닙니다** —
[비디오 필터](/models/video-filter)를 쓰세요.

## 이 표면이 아닌 것

| 필요 | 사용 |
|---|---|
| 클립 하나의 `[start, end)` | [비디오 트림](/models/video-trim) |
| 오디오 트랙을 내구성 wav / mp3로 | [오디오 분리](/models/audio-detach) |
| 오디오 concat / split로 재사용 파일 | [타임라인 오디오](/models/timeline-audio) |
| 한 프레임에 스틸 + 비디오 (반배너) | [타임라인 합성](/models/timeline-compose) |
| 픽셀 패스 (dim / crop) | [비디오 필터](/models/video-filter) |
| 프로브 / 스틸 / 선택 STT | [비디오 검사](/models/video-inspect) |

## 관련

- [타임라인 합성](/models/timeline-compose)
- [타임라인 오디오](/models/timeline-audio)
- [비디오 트림](/models/video-trim)
- [오디오 분리](/models/audio-detach)
- [비디오 필터](/models/video-filter)
- [미디어 입력](/workflows/asset-library)
- [Job과 결과](/workflows/jobs-and-results)
- [MCP 도구와 게이트](/mcp/tools-and-gates)
