Remotion ビジュアルプロダクションスキル
SureCart 4.2 ローンチビデオの実際の制作経験から構築されました。 作成者: Chandresh Vaghanani
始める前に — 2つの質問(必須)
コードを書く前に、この 2つの質問 をしてください。カジュアルに、1メッセージで2つの質問をまとめて行います。ユーザーが「とにかく進めて」や「今すぐ開始」と言っても、これをスキップしないでください。この10秒が何時間もの手戻りを防ぎます。
始める前に、2つだけ確認させてください:
1. 背景は明るいですか、暗いですか?(またはウェブサイトやスクリーンショットを共有してください。そこから取得します)
2. プロダクトのスクリーンショットやモックアップはありますか?(完全に任意です — なくても制作できます)
以上です。ユーザーが自発的に追加情報を提供しない限り、それ以上の質問はしません。
回答への対応:
- モックアップ/スクリーンショットを共有された場合 — 背景色、アクセントカラー、フォントスタイル、UIコピーを抽出し、それを使用します。
- ウェブサイトURLを共有された場合 — それを取得し、同様に抽出します。推測はしないでください。
- 明るい/暗いのみ回答された場合 — 以下の「情報なしの場合のフォールバックデフォルト」で進めます。
- 両方の質問をスキップされた場合 — 以下の「情報なしの場合のフォールバックデフォルト」で進めます。再度質問しないでください。
その他のアセット(ロゴ、音楽、追加の色) — 提供された場合は受け入れますが、決してブロックしないでください。
情報なしの場合のフォールバックデフォルト
ブランド情報がない場合、AIの本能はフォントを縮小しパディングを追加することです。しかしその本能は動画には間違っています。代わりに以下を適用してください:
これらは、モックアップ、スクリーンショット、ウェブサイトが提供されなかった場合に自動的に適用されます。ブランド情報がゼロでもプロフェッショナルな結果を保証します。
レイアウト
- すべてのシーンの
AbsoluteFillにjustifyContent: "center"+alignItems: "center"— 例外なし marginTop: -50でコンテンツを真の中央より少し上に配置- モックアップ/カードの幅: 1200px(上限を使用 — フレームを埋める)
- コンテナーのパディング: 最大 40px — それ以上は不可
- コンテンツは 1080px の高さの少なくとも 75% を占有する必要があります。そうでない場合は、フォントサイズを大きくするか、ギャップを減らします。
フォントサイズ(フォールバック — 範囲の上限)
| 要素 | フォールバックサイズ |
|---|---|
| メイン見出し | 140px |
| サブ見出し | 56px |
| 本文 / 説明 | 36px |
| ラベル / ピル | 22px |
| カードコンテンツテキスト | 28px |
色(フォールバックパレット — 安全かつプロフェッショナル)
- 背景:
#0a0a0f(ほぼ黒、ニュートラル) - アクセント:
#6366f1(インディゴ — 読みやすく、モダンで、プロダクト固有ではない) - テキスト:
#ffffff - ミュートテキスト:
rgba(255,255,255,0.55) - カード背景:
rgba(255,255,255,0.06)
これらは出発点にすぎません。ユーザーがブランドカラーを共有した瞬間、完全に置き換えてください。
ブランド情報なしでやってはいけないこと
- ネオン/サイバーカラーを使用しないでください — それは個人の美的感覚であり、ブランドマッチではありません
paddingTop: 120を使用して「中央揃え」と呼称しないでください — それは上部揃えでデッドスペースができます- 見出しに
fontSize: 32を「すっきり見えるから」と選択しないでください — 動画では判読できません
ルール #1 — キャンバスはWebサイトではない
これはAI生成のRemotion動画で最もよくある間違いです。
Remotionのキャンバスは 1920×1080px です。Webページのようにではなく、これを埋めるようにデザインしてください。
⚠️ これらは最小値です。本文に
fontSize: 18と書くことは、スタイルの選択ではなく、バグです。 最小値の列を下回るものは、1080p画面でテキストが読めないことを意味します。 これらの数値を型エラーのように扱ってください — 先に進む前に修正する必要があります。
| 要素 | 最小値(ハードフロア) | 推奨範囲 |
|---|---|---|
| メイン見出し | 80px | 100–160px |
| サブ見出し | 40px | 48–72px |
| 本文 / 説明 | 28px | 32–40px |
| ラベル / ピル / バッジ | 18px | 20–24px |
| カードコンテンツテキスト | 22px | 24–32px |
ルール:
- コンテンツは画面を埋めているように感じさせること
- モックアップカード:
width: 1100–1200px、中央揃え - コンテナーのパディング: 最大 48px — Webページのように 80–120px ではありません
- テキストが「大きすぎて気持ち悪い」と感じる場合 — おそらく動画には正しいサイズです
ルール #2 — すべてのアニメーションは useCurrentFrame() を使用する必要がある
// 正しい
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 20], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
// 禁止 — 正しくレンダリングされない
// CSS: transition: opacity 1s ease
// Tailwind: animate-fade-in
// CSS @keyframes
すべての interpolate() 呼び出しに、extrapolateLeft: "clamp" と extrapolateRight: "clamp" を常に含めてください。境界のない値が明示的に必要でない限り。これを忘れると、値が範囲外に漏れ出し、微妙なバグを引き起こします。
ルール #3 — 決定論
// 禁止 — レンダリングパスごとに異なる値
const x = Math.random() * 100;
// 正しい — 毎回、すべてのフレームで同じ値
import { random } from "remotion";
const x = random("particle-x-1") * 100; // 文字列シード = 決定論的
ルール #4 — アセット
import { staticFile } from "remotion";
import { Img } from "remotion"; // ネイティブの <img> ではない
import { Audio } from "@remotion/media";
// public/ フォルダ内のものには常に staticFile() を使用
<Audio src={staticFile("bg-music.mp3")} />
<Img src={staticFile("logo.png")} /> // <Img> はフレームレンダリング前にアセットが読み込まれることを保証
// リモートURLは staticFile() を必要としませんが、CORSが必要です
ルール #5 — スムーズなプレビュー再生
<Sequence> コンポーネントに premountFor={30} を追加して、重いコンポーネントが開始時刻の30フレーム前にプリロードされるようにします:
<Sequence from={90} durationInFrames={120} premountFor={30}>
<HeavyScene />
</Sequence>
イージングレシピ
import { Easing } from "remotion";
// シャープなUIエントリー(強いイーズアウト、オーバーシュートなし) — ほとんどのエントリーアニメーション
Easing.bezier(0.16, 1, 0.3, 1)
// スローな編集フェード(バランスの取れたイーズインアウト) — ムードトランジション
Easing.bezier(0.45, 0, 0.55, 1)
// 遊び心のあるオーバーシュート — バウンシーで楽しい要素
Easing.bezier(0.34, 1.56, 0.64, 1)
// スプリング — バウンスなし(モックアップエントリー、カード、UI)
spring({ frame, fps, config: { damping: 200 } })
// スプリング — スナップ感、わずかなバウンスあり(パンチの効いた要素)
spring({ frame, fps, config: { damping: 20, stiffness: 200 } })
// スプリング — バウンシー/遊び心
spring({ frame, fps, config: { damping: 8 } })
プレレイアウトゲート — シーンレイアウトを書く前に実行する
これらは提案ではありません。すべてのシーンの最初の <div> を書く前に、3つのゲートすべてを実行してください。いずれかのゲートに失敗した場合、レイアウトを変更してください — 固定寸法や追加コンテンツで決してパッチしないでください。
ゲート 1 — キャンバス充填(両軸、必須)
幅軸:
dead_side = (1920 − content_width) / 2
≤ 300px であること。> 300px の場合 → コンテンツが狭すぎます。広げるかレイアウトを変更してください。
高さ軸:
fill_h = content_height / 1080
≥ 0.80 であること。< 0.80 の場合 → コンテンツが短すぎます。レイアウト形状を変更してください。
⚠️ 高さで失敗した場合、カードやコンテナーに固定高さを設定して修正しないでください。 固定高さはカード内に空の隙間を作ります — デッドスペースが排除されず、要素の内側に移動するだけです。唯一の本当の修正は、レイアウト形状を変更することです(ゲート2)。
実際の失敗例 — 3つの短いフィーチャーカード:
| バージョン | content_width | dead_side | content_height | fill_h | 判定 |
|---|---|---|---|---|---|
| v1: 3列カード (365px) | 1151px | 384px | 416px | 38% | ❌ 両軸失敗 |
v2: 強制 height: 720px | 1542px | 189px | 864px | 80% | ✅ 幅、❌ 視覚的(カード内に空の隙間) |
| v3: 水平行 (1400px) | 1400px | 260px | 916px | 85% | ✅ 両軸合格 |
ゲート 2 — レイアウト選択決定表
コンテンツ量がレイアウト形状を決定します。コードを書く前に、この表からレイアウトを選択してください。
| アイテム数 | アイテムあたりのコンテンツ | 正しいレイアウト | 理由 |
|---|---|---|---|
| 3–5項目 | アイコン + 名前 + 1行 | 水平行(幅1400px) | 短いコンテンツが縦に積み重なり → 自然に高さを埋める |
| 3項目 | アイコン + 名前 + 2–3行 | 3列のカード(最小幅1100px) | カードの高さを埋めるのに十分なコンテンツ、隙間なし |
| 2項目 | 十分な量 | 横並びの大きなカード または分割画面 | |
| 1項目 | 任意 | フルスクリーンヒーロー |
ゲート1の後、コンテンツに自然なレイアウトがいずれかの軸でしきい値を下回る場合 — そのレイアウトは間違っています。この表の別の行を選んでください。
美学やデフォルトの直感でレイアウトを決して選ばないでください。コンテンツフィットが優先です。美学はその次です。
ゲート 3 — コンテンツ密度制限
アイテムあたりの最大: アイコン + 名前 + 1短い行。絶対的な制限です。 箇条書きなし。サブセクションなし。段落なし。2行目の説明なし。
視聴者はシーンあたり約5秒しかありません。彼らは1行読みます。4つの箇条書きは読みません。
コンテンツが薄く感じられ、スペースを埋めるためにさらに追加したい場合 — それはコンテンツが不足しているのではなく、ゲート2がレイアウト形状が間違っていると伝えているのです。
空のスペースは サイズ(より大きなフォント、より大きなアイコン、アイテム間のより大きなギャップ)で埋めてください — 決してコンテンツを追加しないでください。
ユニバーサルシーンルール
-
垂直方向の配置 —
justifyContent: "center"+marginTop: -40から-60(真の中央よりわずかに上 = モダンでプレミアムな印象。上部揃え+パディングではありません。)❌ 間違い — 上部揃え、下部に空スペース:
<AbsoluteFill style={{ display: "flex", flexDirection: "column", paddingTop: 110 }}> <h1>見出し</h1> <p>サブテキスト</p> {/* 下部に大きな空の隙間 */} </AbsoluteFill>✅ 正しい — 垂直方向に中央揃え、中点よりわずかに上:
<AbsoluteFill style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", marginTop: -50 }}> <h1>見出し</h1> <p>サブテキスト</p> {/* コンテンツがフレームを埋める — デッドスペースなし */} </AbsoluteFill> -
キャンバス充填 — このシーンを書く前にプレレイアウトゲートを実行してください。 ゲート1は幅(
dead_side ≤ 300px)と高さ(fill_h ≥ 0.80)の両方を一緒にチェックします。ゲート2は決定表からレイアウト形状を選択します。ゲート3はアイテムあたりのコンテンツを制限します。3つのゲートすべてが上記の「プレレイアウトゲート」セクションにあります — これらは、ここにあった古い幅のみのチェックに優先します。 -
見出しのz-index — 見出しコンテナーには常に
zIndex: 20を設定し、モックアップがテキストに重ならないようにします -
見出しのオーバーフロー — 見出しテキストには常に
whiteSpace: "nowrap"を設定します(モックアップの後ろでテキストが折り返されるのを防ぎます) -
AbsoluteFill に
overflow: hiddenを設定しない — カーソルやSVG要素がクリップされます。削除するか、カーソルを外側に配置してください。 -
15フレームのホールド — すべてのシーンは、トランジションが発火する前に、最後に少なくとも15フレームの完全に可視のホールドが必要です。 outgoing シーンでアニメーションがまだ再生中にトランジションを開始しないでください。
-
フォント — 全体を通して一貫した1つのフォントを使用します。推奨:
@remotion/google-fontsの Plus Jakarta Sans。利用可能な最大ウェイト: 800(fontWeight: 900を書くと800としてレンダリングされます)。 -
色 — 最大2~3のブランドカラー。1つの暗い背景、1つのプライマリアクセント、テキスト用の白/ミュートホワイト。すべてのシーンで一貫していること。
タイポグラフィ階層
// スーパータイトル / ラベルピル
{ fontSize: 20, letterSpacing: "4px", textTransform: "uppercase", fontWeight: 600 }
// メイン見出し
{ fontSize: 112, fontWeight: 800 } // 範囲: 100–160px
// サブテキスト / 説明
{ fontSize: 36, opacity: 0.7 } // 範囲: 32–40px
// トラストライン / 小さなバッジ
{ fontSize: 26, opacity: 0.5 } // 範囲: 24–28px
フォント設定
import { loadFont } from "@remotion/google-fonts/PlusJakartaSans";
// トップレベルで呼び出し — レンダリング前に読み込む必要あり
const { fontFamily } = loadFont("normal", {
weights: ["400", "600", "800"],
subsets: ["latin"],
});
他のフォントの場合: @remotion/google-fonts/FontName からインストールするか、.woff2 を public/ にドロップし、@remotion/fonts の loadFont を使用してください。
シーン構造テンプレート
すべてのシーンは、この固定レイヤー順序(下 → 上)に従います:
<AbsoluteFill style={{ background: brandBg }}