> ## Documentation Index
> Fetch the complete documentation index at: https://www.tella.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Clips

> Add, cut, reorder, inspect, and transcribe the clips that make up a video.

A clip is a section of a video — Tella videos are made up of one or more clips. Each clip has its own cuts, layouts, transcript, and editing tools.

<Note>
  **Clip tools take milliseconds on the clip's playback timeline** — the clip as watched, with cuts applied, the same timeline as `get_transcript`, thumbnails, and previews. A start at or past the end of the clip is rejected with a `400`.

  Three kinds of tool on this page use a different timeline, and say so on their `startTimeMs`:

  * `get_video_frame` and `get_video_preview` count from the **video's** playback start, cumulative across clips.
  * `get_source_thumbnail` counts from the start of the **raw source file** — no clip cuts apply. `get_storyboard` does the same when given a `sourceId`.
  * Stored cut *definitions* (`get_clip`'s and `update_clip`'s `cuts`) describe removed ranges of the raw recording. Cuts are always undoable by replacing them with `[]`.
</Note>

## upload\_clip

Add a new clip to a video from an uploaded source. Call `create_source` first, `PUT` the bytes to the returned `uploadUrl`, then pass the `sourceId` here.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="sourceId" type="string" required>
  Source ID returned by `create_source`
</ParamField>

<ParamField path="name" type="string">
  Clip name. Defaults to the next `Clip N`.
</ParamField>

## list\_clips

List clips in a video, ordered by their position.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

## get\_clip

Get a single clip's details.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

## update\_clip

Update a clip's name, ordering, cuts, background, transition, Studio Sound opt-out, audio volumes, or animated cursor.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="name" type="string">
  New clip name
</ParamField>

<ParamField path="order" type="integer">
  New position within the video
</ParamField>

<ParamField path="cuts" type="object[]">
  Replaces the clip's full cut set. Each cut is `{startTimeMs, durationMs}` in ms of the raw recording (the playback timeline you'd get after clearing all cuts). Pass `[]` to clear all cuts. To cut what you currently see, use `cut_clip` instead.

  <Expandable title="properties">
    <ParamField path="startTimeMs" type="integer" required>
      Start of the cut, in ms of the raw recording.
    </ParamField>

    <ParamField path="durationMs" type="integer" required>
      Length of the cut, in ms.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="background" type="object">
  Background `{type, color?, sourceId?, imageUrl?, videoUrl?, videoDurationSeconds?, gradientColor1?, gradientColor2?, gradientAngle?}`. `type` is one of `solid`, `image`, `video`, `gradient`. For your own image or video, pass a `sourceId` from `create_source` (`kind: "image"` or `kind: "video"`). To use a catalog background, pass the exact `background` object returned by `list_backgrounds`; arbitrary image and video URLs are rejected.

  <Expandable title="properties">
    <ParamField path="type" type="enum<string>" required>
      Background variant. One of `solid`, `image`, `video`, `gradient`.
    </ParamField>

    <ParamField path="color" type="string">
      Hex color string. Required when type = 'solid'.
    </ParamField>

    <ParamField path="sourceId" type="string">
      Source ID from `create_source` (`kind: 'image'` for type = 'image', `kind: 'video'` for type = 'video'). Required for image/video backgrounds unless using an exact URL from `list_backgrounds`.
    </ParamField>

    <ParamField path="imageUrl" type="string">
      Exact hosted image URL from `list_backgrounds`. Use only when type = 'image'; arbitrary remote URLs are rejected.
    </ParamField>

    <ParamField path="videoUrl" type="string">
      Exact hosted video URL from `list_backgrounds`. Use only when type = 'video'; arbitrary remote URLs are rejected.
    </ParamField>

    <ParamField path="videoDurationSeconds" type="number">
      Catalog video duration returned by `list_backgrounds`. The server always uses its canonical duration.
    </ParamField>

    <ParamField path="gradientColor1" type="string">
      Hex color string. Required when type = 'gradient'.
    </ParamField>

    <ParamField path="gradientColor2" type="string">
      Hex color string. Required when type = 'gradient'.
    </ParamField>

    <ParamField path="gradientAngle" type="integer">
      Linear gradient angle in degrees. Required when type = 'gradient'.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="transition" type="enum<string>">
  How this clip enters from the previous clip — `smooth`, `hard_cut`, or `default`. Use `default` to remove the clip override and follow the video's `defaultClipTransition`. The first clip has nothing to transition from.
</ParamField>

<ParamField path="studioSound" type="boolean">
  Per-clip Studio Sound opt-out. `false` disables enhanced audio for this clip while the video-level switch (`update_video`'s `studioSound`) stays on; `true` re-enables it.
</ParamField>

<ParamField path="microphoneVolume" type="number | null">
  Microphone volume for this clip only, overriding `update_video`'s `microphoneVolume`. 1 is the recorded level, 0 mutes it, 2 doubles it. Pass `null` to clear the override so the clip follows the video again. Errors when the clip has no microphone audio to control.
</ParamField>

<ParamField path="systemAudioVolume" type="number | null">
  System audio (screen or uploaded footage) volume for this clip only, overriding `update_video`'s `systemAudioVolume`. Same range and `null`-to-clear behaviour. Errors when the clip has no such audio to control.
</ParamField>

<ParamField path="animatedCursor" type="boolean">
  Draw an animated cursor from captured mouse data on this clip's screen recording. Errors when the clip has no screen recording.
</ParamField>

Use the volumes to fix a balance in one clip — mic too quiet against loud screen audio, or one clip recorded hotter than the rest. `get_clip` reports each volume as:

* a number — this clip overrides the video setting
* `null` — it follows the video
* absent — there is nothing to control: no such track, or a recording without audio, like a screen recording made without sharing system audio

It also reports the clip's `transition`, plus `animatedCursor` when the clip has a screen recording.

## delete\_clip

Remove a clip from its video.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

## duplicate\_clip

Duplicate a clip. The copy is inserted right after the original by default.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID to duplicate
</ParamField>

<ParamField path="name" type="string">
  Name for the new clip
</ParamField>

<ParamField path="order" type="integer">
  Position for the new clip
</ParamField>

## reorder\_clip

Move a clip to a new position; other clips shift to stay contiguous.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="order" type="integer" required>
  New 0-based position
</ParamField>

## cut\_clip

Cut one or more time ranges from a clip in a single call. Overlapping or adjacent ranges are merged into the clip's existing cuts. To clear all cuts, call `update_clip` with `cuts: []`.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="cuts" type="object[]" required>
  Array of `{fromMs, toMs}` ranges to cut, in ms (what you currently see and hear — the same timeline as `get_transcript` and `get_silences`). All ranges are resolved against the playback timeline as it is when the call starts, so send every range in one call instead of issuing many `cut_clip` calls.

  <Expandable title="properties">
    <ParamField path="fromMs" type="integer" required>
      Start of the range to cut, in ms on the clip's playback timeline.
    </ParamField>

    <ParamField path="toMs" type="integer" required>
      End of the range to cut, in ms on the clip's playback timeline.
    </ParamField>
  </Expandable>
</ParamField>

## cut\_clip\_by\_transcript

Cut one or more ranges from a clip by referencing word indices in the transcript. The server resolves each word's exact start/end ms — no padding is applied. Use `get_transcript` to look up word indices.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="wordRanges" type="object[]" required>
  Array of `{fromWordIndex, toWordIndex}` ranges. Both indices are inclusive and come from the clip's transcript (indices are stable — already-cut words are simply absent).

  <Expandable title="properties">
    <ParamField path="fromWordIndex" type="integer" required>
      Index of the first word to cut (inclusive).
    </ParamField>

    <ParamField path="toWordIndex" type="integer" required>
      Index of the last word to cut (inclusive).
    </ParamField>
  </Expandable>
</ParamField>

## get\_silences

Detect silent ranges in the clip's audio, in ms on the clip's playback timeline (cuts applied) — pass them directly to `cut_clip`. Silences already removed by cuts are not reported.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="minDurationMs" type="integer">
  Minimum silence length to report, in ms. Defaults to 200.
</ParamField>

## remove\_fillers

Auto-detect and cut filler words ("um", "uh", etc.) from the clip's transcript.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

## remove\_silences

Auto-detect and cut silent pauses from the clip's audio, like the editor's Remove silences tool.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="mode" type="enum<string>">
  How aggressively to remove silences — `natural` cuts pauses longer than 800ms, `fast` longer than 500ms, `faster` longer than 300ms. Defaults to `natural`.
</ParamField>

## list\_sources

List the underlying recordings (camera, screen, mic) the clip was cut from, each with the volume it plays at in this clip: `volume` is the clip's own override (`null` when it inherits) and `effectiveVolume` is what actually plays. Read these to inspect a mix; change it with `update_clip`'s `microphoneVolume`/`systemAudioVolume`.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

## get\_clip\_frame

Get a rendered frame from a clip's playback timeline (cuts applied), including the clip's layouts, b-roll media, zooms, and masks. For `jpg`, `png`, or `webp`, returns inline image content the model can see, plus a signed URL. For `gif`, returns the signed URL only (vision models don't read animation, so the bytes aren't inlined).

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="format" type="enum<string>">
  `jpg` (default), `png`, `webp`, or `gif`
</ParamField>

<ParamField path="startTimeMs" type="integer">
  Frame offset in ms on the clip's playback timeline (default 0)
</ParamField>

<ParamField path="durationMs" type="integer">
  Duration in ms when `format` is `gif`
</ParamField>

<ParamField path="width" type="integer">
  Output width in pixels (default 320). The frame keeps the video's aspect ratio.
</ParamField>

<ParamField path="height" type="integer">
  Output height in pixels. Derived from the video's aspect ratio when omitted.
</ParamField>

<ParamField path="download" type="boolean">
  Suggest a download disposition on the signed URL
</ParamField>

While the video is still uploading or converting, the tool returns a result with `code: "thumbnail_not_ready"` and `status: "processing"` instead of an image — retry once the video finishes processing. Other upstream failures return `code: "thumbnail_fetch_failed"` with a signed URL to fetch manually.

## get\_clip\_preview

Get an MP4 preview from a clip's rendered playback timeline. It returns a signed URL rather than inline video content.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="startTimeMs" type="integer">
  Preview offset in ms on the clip's playback timeline (default 0)
</ParamField>

<ParamField path="durationMs" type="integer">
  Preview duration in ms (default 5000, range 500–30000)
</ParamField>

<ParamField path="fps" type="integer">
  `1`, `2`, `5`, `10`, or `30` (default 30)
</ParamField>

<ParamField path="width" type="integer">
  Output width in pixels. Defaults to 320. The preview keeps the video's aspect ratio, so omit height to have it derived automatically.
</ParamField>

<ParamField path="height" type="integer">
  Output height in pixels. Derived from the video's aspect ratio when omitted.
</ParamField>

<ParamField path="download" type="boolean">
  Suggest a download disposition on the signed URL
</ParamField>

## get\_video\_frame

Get a rendered frame from an entire video's playback timeline. It returns the same processing results and accepts the same frame format and sizing options as `get_clip_frame`.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="format" type="enum<string>">
  `jpg` (default), `png`, `webp`, or `gif`
</ParamField>

<ParamField path="startTimeMs" type="integer">
  Frame offset in ms from the video's playback start (cumulative across clips, cuts applied)
</ParamField>

<ParamField path="durationMs" type="integer">
  Duration in ms when `format` is `gif`
</ParamField>

<ParamField path="width" type="integer">
  Output width in pixels. Defaults to 320 (small, cheap in LLM tokens). The frame keeps the video's aspect ratio, so omit height to have it derived automatically.
</ParamField>

<ParamField path="height" type="integer">
  Output height in pixels. Derived from the video's aspect ratio when omitted.
</ParamField>

## get\_video\_preview

Get an MP4 preview from an entire video's rendered playback timeline. It returns a signed URL rather than inline video content.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="startTimeMs" type="integer">
  Preview offset in ms from the video's playback start (cumulative across clips, cuts applied)
</ParamField>

<ParamField path="durationMs" type="integer">
  Preview duration in ms (default 5000, range 500–30000)
</ParamField>

<ParamField path="fps" type="integer">
  `1`, `2`, `5`, `10`, or `30` (default 30)
</ParamField>

<ParamField path="width" type="integer">
  Output width in pixels. Defaults to 320. The preview keeps the video's aspect ratio, so omit height to have it derived automatically.
</ParamField>

<ParamField path="height" type="integer">
  Output height in pixels. Derived from the video's aspect ratio when omitted.
</ParamField>

## get\_storyboard

Get a fixed 4×4 WebP storyboard whose 16 tiles are sampled evenly across the requested window (`durationMs`/16 apart; every 5 seconds for the default 80s window).

* Returns inline WebP image content the model can inspect, plus JSON with the signed `url`, `columns`, `rows`, and `intervalMs`. Tile `i` (row-major) shows the frame at `startTimeMs + i * intervalMs`.
* Pass `videoId` alone for the full story, `videoId` with `clipId` for a rendered clip, or `sourceId` alone for a streaming upload.

Storyboards for videos and their clips are available outside your workspace when the video has an ungated public link. A public or embed-only playlist does not bypass the video's own private link, password, or email gate.

<ParamField path="videoId" type="string">
  Required for a story or clip. Video/story ID
</ParamField>

<ParamField path="clipId" type="string">
  Clip/scene ID; requires `videoId`
</ParamField>

<ParamField path="sourceId" type="string">
  Required for a streaming upload. Source ID; cannot be combined with `videoId` or `clipId`
</ParamField>

<ParamField path="startTimeMs" type="integer">
  Storyboard window start in ms on the selected target's timeline (default 0): the video's cumulative playback timeline, the clip's playback timeline, or the raw source file.
</ParamField>

<ParamField path="durationMs" type="integer">
  Window duration in ms (default 80,000ms). Pass the target's full duration to sample the whole video end to end.
</ParamField>

Tile count, dimensions, and format are fixed; the sampling interval follows from `durationMs`.

## set\_video\_thumbnail

Set a video's thumbnail. Two modes, mutually exclusive:

* **Uploaded image**: call `create_source` with `kind: "image"`, HTTP PUT the image bytes to the returned `uploadUrl`, then pass the `sourceId` here.
* **Frame from the video**: pass `inpointMs`, a time on the video's playback timeline (cuts applied, cumulative across clips). Inspect candidate frames first with `get_video_frame`, passing the same value as `startTimeMs`.

Setting one mode clears the other. A picked frame leaves `customThumbnailURL` null — verify it through `thumbnailInpointMs` in the video's settings from `get_video`.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="sourceId" type="string">
  Uploaded image source ID
</ParamField>

<ParamField path="inpointMs" type="integer">
  Thumbnail frame time in ms
</ParamField>

## remove\_video\_thumbnail

Remove a video's custom thumbnail (uploaded image or picked frame) and revert to the default auto-generated thumbnail.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

## get\_source\_thumbnail

Get a thumbnail of a specific source recording. For `jpg`, `png`, or `webp`, returns inline image content plus a signed URL; for `gif` or `mp4`, returns the signed URL only.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="sourceId" type="string" required>
  Source recording ID
</ParamField>

<ParamField path="format" type="enum<string>">
  `jpg`, `png`, `webp`, `gif`, or `mp4`
</ParamField>

<ParamField path="startTimeMs" type="integer">
  Frame offset in ms from the raw source file's start — no clip cuts apply
</ParamField>

<ParamField path="durationMs" type="integer">
  Duration of the animated preview (gif/mp4 only)
</ParamField>

<ParamField path="width" type="integer">
  Output width in pixels. Defaults to 320 (small, cheap in LLM tokens). The thumbnail keeps the video's aspect ratio, so omit height to have it derived automatically.
</ParamField>

<ParamField path="height" type="integer">
  Output height in pixels. Derived from the video's aspect ratio when omitted.
</ParamField>

## get\_source\_waveform

Get the waveform data for a source recording's audio track.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="sourceId" type="string" required>
  Source recording ID
</ParamField>

## get\_transcript

Transcript for the clip (cuts applied — what the viewer hears). Word indices are stable identifiers for `cut_clip_by_transcript`; they don't shift when cuts change. To see words that were cut out, clear the cuts first (`update_clip` with `cuts: []`) — cuts are always undoable.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

## update\_transcript\_words

Fix what the transcript says. Each edit addresses one word by its `index` from `get_transcript` and sets either `text` (the corrected wording, which also unhides the word) or `hidden` (whether the word shows in captions and subtitles) — never both. Returns the edited words in their new state.

* Corrections apply to the transcript, captions and subtitles together. The audio and the clip's timing are untouched — use `cut_clip_by_transcript` to actually remove spoken words.
* Send every correction for a clip in one call: at most one edit per word, and at most 100 words.
* Hiding or showing a word leaves its wording alone, so the two can be combined in any order.

A batch is applied atomically, so a call never changes only some of its words. An error does not by itself mean nothing changed — the words can land and a later step still fail — so treat the outcome as either fully applied or not applied at all. Every edit assigns a word outright, so re-sending the identical call is safe and settles it.

<ParamField path="videoId" type="string" required>
  Video ID
</ParamField>

<ParamField path="clipId" type="string" required>
  Clip ID
</ParamField>

<ParamField path="words" type="object[]" required>
  Array of `{index, text}` or `{index, hidden}` edits, at most 100. Indices come from `get_transcript`; a word that is currently cut out of the clip can't be edited.

  <Expandable title="properties">
    <ParamField path="index" type="integer" required>
      Index of the word to edit, from get\_transcript.
    </ParamField>

    <ParamField path="text" type="string">
      Corrected text for the word. Must not be empty — use `hidden: true` to drop a word from captions.
    </ParamField>

    <ParamField path="hidden" type="boolean">
      true hides the word from captions and subtitles (the audio is untouched); false shows it again.
    </ParamField>
  </Expandable>
</ParamField>


## Related topics

- [Duplicate a clip](/docs/api-reference/clips/duplicate-a-clip.md)
- [Reorder a clip](/docs/api-reference/clips/reorder-a-clip.md)
- [Get a clip](/docs/api-reference/clips/get-a-clip.md)
- [Update a clip](/docs/api-reference/clips/update-a-clip.md)
- [Delete a clip](/docs/api-reference/clips/delete-a-clip.md)
