Layouts, presets, and thumbnails
Layout and slot schemas, property presets, and thumbnail templates.
Types
Layout
type Layout = z.infer<typeof layoutSchema>A layout as inferred from layoutSchema.
LayoutSlot
type LayoutSlot = z.infer<typeof layoutSlotSchema>A layout slot as inferred from layoutSlotSchema.
PropertyPreset
type PropertyPreset = z.infer<typeof propertyPresetSchema>A property preset as inferred from propertyPresetSchema.
ThumbnailItem
type ThumbnailItem = z.infer<typeof thumbnailItemSchema>A template item as inferred from thumbnailItemSchema.
ThumbnailTemplate
type ThumbnailTemplate = z.infer<typeof thumbnailTemplateSchema>A thumbnail template as inferred from thumbnailTemplateSchema.
Schemas
layoutSchema
const layoutSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
slots: z.array(layoutSlotSchema).min(1),
})Zod schema for a layout, an id, a name, and at least one slot.
layoutSlotSchema
const layoutSlotSchema = z.object({
source: z.string().min(1),
rect: z.object({
x: z.number().min(-1).max(2),
y: z.number().min(-1).max(2),
w: z.number().positive().max(3),
h: z.number().positive().max(3),
}),
fit: z.enum(['cover', 'contain']).default('cover'),
...frameStyleSchema.shape,
})Zod schema for one layout slot, the source key it shows, a rect in normalized canvas coordinates, a fit mode, and the same frame style a video clip takes. The slot's crop picks the source region that is fitted into the rect, so panning a cover slot moves its crop.
The saveLayout command merges each slot it is given into the saved slot with the same source. An omitted field keeps its value, null clears a frame style field, and only a source new to the layout needs a rect. A saved slot whose source is left out is removed.
propertyPresetSchema
const propertyPresetSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
kind: z.string().min(1),
values: z.record(z.string(), z.unknown()),
})Zod schema for a property preset, an id, a name, the kind of surface that captured it, and a record of captured values.
thumbnailItemSchema
const thumbnailItemSchema = z.discriminatedUnion('kind', [
z.object({
kind: z.literal('text'),
rect: rectSchema,
text: z.string(),
role: z.string().default('Text'),
style: textStyleSchema,
}),
z.object({
kind: z.literal('slot'),
rect: rectSchema,
fit: z.enum(['cover', 'contain']).default('cover'),
label: z.string().default('Media'),
}),
])Zod schema for one template item, either a text item with a normalized rect, text, role, and style or a slot with a rect, fit mode, and label.
thumbnailTemplateSchema
const thumbnailTemplateSchema = z.object({
name: z.string().min(1),
items: z.array(thumbnailItemSchema).min(1),
})Zod schema for a thumbnail template, a name and at least one item.
Constants
THUMBNAIL_FRAME_COUNT
const THUMBNAIL_FRAME_COUNT = 5The number of frames the cover spans, 5.
THUMBNAIL_TEMPLATES
const THUMBNAIL_TEMPLATES: ThumbnailTemplate[]The three starter covers, big title, lower third, and center punch.
THUMBNAIL_TRACK_NAME
const THUMBNAIL_TRACK_NAME = 'Thumbnail'The name that marks a track as the thumbnail track, Thumbnail.
Functions
createDefaultLayouts
function createDefaultLayouts(canvas: Pick<Project, 'width' | 'height'>): Layout[]Returns five starter layouts for a screen and camera pair with fresh ids, full screen with camera picture in picture, camera only, screen only, two 3 by 4 panels, and side by side. The picture in picture shadow is sized from the canvas so it scales with the slot. saveLayout gives the same corner radius and shadow to an overlay slot new to a layout that sets none of cornerRadius, stroke, and shadow.
getLayout
function getLayout(layouts: readonly Layout[], layoutId: string): Layout | nullReturns the layout with the given id, or null.
listPresets
function listPresets(project: Project, kind: string): PropertyPreset[]Returns the project's presets whose kind matches, in saved order.
captureThumbnailTemplate
function captureThumbnailTemplate(
project: Project,
name: string,
): ThumbnailTemplate | nullReturns a template built from the thumbnail track, turning text elements into text items and image elements into slots, or null when the track is missing or empty.
expandThumbnailTemplate
function expandThumbnailTemplate(
project: Pick<Project, 'width' | 'height' | 'fps'>,
template: ThumbnailTemplate,
): TimelineElement[]Returns text elements for the template's text items, scaled from 1080p template space to the project size and positioned from their normalized rects, and skips slot items.
findThumbnailTracks
function findThumbnailTracks(project: Project): Track[]Returns every track named Thumbnail in track order, one per text layer of the applied template.
thumbnailDurationMs
function thumbnailDurationMs(fps: number): numberReturns the length of the cover span, five frames at the given fps or the minimum element duration if that is longer.