Agent, CLI, API and plugins

Every edit in Edit mode is a command: run it from the command palette, ask the agent, script it with the popcraft CLI, call it over the REST API, or from a plugin.

The timeline doesn't edit the file itself: every cut, trim, blend and mix it does is the sequence.edit command, and reading a sequence is sequence.get. The same two commands are the agent's edit_sequence and get_sequence, the plugin methods editSequence and getSequence, and popcraft run … sequence.edit on the command line, so all of them edit exactly alike, one undo step each, and sync to everyone in the file.

The command palette

Run an edit from the command palette · 0:03
Description

The AI trailer in Edit with the playhead inside the second shot. ⌘K opens the command palette; typing razor finds Add edit to all tracks, and Enter cuts every track at the playhead.

  1. Press ⌘K.
  2. Type what to do: razor, ripple, mark in, duck, next edit. Edit's rows are under Video editing, with their shortcuts; a row that needs picked clips is greyed out until you pick some.
  3. Press Enter.
Palette rowKeys
Open Edit workspace⌘⇧E
Add edit at playhead⌘B
Add edit to all tracks⌘⇧B
Ripple deleteShift+Backspace
Delete clips (leave gap)Backspace
Ripple trim start to playheadQ
Ripple trim end to playheadW
Mark in, Mark outI, O
Clear in and out⌘⇧X
Lift in to out;
Extract in to out'
Close gap
Enable / disable clipsShift+E
Duck music under voice
Go to next edit, Go to previous edit↓, ↑

The agent

Ask in words: "cut a 20-second version of this sequence", "put the logo frame over the last three seconds at 80% screen", "duck the music under the voiceover", "add a one-second push between every scene". The agent reads the sequence with get_sequence and edits it with edit_sequence, plus the composition tools for making sequences and transitions.

ToolWhat it does
get_sequenceReads sequences by track: V1's scenes, the clips on V2 and up (with opacity, blend, fades, speed), the audio clips on A1 and down (with gain keys), each track's lock, hide, mute, solo, level and pan, the in and out marks, markers, and every edit point. Ids for edit_sequence
edit_sequenceOne edit (op) on one sequence (id): every kind in the table below
create_compositionA new sequence from frames
edit_compositionAdds, moves and removes V1 scenes, sets transitions, renames, markers
get_compositionsLists the file's sequences
add_audio, generate_audioAdds sound from the media store, or generates music or effects
generate_videoGenerates a video clip from a prompt
export_mp4, export_webm, export_gif, export_png_sequenceExports

The edits

sequence.edit takes { id, op }: id is the sequence and op one edit, with a kind. Times are in ms of the sequence; tracks are V1, V2… and A1, A2….

kindWhat it doesMain fields
razorCut at a timeat, tracks? (default: every unlocked track), clips?
deleteDelete clipsclips, ripple? (close the gap; V1 always closes)
rangeLift or extract between two timesin, out, extract?
closeGapClose the gap at a timetrack, at
trimMove a clip's edgeclip, edge (in or out), to, ripple?
trimToPlayheadQ and Wtrack, at, side (start or end)
slipChange what part of the source playsclip, dt
rollMove the cut after a clipclip, dt
slideMove a V2+ clip, its neighbours trimmingclip, dt
placePut a frame on V2 and uptrack (1 is V2), frame, start, length?, in?, mode? (overwrite or insert)
moveMove a clip in time or to another trackclip, start?, track? (0 is V1), mode?
stretchChange a clip's speed by its lengthclip, length
clipA clip's settingsclip, opacity?, blend?, disabled?, muted?, reverse?, fadeIn?, fadeOut?, name?
trackA track's settingstrack, locked?, hidden?, muted?, solo?, name?, gain? (1 is unity), pan?
addTrackAdd a tracktype (video or audio), at?
removeTrackDelete a track and its clipstrack (not V1)
duckDuck a music track under voice trackstrack, under, level? (0.25), ramp? (250 ms)
marksSet or clear in and outin?, out? (null clears)
addAudioAdd a sound from the media storemediaHash, start?, lane?…
audioAn audio clip's settingsclip, start?, lane?, fadeIn?, fadeOut?, fadeCurve?, pan?, muted?, loop?…
trimAudioTrim an audio clipclip, edge, delta
gainKeyA volume key on an audio clipclip, t, v
removeAudioRemove an audio clipclip
splitAudioCut an audio clipclip, at
crossfadeCrossfade two audio clipsclip, with, duration?

Blend modes are NORMAL, MULTIPLY, SCREEN, OVERLAY, DARKEN, LIGHTEN, COLOR_DODGE, COLOR_BURN, HARD_LIGHT, SOFT_LIGHT, DIFFERENCE, EXCLUSION, HUE, SATURATION, COLOR and LUMINOSITY.

The CLI

popcraft run runs a command on a .popcraft file (or a cloud file) and saves it. See Command line.

# Read the sequence: tracks, clips and their ids
popcraft run trailer.popcraft sequence.get --json
 
# Cut every track at 6 s, then ripple-delete the second half of the first shot
popcraft run trailer.popcraft sequence.edit --id comp-1 --op '{"kind":"razor","at":6000}'
popcraft run trailer.popcraft sequence.edit --id comp-1 --op '{"kind":"delete","clips":["clip-9"],"ripple":true}'
 
# A logo frame over the last 3 s on V2, screened at 80%
popcraft run trailer.popcraft sequence.edit --id comp-1 --op '{"kind":"place","track":1,"frame":"12:40","start":29000,"length":3000}'
popcraft run trailer.popcraft sequence.edit --id comp-1 --op '{"kind":"clip","clip":"$LAYER","opacity":0.8,"blend":"SCREEN"}'
 
# Several edits saved once, in order
popcraft run trailer.popcraft --batch @edits.json

edits.json:

[
  { "command": "sequence.edit", "params": { "id": "comp-1", "op": { "kind": "addTrack", "type": "audio" } } },
  { "command": "sequence.edit", "params": { "id": "comp-1", "op": { "kind": "duck", "track": "A2", "under": ["A1"] } } },
  { "command": "sequence.edit", "params": { "id": "comp-1", "op": { "kind": "track", "track": "A2", "gain": 0.8 } } }
]

Export from a script

popcraft run trailer.popcraft export.mp4 --composition comp-1 --resolution 1080p --out trailer.mp4

The CLI renders it in a headless editor, with the sound. popcraft commands export.mp4 lists every option.

The REST API

The same commands run on a cloud file with POST /api/v1/files/{key}/commands (see Editing a design):

curl -X POST -H "Authorization: Bearer pop_…" -H "content-type: application/json" \
  "https://popcraft.app/api/v1/files/$KEY/commands" -d '{
  "commands": [
    { "command": "sequence.get", "params": {} },
    { "command": "sequence.edit", "params": { "id": "comp-1", "op": { "kind": "razor", "at": 6000 } } },
    { "command": "sequence.edit", "params": { "id": "comp-1", "op": { "kind": "marks", "in": 12000, "out": 15000 } } },
    { "command": "sequence.edit", "params": { "id": "comp-1", "op": { "kind": "range", "in": 12000, "out": 15000, "extract": true } } }
  ]
}'

Up to 100 commands run in order and are saved as one edit; anyone in the file sees it merge in. Exports don't run over the REST API: use the CLI. Every command's request and answer: Endpoints.

Plugins

A plugin with the write permission calls the same edits (see the plugin API):

// Read the open sequence (or every one): { sequences, open }
const { sequences } = await popcraft.getSequence({})
const seq = sequences[0]
// Cut every track at each marker, then duck A2 under A1
for (const m of seq.markers ?? []) await popcraft.editSequence({ id: seq.id, op: { kind: 'razor', at: m.t } })
await popcraft.editSequence({ id: seq.id, op: { kind: 'duck', track: 'A2', under: ['A1'] } })