Communitygithub.com

zoih6/masafat-watan-video

Strukturiert Remotion-Markup für Interaktivität

Was ist masafat-watan-video?

Diese Fähigkeit beschreibt, wie Remotion-Markup strukturiert werden muss, damit es im Remotion Studio interaktiv wird – mit Klickauswahl, Drag-and-Drop, Größenänderung, Rotation und CSS-Bearbeitung. Sie richtet sich an Entwickler, die Videos mit Remotion erstellen und die Studio-Oberfläche für Designer oder Nicht-Entwickler zugänglich machen möchten. Die Anleitung deckt die Plattformen Remotion Studio und Remotion Player ab. Sie erklärt, wie man interaktive Komponenten mit `Interactive.create()`, `Track` und verbundenen Kompositionen aufbaut, Schemafelder für Eigenschaften definiert und CSS-Stile inline hält. Wichtig ist die explizite Angabe von `layout` sowie die Trennung von JSX-Knoten für jedes unabhängig editierbare Element, damit die Studio-Quellcode-Bearbeitung funktioniert. Animationen müssen direkt als `interpolate()`-Aufrufe im Markup erfolgen, nicht in externen Variablen. Auch SVG-Pfade werden durch `<Interactive.Path>` visuell editierbar, nach Installation des Pakets `@remotion/paths`.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/zoih6/masafat-watan-video/tree/HEAD/skills-docs/remotion-skills/remotion-interactivity

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Vorschau

Aus dem Skill-README

masafat-watan-video preview

Dokumentation

Durch die spezifische Strukturierung von Remotion-Markup kann das Remotion Studio die Code-Struktur erkennen und interaktiv machen:

  • Auswahl von Elementen durch Klicken
  • Drag-and-Drop, Größenänderung und Rotation
  • Bearbeitung von CSS-Stilen
  • Keyframes und Easing-Werte bearbeitbar

Wenn das Markup zu komplex für die interaktive Bearbeitung im Studio ist, werden die Werte ausgegraut.

Bevorzugt interaktive Komponenten mit eigenen Zeitachsen

Erstelle neue Kompositionen mit Track, verbundenen Kompositionen und Interactive.create().

Setze layout explizit auf 'absolute-fill' für Szenen oder 'none' für begrenzte Elemente. Registriere dieselben exportierten Szenen- und wiederverwendbaren Element-Komponenten mit Composition.

Beginne mit dem vollständigen Track + verbundene Kompositionen Beispiel. Es enthält das Element, die Szene, die übergeordnete Zeitachse und die Root-Registrierungen.

import {Track, useVideoConfig} from 'remotion';
import {Chapter} from './Chapter';

export const MyVideo = () => {
  const {fps} = useVideoConfig();

  return (
    <Track name="Kapitel">
      <Chapter
        name="Eröffnung"
        durationInFrames={3 * fps}
        title="Einleitung"
      />
      <Chapter
        name="Feature"
        from={3 * fps}
        durationInFrames={4 * fps}
        title="Neue Funktionen"
      />
    </Track>
  );
};

Setze Hintergrund- und Ausrichtungsstile auf jede Szeneninstanz, wie im vollständigen Beispiel gezeigt. Behalte reine Layout-Container als einfaches HTML bei.

Schema-Felder auswählen

Jeder Schlüssel im Schema ist eine Eigenschaft, die das Studio an der Aufrufstelle lesen und bearbeiten kann. Eigenschaften, die nicht im Schema sind, funktionieren weiterhin, sind aber im Studio nicht bearbeitbar. Schlüssel können Punktnotation verwenden, wie style.color.

TypVerwendungKeyframable
stringZeichenketten, z. B. Titel, Prompt oder Code-SnippetNein
numberZahlen, mit optionalem min, max, step, integerJa
booleanEin/Aus-SchalterJa (halten)
colorCSS-FarbzeichenkettenJa
enumAuswahl zwischen variants, jede mit eigenem verschachtelten SchemaOpt-in (halten)
arrayListen von Zahlen, Farben, Enums und mehrNein
assetMedienquellen, mit optionalem assetTypeNein
font-familyCSS-SchriftfamilieNein
font-weightSchriftstärkeJa
translate, scale, rotation-css, rotation-degrees, transform-originTransformationenJa
uv-coordinateEin normalisierter [x, y]-Punkt auf dem ElementJa
svg-pathSVG-PfaddatenJa
remotion-captionsCaption[]-DatenNein
hiddenEin Wert, der außerhalb der Steuerelemente bleibt—

Jedes Feld benötigt einen default-Wert und sollte eine description haben, die das Studio als Beschriftung anzeigt. Setze keyframable: false, um ein statisches Bedienelement anzuzeigen.

Lege Inhalt und instanzspezifisches Erscheinungsbild offen, z. B. den Text und eine Akzentfarbe. Füge keine Felder für style.translate, style.scale, style.rotate, style.transformOrigin und style.opacity hinzu: Interactive.create() fügt sie automatisch hinzu.

Um CSS-Eigenschaften des Root-Elements pro Instanz bearbeitbar zu machen, verwende die integrierten Schema-Fragmente:

const cardSchema = {
  ...Interactive.textSchema, // style.color, style.fontSize, style.fontWeight, ...
  ...Interactive.backgroundSchema, // style.backgroundColor
  ...Interactive.borderRadiusSchema, // style.borderRadius, ...
} as const satisfies InteractivitySchema;

Ebenfalls verfügbar: Interactive.borderSchema und Interactive.captionsSchema für Komponenten, die Captions akzeptieren. Für Komponenten, die React.ReactNode-Children akzeptieren, füge ...Interactive.childrenSchema hinzu. Es bietet Steuerelemente für den Children-Inhalt und kann sich weiterentwickeln, um umfangreichere Inhalte zu unterstützen. Derzeit wird ein Zeichenkettenfeld mit der Bezeichnung „Text" und einem Standardwert von '' verwendet. Wenn eine Komponente ausschließlich Zeichenketten-Children erfordert, deklariere stattdessen ein explizites children-Feld mit type: 'string'. Interactive.textSchema steuert typografische Stile; childrenSchema steuert den Inhalt. Das Children-Fragment ist nicht in baseSchema enthalten und wird nicht automatisch zu benutzerdefinierten Komponenten hinzugefügt. Verschachteltes Markup und berechnete Children sind derzeit schreibgeschützt. text-content ist ein veralteter Alias für den Feldtyp string. Siehe InteractivitySchema für alle Optionen.

Wiederverwendbare Komponenten als verbundene Kompositionen registrieren

Registriere Szenen und wiederverwendbare Elemente als eigenständige Kompositionen. Das Studio nennt diese verbundene Kompositionen: Sie können in einer eigenen Zeitachse geöffnet werden, während sie dieselbe Komponentenimplementierung wie das übergeordnete Video verwenden.

Definiere erforderliche Stile und lade Schriftarten innerhalb der Komponente, damit sie ohne ihr übergeordnetes Element funktioniert. Siehe Elternunabhängigkeit.

Registriere dieselbe exportierte Komponentenreferenz, die das übergeordnete Element rendert. Verwende für das obige Beispiel component={Chapter}, nicht ChapterInner oder einen Inline-Wrapper. Interactive.create() stellt die Sequenz bereit, sodass kein zusätzlicher <Sequence> für die Verbindung erforderlich ist.

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: 'Eine neue Perspektive',
      style: {
        backgroundColor: '#111111',
        justifyContent: 'center',
        alignItems: 'center',
      },
    }}
  />
);

Wähle eine eindeutige ID, repräsentative Inline-Standardwerte sowie Abmessungen, fps und Dauer, die für die Vorschau der Komponente geeignet sind. Registrierungsstandards kopieren nicht automatisch Eigenschaften von einer übergeordneten Instanz. Siehe verbundene Kompositionen für Details zur Registrierung und Extraktion.

Timing direkt auf der Komponente setzen

Vermeide einen separaten <Sequence> um eine Komponente, die bereits Timing-Eigenschaften akzeptiert. Integrierte interaktive Komponenten und mit Interactive.create() erstellte benutzerdefinierte Komponenten können name, from, durationInFrames, trimBefore und playbackRate direkt empfangen.

<Chapter
  name="Eröffnungsszene"
  from={30}
  durationInFrames={90}
  style={{opacity: 0.9}}
  title="Eine neue Perspektive"
/>

Für gemeinsames Szenen-Timing gruppiere den Inhalt in einer mit Interactive.create() erstellten Komponente und timing diese Instanz. Verwaltete Roots akzeptieren auch width und height für useVideoConfig().

Verwende <Track>, um Elemente in dieselbe Studio-Zeitachsenzeile zu setzen. Verwende <TransitionSeries>, wenn Szenen sequenziell sind.

Gib jedem unabhängig bearbeitbaren Element einen eigenen JSX-Knoten

Das Studio bearbeitet den JSX-Quellknoten, der ein Element erstellt hat. Wenn mehrere Laufzeitelemente vom selben JSX-Knoten stammen, teilen sie sich ein Quell-Bearbeitungsziel.

Schreibe für jede Kompositionsregistrierung, jeden Clip, jede Szene, jede Ebene oder Sequenz, die eigenständig bearbeitbar sein soll, einen separaten JSX-Knoten und behalte seine bearbeitbaren Eigenschaften auf diesem Knoten. Dies gilt für <Composition>, <Still>, integrierte Medienkomponenten, <Sequence>, <TransitionSeries.Sequence> und benutzerdefinierte Komponenten.

Erstelle zum Beispiel eine bearbeitbare Zeitachse so:

import { Track } from "remotion";

<Track name="Szenen">
  <Introduction name="Einleitung" durationInFrames={90} />
  <Demo name="Demo" from={90} durationInFrames={150} />
</Track>

Ein .map() oder eine andere programmatische Schleife würde mehrere Laufzeitelemente aus einem einzigen JSX-Quellknoten erstellen. Das ist geeignet für wiederholte Ausgaben, die absichtlich als eine Vorlage gesteuert werden, wie z. B. Visualisierungsbalken oder Partikel. Es ist nicht geeignet, wenn die Instanzen unabhängige IDs oder Namen, Eigenschaften, Metadaten, Timing, Reihenfolge, Löschung oder Duplikation im Studio benötigen.

Ein HTML-Element mit Interactive interaktiv machen

Jedes HTML- und SVG-Element (außer <Img>, das bereits interaktiv ist) wie <div> kann mit Interactive interaktiv gemacht werden:

<Interactive.Div
  name="Grußkarte"
  style={{fontSize: 80, padding: 24}}
>
  Hallo
</Interactive.Div>

Dies ermöglicht das Setzen von Stilen und Keyframes im Studio. Sei vernünftig – wenn eine Komponente viele Elemente enthält, könnte die Zeitachse unübersichtlich werden.

Bevorzuge Inline-Text

Wenn der Text festgelegt und nur einmal verwendet wird, schreibe ihn direkt in das interaktive Element, anstatt ihn in eine Konstante zu extrahieren.

// 👍 Fester Text bleibt bearbeitbar
<Interactive.Div name="Titel">
  Remotion Best Practices
</Interactive.Div>

Verwende eine Eigenschaft oder Variable nur, wenn der Text dynamisch oder wiederverwendet wird.

Gib interaktiven Elementen einen beschreibenden Namen

Füge Elementen eine name-Eigenschaft hinzu, um sie leicht identifizierbar zu machen. Vermeide berechnete Namen, gib sie fest ein.

<>
  <Interactive.Div name="Hero-Titel" style={{fontSize: 80}}>
    Launch-Tag
  </Interactive.Div>
  <Img name="Avatar" src="https://remotion.media/image.jpeg" />
  <Video name="Hintergrund" src="https://remotion.media/video.mp4" />
  <Interactive.Div name="Titel">
    Launch-Tag
  </Interactive.Div>
</>

Alle CSS-Stile inline halten

Am besten übergibst du einfach ein einfaches Objekt an style – ohne Verweise auf Konstanten, ohne Objekt-Spreading, ohne Mathematik.

<Interactive.Div
  style={{
    fontSize: 80,
    color: 'red',
  }}
>
  Hallo Welt!
</Interactive.Div>
const baseStyle = useMemo(() => {
  return {
    fontSize: 12 // ❌ Nicht-Inline-Stile werden nicht unterstützt
  }
}, []);

<Interactive.Div
  style={{
    ...baseStyle, // ❌ Spread wird nicht unterstützt
    color: RED, // ❌ Verweise auf Konstanten werden nicht unterstützt
    scale: frame * 10 // ❌ Mathematik wird nicht unterstützt
  }}
>
  Hallo Welt!
</Interactive.Div>

Mit interpolate() animieren

Schreibe Animationen als Inline-interpolate()-Aufrufe auf der Eigenschaft, die sich ändert. Der Ausgabebereich, das Easing, die Extrapolation und die output-Eigenschaft sollten fest codierte Werte verwenden.

Der Eingabebereich kann zusätzlich durationInFrames, fps, width und height verwenden, die direkt aus useVideoConfig() destructuring entnommen werden. Bloße Bezeichner wie durationInFrames, Multiplikation mit einer Zahl wie 2 * fps oder fps * 2 und Subtraktion einer Zahl wie durationInFrames - 1 werden unterstützt.

const {fps, durationInFrames} = useVideoConfig();

// 👍 Inline-Werte können standardisiert und keyframed werden
<Interactive.Div
  name="Produktkarte"
  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]); // ❌ Mathematik sollte direkt im Markup sein

<Interactive.Div
  name="Produktkarte"
  style={{
    translate: translateY, // ❌ Nur Inline-interpolate()-Aufrufe werden unterstützt,
    rotate: interpolate(frame, [start, start + 10], [0, Math.PI]), // ❌ Kann keine Mathematik mit beliebigen Variablen verwenden, kann keine Konstanten verwenden
    scale: interpolate(anyVariable, [0, 30], [0, 1]) // ❌ Kann nur die Variable `frame` interpretieren.
  }}
/>

SVG-Pfade mit Interactive.Path bearbeitbar halten

Verwende <Interactive.Path> aus remotion anstelle von <path> innerhalb eines SVG, um den Pfad visuell bearbeitbar zu machen.

Installiere @remotion/paths für Pfadinterpolation und Studio-Pfad-Keyframes:

bunx remotion add @remotion/paths

Wenn die Geometrie statisch sein soll, setze die Pfadzeichenkette direkt in die d-Eigenschaft. Extrahiere sie nicht in eine Konstante.

import {Interactive} from 'remotion';

<Interactive.Svg width={300} height={300} viewBox="0 0 300 300">
  <Interactive.Path
    name="Dreieck"
    d="M 40 40 L 260 40 L 150 260 Z"
    fill="#0b84f3"
  />
</Interactive.Svg>

Pfade mit Inline interpolieren

…

Individual skills in this repo

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

Verwandte Skills