VidTSX 2D動画ジェネレーター は何をしますか?
ショットや動画の説明から、本番用の2D TSXビデオファイルを生成します。これらのファイルはRemotionコンポジションであり、VidTSXがフレームごとにレンダリングするため、賢さよりも正確さが重要です。単一の非単調なinterpolate範囲や、余計なuseStateがあるだけでレンダリングがクラッシュします。
このスキルは2Dモーショングラフィックスを対象としています。3Dワーク(@remotion/three / React Three Fiber)は対象外です。
このスキルの使い方
- 明確な単一ショット →
.tsxファイルを直接生成します。 - 複雑、マルチショット、または視覚的に曖昧なリクエスト → 最初に1通の短いメッセージでショットの内訳やビジュアルの方向性を確認してから生成します。質問しすぎないでください。1行の確認で十分です。
- 実際の
.tsxファイルとして提供し、インラインコードでは提供しません。これらのTSXコンポーネントは常に20行を超え、ユーザーはこれらのファイルを直接編集します。デフォルトは1ファイル1ショット(アトミックで編集しやすい)ですが、ユーザーが単一の結合された成果物を要求した場合はその限りではありません。 - ファイルにはコンポーネントコードのみを含めます。以下の構造セクションコメントは歓迎しますが、ファイル内にマークダウンフェンスや散文の説明は含めません。
- レンダリングして確認してから完了とします — レンダリングの確認を参照してください。推論しただけのショットは完了ではありません。静止画(および、リビールやスクロールの場合は各キューでのフレーム)が基準です。
出力仕様
解像度プリセット
| フォーマット | 幅 | 高さ | 使用例 |
|---|---|---|---|
| 横長 | 1920 | 1080 | YouTube、プレゼンテーション |
| 縦長 | 1080 | 1920 | TikTok、Reels、Shorts |
| 正方形 | 1080 | 1080 | Instagramフィード |
デフォルト
- フォーマット: 横長 (1920×1080)
- 再生時間: 5秒
- FPS: 30
- スタイル: ミニマリスト(
references/style-presets.mdを参照)
必須ファイル構造
すべての生成ファイルは次のスケルトンに従います。ラベル付きセクションコメントは意図的なもので、大きなファイルをナビゲートしやすくします。
import React from 'react';
import {
useCurrentFrame,
useVideoConfig,
interpolate,
Easing,
AbsoluteFill,
Sequence,
} from 'remotion';
// =============================================================================
// コンポジション設定
// =============================================================================
export const compositionConfig = {
id: 'ComponentName', // パスカルケースのみ — ハイフンやアンダースコアは不可
durationInSeconds: 5,
fps: 30,
width: 1920,
height: 1080,
};
// =============================================================================
// スタイル定数
// =============================================================================
const COLORS = {
primary: '#6366f1',
secondary: '#8b5cf6',
accent: '#06b6d4',
background: '#0f0f23',
text: '#ffffff',
} as const;
const TYPOGRAPHY = {
fontFamily: 'Inter, system-ui, sans-serif',
} as const;
const EASINGS = {
easeOut: Easing.bezier(0.33, 1, 0.68, 1),
easeIn: Easing.bezier(0.32, 0, 0.67, 0),
easeInOut: Easing.bezier(0.37, 0, 0.63, 1),
overshoot: Easing.bezier(0.34, 1.56, 0.64, 1),
} as const;
// =============================================================================
// 事前生成データ(モジュールレベルで一度だけ計算、レンダリング中は計算しない)
// =============================================================================
const seededRandom = (seed: number): number => {
const x = Math.sin(seed * 9999) * 10000;
return x - Math.floor(x);
};
// =============================================================================
// メインコンポーネント
// =============================================================================
const ComponentName: React.FC = () => {
const frame = useCurrentFrame();
const { fps, durationInFrames, width, height } = useVideoConfig();
return (
<AbsoluteFill style={{ backgroundColor: COLORS.background }}>
{/* コンテンツ */}
</AbsoluteFill>
);
};
export default ComponentName;
ComponentName をショットを説明するパスカルケースの名前に置き換え、選択したスタイルプリセットから COLORS ブロックを設定し、リクエストに応じて width/height/durationInSeconds/fps を設定します。
正確性ルール
これらはスタイル上の好みではなく、レンダリングを成功させるための条件です。VidTSX(Remotion経由)は、固定フレーム番号でコンポーネントを呼び出すことにより各フレームをレンダリングします。イベントループ、フレーム間の永続性、壁掛け時間はありません。これらを前提とするものはすべて壊れます。
アニメーションは常にフレームベース
- すべての動きは
useCurrentFrame()+interpolate()で駆動します。 useState、useEffect、setTimeout、setInterval、CSSアニメーション/トランジションは絶対に使用しないでください。これらはフレーム単位のモデルに適合せず、壊れたり非決定論的な出力を生成します。- ランダムまたは手続き的なものには、
seededRandom(または同等のシード付き関数)を使用して、特定のフレームのレンダリングが毎回同一になるようにします。パーティクル/ランダム配列はモジュールレベルで事前生成し、レンダリング関数内では決して生成しないでください。フレームごとに再計算するとちらつきが発生します。 - アニメーションをずらして、要素がすべて同時ではなく順番に表示されるようにします。見栄えが良くなり、期待される外観です。
interpolate — 入力範囲は厳密に増加させる必要があります
interpolate の入力範囲は、厳密に単調増加している必要があります。重複値や降順の値は実行時にエラーをスローします。
// ✅ 正しい
interpolate(frame, [0, 30, 60], [0, 1, 0]);
// ❌ エラー — 入力範囲が降順
interpolate(frame, [60, 30, 0], [0, 1, 0]);
マッピングを反転するには、出力範囲を反転し、入力範囲は絶対に反転しないでください。
// ✅ 正しい — 0→100、1→0 にマッピング
interpolate(value, [0, 1], [100, 0]);
// ❌ 誤り
interpolate(value, [1, 0], [100, 0]);
インデックスベースのタイミングでは、startFrame < endFrame を確認し、常にクランプします。
const startFrame = index * 30;
const endFrame = startFrame + 30;
interpolate(frame, [startFrame, endFrame], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
境界のない値が本当に必要な場合を除き、常に extrapolateLeft: 'clamp' と extrapolateRight: 'clamp' を渡してください。これらがないと、値はキーフレームの前後で範囲を超えてしまいます。
Easing — Easing.bezier() を使用し、ラッパー構文は使用しない
Easing.out(Easing.cubic) のようなラッパー形式はクラッシュします。名前付きベジェを一度定義し(スケルトンの EASINGS ブロックを参照)、それを参照します。
// ❌ クラッシュ
Easing.out(Easing.cubic);
Easing.in(Easing.quad);
// ✅ 正しい
interpolate(frame, [0, 30], [0, 1], {
easing: EASINGS.easeOut,
extrapolateRight: 'clamp',
});
chroma-js — 名前空間インポートのみ
// ✅ 正しい
import * as chroma from 'chroma-js';
const color = chroma('#00bfff').brighten(0.5).hex();
// ❌ 誤り —