Communitygithub.com

jeffersonmendo/remotion-tryslides

インタラクティブな編集を可能にする特定の方法でRemotionマークアップを構造化します。

remotion-tryslides とは?

このスキルは、開発者がRemotion Studioでインタラクティブに編集可能なビデオコンポジションを作成するためのベストプラクティスを提供します。`Interactive.create()`、`Track`、および接続されたコンポジションを使用して、クリックによる選択、ドラッグ&ドロップ、サイズ変更、回転、CSSスタイル編集、キーフレーム編集を可能にする方法を詳しく説明しています。また、スキーマフィールドの選択、CSSプロパティのインライン記述、`interpolate()`を使用したアニメーション、および各編集可能なアイテムに個別のJSXノードを使用する重要性についてのガイドラインも含まれています。対応プラットフォームはRemotion Studioで、Claude Code、Cursor、CodexなどのAIエージェントと組み合わせて使用することで、Remotionプロジェクトの開発効率を向上させることができます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/jeffersonmendo/remotion-tryslides/tree/HEAD/.agents/skills/remotion-interactivity

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

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

プレビュー

スキル README より

remotion-tryslides preview

ドキュメント

Remotionマークアップを特定の方法で記述することで、Remotion Studioがコードの構造を認識し、インタラクティブに操作できるようになります。

  • アイテムをクリックして選択可能
  • ドラッグ&ドロップ、リサイズ、回転を可能にする
  • CSSスタイルの編集
  • キーフレームとイージング値の編集

マークアップが複雑すぎてStudioがインタラクティブにできない場合、値はグレーアウトされます。

独自のタイムラインを持つインタラクティブコンポーネントを優先する

Track、接続されたコンポジション、およびInteractive.create()を使用して新しいコンポジションを構築します。

シーンにはlayoutを明示的に'absolute-fill'に設定し、境界付き要素には'none'に設定します。同じエクスポートされたシーンと再利用可能な要素コンポーネントをCompositionに登録します。

完全なTrack + 接続されたコンポジションの例から始めてください。 要素、シーン、親タイムライン、およびルート登録が含まれています。

import {Track, useVideoConfig} from 'remotion';
import {Chapter} from './Chapter';

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

  return (
    <Track name="Chapters">
      <Chapter
        name="Opening"
        durationInFrames={3 * fps}
        title="Introduction"
      />
      <Chapter
        name="Feature"
        from={3 * fps}
        durationInFrames={4 * fps}
        title="New features"
      />
    </Track>
  );
};

背景と配置スタイルは、完全な例に示すように各シーンインスタンスに配置します。レイアウトのみのコンテナはプレーンなHTMLとして保持します。

スキーマフィールドの選択

スキーマの各キーは、Studioが呼び出し元で読み取りおよび編集できるプロパティです。スキーマにないプロパティも機能しますが、Studioでは編集できません。キーはドット記法(例:style.color)を使用できます。

タイプ用途キーフレーム化可能
stringタイトル、プロンプト、コードスニペットなどの文字列いいえ
number数値。オプションでmin、max、step、integerはい
booleanオン/オフスイッチはい (ホールド)
colorCSSカラー文字列はい
enumvariants間の選択。各バリアントは独自のネストされたスキーマを持つオプトイン (ホールド)
array数値、色、列挙型などのリストいいえ
assetメディアソース。オプションでassetTypeいいえ
font-familyCSSフォントファミリーいいえ
font-weightフォントの太さはい
translate、scale、rotation-css、rotation-degrees、transform-originトランスフォームはい
uv-coordinate要素上の正規化された[x, y]ポイントはい
svg-pathSVGパスデータはい
remotion-captionsCaption[]データいいえ
hiddenコントロールから除外される値—

すべてのフィールドにはdefaultが必要で、ラベルとしてStudioに表示されるdescriptionが必要です。keyframable: falseを設定して、静的なコントロールを表示します。

テキストとアクセントカラーなど、コンテンツとインスタンスごとの外観を公開します。 style.translate、style.scale、style.rotate、style.transformOrigin、style.opacityのフィールドを追加しないでください。Interactive.create()が自動的にそれらを追加します。

ルートのCSSプロパティをインスタンスごとに編集可能にするには、組み込みのスキーマフラグメントをスプレッドします。

const cardSchema = {
  ...Interactive.textSchema, // style.color、style.fontSize、style.fontWeight、...
  ...Interactive.backgroundSchema, // style.backgroundColor
  ...Interactive.borderRadiusSchema, // style.borderRadius、...
} as const satisfies InteractivitySchema;

Interactive.borderSchema、およびキャプションを受け入れるコンポーネント用のInteractive.captionsSchemaも利用できます。 React.ReactNodeの子を受け入れるコンポーネントの場合は、...Interactive.childrenSchemaを追加します。 子コンテンツのコントロールを提供し、将来的にはよりリッチなコンテンツをサポートするように進化する可能性があります。 現在は、デフォルトが''の「テキスト」というラベルの文字列フィールドを使用します。 コンポーネントが文字列専用の子を必要とする場合は、代わりにtype: 'string'で明示的なchildrenフィールドを宣言します。 Interactive.textSchemaはタイポグラフィスタイルを制御し、childrenSchemaはコンテンツを制御します。 childrenフラグメントはbaseSchemaには含まれず、カスタムコンポーネントに自動的に追加されることもありません。 ネストされたマークアップと計算された子は現在読み取り専用です。 text-contentはstringフィールドタイプの非推奨のエイリアスです。 すべてのオプションについては、InteractivitySchemaを参照してください。

再利用可能なコンポーネントを接続されたコンポジションとして登録する

シーンと再利用可能な要素をスタンドアロンのコンポジションとして登録します。Studioはこれらを接続されたコンポジションと呼びます。これらは、親ビデオと同じコンポーネント実装を共有しながら、独自のタイムラインで開くことができます。

コンポーネントが親なしでも機能するように、必要なスタイルを定義し、コンポーネント内にフォントをロードします。 親からの独立性を参照してください。

親がレンダリングするのと同じエクスポートされたコンポーネント参照を登録します。上記の例では、ChapterInnerやインラインラッパーではなく、component={Chapter}を使用します。 Interactive.create()がシーケンスを提供するため、接続のために追加の<Sequence>は必要ありません。

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

export const RemotionRoot = () => (
  <Composition
    id="Chapter"
    component={Chapter}
    width={1280}
    height={720}
    fps={30}
    durationInFrames={90}
    defaultProps={{
      title: 'A new perspective',
      style: {
        backgroundColor: '#111111',
        justifyContent: 'center',
        alignItems: 'center',
      },
    }}
  />
);

ユニークなID、代表的なインラインデフォルト値、およびコンポーネントのプレビューに適した寸法、fps、durationを選択します。登録のデフォルト値は、親インスタンスから自動的にプロパティをコピーしません。登録と抽出の詳細については、接続されたコンポジションを参照してください。

タイミングを直接コンポーネントに配置する

タイミングプロパティをすでに受け入れているコンポーネントの周りに別の<Sequence>を配置しないでください。組み込みのインタラクティブコンポーネントとInteractive.create()で作成されたカスタムコンポーネントは、name、from、durationInFrames、trimBefore、playbackRateを直接受け取ることができます。

<Chapter
  name="Opening scene"
  from={30}
  durationInFrames={90}
  style={{opacity: 0.9}}
  title="A new perspective"
/>

共有シーンタイミングの場合は、Interactive.create()で作成されたコンポーネントにコンテンツをグループ化し、そのインスタンスにタイミングを設定します。管理されたルートは、useVideoConfig()のwidthとheightも受け入れます。

<Track>を使用して、アイテムを同じStudioタイムライン行に配置します。 <TransitionSeries>は、シーンが順次配置されている場合に使用します。

個別に編集可能な各アイテムに独自のJSXノードを与える

Studioは、アイテムを作成したJSXソースノードを編集します。複数のランタイムアイテムが同じJSXノードから作成された場合、それらは単一のソース編集ターゲットを共有します。

個別に編集可能にする必要がある各コンポジション登録、クリップ、シーン、レイヤー、またはシーケンスについて、個別のJSXノードを作成し、そのノードに編集可能なプロパティを保持します。これは、<Composition>、<Still>、組み込みのメディアコンポーネント、<Sequence>、<TransitionSeries.Sequence>、およびカスタムコンポーネントに適用されます。

たとえば、次のように編集可能なタイムラインを作成します。

import { Track } from "remotion";

<Track name="Scenes">
  <Introduction name="Introduction" durationInFrames={90} />
  <Demo name="Demo" from={90} durationInFrames={150} />
</Track>

.map()またはその他のプログラムループは、1つのJSXソースノードから複数のランタイムアイテムを作成します。これは、視覚化バーやパーティクルなど、1つのテンプレートとして意図的に制御される繰り返し出力に適しています。Studioでインスタンスに独立したIDや名前、プロパティ、メタデータ、タイミング、順序、削除、複製が必要な場合は適していません。

Interactiveを使用してHTML要素をインタラクティブにする

<Img>(すでにインタラクティブ)を除くすべてのHTMLおよびSVG要素(<div>など)は、Interactiveを使用してインタラクティブにできます。

<Interactive.Div
  name="Greeting card"
  style={{fontSize: 80, padding: 24}}
>
  Hello
</Interactive.Div>

これにより、Studioでスタイルとキーフレームを設定できます。賢明に使用してください。コンポーネントに多くの要素がある場合、タイムラインが乱雑になる可能性があります。

インラインテキストを優先する

テキストが固定されており、1回だけ使用される場合は、定数に抽出する代わりに、インタラクティブ要素内に直接記述します。

// 👍 固定コピーは編集可能のまま
<Interactive.Div name="Title">
  Remotion Best Practices
</Interactive.Div>

テキストが動的であるか再利用される場合にのみ、プロパティまたは変数を使用します。

インタラクティブ要素に説明的な名前を付ける

要素にnameプロパティを追加して、簡単に識別できるようにします。 計算された名前は避け、ハードコードします。

<>
  <Interactive.Div name="Hero title" style={{fontSize: 80}}>
    Launch day
  </Interactive.Div>
  <Img name="Avatar" src="https://remotion.media/image.jpeg" />
  <Video name="Background" src="https://remotion.media/video.mp4" />
  <Interactive.Div name="Title">
    Launch day
  </Interactive.Div>
</>

すべてのCSSスタイルをインラインに保つ

最善の方法は、プレーンなオブジェクトをstyleに渡すことです。定数を参照したり、オブジェクトをスプレッドしたり、計算をしたりしないでください。

<Interactive.Div
  style={{
    fontSize: 80,
    color: 'red',
  }}
>
  Hello World!
</Interactive.Div>
const baseStyle = useMemo(() => {
  return {
    fontSize: 12 // ❌ インラインでないスタイルはサポートされていません
  }
}, []);

<Interactive.Div
  style={{
    ...baseStyle, // ❌ スプレッドはサポートされていません
    color: RED, // ❌ 定数の参照はサポートされていません
    scale: frame * 10 // ❌ 計算はサポートされていません
  }}
>
  Hello World!
</Interactive.Div>

interpolate()を使用してアニメーション化する

アニメーションは、変更するプロパティに対してインラインのinterpolate()呼び出しとして記述します。 出力範囲、イージング、外挿、およびoutputプロパティは、ハードコードされた値を使用する必要があります。

入力範囲は、useVideoConfig()から直接分割代入されたdurationInFrames、fps、width、heightを追加で使用できます。durationInFramesのような単純な識別子、2 * fpsやfps * 2のような数値との乗算、およびdurationInFrames - 1のような数値の減算がサポートされています。

const {fps, durationInFrames} = useVideoConfig();

// 👍 インライン値は標準化およびキーフレーム化可能
<Interactive.Div
  name="Product card"
  style={{
    color: 'white',
    fontSize: 80,
    scale: interpolate(frame, [0, fps], [0, 1], {
      easing: Easing.spring({damping: 200}),
      output: 'perceptual-scale',
      extrapolateLeft: 'clamp',
      extrapolateRight: 'clamp'
    }),
    rotate: interpolate(frame, [0, 1 * fps], ['0deg', '20deg'], {
      easing: Easing.spring({damping: 200}),
      extrapolateLeft: 'clamp',
      extrapolateRight: 'clamp'
    }),
    translate: interpolate(
      frame,
      [durationInFrames - 30, durationInFrames],
      ['0px 0px', '0px 120px'],
      {
        easing: Easing.spring({damping: 200}),
        output: 'perceptual-scale',
        extrapolateLeft: 'clamp',
        extrapolateRight: 'clamp'
      }
    ),
  }}
/>
const translateY = interpolate(frame, [0, 30], [0, 120]); // ❌ 計算は直接マークアップ内にあるべき

<Interactive.Div
  name="Product card"
  style={{
    translate: translateY, // ❌ インラインのinterpolate()呼び出しのみサポート
    rotate: interpolate(frame, [start, start + 10], [0, Math.PI]), // ❌ 任意の変数を使用した計算は不可、定数は使用不可
    scale: interpolate(anyVariable, [0, 30], [0, 1]) // ❌ `frame`変数のみ解釈可能
  }}
/>

Interactive.PathでSVGパスを編集可能に保つ

SVG内の<path>の代わりにremotionの<Interactive.Path>を使用して、パスを視覚的に編集可能にします。

パス補間とStudioパスキーフレームのために@remotion/pathsをインストールします。

bunx remotion add @remotion/paths

ジオメトリが静的であることを意図している場合は、パス文字列を直接dプロパティに配置します。定数に抽出しないでください。

import {Interactive} from 'remotion';

<Interactive.Svg width={300} height={300} viewBox="0 0 300 300">
  <Interactive.Path
    name="Triangle"
    d="M 40 40 L 260 40 L 150 260 Z"
    fill="#0b84f3"
  />
</Interactive.Svg>

インラインを使用してパスをモーフィングする

…

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

関連スキル