Video reference
Composition model, SDK surfaces, DSL fields, and renderer options for Cuitty Video.
Video reference
Cuitty Video has four core surfaces:
| Surface | Package | Purpose |
|---|---|---|
| SDK | @cuitty/video | Build a composition in TypeScript and export Composition IR. |
| DSL | @cuitty/video-dsl | Parse YAML or JSON into the same Composition IR. |
| Renderer | @cuitty/video-render | Render frames with Playwright and encode with FFmpeg. |
| Player | @cuitty/video-player | Preview Composition IR in the browser. |
The CLI and server are thin workflow layers over those packages.
Composition IR
Every composition resolves to the same shape:
| Field | Type | Notes |
|---|---|---|
id | string | Stable composition identifier. |
width | number | Output width in pixels. |
height | number | Output height in pixels. |
fps | number | Frames per second. |
durationInFrames | number | Timeline length after duration parsing. |
layers | LayerIR[] | Ordered visual layers. |
audioTracks | AudioIR[] | Optional audio tracks. |
transitions | TransitionIR[] | Optional clip transitions. |
Layers contain clips. Clips define startFrame, endFrame, renderType, renderProps, and optional animation metadata.
TypeScript SDK
Use the SDK when composition data comes from code:
import { composition, tween, Easing } from "@cuitty/video";
import { render } from "@cuitty/video-render";
const video = composition({
id: "status-report",
width: 1920,
height: 1080,
fps: 30,
durationInFrames: 180,
});
video.layer("title").clip({
startFrame: 0,
endFrame: 120,
render: (ctx) => {
const opacity = tween(ctx.frame, [0, 30], [0, 1], {
clamp: true,
easing: Easing.out(Easing.cubic),
});
return `<h1 style="opacity:${opacity}">Weekly status</h1>`;
},
});
await render({
composition: video,
outputPath: "./output/status-report.mp4",
codec: "h264",
crf: 18,
});
YAML DSL
Use the DSL when a composition should be editable as data:
composition:
id: status-report
width: 1920
height: 1080
fps: 30
duration: 6s
layers:
- id: title
clips:
- id: headline
start: 0s
end: 4s
render:
type: text
text: "Weekly status"
fontSize: 72
color: "#ffffff"
animate:
- property: opacity
from: 0
to: 1
start: 0s
duration: 1s
easing: cubic-out
The DSL accepts YAML or JSON. duration, start, and end can be frame numbers or time strings such as 500ms, 2s, or 00:00:02.
Render options
| Option | Default | Notes |
|---|---|---|
outputPath | Required | Final output file path. |
codec | h264 | Supports h264, h265, vp9, prores, and gif. |
crf | 18 | Lower is higher quality for CRF-based codecs. |
concurrency | CPU-dependent | Parallel frame rendering. |
onProgress | None | Receives frame count, total frames, and render FPS. |
Server workflow
The render server accepts composition payloads, creates jobs, reports status, and runs the same render pipeline behind an HTTP boundary. Use it when renders should be queued or called by another service instead of run directly in the CLI.
Observe integration
Video render jobs can emit progress, failure, and encoding metadata into Observe. The standalone Video product owns authoring and rendering; the existing Video module remains the Observe module for browser-session recording job metadata.