Last updated: 2026-07-20
Video compositing via FFmpeg, wrapped in clean R functions.
compost turns common ffmpeg filter_complex patterns (overlay, chromakey,
concat, scale, stack) into small, composable R functions, and lowers an
OpenTimelineIO timeline (through
rotio) to a single rendered video.
Every function shells out to ffmpeg/ffprobe. Nothing is reimplemented in R;
the package’s job is to build correct filtergraphs so you don’t have to.
Install
remotes::install_github("cornball-ai/compost")
Requires ffmpeg (>= 5.0) on your PATH. The only R dependency is rotio.
Conventions
A few patterns hold across the API:
- Output format is inferred from the output file’s extension.
overwrite = TRUE(default) passes-yto ffmpeg.dry_run = TRUEreturns the ffmpeg command string instead of running it, so you can inspect or test the filtergraph without rendering.- Functions return the output path invisibly.
What’s in it
Compositing
| Function | Does |
|---|---|
overlay() | Composite a PNG (with alpha) or video over a background |
pip() | Picture-in-picture a clip into a corner |
chromakey() | Key out a colored background and composite |
colorkey() | Key out a flat background, write ProRes 4444 (alpha preserved) |
hstack() | Stack two videos side by side |
vstack() | Stack two videos vertically |
pad() | Scale to fit and pad onto a canvas |
zoom() | Stepped zoom that changes level at STT line boundaries |
compose_layout() | Paint N streams into pixel-rect slots on a canvas (heads over slides, stacks, over-shoulder boxes) |
Stills and sequences
| Function | Does |
|---|---|
still_clip() | One image → a video clip, static or Ken Burns pan/zoom |
frames_clip() | A numbered frame sequence → a video clip |
Joining and transitions
| Function | Does |
|---|---|
concat() | Join segments sequentially via the concat demuxer |
crossfade_concat() | Dissolve between clips, optionally overlay one audio track |
Audio
| Function | Does |
|---|---|
audio_convert() | Re-encode / resample / remix to a new container or codec |
audio_concat() | Join audio files with exact silence gaps (decoded-domain, one encode) |
normalize_audio() | Single EBU R128 loudnorm pass |
broadcast_audio() | Broadcast-clean chain: high-pass, de-hum, loudness, fades |
align_audio() | Locate a clip’s audio within a longer narration |
align_overlaps() | Place chunks on the narration clock and derive overlaps |
subclip() | Cut a [start, end] range out of a media file |
rms_curve() | Per-block RMS levels across a file |
Inspection and frames
| Function | Does |
|---|---|
probe() | Query video properties via ffprobe |
frame_export() | Pull a single frame at a given time as an image |
Timeline
| Function | Does |
|---|---|
render_timeline() | Lower a rotio (OTIO) timeline to a rendered video: source-range trims, dissolve transitions, still/sequence pre-render, cornball.* motion effects, multi-track slot layouts, caption burn, and a narration bed the video locks to |
The cornball.* effect namespace and the slot-layout contract are documented
in inst/schema/cornball-effects.md and
inst/schema/cornball-layout.md.
Examples
Picture-in-picture a webcam into the bottom-right of a screen recording:
library(compost)
pip("screen.mp4", "webcam.mp4", "out.mp4",
scale = 0.25, corner = "lower-right")
Convert a meeting recording to STT-ready audio in one pass:
audio_convert("recording.mp4", "speech.wav",
sample_rate = 16000, channels = 1)
Crossfade a sequence of clips and lay one music bed over the top:
crossfade_concat(c("a.mp4", "b.mp4", "c.mp4"), "reel.mp4",
fade = 0.5, audio = "music.mp3")
Inspect the ffmpeg command without rendering (returns the command string):
overlay("bg.mp4", "logo.png", "out.mp4", x = 40, y = 40, dry_run = TRUE)
License
MIT. Copyright cornball.ai.
Functions
align_audio
compost::align_audioalign_overlaps
compost::align_overlapsaudio_concat
compost::audio_concataudio_convert
compost::audio_convertbroadcast_audio
compost::broadcast_audiochromakey
compost::chromakeycolorkey
compost::colorkeycompose_layout
compost::compose_layoutconcat
compost::concatcrossfade_concat
compost::crossfade_concatframe_export
compost::frame_exportframes_clip
compost::frames_cliphstack
compost::hstacknormalize_audio
compost::normalize_audiooverlay
compost::overlaypad
compost::padpip
compost::pipprobe
compost::proberender_timeline
compost::render_timelinerms_curve
compost::rms_curvestill_clip
compost::still_clipsubclip
compost::subclipvstack
compost::vstackzoom
compost::zoom