Communitygithub.com

gbax316/vidtsx-2d-generator

根據鏡頭、場景或影片描述,生成可用於 VidTSX(基於 Remotion)的生產級 2D TSX 影片檔案。

vidtsx-2d-generator 是什麼?

此技能用於從文字描述生成生產就緒的 2D TSX 影片檔案,專為 VidTSX(基於 Remotion 的框架)設計。它涵蓋強制性的檔案結構與組態設定、尺寸預設(橫向/直向/正方形)、六種風格預設(極簡、孟菲斯、新野獸派、玻璃擬態、霓虹、企業),以及確保渲染不崩潰的嚴格規則。技能嚴格基於影格動畫,禁止使用 useState、useEffect、setTimeout 等 React hooks,並要求 interpolate 的輸入範圍必須嚴格遞增、Easing 必須使用 Easing.bezier() 而非包裝器語法,以及 chroma-js 和 @remotion/paths 的正確匯入方式。支援的平台包括 Claude Code、Cursor 等可執行自訂技能的 AI 代理,但**不適用於** 3D/three.js 合成、一般 React 開發或編輯現有影片檔案。使用時需先確認單一鏡頭或複雜場景的分解,然後輸出獨立 .tsx 檔案,最後務必渲染靜止畫或關鍵影格來驗證視覺效果。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/gbax316/shorts-director/tree/main/.claude/skills/vidtsx-2d-generator

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

VidTSX 2D 影片產生器

根據鏡頭或影片的描述,生成可用於 VidTSX 的生產級 2D TSX 影片檔案。這些檔案是由 Remotion 逐影格渲染的合成元件,因此正確性比巧妙更重要:一個非單調的 interpolate 範圍或一個誤用的 useState 就會導致渲染崩潰。

此技能涵蓋2D 動態圖形。3D 作品(使用 @remotion/three / React Three Fiber)不在此範圍。

如何使用此技能

  1. 清楚的單一鏡頭 → 直接產生 .tsx 檔案。
  2. 複雜、多鏡頭或視覺上不明確的需求 → 先以一條簡短訊息確認鏡頭分解或視覺方向,然後再產生。不要過度詢問;一行確認就夠了。
  3. 交付為實際的 .tsx 檔案,而非內嵌程式碼。這些 TSX 元件通常超過 20 行,且使用者會直接編輯這些檔案。預設為每個檔案一個鏡頭(原子化,易於編輯),除非使用者要求單一合併的交付物。
  4. 檔案內容僅包含元件程式碼 — 歡迎加入下方結構性的區塊註解,但檔案內不得有 Markdown 圍欄或散文式說明。
  5. 先渲染並檢查,再宣告完成 — 請參閱驗證渲染結果。僅靠推理完成的鏡頭不算完成;靜止畫(對於揭示/捲動效果,則需要每個關鍵提示點的影格)是驗收標準。

輸出規格

尺寸預設

格式寬度高度使用情境
橫向 (horizontal)19201080YouTube、簡報
直向 (vertical)10801920TikTok、Reels、Shorts
正方形 (square)10801080Instagram 貼文

預設值

  • 格式: 橫向 (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', // 僅限 PascalCase — 不可有連字號或底線
  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 替換為描述該鏡頭的 PascalCase 名稱,根據選定的風格預設設定 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 並始終進行裁切(clamp):

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();

// ❌ 錯誤 — "chroma is not a function"
import chroma from 'chroma-js';

@remotion/paths — 僅存在真實的函數

這些輔助函數不存在且絕對不能使用: makeCircle()、makeRect()、makeTriangle()、makeLine()、makePie()、makePolygon()、makeEllipse()、makeStar()。

只有這些匯入是有效的:

import { evolvePath, getLength, getPointAtLength, getTangentAtLength } from '@remotion/paths';

手動編寫 SVG 路徑字串,並使用 evolvePath 為它們製作動畫:

const circlePath = 'M 50 10 A 40 40 0 1 1 49.99 10 Z';
const rectPath = 'M 0 0 L 100 0 L 100 50 L 0 50 Z';
const linePath = 'M 0 0 L 100 100';

const { strokeDasharray, strokeDashoffset } = evolvePath(progress, rectPath);

合成 ID

compositionConfig.id僅限 PascalCase — 沒有連字號,沒有底線(例如 ProductReveal,而不是 product-reveal 或 product_reveal)。


版面配置

安全區域

  • 上方 10%: 預留給平台 UI。
  • 下方 15%: 預留給字幕/按鈕。
  • 將主要內容保持在垂直方向的 25%–75% 之間。

置中輔助

const centered: React.CSSProperties = {
  position: 'absolute',
  top: '50%',
  left: '50%',
  transform: 'translate(-50%, -50%)',
};

排版

元素大小粗細
標題72–120px700–900
副標題36–48px500–700
內文28–36px400–500

始終對文字元素設定 margin: 0 — 瀏覽器預設值會使版面偏移。


風格預設

在此儲存庫中,預設是品牌風格,而不是某個預設。 鏡頭從 remotion/src/brand.ts 匯入 COLORS、GRADIENT、RADIUS、SHADOW、EASINGS,並從 remotion/src/fonts.ts 匯入 FONT_HEADLINE、FONT_DISPLAY、FONT_BODY、FONT_MONO,而不是使用骨架中的區域 COLORS/TYPOGRAPHY 區塊,並遵循 brand.md。FONT_HEADLINE(Instrument Serif)只有一種粗細:切勿對其設定 fontWeight。除非其 compositionConfig 指定了 ground: 'night',否則鏡頭應位於日間底色上;套件元件(lib/shorts.tsx、BrandBg)會從中選取顏色,因此請從 brand.ts 讀取 useGround() 來設定您自行設定的任何顏色。

當使用者指定某種風格時,請從 references/style-presets.md 載入其調色盤和特性,並將 COLORS 物件放入骨架中。六種預設為:極簡 (minimalist)、孟菲斯 (memphis)、新野獸派 (neo-brutalism)、玻璃擬態 (glassmorphism)、霓虹/賽博龐克 (neon/cyberpunk) 以及企業 (corporate)。如果未指定風格,則使用上述的品牌風格。


驗證渲染結果(請勿跳過)

一個鏡頭在您親眼看過之前不算完成。撰寫完 .tsx 後,至少渲染一張靜止畫並打開它——絕不要交出一個您僅憑推理得出的鏡頭。渲染成功且數字看起來正確,但文字溢出其容器、圖片裁切錯誤、元素超出畫面,或兩個東西重疊,這些都是常見的問題。只有螢幕截圖才能捕捉到這些。

  • 渲染一張靜止畫(例如 node scripts/render-all.mjs --still --scale=1 <ShotId>)並檢查 PNG 檔案。
  • 對於時間驅動的揭示效果(元素在某個提示點進入、捲動效果、分階段),單張處於 60% 長度時間點的靜止畫是不夠的——請渲染完整片段並在每個關鍵時刻提取影格(使用 ffmpeg -ss <t> -i out/<id>.mp4 -frames:v 1 f.jpg),或在多個偏移點渲染靜止畫。驗證每個提示點的狀態,而不只是一個影格。
  • 特別檢查:圖片是否符合其位置(重要內容未被裁切;對於異質的真實圖片,偏向於在匹配的背景上使用 objectFit: contain)、文字未被裁剪或溢出、無任何元素超出安全區域、以及每個動畫元素在應該出現時確實可見。
  • 如果它被合成到其他影片素材上,也應從最終的烘焙輸出中抽樣檢查一個影格,而不僅僅是單獨的鏡頭。

修復螢幕截圖所揭示的問題,然後重新渲染並再次檢查。將「我已渲染且看起來正確」——並顯示該影格——視為完成的標準。


最終輸出

產生完整的 .tsx 檔案,且檔案內部不得包含任何其他內容——沒有前後的 Markdown、沒有程式碼前後的評論或說明。在對話中交接檔案時,附上一句簡短的單行備註是可以接受的。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

gbax316/make-ai-short

Build a GENERATIVE-pixels vertical short (1080×1920, ~35-40s) end-to-end — a recurring locked character animated by a fal video model (Seedance 1.5 Pro default) under a philosophical/story VO, composited in Remotion with word-synced captions, SFX audition, seamless frame-0==last-frame loop. Use when the user wants to "make an AI video short", "make an ai short", "make a blue-man video", or any short where the pixels come from a VIDEO MODEL — not TSX animation (that is make-short) and not layered collage (that is make-vox). Defers model choice re-litigating to ai-shorts/IDEAS.md, TSX crash rules to vidtsx-2d-generator, SFX taste to suggest-sfx + brand §7. For a NEW short (writers' room, dialogue skits, documentaries, mixed render paths), start with shorts-director, which calls this track as an engine.

gbax316/shorts-director

Directs a faceless vertical short from idea to finished, mastered file, and gets better with every run. Picks a format, writes the episode in a writers' room (three premises judged as the buyer), voices it, gates on an animatic, then decides beat by beat how each moment is made: drawn in code in Remotion, a cut-out from a generated still, a generated clip, or one of the engine tracks. Modes: series, writers-room, produce, sound, finish, bakeoff, effects (/effects), improve (the learning loop after every short). Formats so far: character skit with dialogue and synced mouths, photoreal mini documentary with sourced figures. Triggers on "make a short", "next episode", "make a video about X", "faceless video", "reel for this offer". Do NOT trigger for editing an existing video file, for a pure code-drawn explainer with no writers' room (make-short), or for collage (make-vox).

相關技能