Skip to main content
The cut op removes stretches of a clip’s source — the dead air, the false start, the “um” — from a project. Send it like any other op, through POST /v1/projects/{id}/ops or the MCP edit_project tool:
The renderer plays one source range per element, so a cut splits each target into ordinary elements, one per kept range (its pieces), and moves everything else on the timeline in the same version. Nothing is half-applied: if any part of the op cannot be made, the whole batch is refused and the head stays where it was. All times in a cut are source seconds — seconds into the file — never timeline seconds. A range that was already removed lies outside every piece, so sending the same cut twice changes nothing.

Say what goes

Use exactly one of these three: ids lists the video or audio elements to cut: an element, or pieces an earlier cut made. Each target is cut only inside its own source window (in_point to out_point); a range outside every target is listed once, in the first target’s skipped_ranges, and does nothing. To cut a talking head whose sound is a separate audio element, list both: they are cut in step. Leave one out and the report warns, because it plays on out of step after the first join.

Cutting by words

Cut with the transcript’s own word timings rather than times you work out yourself:
  • transcript_task_id is a completed transcribe task in your workspace, made from the same source_url the targets play. Transcribe with disfluencies: true if you want to cut filler words: without it they are left out of the transcript and have no index.
  • remove (or keep) takes word-index ranges [i, j], both ends included, listed in order with each word once. Indices are integers; "14" is refused.
  • A cut takes about 90% of the pause on each side of the removed words. It leaves 10% of each pause next to the words that stay, and never less than 20 ms, so the cut never lands inside a word you kept.
  • The server converts the transcript’s millisecond timings itself, and first clamps any words the recogniser overlapped, so every pause is zero or more.
  • If the transcript’s mean word confidence is under 0.8, the report says so: preview the joins before you render.

Silences

silences shortens long pauses between the words that stay, including the pause left at a join where words were removed. Send {} for the defaults: A sentence ends at ., !, ?, 。, ! or ?, and the last word always ends one, so an unpunctuated final sentence is treated as finished speech. A pause counts only for the part that still plays, so running the same silence pass twice changes nothing.

Pieces

The first piece keeps the element’s id. Each later piece is named after the element and the second its source starts at, in milliseconds: cutting talk at 12.4–13.1 s makes talk and talk~13100. The names come from the source, so the same cut always makes the same names, and sending it again makes none. A piece keeps its name for good, though: if a later cut takes the head of talk~13100, that piece starts later than 13.1 s under the same name, so read where a piece starts from its in_point. Splitting one cut over several ops can therefore name the pieces differently from a single op; what plays where is the same. Every piece is a full copy of the element with its own in_point, out_point and time. Its motion goes where it plays: an entrance on the first piece, an exit on the last (still anchored to the end), a mid-clip accent on the piece it lands in, and loops and slow drifts such as Ken Burns on every piece, in phase.

Ripple

ripple decides what happens to the rest of the timeline:
  • all (the default) closes every gap, as if the removed moments never played:
    • Later elements move up, with their animations and keyframes.
    • An overlay that plays across a cut gets shorter: video and audio through their out_point, everything else through duration. A music bed under the speech simply ends sooner.
    • Captions (word_animation) are re-timed. A word with less than a quarter of it left is dropped, from the caption’s text too when the text’s words line up with the timings.
    • The request duration, when it is set, shrinks by what was removed.
  • none leaves each piece where it played, gaps and all, and moves nothing else.
Either way, a transition into a cut element stays on its first piece and one out of it moves to the last piece, and groups list the new pieces beside the element. An element that would lie entirely inside a removed range — a title over the take you cut — makes the op fail with its id, so nothing disappears silently. Move it, or send "contained": "remove" to delete it with the cut. A caption with none of its words left is removed either way.

Dry run

Add "dry_run": true to the ops body to see exactly what the batch would do — the diff, the changed ids, the lint and the cut report — without saving a version. It works for any batch, not only cuts, and checks if_version like a real apply. Read the report, then send the same body without dry_run. The result’s cut_report has one entry per target:

Joins and fades

Each new join gets a short linear audio fade on both sides, 15 ms by default, so a cut through a waveform does not click. Set join_fade (0–0.5 s; 0 for hard joins). A fade the element already had stays on its outer ends: the fade-in on the first piece, the fade-out on the last. These fades shape the sound only; the picture cuts hard.

Limits

  • Cut boundaries snap inward to the output’s frame grid (frame_rate, 30 by default), where the clip plays them at its speed, so every join lands on a frame and a removal never grows past what you asked for. Ranges that touch or overlap merge first; a removal shorter than one frame is then skipped.
  • A piece shorter than two frames is removed with its neighbours and reported: the renderer drops video and audio items under 10 ms.
  • One cut op makes at most 300 pieces. Each piece re-opens and seeks its source when it renders, so many short pieces render slowly; the MANY_SHORT_PIECES warning says when a source has 20 or more pieces with a median under half a second, and SLIVER_PIECE flags any video or audio element under two frames.
  • Speed-ramped elements, loop: true elements and track-matte sources cannot be cut. A speed-ramped overlay cannot play across a cut either.
  • A target without an out_point takes its length from the stored upload. If the file was never uploaded, set out_point first.
  • Targets that overlap on the timeline must remove the same moments: a video and its own audio track, cut with the same ranges, are fine.
  • Removing everything a cut targets is refused. Delete an element with remove_element.