remotion-markup

コンテンツ、アニメーション、エフェクトのベストプラクティス

remotion-markup とは?

このスキルは、Remotionを使用したReactマークアップのベストプラクティスを提供します。主にアニメーション駆動のビデオコンポーネントを作成する際に、`useCurrentFrame()`と`interpolate()`を使用したCSSプロパティのインラインキーフレーム定義方法、`Interactive.withSchema()`を用いたインタラクティブコンポーネントの設計、そして`premountFor`プロパティによるタイミング制御に焦点を当てています。また、CSSの`transition`や`animation`の代わりにRemotionのタイミング関数を使用する必要がある点、Mediaコンポーネント(Video, Audio, CanvasImage, AnimatedImage)の正しい使用方法、シーン間のトランジションやマルチシーンビデオの構造化方法についても説明しています。このスキールは主にClaude CodeやCursorなどのコード生成AIエージェント向けに設計されており、ユーザーが編集可能な対応コンポジションをルートに登録する方法や、ビジュアルエフェクト(`effects`プロパティ)の適用可能なコンポーネント一覧も含まれています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/remotion-dev/skills/tree/main/skills/remotion-markup

Installed? Explore more ビデオ&アニメーション skills: steipete/video-frames, steipete/summarize, openclaw/openclaw · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

プレビュー

スキル README より

ドキュメント

これはRemotionのReactマークアップを記述するためのガイダンスです。 該当しない場合は、代わりにRemotionのベストプラクティスを読み込んでください。

ユーザーによる変更の保持

ユーザーは会話以外の場所でコードを編集することがあります。 その間に予期しない変更を検出した場合は、上書きせず、意図的なものとみなすか、確認を求めてください。

一般ルール

コンポジションまたはシーンコンポーネント内では、useVideoConfig()からfpsを取得し、すべての秒数からフレームへの計算(from、trimBefore、durationInFrames、premountForなどのタイミングプロパティを含む)に使用してください。trimBefore={4 * fps}のように式をJSXノード上に保持することで、Studioがタイミングを編集でき、コンポジションのフレームレートが変更されても正しく動作します。

アニメーションの駆動にはuseCurrentFrame()とinterpolate()を使用してください。 CSSのtransitionやanimationは正しくレンダリングされないため、リファクタリングが必要です。 Tailwindアニメーションクラスも正しくレンダリングされないため、リファクタリングが必要です。

タイミングのカスタマイズにはEasing.bezier()とEasing.spring()を使用してください。

マークアップはRemotionインタラクティビティのベストプラクティスに従って構造化してください。 編集可能なプロパティを持つシーンには、Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'})を使用することを推奨します。それらの内部マークアップはフラグメントを返すことができ、ラッパーがレイアウトとインスタンスのスタイルを処理します。ローワーサードなどのサイズ指定要素はデフォルトレイアウトを維持し、styleを自身のルートに転送できます。再利用可能なシーンは対応コンポジションとして登録してください。 タイミングはそれをサポートするコンポーネントに直接配置し、冗長な<Sequence>ラッパーは避けてください。 premountForをサポートするすべてのタイミング付きコンポーネントには、1秒のプリマウントを設定してください:premountFor={fps}(fpsはuseVideoConfig()から取得)。これをメディア、インタラクティブコンポーネント、<Sequence>、<TransitionSeries.Sequence>、<TransitionSeries.Overlay>、およびシーン内にネストされたタイミング付きコンポーネントに適用してください。ネストされたアイテムが親より前にマウントする必要がある場合は、親のタイムラインアイテムもプリマウントしてください。<TransitionSeries.Transition>のようにpremountForがないコンポーネントは代替の必要はありません。

Studioはアイテムを作成したJSXソースノードを編集します。個別に編集可能な各コンポジション登録、クリップ、シーン、レイヤー、シーケンスは、独自のJSXノードとして、編集可能なプロパティをインラインで記述してください。 生成されたインスタンスを意図的に1つのソーステンプレートとして制御する場合はプログラムループが適していますが、ユーザーが個別にインスタンスを編集する必要がある場合は適していません。

import { useCurrentFrame, useVideoConfig, Easing, interpolate, Interactive } from "remotion";

export const FadeIn = () => {
  const frame = useCurrentFrame();
  const {fps} = useVideoConfig();

  return (
    <Interactive.Div
      name="Title"
      premountFor={fps}
      style={{
        opacity: interpolate(frame, [0, 2 * fps], [0, 1], {
          extrapolateRight: "clamp",
          extrapolateLeft: "clamp",
          easing: Easing.bezier(0.16, 1, 0.3, 1),
        }),
      }}
    >
      Hello World!
    </Interactive.Div>
  );
};

interpolate()の呼び出しはstyleプロパティ内にインラインで記述してください。 transformの代わりにscale、translate、rotateのCSSプロパティを使用してください。

// 👍 インライン編集可能なキーフレームとtransformのショートハンド
style={{
  scale: interpolate(frame, [0, 100], [0, 1], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
    output: 'perceptual-scale' // `scale`アニメーションの場合は"output: 'perceptual-scale'"を使用
  }),
  translate: interpolate(frame, [0, 100], ["0px 0px", "100px 100px"], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
  }),
  rotate: interpolate(frame, [0, 100], ["20deg", "90deg"], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
  }),
}}

// 👎 インラインでない値とtransform文字列はStudioでの編集が困難になります
const scale = interpolate(frame, [0, 100], [0, 1]);

style={{
  transform: `scale(${scale})`,
}}

アセット

アセットはプロジェクトルートのpublic/フォルダに配置してください。 public/フォルダ内のファイルを参照するにはstaticFile()を使用してください。

メディアコンポーネント

ビデオとオーディオは@remotion/mediaから<Video>と<Audio>を使用して追加してください。 画像は<CanvasImage>コンポーネントを使用して追加してください。 アニメーションGIF、APNG、WebP、AVIF画像は<AnimatedImage>を使用し、Chrome以外の場合は@remotion/gifを使用してください。 public/内のファイルにはstaticFile()を使用し、リモートURLを直接渡すこともできます:

import { Audio, Video } from "@remotion/media";
import { staticFile, CanvasImage, AnimatedImage, useVideoConfig } from "remotion";

export const MyComposition = () => {
  const {fps} = useVideoConfig();

  return (
    <>
      <Video src={staticFile("video.mp4")} premountFor={fps} style={{ opacity: 0.5 }} />
      <Audio src={staticFile("audio.mp3")} premountFor={fps} />
      <CanvasImage
        src={staticFile("logo.png")}
        premountFor={fps}
        style={{ width: 100, height: 100 }}
      />
      <Video src="https://remotion.media/video.mp4" premountFor={fps} />
      <AnimatedImage src={staticFile('nyancat.gif')} premountFor={fps} />
    </>
  );
};

コンポジションが主にビデオまたはオーディオクリップのタイムラインである場合は、ソース構造を選択する前にvideo-editing.mdを読んでください。

シーンの例

背景ビデオとローワーサード。 ローワーサードは独自のタイムラインを持つインタラクティブコンポーネントで、対応コンポジションとして登録されています。 そのテキストはchildrenとして渡され、accentColorは編集可能なプロパティです。 フェードインは呼び出し箇所でインラインにキーフレーム設定されています。

// MyScene.tsx
import { Video } from "@remotion/media";
import { Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
import { LowerThird } from "./LowerThird";

export const MyScene = () => {
  const { fps } = useVideoConfig();
  const frame = useCurrentFrame();

  return (
    <>
      <Video
        name="Background"
        src="https://remotion.media/video.mp4"
        premountFor={fps}
        objectFit="cover"
        style={{
          position: "absolute",
          width: "100%",
          height: "100%",
        }}
      />
      <LowerThird
        name="Lower third"
        from={1 * fps}
        premountFor={fps}
        accentColor="#0b84f3"
        style={{
          opacity: interpolate(frame, [1 * fps, 2 * fps], [0, 1], {
            extrapolateRight: "clamp",
            extrapolateLeft: "clamp",
            easing: Easing.bezier(0.16, 1, 0.3, 1),
          }),
        }}
      >
        Jane Doe, Product Designer
      </LowerThird>
    </>
  );
};
// LowerThird.tsx
import type React from "react";
import { Interactive, type InteractivitySchema } from "remotion";

type LowerThirdProps = {
  readonly children: React.ReactNode;
  readonly accentColor: string;
  readonly style?: React.CSSProperties;
};

const LowerThirdInner: React.FC<LowerThirdProps> = ({
  children,
  accentColor,
  style,
}) => {
  return (
    <Interactive.Div
      style={{
        position: "absolute",
        left: 80,
        bottom: 80,
        display: "flex",
        alignItems: "center",
        gap: 20,
        backgroundColor: "white",
        borderRadius: 16,
        padding: "20px 32px",
        color: "black",
        fontFamily: "Helvetica, Arial, sans-serif",
        fontSize: 48,
        fontWeight: 600,
        ...style,
      }}
    >
      <div
        style={{
          width: 8,
          alignSelf: "stretch",
          borderRadius: 4,
          backgroundColor: accentColor,
        }}
      />
      {children}
    </Interactive.Div>
  );
};

const lowerThirdSchema = {
  ...Interactive.childrenSchema,
  accentColor: {
    type: "color",
    default: "#0b84f3",
    description: "アクセントカラー",
  },
} as const satisfies InteractivitySchema;

export const LowerThird = Interactive.withSchema({
  Component: LowerThirdInner,
  componentName: "LowerThird",
  schema: lowerThirdSchema,
  wrapInSequence: true,
});
import { Composition } from "remotion";
import { LowerThird } from "./LowerThird";
import { MyScene } from "./MyScene";

export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="MyScene"
        component={MyScene}
        durationInFrames={60}
        fps={30}
        width={1280}
        height={720}
      />
      <Composition
        id="LowerThird"
        component={LowerThird}
        durationInFrames={30}
        fps={30}
        width={1280}
        height={720}
        defaultProps={{
          children: "Jane Doe, Product Designer",
          accentColor: "#0b84f3",
        }}
      />
    </>
  );
};

遅延、トリミング

タイミングはそれをサポートするコンポーネントに直接配置してください。サポートされるプロパティ、例、実行順序についてはTiming propsを参照してください。

マップ

ビデオにマップを含めたい場合はRemotion Mapsを参照してください。

テキストハイライトと注釈

テキストハイライト(ハイライトマーカー)、円、下線、取り消し線、取り消しテキスト、ボックスについてはtext-highlights.mdを参照してください。

マルチシーンビデオ

複数の連続するシーンを含むビデオを作成する場合はmulti-scene-video.mdを参照してください。

対応コンポジション

シーンまたはレイヤーグループが独自の編集可能なタイムラインを持つべき場合、connected-compositions.mdに従ってください。マルチシーンビデオ内の重要なシーンにはこの構造を推奨します。

プリコンポーズアクション

Pre-compose Ambient glow (src/BarChart.tsx:134)のようなStudioリクエストに対しては、指定された場所にある選択されたシーケンスマークアップを見つけてください。connected-compositions.mdに従って対応コンポジションを作成します。マークアップを名前付きコンポーネントに抽出し、できればInteractive.withSchema({wrapInSequence: true})でインタラクティブにし、同じエクスポートされたコンポーネント参照をルート内の一意の<Composition>で登録します。インタラクティブコンポーネントをタイミングプロパティとともに直接レンダリングするか、ラッパーに目的がある場合に限りシーケンスの唯一の子としてレンダリングします。選択されたノードがすでにシーケンスの場合は、そのプロパティを保持し、子を抽出します。登録には、親の使用と同等の寸法、fps、duration、defaultPropsが必要です。登録されたコンポジションがないコンポーネント抽出はプリコンポーズリクエストを完了しません。

fontFamilyやフォント読み込みなどの継承されたスタイルは抽出されたコンポーネントに引き継いでください。親からの独立性を参照してください。

ナレーション

ElevenLabs TTSを使用してRemotionコンポジションにAI生成ナレーションを追加するにはvoiceover.mdを参照してください。

ビデオの埋め込み

ビデオの埋め込みに関する高度な知識(トリミング、音量、速度、ループ、ピッチ)についてはembedding-videos.mdを参照してください。

オーディオの埋め込み

トリミング、音量、速度、ピッチなどの高度なオーディオ機能についてはaudio.mdを参照してください。

クロッピング

コンポーネントの可視領域をクロップする必要がある場合はcropping.mdを参照してください。

トランジション

シーントランジションパターンについてはtransitions.mdを参照してください。

モーションブラー

モーションブラーや動きの軌跡を追加する場合は、推奨されるHTML-in-canvasアプローチ、プレビュー要件、代替案についてmotion-blur.mdを読んでください。

ビジュアルエフェクトとピクセルエフェクト

ビジュアルエフェクトを追加する場合、まず影響を与える要素またはグループを特定してください。 対象のコンポーネントがeffectsをサポートしており、以下の組み込みエフェクトがリクエストに一致する場合は、CSSでの近似よりもそのエフェクトを優先してください。例えば、ビネットを特定のビデオに適用する場合は、<Video>のeffectsプロパティに直接vignette()を適用してください。

以下のコンポーネントはeffectsを直接受け入れます:

インポート元コンポーネント
remotion<Img>, <CanvasImage>, <AnimatedImage>, <Solid>, <HtmlInCanvas>
@remotion/media<Video>
@remotion/gif<Gif>
@remotion/rive<RemotionRiveCanvas>
@remotion/shapes<Arrow>, <Callout>, <Circle>, <Ellipse>, <Heart>, <Pie>, <Polygon>, <Rect>, <Spark>, <Star>, <Triangle>

通常のHTML要素、<Interactive.*> DOMラッパー、<AbsoluteFill>、<Sequence>はeffectsを直接受け入れません。それらのコンテンツにエフェクトを適用するには、<HtmlInCanvas>でラップし、ラッパーにeffectsプロパティを設定してください。

その他の要素には、適切な場合は通常のHTMLとCSSを優先してください。グループ全体を後処理することが適切で環境がサポートしている場合は、グループを<HtmlInCanvas>でラップすることを検討してください。

エフェクトを適用する前に、インポート、パラメータ、設定についてeffects.mdを読んでください。組み込みエフェクトが一致しない場合にcreateEffect()を使用した再利用可能なカスタムエフェクトについても説明しています。

利用可能なエフェクト

@remotion/effectsからの組み込みエフェクト:

  • カラーとトーン:brightness(), colorCorrection(), colorKey(), contrast(), duotone(), exposure(), grayscale(), hue(), invert(), levels(), linearGradient(), linearGradientTint(), lut(), saturation(), shadowsHighlights(), thermalVision(), tint(), vibrance(), whiteBalance().
  • ブラーと軌跡:blur(), lightTrail(), linearProgressiveBlur(), radialProgressiveBlur(), regionBlur...

[truncated for translation]

Individual skills in this repo

This repo contains 19 individual skills — each has its own dedicated page.

関連スキル