mcut
@mcut/editor

Functions

Functions and constants exported by @mcut/editor.

Constants

TEXT_PRESETS

const TEXT_PRESETS: TextPreset[]

Built-in text presets, a title, a subtitle, a lower third, and a pop label.

PLATFORM_PRESETS

const PLATFORM_PRESETS: PlatformPreset[]

Delivery presets for YouTube, YouTube 4K, Shorts, TikTok, Reels, and square feeds, read by mcut new --preset and the agent skill.

Functions

addTextAtPlayhead

function addTextAtPlayhead(engine: EditorEngine, text = 'Your text'): ElementId

Inserts a default text element at the playhead through insertElementAtPlayhead and returns its id.

allElementIds

function allElementIds(engine: EditorEngine): `e-${string}`[]

Returns every element id in the project across all tracks.

clipEdges

function clipEdges(engine: EditorEngine): number[]

Returns every clip start and end time plus zero, sorted ascending.

createSequentialVideoCollage

function createSequentialVideoCollage(
  engine: EditorEngine,
  options: SequentialVideoCollageOptions,
): SequentialVideoCollageResult

Builds a collage where each video plays in turn in its own slot, with frozen frames before and after its active clip and its audio on one shared lane.

duplicateElement

function duplicateElement(engine: EditorEngine, elementId: ElementId): ElementId | null

Adds a copy of the element in the nearest free slot after it on the same track, selects the copy, and returns its id or null.

duplicateSelection

function duplicateSelection(engine: EditorEngine): void

Duplicates every selected element after itself in one transaction, skipping elements with no room, and selects the copies.

elementForAsset

function elementForAsset(engine: EditorEngine, asset: AssetRef): TimelineElementInput

Returns the default timeline element for a media bin asset, sized to fit the project canvas.

elementForTextPreset

function elementForTextPreset(engine: EditorEngine, preset: TextPreset): TimelineElementInput

Returns a text element input built from a TextPreset, with a box 70 percent of the project width and the preset's style and vertical offset.

fitCanvasToVideoCollage

function fitCanvasToVideoCollage(
  engine: EditorEngine,
  assets: readonly AssetRef[],
  layout: Exclude<SequentialCollageLayout, 'auto'>,
): { width: number; height: number }

Resizes the project canvas to hold the given equal-aspect videos side by side or stacked, and returns the new size.

insertElementAtPlayhead

function insertElementAtPlayhead(engine: EditorEngine, element: TimelineElementInput): ElementId

Inserts an element at the playhead on the topmost unlocked track with room, adds a track when none fits, and returns the new element id.

insertElementOnNewTrack

function insertElementOnNewTrack(
  engine: EditorEngine,
  element: TimelineElementInput,
  startMs: number,
): ElementId

Adds a new topmost track, places the element on it at startMs, and returns the new element id.

insertElementOnTrack

function insertElementOnTrack(
  engine: EditorEngine,
  trackId: TrackId,
  element: TimelineElementInput,
  startMs: number,
  editMode: 'normal' | 'overwrite' | 'insert' = 'normal',
): ElementId

Places an element on a track near startMs, clamping to free space in normal mode and keeping the requested position in overwrite and insert modes.

isSoloTrack

function isSoloTrack(engine: EditorEngine, trackId: TrackId): boolean

Returns true when the track is unmuted and every other track is muted.

keyframeTimes

function keyframeTimes(element: TimelineElement): number[]

Returns the unique element-local keyframe times across every animatable property, sorted ascending.

moveKeyframesAtTime

function moveKeyframesAtTime(
  engine: EditorEngine,
  elementId: `e-${string}`,
  fromTimeMs: number,
  toTimeMs: number,
  properties?: AnimatableProperty[],
): void

Moves the keyframes at fromTimeMs to toTimeMs on the given properties, or on all animatable properties, in one transaction.

removeKeyframesAtTime

function removeKeyframesAtTime(
  engine: EditorEngine,
  elementId: `e-${string}`,
  timeMs: number,
  properties?: AnimatableProperty[],
): void

Removes the keyframes at timeMs on the given properties, or on all animatable properties, in one transaction.

removeSelection

function removeSelection(engine: EditorEngine): void

Removes every selected element in one transaction and clears the selection.

retimeSequentialCollage

function retimeSequentialCollage(
  engine: EditorEngine,
  groupOrder?: readonly GroupId[],
): SequentialVideoCollageResult | null

Rebuilds the freeze frames and audio positions of an existing collage around each group's active video clip, or returns null when no collage groups exist.

selectTrackElements

function selectTrackElements(engine: EditorEngine, trackId: TrackId): void

Selects every element on one track.

shuttle

function shuttle(engine: EditorEngine, direction: -1 | 0 | 1): void

Implements J, K, and L transport, where 0 pauses and resets the rate and a direction plays at 1x or doubles the current rate up to 8x.

splitAllAtPlayhead

function splitAllAtPlayhead(engine: EditorEngine): void

Splits every clip under the playhead on every unlocked track at the frame-quantized playhead time.

splitSelectionAtPlayhead

function splitSelectionAtPlayhead(engine: EditorEngine): void

Splits every selected element the playhead crosses, splits linked partners with it, and re-pairs the right halves under a new link id.

toggleMasterKeyframe

function toggleMasterKeyframe(engine: EditorEngine): void

Removes the keyframes at the playhead on the selected element's visual properties when one exists there, and otherwise adds keyframes at the current values.

toggleSoloTrack

function toggleSoloTrack(engine: EditorEngine, trackId: TrackId): void

Mutes every other track so the given track plays alone, or unmutes all tracks when it is already soloed.

trackOfSelection

function trackOfSelection(engine: EditorEngine): Track | undefined

Returns the track that holds the first selected element, or undefined.

trimSelectionToPlayhead

function trimSelectionToPlayhead(engine: EditorEngine, edge: 'start' | 'end'): void

Trims the start or end of every selected clip the playhead crosses to the frame-quantized playhead time.

unlinkElements

function unlinkElements(engine: EditorEngine, elementId: `e-${string}`): void

Clears the linkId on an element and every element linked to it.

canPlaceIgnoring

function canPlaceIgnoring(
  track: Track,
  startMs: number,
  durationMs: number,
  ignore: ReadonlySet<string>,
): boolean

Returns true when a clip at startMs with durationMs would not overlap any element on the track outside the ignored ids.

collectClipDragBases

function collectClipDragBases(
  project: Project,
  ids: readonly ElementId[],
): Map<ElementId, ClipDragBase>

Returns the starting position, duration, trim, reversal, time map presence, and track index for each element id found in the project.

computeSlipRange

function computeSlipRange(
  project: Project,
  ids: readonly ElementId[],
): { minMs: number; maxMs: number }

Returns how far the slippable elements can slip earlier and later without running past their source media.

planAutoCrossfade

function planAutoCrossfade(
  project: Project,
  input: AutoCrossfadePlanInput,
): BuiltinCommand | null

Returns a setTransition command when dragging a clip into its neighbor by an overlap within the attempted range, or null when no crossfade applies.

planDuplicateClipsToNewTracks

function planDuplicateClipsToNewTracks(
  project: Project,
  ids: readonly ElementId[],
  options: DuplicateClipsToNewTracksOptions = {},
): DuplicateClipsToNewTracksPlan | null

Returns commands that add one new track per source track and copy the given elements onto them, or null when no element is found.

resolveToolMode

function resolveToolMode(
  project: Project,
  mode: ClipDragMode,
  ids: readonly ElementId[],
): ResolvedClipDragMode

Downgrades a drag mode to one whose structural requirements the anchor element meets, and names the roll partner when rolling.

planZoomAtPlayhead

function planZoomAtPlayhead(
  element: ZoomableElement,
  zoom: keyof typeof ZOOM_REGION_PRESETS | ZoomShape,
  playheadMs: number,
): CommandOfType<'addZoomRegion'>

Returns an addZoomRegion command that starts the preset at the playhead in element-local time, moved earlier when the zoom would run past the element. On a multicam the zoom targets the screen source, or the first source when there is no screen.

planZoomRegionDrag

function planZoomRegionDrag(
  element: ZoomableElement,
  zoom: ZoomRegion,
  mode: ZoomRegionDragMode,
  deltaMs: number,
): ZoomRegion

Returns the zoom region after a drag of deltaMs. Ramps stay at least 1 ms long and the hold stays at least 0 ms. Within those limits a move, start, or end drag keeps the zoom inside the element and clear of other zooms on its target, which pulls a zoom that a split or trim left running past an edge back inside. When no drag of that kind can fit the zoom there, the zoom comes back unchanged. A ramp drag keeps the span, so on such a zoom updateZoomRegion rejects the result.

planSilenceCuts

function planSilenceCuts(
  project: Project,
  elementId: string,
  transcript: SilenceCutTranscript,
  options: SilenceCutOptions = {},
): SilenceCutPlan

Cuts the silences between transcript words out of one clip with source audio, playing forward at 1x, applying splits and ripple deletes last to first, and returns the commands and resulting project. A multicam is cut on its audio source before volume, fades, and mute. A time remap or reverse playback is rejected. A multicam with no audio source fails until setMulticamAudio.

planCenterPerson

function planCenterPerson(
  project: Project,
  target: { elementId: ElementId; source?: string },
  samples: ReadonlyArray<FaceSample>,
  options: CenterPersonOptions,
): [CommandOfType<'setReframe'>, ...Array<CommandOfType<'updateElement'>>]

Turns face samples into a list of commands to apply in one engine.transact, so they are one undo step. The first is a setReframe. It smooths the face centers with a critically damped spring and a dead zone, keeps the window inside the frame, and drops keys that a straight line between their neighbors already covers. Higher smoothing slows the spring and widens the dead zone. On a video it also sets a centered crop at options.aspect, which needs the asset's width and height. When the crop aspect is within 1% of the project aspect, an updateElement follows that scales the clip to cover the frame and centers it. options.fill true adds it at any aspect, and false leaves the size alone. On a multicam, target.source names the source to follow, and there is no fill. Throws an OperatorError when no sample has a face.

applyCommands

function applyCommands(engine: EditorEngine, commands: readonly BuiltinCommand[]): void

Dispatches the commands in order inside one transaction, so the batch becomes a single undo entry. If a command throws, none of the batch applies and the error propagates. Each command passes through withPlayheadDefaults first.

withPlayheadDefaults

function withPlayheadDefaults(engine: EditorEngine, command: BuiltinCommand): BuiltinCommand

Returns an applyAnimationPreset command without atMs with atMs set to the playhead's element-local time when the playhead is on the clip. An out preset needs the playhead past the clip start. Any other command, or a playhead off the clip, comes back unchanged, so the preset falls back to the clip edge.

summarizeEngine

function summarizeEngine(engine: EditorEngine): string

Returns the summarizeProject text for the engine's project followed by the playhead position, playing state, and selection.

lintProject

function lintProject(project: Project): LintIssue[]

Reports cross-entity problems that parseProject accepts, such as elements that reference missing assets, links with one member, empty tracks, and empty captions.

getPlatformPreset

function getPlatformPreset(id: string): PlatformPreset | undefined

Returns the preset from PLATFORM_PRESETS with the given id, or undefined.

On this page