diff --git a/.claude/skills/remotion-video/SKILL.md b/.claude/skills/remotion-video/SKILL.md index 754c137..41fbe22 100644 --- a/.claude/skills/remotion-video/SKILL.md +++ b/.claude/skills/remotion-video/SKILL.md @@ -80,5 +80,12 @@ export const Hello = ({ title }: { title: string }) => { - **Flicker**: an image or font not loaded; use `` and `@remotion/google-fonts`. - **Slow render**: lower resolution/fps while testing, or use `--concurrency`. +## Templates +Copy-paste starting points. Read the one that fits: +- `templates/captions.md` - words highlighted in time with speech +- `templates/charts.md` - animated bar chart +- `templates/intro-outro.md` - title card + chaining scenes with `Series` +- `templates/vertical.md` - 1080x1920 clips for Reels/TikTok/Shorts + ## Docs https://www.remotion.dev/docs diff --git a/.claude/skills/remotion-video/templates/captions.md b/.claude/skills/remotion-video/templates/captions.md new file mode 100644 index 0000000..a8ff260 --- /dev/null +++ b/.claude/skills/remotion-video/templates/captions.md @@ -0,0 +1,37 @@ +# Template: Captions + +Words appear in time with speech. Give each word a start time in seconds. + +`src/Captions.tsx` +```tsx +import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion"; + +type Word = { text: string; start: number; end: number }; // seconds + +export const Captions = ({ words }: { words: Word[] }) => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const t = frame / fps; + + // Show a window of up to 5 words around the current one. + const current = words.findIndex((w) => t >= w.start && t < w.end); + const i = current === -1 ? 0 : current; + const visible = words.slice(Math.floor(i / 5) * 5, Math.floor(i / 5) * 5 + 5); + + return ( + +
+ {visible.map((w, k) => ( + = w.start && t < w.end ? "#ffd400" : "white", marginRight: 16 }}> + {w.text} + + ))} +
+
+ ); +}; +``` + +Tips +- Get word times from a transcription tool (e.g. `@remotion/captions` or Whisper) and save them as JSON in `public/`. +- Layer it over the video: ``. diff --git a/.claude/skills/remotion-video/templates/charts.md b/.claude/skills/remotion-video/templates/charts.md new file mode 100644 index 0000000..9369abb --- /dev/null +++ b/.claude/skills/remotion-video/templates/charts.md @@ -0,0 +1,37 @@ +# Template: Animated bar chart + +Bars grow one after another. + +`src/BarChart.tsx` +```tsx +import { AbsoluteFill, spring, useCurrentFrame, useVideoConfig } from "remotion"; + +type Bar = { label: string; value: number }; + +export const BarChart = ({ data, color = "#4f8cff" }: { data: Bar[]; color?: string }) => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const max = Math.max(...data.map((d) => d.value)); + + return ( + +
+ {data.map((d, i) => { + const grow = spring({ frame: frame - i * 6, fps, config: { damping: 15 } }); + return ( +
+
+
{d.label}
+
+ ); + })} +
+ + ); +}; +``` + +Tips +- Delay each bar with `frame - i * 6` (6 frames apart). +- For lines, animate `strokeDashoffset` on an SVG path using `interpolate`. +- Keep numbers readable: show the value as text, rounded. diff --git a/.claude/skills/remotion-video/templates/intro-outro.md b/.claude/skills/remotion-video/templates/intro-outro.md new file mode 100644 index 0000000..e6089d6 --- /dev/null +++ b/.claude/skills/remotion-video/templates/intro-outro.md @@ -0,0 +1,34 @@ +# Template: Title intro / outro card + +A short card (2-3 seconds) with a title and subtitle. Use at the start or end. + +`src/TitleCard.tsx` +```tsx +import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; + +export const TitleCard = ({ title, subtitle }: { title: string; subtitle?: string }) => { + const frame = useCurrentFrame(); + const { fps, durationInFrames } = useVideoConfig(); + const rise = spring({ frame, fps, config: { damping: 14 } }); + const fadeOut = interpolate(frame, [durationInFrames - 15, durationInFrames], [1, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + + return ( + +

{title}

+ {subtitle &&

{subtitle}

} +
+ ); +}; +``` + +Chain with the main video using ``: +```tsx + + + + + +``` diff --git a/.claude/skills/remotion-video/templates/vertical.md b/.claude/skills/remotion-video/templates/vertical.md new file mode 100644 index 0000000..a8b008d --- /dev/null +++ b/.claude/skills/remotion-video/templates/vertical.md @@ -0,0 +1,23 @@ +# Template: Vertical clips (Reels / TikTok / Shorts) + +Same code, different size. Register a vertical composition: + +```tsx + +``` + +Render: `npx remotion render Vertical out/vertical.mp4` + +Rules +- Keep text inside the **safe zone**: about 150px from the top, 350px from the bottom (apps cover those parts with buttons and captions), and 60px from the sides. +- Use big text (60px+). Phone screens are small. +- Keep clips under 60 seconds (Shorts limit); 15-30 seconds does best. +- Use `useVideoConfig()` for width/height instead of hard-coding, so the same scene works wide and tall. +- Put captions in the lower-middle, above the bottom safe zone (see captions.md).