mcut
@mcut/timeline

Model schemas

Zod schemas and constants for the project document and its elements.

Schemas

assetIdSchema

const assetIdSchema = z
  .custom<AssetId>(
    (v) => typeof v === 'string' && /^a-[\w-]+$/.test(v),
    'invalid asset id (expected "a-..." prefix)',
  )
  .meta({ type: 'string', pattern: '^a-[\\w-]+$' })

Zod schema for an AssetId, a string with the a- prefix.

assetRefSchema

const assetRefSchema = z.object({
  id: assetIdSchema,
  kind: z.enum(['video', 'audio', 'image']),
  src: z.string(),
  hash: z.string().optional(),
  name: z.string().optional(),
  mimeType: z.string().optional(),
  nativePreview: z.boolean().optional(),
  durationMs: z.number().int().positive().optional(),
  width: z.number().int().positive().optional(),
  height: z.number().int().positive().optional(),
})

Zod schema for a project asset, its id, kind, source URL, and optional hash, name, MIME type, native preview flag, duration, and size.

audioElementSchema

const audioElementSchema = composeFull('audio', audioShape)

Zod schema for an audio element, the shared id and timing fields plus asset, trim, time map, reversal, volume, mute, fades, and an optional voice mix.

captionElementSchema

const captionElementSchema = composeFull('caption', captionShape)

Zod schema for a caption element, the shared id and timing fields plus text, optional word timings, and caption style.

captionStyleSchema

const captionStyleSchema = z
  .object({
    fontFamily: z.string().default('sans-serif'),
    fontSize: z.number().positive().default(48),
    fontWeight: z.number().int().min(100).max(1000).default(700),
    color: z.string().default('#ffffff'),
    activeWordColor: z.string().optional(),
    backgroundColor: z.string().default('rgba(0, 0, 0, 0.55)'),
    position: z.enum(['top', 'middle', 'bottom']).default('bottom'),
  })
  .prefault({})

Zod schema for caption styling, font, size, weight, colors, background, and vertical position, with defaults for every field.

captionWordSchema

const captionWordSchema = z.object({
  text: z.string(),
  startMs: z.number().int().nonnegative(),
  endMs: z.number().int().nonnegative(),
}).refine((word) => word.endMs >= word.startMs, 'caption word endMs must be >= startMs')

Zod schema for one caption word with timing relative to the caption's startMs, rejecting a word whose endMs is before its startMs.

elementIdSchema

const elementIdSchema = z
  .custom<ElementId>(
    (v) => typeof v === 'string' && /^e-[\w-]+$/.test(v),
    'invalid element id (expected "e-..." prefix)',
  )
  .meta({ type: 'string', pattern: '^e-[\\w-]+$' })

Zod schema for an ElementId, a string with the e- prefix.

elementInputSchema

const elementInputSchema: z.ZodType<TimelineElementDraft, TimelineElementInput>

Zod discriminated union over the six element kinds with id optional, used when inserting elements.

elementSchema

const elementSchema: z.ZodType<TimelineElement>

Zod discriminated union on type over the six element schemas, from videoElementSchema to multicamElementSchema.

groupIdSchema

const groupIdSchema = z
  .custom<GroupId>(
    (v) => typeof v === 'string' && /^g-[\w-]+$/.test(v),
    'invalid group id (expected "g-..." prefix)',
  )
  .meta({ type: 'string', pattern: '^g-[\\w-]+$' })

Zod schema for a GroupId, a string with the g- prefix.

imageElementSchema

const imageElementSchema = composeFull('image', imageShape)

Zod schema for an image element, the shared id and timing fields plus asset, transform, opacity, visual effects, and frame styling.

markerIdSchema

const markerIdSchema = z
  .custom<MarkerId>(
    (v) => typeof v === 'string' && /^m-[\w-]+$/.test(v),
    'invalid marker id (expected "m-..." prefix)',
  )
  .meta({ type: 'string', pattern: '^m-[\\w-]+$' })

Zod schema for a MarkerId, a string with the m- prefix.

markerSchema

const markerSchema = z.object({
  id: markerIdSchema,
  timeMs: z.number().int().nonnegative(),
  label: z.string().optional(),
  color: z.string().optional(),
})

Zod schema for a project marker, a named point on the time ruler with an optional label and color.

multicamElementSchema

const multicamElementSchema = composeFull('multicam', multicamShape)

Zod schema for a multicam element, the shared id and timing fields plus synced sources, angle cuts on the source clock, angle transition, audio source, trim, time map, reversal, transform, opacity, audio fields, an optional voice mix, visual effects, and frame styling. It is a media clip like a video element, and its trim, time map, and reversal read the source clock that every source shares.

projectSchema

const projectSchema = z.object({
  version: z.literal(PROJECT_VERSION).default(PROJECT_VERSION),
  id: z.string(),
  name: z.string(),
  width: z.number().int().positive(),
  height: z.number().int().positive(),
  fps: z.number().positive(),
  tracks: z.array(trackSchema).default([]),
  assets: z.record(z.string(), assetRefSchema).default({}),
  layouts: z.array(layoutSchema).default([]),
  presets: z.array(propertyPresetSchema).default([]),
  markers: z.array(markerSchema).default([]),
  vocabulary: z.array(z.string().trim().min(1).max(100)).max(1000).optional(),
})

Zod schema for a project, its version, id, name, size, fps, tracks, assets, layouts, presets, markers, and the vocabulary of names and terms transcription gets as hints.

textElementSchema

const textElementSchema = composeFull('text', textShape)

Zod schema for a text element, the shared id and timing fields plus text, style, rich text runs, box, transform, opacity, and visual effects.

textBoxSchema

const textBoxSchema = z.object({
  width: z.number().positive(),
  height: z.number().positive().optional(),
  overflow: z.enum(['visible', 'clip']).default('clip'),
})

Zod schema for a text box with a width, optional height, and overflow mode.

textShadowSchema

const textShadowSchema = shadowSchema

Zod schema for a text shadow, the same shape as shadowSchema.

textStrokeSchema

const textStrokeSchema = strokeSchema

Zod schema for a text outline, the same shape as strokeSchema.

textStyleSchema

const textStyleSchema = z
  .object({
    fontFamily: z.string().default('sans-serif'),
    fontSize: z.number().positive().default(64),
    fontWeight: z.number().int().min(100).max(1000).default(600),
    fontStyle: z.enum(['normal', 'italic']).default('normal'),
    color: z.string().default('#ffffff'),
    align: z.enum(['left', 'center', 'right']).default('center'),
    backgroundColor: z.string().optional(),
    letterSpacing: z.number().default(0),
    lineHeight: z.number().positive().default(1.25),
    textTransform: z.enum(['none', 'uppercase', 'lowercase']).default('none'),
    stroke: textStrokeSchema.optional(),
    shadow: textShadowSchema.optional(),
  })
  .prefault({})

Zod schema for text styling, font, weight, style, color, alignment, background, spacing, line height, case transform, stroke, and shadow.

trackIdSchema

const trackIdSchema = z
  .custom<TrackId>(
    (v) => typeof v === 'string' && /^t-[\w-]+$/.test(v),
    'invalid track id (expected "t-..." prefix)',
  )
  .meta({ type: 'string', pattern: '^t-[\\w-]+$' })

Zod schema for a TrackId, a string with the t- prefix.

trackSchema

const trackSchema = z.object({
  id: trackIdSchema,
  name: z.string(),
  muted: z.boolean().default(false),
  hidden: z.boolean().default(false),
  locked: z.boolean().default(false),
  magnetic: z.boolean().default(false),
  elements: z.array(elementSchema).default([]),
})

Zod schema for a track, its id, name, muted, hidden, locked, and magnetic flags, and its elements.

transformSchema

const transformSchema = z
  .object({
    x: z.number().default(0),
    y: z.number().default(0),
    scaleX: scaleSchema.default(1),
    scaleY: scaleSchema.default(1),
    rotation: z.number().default(0),
  })
  .prefault({})

Zod schema for position, scale, and rotation, where coordinates are center-origin and scale may be negative but not zero.

videoElementSchema

const videoElementSchema = composeFull('video', videoShape)

Zod schema for a video element, the shared id and timing fields plus asset, trim, time map, reversal, transform, opacity, audio fields, an optional voice mix, visual effects, and frame styling.

voiceSchema

const voiceSchema = z.object({ enabled: z.boolean(), amount: z.number().min(0).max(1) })

Zod schema for the optional voice cleanup mix on video, audio, and multicam clips. enabled turns the cleaned stem on, and amount is the wet level from 0 to 1.

Constants

MIN_ELEMENT_DURATION_MS

const MIN_ELEMENT_DURATION_MS = 10

The shortest element duration the schema accepts, 10 ms.

On this page