Skip to content
Apexify.jsDocs
Apexify.js version v5.4.5

Node / Video Ffmpeg · guide

Compositing & building videos

Current Apexify.js 6.0.0 documentation for Compositing & building videos.

apexify.jsRuntime: nodeCURRENTSince 6.0.0

merge

Ignores top-level source — uses videos only.

modeBehaviour
sequential (default)concat demuxer -c copy — fast; clips should match codecs for reliability.
side-by-sidehstack first two inputs only.
gridCurrently same as side-by-side in code (two-input hstack) — grid dims reserved.
SOURCEtypescript
typescript
Studio
await painter.createVideo({  source: './placeholder.mp4',  merge: {    videos: ['./part1.mp4', './part2.mp4'],    mode: 'sequential',    outputPath: './full.mp4',  },});

splitScreen

Ignores top-level source.

layoutNeedsBehaviour
side-by-side≥2hstack.
top-bottom≥2vstack.
grid≥42×2 pipeline.
SOURCEtypescript
typescript
Studio
await painter.createVideo({  source: './placeholder.mp4',  splitScreen: {    videos: ['./a.mp4', './b.mp4'],    layout: 'top-bottom',    outputPath: './stacked.mp4',  },});

pictureInPicture

Uses source as background and overlayVideo as inset.

FieldDefaultEffect
overlayVideo✓Path / buffer / URL.
positionbottom-rightCorner placement.
size320×180Scales overlay before composite.
opacity1Alpha via colorchannelmixer.
outputPath✓
SOURCEtypescript
typescript
Studio
await painter.createVideo({  source: './slides.mp4',  pictureInPicture: {    overlayVideo: './presenter.mp4',    position: 'bottom-right',    size: { width: 480, height: 270 },    opacity: 1,    outputPath: './webinar-layout.mp4',  },});

createFromFrames

Ignores source for logic — still required by type.

What it does: Writes frames as frame-%06d.png, runs FFmpeg -framerate → encoded video -pix_fmt yuv420p.

FieldDefaultEffect
frames✓Paths or Buffers.
fps30Timeline speed.
qualitymediumCRF ladder unless bitrate set.
bitrate—Overrides CRF.
resolutionautoscale+pad from first frame or forced WxH.
formattypedContainer hint; encode uses libx264-style path.
SOURCEtypescript
typescript
Studio
await painter.createVideo({  source: Buffer.alloc(0),  createFromFrames: {    frames: ['./renders/f_001.png', './renders/f_002.png'],    fps: 24,    outputPath: './anim.mp4',    quality: 'high',  },});

createLoop

What it does: Concat demuxer plays source twice (-c copy). smooth flag unused in helper.

SOURCEtypescript
typescript
Studio
await painter.createVideo({  source: './sting.mp4',  createLoop: { outputPath: './sting-doubled.mp4' },});

batch

What it does: Loops videos[] calling createVideo({ source, ...operations }) per row.

Important: Put outputPath inside each nested operation (trim.outputPath, etc.). The outputDirectory helper field does not auto-inject paths into operations.

Prefer your own for loop until batch wiring saves outputs predictably.

SOURCEtypescript
typescript
Studio
await painter.createVideo({  source: './unused.mp4',  batch: {    outputDirectory: './batch',    videos: [      {        source: './a.mp4',        operations: {          trim: { startTime: 0, endTime: 5, outputPath: './batch/a.mp4' },        },      },    ],  },});

Next steps