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 | オン/オフスイッチ | はい (ホールド) |
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が必要で、ラベルとして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>
インラインを使用してパスをモーフィングする
…
