Advanced / Video · guide
Video pipeline (videoPipeline)
Current Apexify.js 6.0.0 documentation for Video pipeline (videoPipeline).
painter.videoPipeline(source?) is the recommended API when several edits belong to one project: trim, deterministic segment replacement, captions, file audio, and procedural SFX. It uses a validated layer stack and isolated internal workspaces rather than asking application code to manage a chain of temporary output files.
Also on: painter.video.videoPipeline() (same VideoStack entry).
Basics (single ops): Video overview · Timeline · Text overlays · Video audio · createAudio
When to use what
| Situation | API |
|---|---|
| Building a video editor, server render project, or saved edit JSON | videoPipeline() |
| Exactly one FFmpeg job (probe, trim only, one audio mix, …) | createVideo({ … }) |
Generated motion (gameplay, animate, scenes) | animate / renderSceneToVideoFrames → then pipeline |
Rich captions matching createText | addTextOverlay or pipeline.text() |
| Procedural SFX | painter.createAudio + pipeline.audio() or mixAudio |
Requirements and source policy are the same as createVideo: FFmpeg/ffprobe plus the centralized Buffer/local/HTTP(S) resolver described in Video overview.
Layer stack model
Each builder call adds or updates a validated layer:
| Layer kind | Builder method | Purpose |
|---|---|---|
source | .source(path | Buffer, id?) | Input video (exactly one render source). |
trim | .trim(start, end, id?) | Keep [startTime, endTime] before later layers. |
splice | .splice({ targetStartTime, targetEndTime, replacementVideo/replacementFrames, … }, id?) | Replace a timeline range. |
text | .text(overlay | overlays[], id?) | Timed createText-style overlays. |
audio | .audio(tracks, options?, id?) | File/Buffer/WAV plus procedural preset/synth/sequence tracks. |
Stable layer IDs
- Same
idon source / trim / splice replaces the previous layer with that id. - Same
idon text / audio merges overlays or tracks. pushLayer(layer, { replace: true })explicitly replaces instead of merging.- Invalid mutations are transactional: a rejected edit does not leave the stack partially changed.
This makes IDs suitable for editor timeline rows and deterministic project updates.
Execution order and splice determinism
Rendering is normalized to this order:
- source resolution;
- trim;
- splices, sorted by
targetStartTimeand thenid; - text overlays;
- audio mix;
- optional
previewencode.
Overlapping splice ranges are rejected. Multiple durationPolicy: 'preserve' splices are rejected because changing total timeline length would make later source coordinates ambiguous.
The render result exposes the plan that actually ran:
passes is the actual internal FFmpeg stage count, not an estimate.
Full example — trim, B-roll, titles, music + synth SFX
Text layers — createText parity
.text() accepts VideoTextOverlayClip: the TextProperties styling surface plus timed video fields.
| Field | Meaning |
|---|---|
startTime, endTime | Visible window on the current timeline. |
transitionIn, transitionOut | Fade/slide/zoom/bounce presets or validated custom expressions. |
overlayOpacity | Master 0–1 overlay multiplier, separate from glyph fill opacity. |
Unicode, quotes, newlines, multiple overlays, timed visibility, and transitions are handled without shell command interpolation. Later overlays in the same text layer are applied after earlier ones.
Single-op equivalent: Text overlays.
Audio layers — files + procedural audio
.audio(tracks, options?, id?) accepts:
Track type | Purpose |
|---|---|
file | Local path, URL, or Buffer. Supports placement plus volume/pan/fades. |
preset | createAudio preset at startTime. |
synth | SynthSoundOptions at startTime. |
sequence | Procedural event timeline placed on the video. |
wav | Pre-built WAV Buffer. |
Audio-layer options include original-audio retention/volume/speed/pitch and durationPolicy: 'video' | 'shortest' | 'longest'.
Undo / redo
The builder keeps bounded project history for editor-style mutations:
undo() and redo() return false when no corresponding history entry exists. A new successful mutation clears redo history.
Versioned saved projects
toJSON() emits a versioned snapshot:
For path/URL-backed projects, restore the persisted layer array through the public painter entry:
For durable editor projects, prefer stable path/URL/object-storage references rather than embedding large media Buffers in database JSON.
render options
preset: 'export'keeps the full export path.preset: 'preview'adds a real low-quality proxy encode, constrained to a maximum 960-pixel dimension while preserving aspect ratio.signal,timeoutMs,overwrite, andonProgressuse the same shared execution controls ascreateVideo.
Pipeline vs chained createVideo
Chained createVideo | videoPipeline |
|---|---|
| Application manages intermediate paths | Pipeline owns and cleans isolated workspaces |
| Easy to accidentally re-encode every step | Deterministic normalized pass plan |
| Exactly one operation per call | Declarative multi-layer project |
| Fine for scripts | Better for editor/server project state |
Operations that are not pipeline layer kinds (for example LUT, stabilization, or batch orchestration) remain single createVideo operations and can run before or after a pipeline export.
Combine with Scene export
Typical product flow:
renderSceneToVideoFramesoranimatefor branded/generated segments.videoPipelineto trim uploads, splice generated segments, burn captions, and mix file/procedural audio.