mcut
@mcut/timeline

Zoom regions

Punch-ins as one object with in, hold, and out timing, a target, easing, and motion blur.

A zoom region is one punch-in on a video, image, or multicam element. It zooms in over inMs, holds for holdMs, and zooms back out over outMs, all in element-local time. A multicam zoom names a source key, so every slot showing that source zooms and the other slots keep their framing. The screen can zoom while the camera overlay stays put. A slot zooms inside its crop, so a zoom never shows source the crop cuts away. A multicam zoom with no source zooms the whole composite, overlays included, inside the element's frame.

Regions on one target never overlap. The zoom commands keep the region they add or change inside the element. A split copies a region that crosses the cut into both halves, so the picture on each side stays the same. The right half's copy gets the id with -r appended, so no two pieces share a zoom id. A trim can leave a region running past an edge, where it plays cut off. Growing a clip from its start shifts the regions with the content.

addZoomRegion and updateZoomRegion take time. "element", the SDK default, reads atMs as element-local ms. "timeline", the MCP server default, reads it as project timeline ms. With "timeline", addZoomRegion covers that timeline range on every abutting piece of the same media on the element's track, so a zoom over a cut between two pieces is one command. Each piece after the first gets a copy with -r appended to the id, and each copy updates on its own. updateZoomRegion only needs the region to overlap the element, so those copies stay editable. A range that starts off a piece, runs past the last piece, or crosses a gap is rejected.

engine.dispatch({
  type: 'addZoomRegion',
  elementId: 'e-multicam',
  zoom: { preset: 'detailZoom', source: 'screen', atMs: 12_000, focus: { x: 0.75, y: 0.3 } },
})

Types

ZoomRegion

ZoomRegion is z.infer<typeof zoomRegionSchema>, one stored zoom region with every field resolved.

ZoomRegionRef

ZoomRegionRef extends ZoomRegion with elementId and the region's timeline startMs and endMs, cut at the element's edges. A region that crosses a split lists the part each piece plays.

ZoomableElement

ZoomableElement is a video, image, or multicam element, the element types that hold zoom regions.

ContentView

ContentView is { scale, focus }, how a clip or slot frames its source at one instant. scale multiplies the fit scale. focus is the anchor point from 0 to 1 that stays fixed while it scales.

VisibleFraction

VisibleFraction is { x, y }, the share of a slot's cropped source each axis shows at scale 1 after the slot's fit. A cover slot shows less than 1 on the axis it cuts, and a contain slot shows more than 1 on the axis it letterboxes. getSlotView and centeredFocus take it.

Schemas

zoomRegionSchema

FieldTypeMeaning
idstringStable id, minted as z-... when omitted
sourcestring, optionalMulticam source key whose slots zoom. Absent on clips, and absent on a multicam zoom of the whole composite
atMsinteger msElement-local start of the zoom-in, negative on the right half of a split through a zoom
inMs, holdMs, outMsinteger msRamp in, hold, ramp out
focus{ x, y } from 0 to 1Target center, across the cropped frame of a clip or multicam slot
scale1 to 8Scale at the hold
easingEasingApplied to both ramps
motionBlur0 to 1Shutter as a fraction of one frame while the zoom moves. 0 turns it off

zoomCommandSchema

zoomCommandSchema is the discriminated union of addZoomRegion, updateZoomRegion, and removeZoomRegion with their type. It is the input of the MCP edit_zooms tool.

Presets

ZOOM_REGION_PRESETS

PresetScaleInHoldOut
subtlePunchIn1.15700 ms1600 ms700 ms
detailZoom1.3600 ms3000 ms600 ms

addZoomRegion defaults to subtlePunchIn, easeOutExpo, and motion blur 0.5. Explicit fields override the preset. A rect aims the zoom at its center and fills it only up to the preset scale, so a region never makes a detail zoom severe. Pass focus and scale for a stronger zoom. The MCP tools warn when any zoom goes above 1.5x.

Functions

listZoomRegions

listZoomRegions(project) returns every zoom region in the project as ZoomRegionRef[], in track and element order.

isZoomable

isZoomable(element) returns true for a video, image, or multicam element and narrows it to ZoomableElement.

zoomRegionEndMs

zoomRegionEndMs(region) returns the element-local time a zoom region ends, atMs + inMs + holdMs + outMs.

getSlotView

getSlotView(element, slot, timelineMs, visible, rest) returns the ContentView of one multicam layout slot. It is the one place a renderer reads a slot's framing. visible is the VisibleFraction of the slot, which differs from 1 when the slot's shape differs from its crop, and it defaults to the full frame. rest is the focus outside a zoom, where a zoom starts and ends, and it defaults to the center. The compositor passes the reframed focus from centeredFocus for a source with a reframe track. With neither a zoom nor a track, the view is the center at scale 1, so the slot's crop alone sets its framing.

getClipView

getClipView(element, timelineMs) returns the ContentView of a video or image clip inside its crop, or of a whole multicam composite from its zooms with no source.

getZoomWindow

getZoomWindow(view, visible) returns the part of the content a ContentView shows, as a normalized rect across the content. The window covers visible / scale of the content on each axis, anchored at the view's focus. visible is the VisibleFraction the target shows at scale 1, and it defaults to the full frame. Below scale 1 the window reaches past the content. The compositor draws a clip's window of its crop. It clamps a slot's window to the slot crop, so a contain slot keeps its letterbox centered.

getZoomedRect

getZoomedRect(view, rect) maps a normalized frame rect through a whole-composite ContentView. It returns where the rect lands on the canvas when the composite shows the view's getZoomWindow window. The multicam renderer maps its whole composite through it before the crop, and flattenMulticam bakes it into each flattened clip's transform keyframes, so a flattened clip follows its slot exactly.

getZoomShutterMs

getZoomShutterMs(element, timelineMs, frameMs) returns the motion blur shutter in milliseconds while any zoom on the element ramps, and 0 while every zoom holds or rests. The compositor renders the element at views sampled across this window into a scratch canvas and composites the average once, the same path as keyframe motion blur.

On this page