Remotion マークアップを特定の方法で記述することで、Remotion Studio はコードの構造を認識し、インタラクティブにすることができます:
- 要素をクリックして選択可能にする
- ドラッグ&ドロップ、リサイズ、回転を可能にする
- CSS スタイルの編集
- キーフレームとイージング値を編集可能にする
マークアップが Studio でインタラクティブにするには複雑すぎる場合、値はグレー表示されます。
独自のタイムラインを持つインタラクティブコンポーネントを推奨
親要素を埋めるコンポーネントには Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'}) を使用します。ラッパーはビジュアルルートとタイムラインアイテムを提供し、デフォルトでオーバーフローをクリップするため、内部コンポーネントはフラグメントを返すことができます。タイミング、プリマウント、寸法、インスタンスごとのスタイルはエクスポートされたコンポーネントに設定します。
同じコンポーネント内で一緒に属するビジュアルを保持することで、それらは一緒に移動およびトリミングされます。内部レイアウトコンテナは、アライメント、小さいエリア内でのクリッピング、またはアニメーショングループを提供できます。シーンを埋めるだけのコンテナは通常不要です。カード、テキストボックス、および独自の境界を持つ SVG は、デフォルトの layout: 'none' を維持し、style をビジュアルルートに転送できます。
import {Video} from '@remotion/media';
import type React from 'react';
import {Interactive, useVideoConfig, type InteractivitySchema} from 'remotion';
type SceneProps = {
readonly title: string;
};
const SceneInner: React.FC<SceneProps> = ({title}) => {
const {fps} = useVideoConfig();
return (
<>
<Video
name="背景映像"
src="https://remotion.media/video.mp4"
premountFor={fps}
objectFit="cover"
style={{width: '100%', height: '100%'}}
/>
<Interactive.Div
name="シーンタイトル"
style={{
position: 'absolute',
left: 80,
bottom: 80,
color: 'white',
fontFamily: 'Helvetica, Arial, sans-serif',
fontSize: 80,
}}
>
{title}
</Interactive.Div>
</>
);
};
const sceneSchema = {
title: {type: 'string', default: '', description: 'タイトル'},
} as const satisfies InteractivitySchema;
export const Scene = Interactive.withSchema({
Component: SceneInner,
componentName: 'Scene',
schema: sceneSchema,
wrapInSequence: true,
layout: 'absolute-fill',
});
スキーマフィールドの選択
スキーマ内の各キーは、Studio が呼び出し箇所で読み取りおよび編集できるプロパティです。
スキーマにないプロパティも機能しますが、Studio では編集できません。
キーはドット記法(style.color など)を使用できます。
| タイプ | 用途 | キーフレーム可能 |
|---|---|---|
string | タイトル、プロンプト、コードスニペットなどの文字列 | いいえ |
number | 数値(オプションで min、max、step、integer) | はい |
boolean | オン/オフスイッチ | はい(ホールド) |
color | CSS カラー文字列 | はい |
enum | variants からの選択(各バリアントは独自のネストスキーマを持つ) | オプトイン(ホールド) |
array | 数値、色、列挙型などのリスト | いいえ |
asset | メディアソース(オプションで assetType) | いいえ |
font-family | CSS フォントファミリー | いいえ |
font-weight | フォントの太さ | はい |
translate、scale、rotation-css、rotation-degrees、transform-origin | トランスフォーム | はい |
uv-coordinate | 要素上の正規化された [x, y] ポイント | はい |
svg-path | SVG パスデータ | はい |
remotion-captions | Caption[] データ | いいえ |
hidden | コントロールから隠される値 | — |
すべてのフィールドには default が必要で、description を持つべきです(Studio はそれをラベルとして表示します)。
keyframable: false を設定すると、静的なコントロールが表示されます。
コンテンツとインスタンスごとの外観(テキストやアクセントカラーなど)を公開します。
style.translate、style.scale、style.rotate、style.transformOrigin、style.opacity のフィールドは追加しないでください:wrapInSequence: true で既に追加されています。
ルートの 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 を追加します。
これにより子コンテンツのコントロールが提供され、将来的にリッチコンテンツをサポートするように進化する可能性があります。
現在は、デフォルト '' の "Text" ラベルが付いた文字列フィールドを使用します。
コンポーネントが文字列のみの子を必要とする場合は、代わりに type: 'string' の明示的な children フィールドを宣言します。
Interactive.textSchema はタイポグラフィスタイルを制御し、childrenSchema はコンテンツを制御します。
children フラグメントは baseSchema に含まれず、カスタムコンポーネントに自動的に追加されません。
ネストされたマークアップと計算された子は現在読み取り専用です。
text-content は string フィールドタイプの非推奨のエイリアスです。
すべてのオプションについては InteractivitySchema を参照してください。
再利用可能なコンポーネントを接続コンポジションとして登録
実質的なシーンや再利用可能なコンポーネントを、独自のレイヤーやアニメーションを持つスタンドアロンのコンポジションとして登録します。Studio はこれらを接続コンポジションと呼びます:親ビデオと同じコンポーネント実装を共有しながら、独自のタイムラインで開くことができます。
コンポーネントが親なしで動作するように、必要なスタイルを定義し、フォントをコンポーネント内でロードします。 親独立性を参照してください。
親がレンダリングするのと同じエクスポートされたコンポーネント参照を登録します。上記の例では、component={Scene} を使用し、SceneInner やインラインラッパーは使用しません。
wrapInSequence: true の場合、接続のために追加の <Sequence> は不要です。
import {Composition} from 'remotion';
import {Scene} from './Scene';
export const RemotionRoot = () => (
<Composition
id="Scene"
component={Scene}
width={1280}
height={720}
fps={30}
durationInFrames={30}
defaultProps={{
title: '新しい視点',
}}
/>
);
一意の ID、代表的なインラインのデフォルト値、およびコンポーネントのプレビューに適した寸法、fps、duration を選択します。登録のデフォルトは、親インスタンスからプロパティを自動的にコピーしません。 登録と抽出の詳細については、接続コンポジションを参照してください。
タイミングを直接コンポーネントに設定
タイミングプロパティを既に受け入れているコンポーネントの周りに別の <Sequence> を配置しないでください。組み込みのインタラクティブコンポーネントや wrapInSequence: true で作成されたカスタムコンポーネントは、name、from、durationInFrames、trimBefore、playbackRate、premountFor を直接受け取ることができます。
<Scene
name="オープニングシーン"
from={30}
durationInFrames={90}
premountFor={fps}
style={{opacity: 0.9}}
title="新しい視点"
/>
冗長なシーケンスを削除する場合は、そのタイミングと名前を子に移動します。既存の子のタイミングを保持します。オフセットを上書きしたり、二重適用したりしないでください。
コンポーネント内の useCurrentFrame() 呼び出しはローカルフレームを読み取りますが、呼び出し箇所でのスタイル式は呼び出し元のフレームを使用します。アニメーションスタイルを移動する際は、その区別を維持します。
複数の兄弟に共有タイミングを提供する場合、タイミングを処理しないコンポーネントをラップする場合、または子が直接受け入れられない寸法を提供する場合は、<Sequence> を維持します。管理ルートは useVideoConfig() 用に width と height も受け入れます。トランジションの有無にかかわらず、連続レイアウトには <TransitionSeries.Sequence> を維持します。直接の from プロパティはこれらの動作を置き換えません。
独立して編集可能な各アイテムに独自の JSX ノードを与える
Studio はアイテムを作成した JSX ソースノードを編集します。複数のランタイムアイテムが同じ JSX ノードから作成された場合、それらは 1 つのソース編集ターゲットを共有します。
各コンポジション登録、クリップ、シーン、レイヤー、またはシーケンスが個別に編集可能である必要がある場合は、別々の JSX ノードを作成し、編集可能なプロパティをそのノードに保持します。これは <Composition>、<Still>、組み込みのメディアコンポーネント、<Sequence>、<TransitionSeries.Sequence>、およびカスタムコンポーネントに適用されます。
たとえば、次のように編集可能なタイムラインを作成します:
import { TransitionSeries } from "@remotion/transitions";
<TransitionSeries>
<TransitionSeries.Sequence name="導入" durationInFrames={90}>
<Introduction />
</TransitionSeries.Sequence>
<TransitionSeries.Sequence name="デモ" durationInFrames={150}>
<Demo />
</TransitionSeries.Sequence>
</TransitionSeries>
.map() やその他のプログラムによるループは、1 つの JSX ソースノードから複数のランタイムアイテムを作成します。これは、可視化バーやパーティクルなど、意図的に 1 つのテンプレートとして制御される繰り返し出力に適しています。インスタンスに独立した ID や名前、プロパティ、メタデータ、タイミング、順序、削除、または Studio での複製が必要な場合には適していません。
Interactive を使用して HTML 要素をインタラクティブにする
すべての HTML および SVG 要素(<Img> を除く。既にインタラクティブです)は、Interactive を使用してインタラクティブにできます:
<Interactive.Div
name="グリーティングカード"
style={{fontSize: 80, padding: 24}}
>
こんにちは
</Interactive.Div>
これにより、Studio でスタイルとキーフレームを設定できます。コンポーネントに多くの要素がある場合、タイムラインが乱雑になる可能性があるため、適切に使用してください。
インラインテキストを推奨
テキストが固定されており、一度だけ使用される場合は、定数に抽出する代わりに、インタラクティブ要素内に直接記述します。
// 👍 固定コピーは編集可能なまま
<Interactive.Div name="タイトル">
Remotion ベストプラクティス
</Interactive.Div>
テキストが動的または再利用される場合にのみ、プロパティまたは変数を使用します。
インタラクティブ要素に説明的な名前を付ける
要素に name プロパティを追加して、識別しやすくします。
計算された名前は避け、ハードコードします。
<>
<Interactive.Div name="ヒーロータイトル" style={{fontSize: 80}}>
発売日
</Interactive.Div>
<Img name="アバター" src="https://remotion.media/image.jpeg" />
<Video name="背景" src="https://remotion.media/video.mp4" />
<Interactive.Div name="タイトル">
発売日
</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="プロダクトカード"
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({d
