agentsclimarketplace

Remotion

Skill PIXARTSeu/Synapse/packages/codegraph/data/skill/remotion

Remotion knowledge base - programmatic video creation with React, rendering, compositions, animations. Use when creating programmatic videos, building Remotion compositions, rendering video with React, or creating social video clips.From its SKILL.md

Install
npx -y skills add PIXARTSeu/Synapse --skill remotion

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.4 KB, ~2.3k tokens by cl100k_base, as published. Nobody here has run it

Remotion Knowledge Base

React framework per creazione video programmatica. Versione stabile: v4.0.410+.

Installazione (Next.js 15 esistente)

pnpm add remotion @remotion/cli @remotion/player @remotion/bundler zod
pnpm add @remotion/renderer                         # Server-side rendering
pnpm add @remotion/shapes @remotion/paths @remotion/google-fonts @remotion/zod-types
pnpm add -D @remotion/tailwind-v4 tailwindcss @tailwindcss/postcss

Struttura Progetto

├── remotion.config.ts
├── src/remotion/
│   ├── index.ts              # registerRoot() entry point
│   ├── Root.tsx              # <Composition> definitions
│   └── compositions/
│       ├── IntroVideo/       # Main.tsx + schema.ts
│       ├── SocialClip/
│       └── ProductShowcase/
├── public/videos/assets/     # staticFile() references
└── out/                      # Rendered output (gitignored)

File Chiave

remotion.config.ts

import { Config } from "@remotion/cli/config";
import { enableTailwind } from "@remotion/tailwind-v4";

Config.setVideoImageFormat("jpeg");
Config.overrideWebpackConfig((config) => enableTailwind(config));

Entry Point + Root

// src/remotion/index.ts
import { registerRoot } from "remotion";
import { RemotionRoot } from "./Root";
registerRoot(RemotionRoot);

// src/remotion/Root.tsx
import { Composition } from "remotion";
import { IntroVideo } from "./compositions/IntroVideo/Main";
import { introSchema } from "./compositions/IntroVideo/schema";

export const RemotionRoot: React.FC = () => (
  <>
    <Composition id="IntroVideo" component={IntroVideo} schema={introSchema}
      defaultProps={{ title: "Welcome", primaryColor: "#0066cc" }}
      durationInFrames={150} fps={30} width={1920} height={1080} />
  </>
);

Schema con Zod

import { z } from "zod";
import { zColor } from "@remotion/zod-types";

export const introSchema = z.object({
  title: z.string(),
  subtitle: z.string().optional(),
  primaryColor: zColor(),
  logoUrl: z.string().url().optional(),
});
export type IntroProps = z.infer<typeof introSchema>;

API Core

import {
  AbsoluteFill, interpolate, Sequence, Series, Loop, Freeze,
  useCurrentFrame, useVideoConfig, spring, interpolateColors,
  Easing, Img, Audio, staticFile, delayRender, continueRender,
} from "remotion";

// --- useCurrentFrame / useVideoConfig ---
const frame = useCurrentFrame();                     // 0, 1, 2...
const { fps, durationInFrames, width, height } = useVideoConfig();

// --- interpolate (SEMPRE con clamp!) ---
const opacity = interpolate(frame, [0, 30], [0, 1], {
  extrapolateLeft: "clamp", extrapolateRight: "clamp",
});
const translateY = interpolate(frame, [0, 30], [50, 0], {
  extrapolateRight: "clamp", easing: Easing.bezier(0.25, 0.1, 0.25, 1),
});

// --- spring (animazioni naturali) ---
const scale = spring({ frame, fps, config: { damping: 200 } });
const delayed = spring({ frame: frame - 25, fps, config: { damping: 100, stiffness: 100 } });

// --- interpolateColors ---
const color = interpolateColors(frame, [0, 30, 60], ["#ff0000", "#00ff00", "#0000ff"]);

// --- Sequence (time-shifting, overlap possibile) ---
<Sequence from={0} durationInFrames={30}><Scene1 /></Sequence>
<Sequence from={30} durationInFrames={60}><Scene2 /></Sequence>

// --- Series (sequenziale, no overlap) ---
<Series>
  <Series.Sequence durationInFrames={30}><Scene1 /></Series.Sequence>
  <Series.Sequence durationInFrames={60}><Scene2 /></Series.Sequence>
</Series>

// --- delayRender (blocca render per dati async) ---
const [handle] = useState(() => delayRender("Loading..."));
useEffect(() => {
  fetch("/api/data").then(r => r.json()).then(data => {
    setData(data); continueRender(handle);
  });
}, [handle]);

// --- Media ---
<Img src={staticFile("logo.png")} />
<Audio src={staticFile("music.mp3")} volume={0.5} />

Player (Embedding in Next.js)

"use client";
import { Player, PlayerRef } from "@remotion/player";
import { IntroVideo } from "@/remotion/compositions/IntroVideo/Main";

const playerRef = useRef<PlayerRef>(null);

<Player ref={playerRef} component={IntroVideo}
  inputProps={{ title: "Hello", primaryColor: "#0066cc" }}
  durationInFrames={150} fps={30}
  compositionWidth={1920} compositionHeight={1080}
  style={{ width: "100%" }} controls autoPlay loop />

// PlayerRef: play(), pause(), toggle(), seekTo(frame), getCurrentFrame(), requestFullscreen()

CLI Rendering

npx remotion studio                                  # Preview interattivo
npx remotion render IntroVideo out/video.mp4         # MP4 (H.264)
npx remotion render --codec=vp8 IntroVideo out/v.webm # WebM (trasparenza)
npx remotion render --codec=gif --every-nth-frame=2 IntroVideo out/v.gif
npx remotion render IntroVideo out/v.mp4 --props='{"title":"Custom"}'
npx remotion render IntroVideo out/v.mp4 --crf=18    # Qualità alta
CodecFormatoNote
h264MP4Default, più compatibile
h265MP4Compressione migliore
vp8/vp9WebMSupporta trasparenza
gifGIFUsa --every-nth-frame=2

Server-Side Rendering

import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";

export async function renderVideo(compositionId: string, inputProps: Record<string, unknown>, outputPath: string) {
  const bundleLocation = await bundle({ entryPoint: "./src/remotion/index.ts" });
  const composition = await selectComposition({ serveUrl: bundleLocation, id: compositionId, inputProps });
  await renderMedia({ codec: "h264", composition, serveUrl: bundleLocation, outputLocation: outputPath, inputProps,
    chromiumOptions: { enableMultiProcessOnLinux: true } });
}

Docker

FROM node:22-bookworm-slim
RUN apt-get update && apt-get install -y libnss3 libdbus-1-3 libatk1.0-0 libgbm-dev libasound2 \
  libxrandr2 libxkbcommon-dev libxfixes3 libxcomposite1 libxdamage1 libatk-bridge2.0-0 \
  libpango-1.0-0 libcairo2 libcups2 && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN npm ci && npx remotion browser ensure
CMD ["node", "render.mjs"]

Docker rules: Debian only (no Alpine), no FFmpeg needed (bundled), npx remotion browser ensure per Chromium, --cpus=16 per performance.

Dimensioni Standard

PiattaformaDimensioniDurata tipica
YouTube/LinkedIn1920×10805-30s
Instagram Reel/TikTok/Stories1080×192015-60s
Instagram Post1080×10809-15s
OG Preview1200×6303-5s
Twitter/X1280×72015-60s

Tailwind v4 in Remotion

// remotion.config.ts — già configurato sopra
// postcss.config.mjs
export default { plugins: { "@tailwindcss/postcss": {} } };
// src/remotion/styles.css (importare in Root.tsx)
@import "tailwindcss";

Se package.json ha "sideEffects": false, cambiare a "sideEffects": ["*.css"].

API Aggiuntive

APIPackageUso
<OffthreadVideo>remotionVideo sync con timeline
<Loop>remotionRipeti contenuto N volte
<Freeze>remotionCongela a frame specifico
measureSpring()remotionDurata spring in frames
@remotion/shapesshapesSVG: Circle, Rect, Triangle
@remotion/pathspathsManipolazione SVG path
@remotion/google-fontsgoogle-fontsCarica Google Fonts
@remotion/zod-typeszod-typeszColor, zTextarea

NPM Scripts

{
  "remotion:studio": "remotion studio",
  "remotion:render": "remotion render IntroVideo out/video.mp4",
  "remotion:render:gif": "remotion render --codec=gif --every-nth-frame=2 IntroVideo out/video.gif"
}

Best Practices

  1. Composizioni pure React — deterministiche, no side effects
  2. Zod schemas per ogni composizione
  3. SEMPRE clamp su interpolate (extrapolateRight: "clamp")
  4. spring() per animazioni naturali
  5. delayRender per async (font, dati, immagini)
  6. Sequence/Series per organizzare scene
  7. OffthreadVideo per video di sfondo
  8. 30 FPS sufficiente per web
  9. Test in Studio prima di renderizzare
  10. Docker: solo Debian, mai Alpine

What ships with it: 3 files

2.6 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.