Communitygithub.com

3bkader-gpt/remotion-tiktok-gym-editor

以結構化方式撰寫 Remotion 標記,使 Remotion Studio 能夠辨識程式碼結構並實現互動功能

remotion-tiktok-gym-editor 是什麼?

這項技能提供了一個完整的指南,教導開發者如何以特定方式撰寫 Remotion 標記,讓 Remotion Studio 能夠辨識結構並實現互動功能。它涵蓋了從基礎的點擊選取、拖放、縮放與旋轉,到進階的 CSS 樣式編輯、關鍵影格和緩動函數編輯等多種互動行為。技能重點強調使用 `Track`、`Interactive.create()` 和連線組合(connected compositions)來建立具有獨立時間軸的組件,並詳細說明了如何定義可編輯的 schema 欄位(如 `string`、`number`、`color`、`enum` 等),以及如何將這些欄位映射到組件的 props 上。此外,它還提供了關於將 CSS 樣式內聯化、使用 `interpolate()` 進行動畫處理、使用 `Interactive.Path` 編輯 SVG 路徑,以及為每個可獨立編輯的項目建立單獨 JSX 節點的具體指導。此技能適用於所有現代 Remotion 專案,可顯著提升開發者在使用 Remotion Studio 進行影片編輯時的工作效率和互動體驗。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/3bkader-gpt/remotion-tiktok-gym-editor/tree/HEAD/.agents/skills/remotion-interactivity

在你喜歡的 AI 中提問

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

預覽

來自技能 README

remotion-tiktok-gym-editor preview

說明文件

透過以特定方式撰寫 Remotion 標記,Remotion Studio 能夠辨識程式碼結構並使其具備互動性:

  • 允許透過點擊選取項目
  • 允許拖放、調整大小和旋轉
  • 編輯 CSS 樣式
  • 讓關鍵影格和緩動函數值可編輯

如果標記過於複雜,Studio 無法使其具備互動性,則這些值會變成灰色。

偏好使用具有獨立時間軸的互動式組件

使用 Track、連線組合(connected compositions)和 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。

選擇 Schema 欄位

Schema 中的每個鍵都是一個 prop,Studio 可以在呼叫處讀取和編輯。 不在 Schema 中的 Props 仍然可以運作,但在 Studio 中無法編輯。 Keys 可以使用點記法,例如 style.color。

類型用途可關鍵影格化
string字串,例如標題、提示或程式碼片段否
number數字,可選用 min、max、step、integer是
boolean開關是 (保持)
colorCSS 顏色字串是
enum在 variants 之間選擇,每個都有其自己的巢狀 Schema可選 (保持)
array數字、顏色、列舉等清單否
asset媒體來源,可選用 assetType否
font-familyCSS 字型系列否
font-weight字型粗細是
translate、scale、rotation-css、rotation-degrees、transform-origin變形是
uv-coordinate元素上標準化的 [x, y] 點是
svg-pathSVG 路徑資料是
remotion-captionsCaption[] 資料否
hidden一個保留在控制項之外的值—

每個欄位都需要一個 default,並且應該有一個 description,Studio 會將其顯示為標籤。 設定 keyframable: false 以顯示靜態控制項。

公開內容和每個實例的外觀,例如文字和強調色。\n不要為 style.translate、style.scale、style.rotate、style.transformOrigin 和 style.opacity 新增欄位:Interactive.create() 會自動新增它們。

若要讓每個實例的根 CSS 屬性可編輯,請展開內建的 schema 片段:

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。 它提供了子內容的控制項,並且未來可能演進以支援更豐富的內容。 目前,它使用一個標籤為「Text」且預設值為 '' 的字串欄位。 如果一個組件只需要字串類型的子元件,請改為使用 type: 'string' 宣告一個明確的 children 欄位。 Interactive.textSchema 控制排版樣式;childrenSchema 控制內容。 子元件片段不包含在 baseSchema 中,也不會自動新增到自訂組件。 巢狀標記和計算後的子元件目前是唯讀的。 text-content 是 string 欄位類型的已棄用別名。 有關所有選項,請參閱 InteractivitySchema。

將可重複使用的組件註冊為連線組合(Connected Compositions)

將場景和可重複使用的元素註冊為獨立的 Composition。Studio 將這些稱為連線組合:它們可以在自己的時間軸中開啟,同時與父影片共用同一個組件實作。

在組件內部定義所需的樣式並載入字型,以便它在沒有父元件的情況下也能運作。請參閱父元件獨立性。

註冊與父元件渲染的相同匯出組件參考。對於上面的範例,使用 component={Chapter},而不是 ChapterInner 或內聯包裝器。 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 和持續時間。註冊預設值不會自動從父實例複製 props。請參閱連線組合以了解註冊和提取細節。

將時間直接放在組件上

避免在一個已經接受時間 props 的組件周圍使用單獨的 <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() 製作的組件中,並為該實例設定時間。受管理的根也可以接受 width 和 height 供 useVideoConfig() 使用。

使用 <Track> 將項目放在同一個 Studio 時間軸行上。 當場景是連續的時,使用 <TransitionSeries>。

為每個可獨立編輯的項目提供自己的 JSX 節點

Studio 編輯的是建立項目的 JSX 原始碼節點。如果多個執行時項目來自同一個 JSX 節點,它們會共享同一個原始碼編輯目標。

對於每個應該可獨立編輯的 Composition 註冊、剪輯、場景、圖層或序列,請撰寫一個單獨的 JSX 節點,並將其可編輯的 props 保留在該節點上。這適用於 <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() 或其他程式化迴圈會從一個 JSX 原始碼節點建立多個執行時項目。這適用於重複的輸出,且有意將其控制為一個範本,例如視覺化條形圖或粒子。但當實例在 Studio 中需要獨立的 ID 或名稱、props、元資料、時間、排序、刪除或複製時,則不適用。

使用 Interactive 讓 HTML 元素具備互動性

每個 HTML 和 SVG 元素(除了 <Img>,它已經具有互動性),例如 <div>,都可以使用 Interactive 變成互動式:

<Interactive.Div
  name="Greeting card"
  style={{fontSize: 80, padding: 24}}
>
  Hello
</Interactive.Div>

這允許在 Studio 中設定樣式和關鍵影格。請明智使用,如果一個組件有太多元素,時間軸可能會變得雜亂。

偏好使用內聯文字

如果文字是固定的並且僅使用一次,請直接將其寫在互動式元素內部,而不是將其提取到常數中。

// 👍 固定副本保持可編輯
<Interactive.Div name="Title">
  Remotion Best Practices
</Interactive.Div>

僅在文字是動態或可重複使用時,才使用 prop 或變數。

為互動式元素提供描述性名稱

為元素新增 name prop,使其易於識別。 避免使用計算後的名稱,請對其進行硬編碼。

<>
  <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 內部使用 remotion 的 <Interactive.Path> 而不是 <path>,可以使路徑在視覺上可編輯。

安裝 @remotion/paths 以進行路徑插值和 Studio 路徑關鍵影格:

bunx remotion add @remotion/paths

如果幾何圖形是靜態的,請將路徑字串直接放在 d prop 中。不要將其提取為常數。

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>

使用內聯 morphology 路徑

…

[為翻譯而截斷]

Individual skills in this repo

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

相關技能