Data and assets

Use prepare.ts for network requests, database queries, and file reads. Return the data your video needs before playback starts:

videos/changelog/prepare.ts
import {definePrepare} from "odori";

export const prepare = definePrepare(async ({input, assets, cache, signal}) => {
  const release = await cache.getOrSet(
    `release:${input.tag}`,
    () => fetchRelease(input.tag, {signal}),
  );

  const logo = await assets.resolve("brand:product-mark");

  return {release, logo};
});

The prepared result becomes a prop of the video entry:

export default function ChangelogVideo({prepared}) {
  return (
    <Video>
      <Scene duration="6s">
        <ReleaseTitle release={prepared.release} logo={prepared.logo} />
      </Scene>
    </Video>
  );
}

Provide fallback data for previews where preparation hasn't run:

export default function WorkflowVideo({prepared}: {prepared?: {commands: Step[]}}) {
  return <Terminal steps={prepared?.commands ?? FALLBACK} />;
}

Inputs

Define serializable inputs to validate CLI arguments and generate Studio controls:

videos/launch/schema.ts
import {defineInputSchema} from "odori";

export const launchInput = defineInputSchema({
  headline: {type: "text", defaultValue: "Author the story.", maxLength: 64, multiline: true},
});

defineInputSchema validates, fills defaults, and describes itself so Studio can generate controls. Any zod-compatible object with a parse() method is accepted instead.

Readiness and integrity

Fonts and images resolve before the first frame is captured, and audio is collected into a track the encoder mixes. Assets declared in odori.config.ts are addressable by reference through useAssets().

Every font, asset, and audio source in the manifest carries a real content hash. Local files hash their bytes; remote files are fetched once and cached by URL under .odori/cache/integrity.json. A source that cannot be read is recorded as unresolved rather than pretending to be verified.

font Geist Sans /fonts/Geist-Variable.woff2 sha256-o2n89WKOoqpOG54uxqWzYk42W9pYjh8PLxK1ZPco+7g=

Cache keys

Prepared data is cached on disk under .odori/cache/prepare/, keyed by video source hash, validated input, and prepare version. Changing scene styling does not refetch source data; changing a data dependency invalidates deterministically. Repeated stills and exports of an approved cut reuse the cached result, and a retry never reruns preparation at all because it replays the frozen manifest.

On this page