ScreenPilot

Combine recordings

Join several storyboards into one video with sequence.json, and insert a new feature clip into the middle of an existing demo without re-recording it.

A sequence.json joins several storyboards, each with its own recording, into one MP4. The AI app can write it for you, or you write it yourself. The main use is to add a new feature to a demo you already made: you record only the new part, and the old recording stays untouched.

Insert a feature clip into a demo#

Say demo.json is a finished demo, and the feature you want to show belongs after second 42 of its recording. You do not re-record the demo and you do not edit its storyboard. You do three things.

  1. Record the feature on its own and write a storyboard for it, feature/feature.json. Start it with "extends": "../demo.json" so it takes the demo's look: theme, voice, output size and music. See Share a look with extends.
  2. Write sequence.json next to demo.json. List the demo twice, split at second 42, and put the feature between the two halves.
  3. Validate and render.

The feature storyboard only needs what is different:

{
  "extends": "../demo.json",
  "source": "rec.mp4",
  "segments": [{ "in": 0, "out": 12 }],
  "captions": [{ "at": 1, "text": "New: recurring invoices", "style": "title" }],
  "narration": [{ "at": 1, "text": "Invoices can now repeat on a schedule." }]
}

And the sequence:

{
  "version": 1,
  "parts": [
    { "storyboard": "demo.json", "to": 42 },
    { "storyboard": "feature/feature.json", "transition": { "type": "crossfade", "dur": 0.5 } },
    { "storyboard": "demo.json", "from": 42, "transition": { "type": "crossfade" } }
  ]
}
screenpilot sequence-validate sequence.json
screenpilot sequence sequence.json -q draft
screenpilot check sequence.mp4 --at 5,40,50
screenpilot sequence sequence.json -q delivery -o demo-with-feature.mp4

The result plays the demo up to second 42, crossfades into the feature clip, then crossfades back and plays the rest of the demo. The demo's intro plays once at the start and its outro once at the end.

The seconds in from and to are source seconds of that storyboard, the same seconds you use for zooms and captions. Pick the split from a frame: screenpilot frames demo.mp4 --at 42 --grid.

The sequence file#

Paths in sequence.json are relative to the sequence file. screenpilot sequence-schema (or the sequence_schema tool) prints the authoritative JSON Schema.

FieldDefaultMeaning
version1Format version. Always 1.
partsrequiredStoryboards in playing order. At least one. The same storyboard can appear more than once.
outputfirst part's outputwidth, height and fps for the whole video. Fields you give here override the first part's output.

Part fields#

FieldDefaultMeaning
storyboardrequiredPath to a storyboard, relative to the sequence file.
fromthe startSource second this part starts at.
tothe endSource second this part ends at.
transitioncutHow this part enters from the previous one. See Transitions. Ignored on the first part.

What every part shares#

  • One output size. All parts are rendered at the same width, height and frame rate, even if their storyboards say different things.
  • One intro, one outro. intro plays only on the first part and outro only on the last. The other parts' cards are left out.
  • Your files stay as they are. ScreenPilot writes a derived storyboard for each part into a build folder.

Source ranges: from and to#

from and to keep only the range [from, to) of a storyboard's source time. The range is half-open: something at exactly to belongs to the part that starts there. That is why {"to": 42} followed by {"from": 42} keeps every item of the demo exactly once.

ItemWhat happens at the edges
SegmentsCut to the range. If nothing is left, the sequence is invalid.
NarrationKept when it starts inside the range. A line that started before from is dropped, because a line cannot resume in the middle of a word.
Zooms, captions, highlightsCut to the range. One that straddles an edge is shortened. If less than 0.5 seconds is left, it is dropped.
Holds, chapter cardsKept when their at is inside the range.
OverlaysAn overlay with at is cut to the range like a zoom. An overlay without at (a logo for the whole video) is kept in every part.
Camera viewThe view in force at from carries in, so the second half does not start on the wrong window or monitor.

sequence-validate warns when to is past the end of the source.

Transitions#

transition on a part says how it enters from the previous part. It has a type and an optional dur.

TypeWhat the viewer sees
cutA plain cut. This is the default.
crossfadeThe previous part fades into this one.
fade-blackThe previous part fades to black, then this one fades in.
wipe-left, wipe-rightThis part is revealed by a wipe in that direction.
slide-left, slide-rightThis part slides in over the previous one in that direction.

dur is the number of seconds the two parts overlap. It defaults to 0.5 and is clamped to half the length of either neighbouring part, so a short clip never disappears into a long transition. Audio crossfades together with the picture.

Render a sequence#

CommandWhat it does
screenpilot sequence-validate <sequence>Checks the sequence and every storyboard it uses. It fails with the schema issues, or prints valid: true with the warnings of each part.
screenpilot sequence <sequence>Renders every part and joins them. Flags: -o, --output (default <sequence>.mp4), -q, --quality (draft, looks, delivery), --png-frames, --workers, --build-dir.
screenpilot sequence-schemaPrints the JSON Schema of sequence.json.

The same steps are the tools sequence_validate, sequence_render (inputs sequence, output, quality) and sequence_schema. See MCP tools.

  • Unchanged parts are reused. Each part is rendered like a storyboard into <sequence>.build/part-N/. On the next run, a part whose storyboard, recording, events, music, overlays and quality are the same is not rendered again. Editing the feature clip does not re-render the demo.
  • The join. When every part is cut to the next and they are encoded the same way, the parts are joined by stream copy, with no quality loss. With a transition, or when the encodings differ, the video is re-encoded. The result tells you which one happened in join (copy or encode).
  • The result. The command prints the output path, the duration, join and each part with its duration, whether it was reused and its warnings.
Review with -q draft first, then look at frames with screenpilot check around each join. Use -q delivery only for the final file.

Limits#

  • sequence has no --from, --to or --formats. To review one part quickly, render its storyboard with screenpilot render --from --to. For another size, set output in the sequence.
  • A part keeps its own recording and its own narration. Nothing is shared between parts except the output size, the intro on the first part and the outro on the last.
  • A storyboard that fails validation fails the sequence. The error names the part, for example parts[1] (feature/feature.json).