Files
claude-skills/remotion/rules/compositions.md
2026-01-30 03:04:10 +00:00

3.6 KiB

name, description, metadata
name description metadata
compositions Defining compositions, stills, folders, default props and dynamic metadata
tags
composition, still, folder, props, metadata

A <Composition> defines the component, width, height, fps and duration of a renderable video.

It normally is placed in the src/Root.tsx file.

import {Composition} from 'remotion';
import {MyComposition} from './MyComposition';

export const RemotionRoot = () => {
  return <Composition id="MyComposition" component={MyComposition} durationInFrames={100} fps={30} width={1080} height={1080} />;
};

Default Props

Pass defaultProps to provide initial values for your component.
Values must be JSON-serializable (Date, Map, Set, and staticFile() are supported).

import {Composition} from 'remotion';
import {MyComposition, MyCompositionProps} from './MyComposition';

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyComposition"
      component={MyComposition}
      durationInFrames={100}
      fps={30}
      width={1080}
      height={1080}
      defaultProps={
        {
          title: 'Hello World',
          color: '#ff0000',
        } satisfies MyCompositionProps
      }
    />
  );
};

Use type declarations for props rather than interface to ensure defaultProps type safety.

Folders

Use <Folder> to organize compositions in the sidebar.
Folder names can only contain letters, numbers, and hyphens.

import {Composition, Folder} from 'remotion';

export const RemotionRoot = () => {
  return (
    <>
      <Folder name="Marketing">
        <Composition id="Promo" /* ... */ />
        <Composition id="Ad" /* ... */ />
      </Folder>
      <Folder name="Social">
        <Folder name="Instagram">
          <Composition id="Story" /* ... */ />
          <Composition id="Reel" /* ... */ />
        </Folder>
      </Folder>
    </>
  );
};

Stills

Use <Still> for single-frame images. It does not require durationInFrames or fps.

import {Still} from 'remotion';
import {Thumbnail} from './Thumbnail';

export const RemotionRoot = () => {
  return <Still id="Thumbnail" component={Thumbnail} width={1280} height={720} />;
};

Calculate Metadata

Use calculateMetadata to make dimensions, duration, or props dynamic based on data.

import {Composition, CalculateMetadataFunction} from 'remotion';
import {MyComposition, MyCompositionProps} from './MyComposition';

const calculateMetadata: CalculateMetadataFunction<MyCompositionProps> = async ({props, abortSignal}) => {
  const data = await fetch(`https://api.example.com/video/${props.videoId}`, {
    signal: abortSignal,
  }).then((res) => res.json());

  return {
    durationInFrames: Math.ceil(data.duration * 30),
    props: {
      ...props,
      videoUrl: data.url,
    },
  };
};

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyComposition"
      component={MyComposition}
      durationInFrames={100} // Placeholder, will be overridden
      fps={30}
      width={1080}
      height={1080}
      defaultProps={{videoId: 'abc123'}}
      calculateMetadata={calculateMetadata}
    />
  );
};

The function can return props, durationInFrames, width, height, fps, and codec-related defaults. It runs once before rendering begins.

Nesting compositions within another

To add a composition within another composition, you can use the <Sequence> component with a width and height prop to specify the size of the composition.

<AbsoluteFill>
  <Sequence width={COMPOSITION_WIDTH} height={COMPOSITION_HEIGHT}>
    <CompositionComponent />
  </Sequence>
</AbsoluteFill>