Video inputs and variants

Use an input schema when the same timeline needs different headlines, colors, or content. Odori validates inputs before rendering and uses the schema to generate Studio controls.

Define defaults and constraints

Create videos/launch/schema.ts with fields that describe the content your video accepts:

import {defineInputSchema} from "odori";

export const launchInput = defineInputSchema({
  headline: {
    type: "text",
    defaultValue: "Meet the new editor.",
    maxLength: 64,
  },
  accent: {type: "color", defaultValue: "#6366f1"},
  showBadge: {type: "boolean", defaultValue: true},
  edition: {
    type: "select",
    options: ["Team", "Enterprise"],
    defaultValue: "Team",
  },
});

Attach schema: launchInput to the entry's defineVideoMetadata() call. The default component receives the resolved input fields as props.

Choose field types

The built-in schema supports these descriptors:

TypeOptions
textString default, optional maxLength and multiline
numberNumeric default, optional min, max, and control step
booleanBoolean default
selectString default and allowed options
colorString default
jsonSerializable default value

A color field accepts a string; it does not validate CSS color syntax. A json field does not validate a nested domain model. Use a schema with a parse() method when you need additional validation. Studio's built-in field controls come from defineInputSchema() descriptions.

Pass inputs from the CLI

Use the same input while inspecting, reviewing a frame, and exporting:

pnpm odori inspect launch --input '{"headline":"Built for teams."}'
pnpm odori frame launch --at 2s --input '{"headline":"Built for teams."}'
pnpm odori export launch --input '{"headline":"Built for teams."}'

Fields omitted from the object use schema defaults. Keep the JSON inside single quotes so your shell preserves its double quotes.

For larger inputs, create inputs/team.json and pass its path:

{
  "headline": "Built for teams.",
  "edition": "Team",
  "showBadge": true
}

Export that input to a distinct output path:

pnpm odori export launch --input-file inputs/team.json --output out/team.mp4

Choose either --input or --input-file, not both. Give each variant a different output path to avoid replacing an earlier export.

Keep content separate from preparation

Inputs should be serializable content and configuration. Fetch external data in prepare.ts and pass the result through prepared, rather than fetching during React render. See data and assets.

Test the longest headline, missing optional content, and every select option in Studio. A valid schema does not prove that the rendered layout is readable.

On this page