SCREENCAST-MCP / TOOLS / EDIT
Edit Pipeline
pipeline
Run several edits (trim, crop, scale, speed, cut_idle, redact, callout, keystroke_overlay, cursor, reframe, zoom, backdrop, audio, burn_subtitles, then optionally export_preset or export_gif) in one ffmpeg pass: one re-encode, no intermediate files. Prefer it over chaining edit tools; a recipe does the usual polish in one call.
editwritesdestructivesince v0.30.0
00:00PARAMETERS
| Name | Type | Description |
|---|---|---|
input required | string | Path to the source video. |
steps | object[] | Edits in order, each { op, ...its tool's options }; export_preset/export_gif only last. Times and pixels are relative to the video as it is at that step (after earlier trims, speed, crops). zoom follow:"clicks" plans from the event log; burn_subtitles takes subtitles or transcribe:true. at most 30 items |
steps[trim].start required | number | ≥ 0 |
steps[trim].end | number | > 0 |
steps[trim].duration | number | > 0 |
steps[crop].x required | integer | ≥ 0, ≤ 9007199254740991 |
steps[crop].y required | integer | ≥ 0, ≤ 9007199254740991 |
steps[crop].width required | integer | > 0, ≤ 9007199254740991 |
steps[crop].height required | integer | > 0, ≤ 9007199254740991 |
steps[scale].width | integer | > 0, ≤ 9007199254740991 |
steps[scale].height | integer | > 0, ≤ 9007199254740991 |
steps[speed].factor required | number | > 0 |
steps[redact].regions required | object[] | at least 1 items |
steps[redact].regions[].x required | integer | ≥ 0, ≤ 9007199254740991 |
steps[redact].regions[].y required | integer | ≥ 0, ≤ 9007199254740991 |
steps[redact].regions[].width required | integer | > 0, ≤ 9007199254740991 |
steps[redact].regions[].height required | integer | > 0, ≤ 9007199254740991 |
steps[redact].regions[].start | number | ≥ 0 |
steps[redact].regions[].end | number | > 0 |
steps[redact].style | "box" | "blur" | "pixelate" | |
steps[redact].pad | integer | ≥ 0, ≤ 9007199254740991 |
steps[redact].color | string | |
steps[callout].items required | object[] | at least 1 items, at most 50 items |
steps[callout].items[box].x required | number | |
steps[callout].items[box].y required | number | |
steps[callout].items[box].width required | number | > 0 |
steps[callout].items[box].height required | number | > 0 |
steps[callout].items[box].thickness | number | Outline px (default 4). > 0 |
steps[callout].items[box].fill | boolean | Fill instead of outline. |
steps[callout].items[box].from | number | ≥ 0 |
steps[callout].items[box].to | number | > 0 |
steps[callout].items[box].color | string | |
steps[callout].items[text].x required | number | |
steps[callout].items[text].y required | number | |
steps[callout].items[text].text required | string | |
steps[callout].items[text].size | number | Font size px (default 32). > 0 |
steps[callout].items[text].background | boolean | Dark panel behind the text (default true). |
steps[callout].items[text].from | number | ≥ 0 |
steps[callout].items[text].to | number | > 0 |
steps[callout].items[text].color | string | |
steps[callout].items[arrow].x1 required | number | |
steps[callout].items[arrow].y1 required | number | |
steps[callout].items[arrow].x2 required | number | Head (x2,y2) is the point the arrow points at. |
steps[callout].items[arrow].y2 required | number | |
steps[callout].items[arrow].thickness | number | Shaft px (default 8). > 0 |
steps[callout].items[arrow].from | number | ≥ 0 |
steps[callout].items[arrow].to | number | > 0 |
steps[callout].items[arrow].color | string | |
steps[callout].fontFile | string | Font: a .ttf/.otf/.ttc path or a C:\Windows\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...). |
steps[reframe].aspect required | "16:9" | "9:16" | "1:1" | "4:5" | |
steps[reframe].fit | "pad" | "crop" | |
steps[zoom].keyframes | object[] | at least 1 items, at most 100 items |
steps[zoom].keyframes[].t required | number | ≥ 0 |
steps[zoom].keyframes[].x | number | |
steps[zoom].keyframes[].y | number | |
steps[zoom].keyframes[].width | number | > 0 |
steps[zoom].keyframes[].height | number | > 0 |
steps[zoom].keyframes[].full | boolean | |
steps[zoom].follow | "clicks" | |
steps[zoom].maxZoom | number | ≥ 1, ≤ 6 |
steps[zoom].holdSec | number | > 0, ≤ 30 |
steps[zoom].transitionSec | number | > 0, ≤ 5 |
steps[cut_idle].minIdleSec | number | > 0 |
steps[cut_idle].keepSec | number | ≥ 0 |
steps[audio].normalize | "youtube" | "podcast" | "broadcast" | number | |
steps[audio].denoise | "light" | "medium" | "strong" | |
steps[burn_subtitles].subtitles | string | |
steps[burn_subtitles].transcribe | boolean | |
steps[burn_subtitles].style | "clean" | "social" | |
steps[backdrop].preset | "desktop" | "rec" | "amber" | "light" | |
steps[backdrop].colors | string[] | at least 1 items, at most 4 items |
steps[backdrop].image | string | |
steps[backdrop].padding | integer | ≥ 0, ≤ 2000 |
steps[backdrop].radius | integer | ≥ 0, ≤ 1000 |
steps[backdrop].shadow | integer | ≥ 0, ≤ 200 |
steps[backdrop].shadowOpacity | number | ≥ 0, ≤ 1 |
steps[backdrop].aspect | "16:9" | "9:16" | "1:1" | "4:5" | |
steps[keystroke_overlay].events | string | |
steps[keystroke_overlay].clicks | boolean | |
steps[keystroke_overlay].typing | boolean | |
steps[keystroke_overlay].keys | "shortcuts" | "masked" | |
steps[keystroke_overlay].lingerSec | number | > 0, ≤ 10 |
steps[keystroke_overlay].position | "bottom" | "bottom-left" | "bottom-right" | "top" | "top-left" | "top-right" | |
steps[keystroke_overlay].size | number | ≥ 8, ≤ 400 |
steps[keystroke_overlay].color | string | |
steps[keystroke_overlay].fontFile | string | |
steps[cursor].events | string | |
steps[cursor].size | number | ≥ 0.25, ≤ 8 |
steps[cursor].smoothing | number | ≥ 0, ≤ 1 |
steps[cursor].hideAfterSec | number | ≥ 0, ≤ 600 |
steps[cursor].clicks | boolean | |
steps[cursor].spotlight | boolean | |
steps[export_preset].platform required | "youtube" | "instagram_reel" | "tiktok" | "x" | "square" | "steam_trailer" | "vertical_reel" | |
steps[export_preset].fit | "pad" | "crop" | |
steps[export_gif].format | "gif" | "webp" | |
steps[export_gif].maxBytes | integer | ≥ 10000, ≤ 9007199254740991 |
steps[export_gif].fps | number | > 0, ≤ 30 |
steps[export_gif].width | integer | ≥ 64, ≤ 1920 |
recipe | "pr_demo" | "tutorial" | "social_reel" | Polish preset expanded to steps (see dryRun): pr_demo = cut_idle, click zoom, GIF <=10 MB; tutorial = + audio, captions, 1080p mp4; social_reel = 9:16, big captions. Given steps replace its same-op step. |
quality | "draft" | "standard" | "high" | Encoder preset for an mp4 result (default standard). |
dryRun | boolean | Return the plan (ffmpeg command, output size) without running it. |
output | string | Optional output path. Defaults under SCREENCAST_HOME/edits. |
overwrite | boolean | Allow replacing an existing file at the output path (default false). |
chapters | boolean | Keep the input's markers as chapters, re-timed through trims and speed. |
00:05A MINIMAL CALL
pipeline { "input": "recording.mp4" }
The required arguments only, with placeholder values. Everything else takes its default.
00:10WHAT COMES BACK
Structured content (structuredContent), alongside a text summary:
| Field | Type | Description |
|---|---|---|
processes always | integer | ≥ -9007199254740991, ≤ 9007199254740991 |
steps always | string[] |
00:15SEEN IN