skills/remotion-animations/SKILL.md
Advanced animation patterns, transitions, and effects for Remotion. Use when the user mentions 'animate', 'transition', 'spring', 'easing', 'effect', 'motion', 'interpolate', 'keyframe', or asks about Remotion animation techniques.
npx skillsauth add mylesfranklin/skills remotion-animationsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Springs create natural, physics-based motion.
import { spring } from 'remotion';
// Smooth, no bounce (subtle reveals)
const smooth = spring({
fps,
frame,
config: { damping: 200 }
});
// Snappy, minimal bounce (UI elements)
const snappy = spring({
fps,
frame,
config: { damping: 20, stiffness: 200 }
});
// Bouncy entrance (playful animations)
const bouncy = spring({
fps,
frame,
config: { damping: 8 }
});
// Heavy, slow, small bounce
const heavy = spring({
fps,
frame,
config: { damping: 15, stiffness: 80, mass: 2 }
});
const delayedSpring = spring({
fps,
frame: frame - 30, // Start 30 frames later
config: { damping: 200 }
});
const timedSpring = spring({
fps,
frame,
durationInFrames: 60, // Stretch to exactly 60 frames
config: { damping: 200 }
});
import { Easing } from 'remotion';
// Basic easing
Easing.linear
Easing.ease
Easing.quad
Easing.cubic
Easing.quart
Easing.quint
Easing.sin
Easing.expo
Easing.circ
Easing.back
Easing.elastic
Easing.bounce
// Combine with in/out/inOut
Easing.in(Easing.quad) // Accelerate
Easing.out(Easing.quad) // Decelerate
Easing.inOut(Easing.quad) // Both
// Custom bezier
Easing.bezier(0.4, 0, 0.2, 1) // Material design easing
const value = interpolate(frame, [0, 100], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp'
});
const value = interpolate(
frame,
[0, 30, 60, 90], // Keyframe positions
[0, 1, 1, 0], // Values at each keyframe
{ extrapolateLeft: 'clamp', extrapolateRight: 'clamp' }
);
const value = interpolate(frame, [0, 60], [0, 1], {
easing: Easing.inOut(Easing.cubic),
extrapolateRight: 'clamp'
});
import { TransitionSeries } from '@remotion/transitions';
import {
fade,
wipe,
flip,
cube,
slide
} from '@remotion/transitions';
import {
linearTiming,
springTiming
} from '@remotion/transitions';
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={60}>
<Scene1 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
timing={springTiming({ config: { damping: 200 } })}
presentation={fade()}
/>
<TransitionSeries.Sequence durationInFrames={60}>
<Scene2 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
timing={linearTiming({ durationInFrames: 15 })}
presentation={wipe({ direction: 'from-left' })}
/>
<TransitionSeries.Sequence durationInFrames={60}>
<Scene3 />
</TransitionSeries.Sequence>
</TransitionSeries>
| Transition | Options |
|------------|---------|
| fade() | None |
| wipe() | direction: 'from-left' \| 'from-right' \| 'from-top' \| 'from-bottom' |
| flip() | direction: 'from-left' \| 'from-right' |
| cube() | direction: 'from-left' \| 'from-right' |
| slide() | direction: 'from-left' \| 'from-right' |
import {
interpolateStyles,
makeTransform,
translateX,
translateY,
translateZ,
rotate,
rotateX,
rotateY,
rotateZ,
scale
} from '@remotion/animation-utils';
// Animate multiple properties
const styles = interpolateStyles(
frame,
[0, 30, 60],
[
{
opacity: 0,
transform: makeTransform([translateY(-50), scale(0.8)])
},
{
opacity: 1,
transform: makeTransform([translateY(0), scale(1)])
},
{
opacity: 0,
transform: makeTransform([translateY(50), scale(0.8)])
}
]
);
return <div style={styles}>Content</div>;
import { interpolateColors } from 'remotion';
const color = interpolateColors(
frame,
[0, 60],
['#ff0000', '#0000ff']
);
return <div style={{ backgroundColor: color }} />;
import { MotionBlur } from '@remotion/motion-blur';
<MotionBlur shutterAngle={180}>
<MovingComponent />
</MotionBlur>
import { noise } from '@remotion/noise';
// Perlin noise
const n = noise(frame * 0.01);
// For visual effects
<div style={{
transform: `translateY(${n * 20}px)`
}} />
import { interpolatePath } from '@remotion/paths';
const path = interpolatePath(
frame,
[0, 60],
[
'M 0 0 L 100 0 L 100 100 L 0 100 Z',
'M 50 0 L 100 50 L 50 100 L 0 50 Z'
]
);
<svg>
<path d={path} fill="red" />
</svg>
import { Lottie } from '@remotion/lottie';
import animationData from './animation.json';
<Lottie
animationData={animationData}
playbackRate={1}
/>
import { ThreeCanvas } from '@remotion/three';
<ThreeCanvas
width={1920}
height={1080}
>
<ambientLight intensity={0.5} />
<pointLight position={[10, 10, 10]} />
<mesh rotation={[0, frame * 0.02, 0]}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="hotpink" />
</mesh>
</ThreeCanvas>
const text = "Hello World";
const chars = text.split('');
return (
<div>
{chars.map((char, i) => {
const charFrame = frame - i * 2;
const opacity = interpolate(charFrame, [0, 10], [0, 1], {
extrapolateRight: 'clamp'
});
return (
<span key={i} style={{ opacity }}>
{char}
</span>
);
})}
</div>
);
const text = "Hello World";
const charsToShow = Math.floor(interpolate(frame, [0, 60], [0, text.length]));
const visibleText = text.slice(0, charsToShow);
return <div>{visibleText}</div>;
import { useAudioData, visualizeAudio } from '@remotion/media-utils';
const audioData = useAudioData(staticFile('audio.mp3'));
if (!audioData) {
return null;
}
const visualization = visualizeAudio({
fps,
frame,
audioData,
numberOfSamples: 10
});
return (
<div style={{ display: 'flex', gap: 4 }}>
{visualization.map((v, i) => (
<div
key={i}
style={{
height: `${v * 200}px`,
width: '20px',
backgroundColor: 'blue'
}}
/>
))}
</div>
);
// Parallax layers
const layer1Offset = interpolate(frame, [0, 300], [0, -100]);
const layer2Offset = interpolate(frame, [0, 300], [0, -200]);
const layer3Offset = interpolate(frame, [0, 300], [0, -400]);
return (
<AbsoluteFill>
<div style={{ transform: `translateY(${layer1Offset}px)` }}>
<Background />
</div>
<div style={{ transform: `translateY(${layer2Offset}px)` }}>
<Midground />
</div>
<div style={{ transform: `translateY(${layer3Offset}px)` }}>
<Foreground />
</div>
</AbsoluteFill>
);
development
Query the Polymarket Wallet Hunter API and AlloyDB. Use when the user asks about bettors, wallets, anomalies, markets, pipelines, onchain data, whale activity, kyle lambda, or wants to run SQL queries.
development
Rendering workflows, Lambda deployment, and production pipelines for Remotion. Use when the user mentions 'render', 'deploy', 'lambda', 'export', 'build', 'bundle', 'production', 'CI/CD', or asks about rendering Remotion videos.
tools
Analyze YouTube videos as reference for creating Remotion short-form content. Use when the user provides a YouTube URL, mentions 'reference video', 'short form', 'clip factory', 'reels', 'tiktok', 'shorts', or wants to create short clips from a video source.
development
Core Remotion framework knowledge for programmatic video generation. Use when working with .tsx/.ts video components, creating Remotion compositions, or when the user mentions 'video', 'remotion', 'composition', 'useCurrentFrame', 'programmatic video', or 'react video'.