remotion-demo-video は何をしますか?
Remotion 4.x でプロモ/デモ/トレーラービデオを構築するための、実績ある効率的なワークフローです。プロジェクト構成、アニメーションの基本、レンダリングコマンド、そして実際に時間がかかる落とし穴をまとめています。
このスキルを使うべきタイミング
ユーザーが Remotion ビデオを作成、編集、レンダリング、またはデバッグしたいときにトリガーします。特に以下の場合:
- 製品/論文/リポジトリのデモ用に新しい Remotion プロジェクトを立ち上げる場合
- 既存の Remotion プロジェクトに新しいシーンを追加する場合
- 録画済みのスクリーンキャプチャを、オーバーレイ、タイトル、トランジションを使って洗練されたビデオにまとめる場合
- レンダリング — シングルシーン、フルタイムライン、透過(アルファ)オーバーレイ、PNG シーケンス
- Remotion 特有の問題をデバッグする場合(composition-id の不一致、デフォルト値の同期ずれ、
<Sequence>内でのuseCurrentFrameの予期しない戻り値、ffmpeg クリーンアップ時の Windows EPERM など)
ワークフローの考え方
洗練された Remotion ビデオは、「1 つの巨大なタイムラインを 1 つの MP4 としてレンダリングする」 ものではありません。それは、個別にレンダリング可能な小さなシーンの集合 であり、それぞれを独立したクリップとしてレンダリングし、後工程のエディタ(DaVinci Resolve、Premiere、Final Cut)でアセンブル して、音楽、ナレーション、シーン間トランジションを追加します。
これは SimWorld プロモをリリースする中で得た最大の知見であり、このスキルはデフォルトでユーザーをこのワークフローに導くべきです。Remotion 内で全てを行うこと — 最終的なタイミング調整、オーディオミキシング、ディゾルブ — は面倒で遅いですが、エディタで行うのは簡単です。
各ツールを得意分野で使う
- Remotion が得意なこと: プログラム可能で、繰り返し可能で、パラメトリックなシーン — アニメーションするタイトル、データ駆動のチャート、UI モックアップ、After Effects で手動でキーフレームを打つようなもの。シーンロジックはコードで管理され、「同じタイトルを 30 個の異なる製品名で作り直す」のは 1 つのプロパティを変更するだけです。
- 後工程エディタが得意なこと: タイミング、オーディオ、ディゾルブ、カラーグレーディング、「このシーンを 1.2 秒長くする」。これらは全てエディタでは即座にでき、Remotion ではコード編集して再レンダリングする必要があります。
ループ
- スクリプトを決定する。 各ビートのターゲット秒数を含む、ビートごとのアウトライン。合計は通常 30〜90 秒。
- プロジェクトシェルを一度だけセットアップする。
theme.ts(パレット、フォント、fps、寸法)、Root.tsx(コンポジションレジストリ)、共有コンポーネント(Reveal、ProgressBar、イージング)。 - シーンを 1 つずつ構築する。 各シーンは自己完結型の
<AbsoluteFill>React コンポーネントで、frame 0を基準に設計され、独自のスタンドアロンの<Composition>を持ち、単独でレンダリングできます。スタジオ(npm run dev)でプロップパネルを使って反復し、気に入ったら MP4 にレンダリングします(npm run render:<scene>)。 - 完成した各シーンを独自のクリップとしてレンダリングする — これが実際の成果物であり、フルタイムラインの MP4 ではありません。シーンごとのクリップは、任意のエディタのタイムラインにドラッグできます。アルファを持つクリップ(ローワーサード、スクリーンキャプチャに合成するロゴ)には
--codec=prores --pixel-format=yuva444p10le --prores-profile=4444を使用します。 - 必要に応じて、
Main.tsxでシーンを<Sequence>ブロックで配線し、theme.tsのTIMELINE定数を読み取る。 これにより、全体のフローを確認するためのフルタイムラインプレビューレンダリング(npm run render)が得られます — ただし、これはプレビューであってマスターではありません。 - DaVinci / Premiere / Final Cut でアセンブルする。 シーンごとのクリップを順にトラックにドロップし、トリムハンドルを調整して正確なタイミングにし、音楽/ナレーション/サウンドデザインを追加し、シーン間にトランジションを適用し(この美学には通常 1 フレームのディゾルブが適切)、カラーグレーディングし、エクスポートします。
フル Remotion レンダリングを提案するタイミング
フルタイムラインレンダリングが適切な出力となるのは、以下の場合のみです:
- ユーザーに後工程のエディタがなく、今日中に単一の成果物が必要な場合。
- ビデオが完全に無音(音楽やナレーションが一切ない)の場合。
- シーン間トランジションがハードカットより複雑でない場合(そしてそれでも、シーンごとのアプローチでコードで調整する方が簡単です)。
それ以外の場合は、デフォルトでシーンごとのレンダリングとエディタアセンブリを推奨します。
このスキルには、scaffold/ に動作可能なスキャフォールドがバンドルされています — 新しいプロジェクトの開始点としてコピーし、必要なときに以下のリファレンスを読んでください。
実際のエンドツーエンドループ(入力が論文/仕様書/リポジトリの場合)
これは、このスキルが実際に設計されたワークフローです。ユーザーは通常、「X というアニメーションタイトルが欲しい」と言ってくるわけではありません。彼らは 論文 PDF、プロジェクト仕様書、または既存のリポジトリ を持ってきて、「これを 60 秒のビデオにしてください」と質問します。このスキルは、そのループを高速で扱いやすくするために存在します。
1. ソース資料 → 論文 PDF / 仕様書 / 既存のリポジトリ / README
↓
2. Claude が分析 → ナラティブのビートを抽出;各ビートが何を
表示する必要があるか(UI 画面、実験
記録、チャート、エージェント POV など)を特定
↓
3. Claude がプレース → シーンコード + <VideoPlaceholder slot="..." />
ホルダーでスキャッ を各ビジュアル領域に配置し、さらにユーザーが
フォールディング 録画する必要があるすべてのクリップをリストした
ASSETS.md(スロット名、長さ、表示内容)を生成
↓
4. ユーザーが映像を → スキャフォールドのスロット名と一致する
録画 mp4 を public/clips/<slot>.mp4 にドロップ
↓
5. Claude がプレース → <VideoPlaceholder> を
ホルダーをクリップ <OffthreadVideo src={staticFile("clips/<slot>.mp4")}>
に置き換え に置き換え
↓
6. シーンごとに反復 → npm run render:<scene>、確認、テキスト/
タイミング/アニメーションを微調整、再レンダリング。
コード側の変更は高速;映像の再録画が必要な場合
がループ内で最も時間がかかる部分。
↓
7. エディタでアセンブル → シーンごとの MP4 を DaVinci / Premiere / FCP に
取り込み、音楽+ナレーション+シーン間
トランジションを追加、エクスポート。
ステップ 2 の詳細 — ソース資料の分析
ユーザーが論文/仕様書を渡してきたら、コードを書く前に以下を行ってください:
- ナラティブを抽出する。 3〜5 ビートのアークは何か?(「問題 → 私たちの手法 → 主要な結果 → インパクト」が開始テンプレートです。実際の論文に合わせて変更してください。)ナラティブがシーンリストを決定します。
- 各ビートについて、何を表示するか決定する。 アニメーションテキストだけでは退屈です。各ビートには具体的なビジュアルが必要です — UI 画面、実験記録、チャート、比較、システム図など。ビジュアルを主張と一致させてください: 論文が「手法 X は 3 倍高速」と主張しているなら、サイドバイサイドのタイミングチャートを表示します。
- Remotion が生成するものと、ユーザーが録画する必要があるものを区別する。 Remotion は以下に優れています: タイトル、トランジション、チャート、UI モックアップ、レイアウト、アニメーション図。Remotion は生成できません: ユーザーの製品の実際のスクリーンレコーディング、実験映像、エージェント POV、プロジェクト外のもの。これらはユーザー提供の映像としてリストアップします。
- スキャフォールディングの前にタイムラインをスケッチする。 ビートごとに目標時間を合計 30〜90 秒に収めます。
theme.tsのTIMELINEを一致するように更新します。シーンを構築する前に合計時間を決めておくことで、各シーンが予算を把握できます。
ステップ 3 の詳細 — プレースホルダーでのスキャフォールディング
このスキルの重要な受け渡し規約: スロット名。ユーザーが録画する必要があるすべてのクリップには、安定した slot 文字列が割り当てられます。プレースホルダーと実際のクリップはそのスロット名を共有します。
// スキャフォールディング中:
<VideoPlaceholder
slot="agent-loop"
description="継続的エージェント録画: 歩行、失敗、更新ポリシーで再試行。"
accent={COLORS.blue}
/>
// ユーザーが public/clips/agent-loop.mp4 を録画した後、以下に置き換え:
<OffthreadVideo
src={staticFile("clips/agent-loop.mp4")}
muted
style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }}
/>
常に ASSETS.md をスキャフォールドルートに書く(スキャフォールドにはテンプレートが同梱されています)。これには、ユーザーが埋める必要があるすべてのスロットがリストされています: スロット名(= ファイル名)、表示内容、目標時間、アスペクト比の推奨、タイミングに関する注意事項(例:「約 7 秒地点で失敗イベント」)。これはユーザーの録画タスクの唯一の情報源です。
ステップ 4〜5 の詳細 — アセットの受け渡し
ユーザーが public/clips/ にドロップしたファイルを持って戻ってきます。チェックすべき 3 つのこと:
- ファイル名がスロット名と完全に一致していること。
agent-loop.mp4であって、agent_loop.mp4やAgentLoop.mp4ではないこと。 - 長さが少なくともシーン長以上であること(または、短くて繰り返しを意図している場合は
<Loop>を使用すること)。 - アスペクト比が適切であること — フルフレームシーンでは、コンポジションの 1920×1080 に一致させます。2×2 グリッドのカードでは、4:3 と 16:9 のどちらでも機能しますが、一貫性を保ちます。
その後、各 <VideoPlaceholder> を機械的に <OffthreadVideo> に置き換えます。これはスロットごとに 1 行の置き換えです。アニメーションロジックは変更されません。ユーザーの録画がタイミングに敏感な場合(例:「7 秒で失敗イベント」)、それをシーンプロップとして公開することで、タイミングに依存するオーバーレイ(FAIL スタンプ、報酬数字)を再録画せずに調整できます。
このループがスキルにとって重要な理由
スキルの役割は「要求に応じて Remotion コードを書く」ことではなく、ソース資料から出荷可能なビデオへのループを扱いやすくする ことです。プレースホルダーパターンにより、Claude がビデオ全体の構造を 1 回のパスでスキャフォールディングし、ASSETS.md を返してユーザーが正確に何を録画すべきかを把握できます。これがないと、ループは停滞します — ユーザーは間違ったものを録画したり、スキャフォールディングが映像を待ったり、コード構造を後から適合させる必要が生じたりします。
ユーザーがソース資料を持って現れた場合、適切な最初の動きは通常次の通りです:
「まず論文/仕様書を読ませてください。その後、目標時間付きのシーンごとのアウトライン、録画が必要なクリップのリストを提案し、プレースホルダーでコードをスキャフォールディングして、私がシーンを構築し続ける間に録画を開始できるようにします。」
新しいプロジェクトのクイックスタート
# 1. スキャフォールドをコピー
cp -r <skill-dir>/scaffold ./my-demo
cd my-demo
npm install
# 2. ライブ編集のために Remotion Studio を開く
npm run dev # http://localhost:3000 が開く
# 3. 反復中にシングルシーンをレンダリング
npm run render:opening
# 4. 準備ができたらフルタイムラインをレンダリング
npm run render
スキャフォールドには、1 つの動作するシーン(OpeningTitle)、クリームウォームテーマ、Reveal + イージング、ProgressBar、プレースホルダーの Main タイムライン、そしてレンダリングスクリプトが事前に設定された package.json が含まれています。
プロジェクトレイアウト(機能する形)
my-demo/
├── package.json # レンダリングスクリプト、プリレンダーフック
├── remotion.config.ts # コーデック/ピクセルフォーマットのデフォルト
├── tsconfig.json
├── public/
│ ├── assets/ # ロゴ、静的画像(staticFile("assets/..."))
│ └── clips/ # スクリーンキャプチャ/ビデオソース
├── scripts/
│ └── sync-clips.mjs # 各レンダリング前にクリップを正規化
└── src/
├── index.ts # registerRoot(Root)
├── Root.tsx # <Composition> レジストリ — id, schema, defaultProps
├── theme.ts # COLORS, FONT_STACK, RADIUS, SHADOWS, TIMELINE
├── fonts.ts # @remotion/google-fonts + ローカル @font-face
├── Main.tsx # フルタイムラインコンポーザー(<Sequence> ブロック)
├── components/
│ ├── Reveal.tsx # フェード+ライズラッパー(delay/duration/rise)
│ ├── Easing.ts # EASE_OUT, EASE_IN_OUT(ベジェ)
│ ├── ProgressBar.tsx # 下部に固定された 4 段階インジケーター
│ └── VideoPlaceholder.tsx # スロットラベル付きグレーカード、後で OffthreadVideo に交換
└── scenes/
├── OpeningTitle.tsx # ファイルごとに 1 シーン、各シーンは <AbsoluteFill>
├── ProductReveal.tsx
├── AgentLoop.tsx
└── ...
なぜこの形か: シーンは独立しており(簡単に単独レンダリングと反復が可能)、共有のビジュアル言語は theme.ts + components/ に存在するためルックが一貫し、Root.tsx は何がレンダリング可能かの唯一の情報源です。
コンポジションパターン(注意深く読んでください)
すべてのシーンは 3 つのものをエクスポートします:
- zod スキーマ — Remotion Studio のプロップパネル UI(スライダー、ドロップダウン)を定義します。
*_DEFAULTS定数 — このシーンがフルタイムラインに埋め込まれたときにMain.tsxが消費する値。- React コンポーネント自体、
React.FC<Props>として型付けされます。
// src/scenes/ProductReveal.tsx
import { z } from "zod";
export const productRevealSchema = z.object({
titleSize: z.number().min(40).max(280),
subtitleSize: z.number().min(14).max(80),
outerPaddingV: z.number().min(0).max(200),
});
export type ProductRevealProps = z.infer<typeof productRevealSchema>;
export const PRODUCT_REVEAL_DEFAULTS: ProductRevealProps = {
titleSize: 168,
subtitleSize: 64,
outerPaddingV: 80,
};
export const ProductReveal: React.FC<ProductRevealProps> = (p) => { ... };
次に Root.tsx で、デフォルト値のインラインコピー とともに登録します:
<Composition
id="ProductReveal"
component={ProductReveal}
durationInFrames={120}
fps={30}
width={1920}
height={1080}
schema={productRevealSchema}
defaultProps={{
// ⚠ PRODUCT_REVEAL_DEFAULTS のインラインコピー — Remotion Studio の
// 「デフォルトプロップを保存」は AST 操作を介してこのオブジェクトに
// 書き戻します。上記のエクスポートされた定数と同期を保ってください。
titleSize: 168,
subtitleSize: 64,
outerPaddingV: 80,
}}
/>
なぜ重複が必要か: Remotion Studio の「デフォルトプロップを保存」ボタンは、AST 操作を介して Root.tsx の defaultProps={…} リテラルを編集します。インポートされた定数を書き換えることはできません。したがって、インラインコピーは Studio が変更するものであり、エクスポートされた *_DEFAULTS は Main.tsx が読み取るものです。Studio が新しい値を書き込んだら、エクスポートされた定数にコピーして、フルタイムラインレンダリングでもそれらが使用されるようにします。これが references/pitfalls.md の落とし穴 #4 です。
アニメーションの基本(実際に必要な最小セット)
Remotion のすべてのアニメーションは useCurrentFrame() + interpolate() です。内部クロックや「再生」はなく、すべてのフレームは frame の純粋関数です。
正規の方法:
const frame = useCurrentFrame(); // 0, 1, 2, ...
const opacity = interpolate(frame, [0, 20], [0, 1], {
extrapolateRight: "clamp",
}); // フレーム 0〜20 で 0→1 にフェードイン
interpolate は範囲の外側でエクストラポレートします(デフォルト)。不要な場合は { extrapolateRight: "clamp" } または { extrapolateLeft: "clamp" }。
イージング: Easing.ts のベジェパス:
import { interpolate, Easing } from "remotion";
const easeOut = Easing.bezier(0.16, 1, 0.3, 1);
const progress = interpolate(frame, [0, 30], [0, 1], {
easing: easeOut,
extrapolateRight: "clamp",
});
スキャフォールドの Easing.ts には EASE_OUT と EASE_IN_OUT が事前定義されています。新たに定義する必要はほとんどありません。
<Sequence> について:
<Sequence from={60} durationInFrames={30}>
<ProductReveal {...PRODUCT_REVEAL_DEFAULTS} />
</Sequence>
クロックのリセット: <Sequence> 内では、useCurrentFrame() は 0 から再びカウントを開始します。これが、各シーンが frame 0 に対して設計されている理由です — これは自然なことです。しかし、落とし穴があります。<Sequence> の外側にある useCurrentFrame() は、囲んでいる <Composition> の絶対フレームを返します。フックを間違ったコンポーネントに置くと、微妙に壊れる可能性があります。必要な場合にのみ、深くネストするか、明示的に frame を props として渡します。
レンダリング(プロジェクトごとのスクリプト)
package.json はインラインの npx remotion render 呼び出しを使用します:
{
"scripts": {
// スタジオ
"dev": "remotion studio",
// 個々のシーン
"render:opening": "remotion render --codec=h264 --crf=18 src/index.ts OpeningTitle out/opening.mp4",
"render:product": "remotion render src/index.ts ProductReveal out/product.mp4",
// プロレス(アルファ)
"render:opening-alpha": "remotion render --codec=prores --pixel-format=yuva444p10le --prores-profile=4444 src/index.ts OpeningTitle out/opening.mov",
// フルタイムラインプレビュー
"render": "remotion render src/index.ts Main out/final.mp4",
// PNG シーケンス(プロのように背景除去用)
"render:frames": "remotion render src/index.ts OpeningTitle out/frames/%04d.png --sequence"
}
}
実績あるコーデックの選択:
| ユースケース | コマンド | 備考 |
|---|---|---|
| 反復 | --codec=h264 --crf=18 | 高速、ロスレスに近い |
| アルファ付き最終 | --codec=prores --pixel-format=yuva444p10le --prores-profile=4444 | 編集ソフト取り込み用。.mov を出力 |
| スクリーンキャプチャ上 | --codec=h264、背景除去なし。アルファ不要 | |
| PNG シーケンス | --sequence | プロフェッショナルな背景除去用 |
このスキル全体のリファレンス
詳細についてはスキャフォールド内のドキュメントを参照またはトリガーしてください:
scaffold/references/pitfalls.md— Remotion ではまる時間トップ 5scaffold/references/performance.md— スローな Studio / 長時間レンダリング / メモリリークscaffold/references/patterns.md—TimelineContext、動的コンポジション、状態管理scaffold/references/upgrading.md— v3 → v4、破壊的変更