Remotion Composition
Generates composition structure documents that define how scenes are ordered, timed, and transitioned in a Remotion video. This skill focuses exclusively on Sequence layout and timing orchestration.
What This Skill Does
Generates composition structure for:
- Sequence layout — Ordering and positioning of scene Sequences
- Timing calculations — Start frames, end frames, duration for each scene
- Scene transitions — Overlap and crossfade timing between scenes
- Duration mapping — Converting seconds to frames for all scenes
- Timing constants — Structured timing object for constants.ts
Scope Boundaries
IN SCOPE:
- Sequence component organization
- Frame calculations for scene timing
- Scene overlap and transition timing
- Duration constant generation
- Scene ordering logic
OUT OF SCOPE:
- Scene component implementation (use
/remotion-component-gen) - Animation parameters (use
/remotion-animation) - Visual styling (colors, layouts)
- Asset management (use
/remotion-asset-coordinator)
Input/Output Formats
Input Format: Scene List with Durations
Accepts scene timing specifications:
Natural Language:
Scene 1 (Intro): 0-5 seconds
Scene 2 (Features): 5-15 seconds
Scene 3 (Demo): 15-25 seconds
Scene 4 (CTA): 25-30 seconds
Structured Format:
## Scene Timing
**Total Duration:** 30 seconds
**Frame Rate:** 30 fps
**Total Frames:** 900
**Scenes:**
1. Scene 1 - Intro: 5 seconds (0s - 5s)
2. Scene 2 - Features: 10 seconds (5s - 15s)
3. Scene 3 - Demo: 10 seconds (15s - 25s)
4. Scene 4 - CTA: 5 seconds (25s - 30s)
**Transitions:**
- Fade transition between scenes: 0.5 seconds (15 frames)
Output Format: COMPOSITION_STRUCTURE.md
Generates composition structure document:
# Composition Structure: ProductDemo
## Status
✅ Sequence layout defined
✅ Timing calculations complete
⏳ Ready for scene implementation
## Composition Overview
**Total Duration:** 30 seconds (900 frames @ 30fps)
**Scenes:** 4
**Transitions:** Crossfade (15 frames)
## Scene Timing Constants
```typescript
const FPS = 30;
export const SCENE_TIMING = {
intro: {
start: 0,
end: 150,
duration: 150,
// 0s - 5s
},
features: {
start: 150,
end: 450,
duration: 300,
// 5s - 15s
},
demo: {
start: 450,
end: 750,
duration: 300,
// 15s - 25s
},
cta: {
start: 750,
end: 900,
duration: 150,
// 25s - 30s
},
} as const;
// Transition timing
export const TRANSITIONS = {
crossfadeDuration: 15, // frames (0.5 seconds)
} as const;
Composition Layout
Main composition with Sequence structure:
import { AbsoluteFill, Sequence } from "remotion";
import { SCENE_TIMING } from "./constants";
import { Scene1Intro } from "./scenes/Scene1Intro";
import { Scene2Features } from "./scenes/Scene2Features";
import { Scene3Demo } from "./scenes/Scene3Demo";
import { Scene4CTA } from "./scenes/Scene4CTA";
export function ProductDemo() {
return (
<AbsoluteFill>
{/* Scene 1: Intro (0s - 5s) */}
<Sequence
from={SCENE_TIMING.intro.start}
durationInFrames={SCENE_TIMING.intro.duration}
>
<Scene1Intro />
</Sequence>
{/* Scene 2: Features (5s - 15s) */}
<Sequence
from={SCENE_TIMING.features.start}
durationInFrames={SCENE_TIMING.features.duration}
>
<Scene2Features />
</Sequence>
{/* Scene 3: Demo (15s - 25s) */}
<Sequence
from={SCENE_TIMING.demo.start}
durationInFrames={SCENE_TIMING.demo.duration}
>
<Scene3Demo />
</Sequence>
{/* Scene 4: CTA (25s - 30s) */}
<Sequence
from={SCENE_TIMING.cta.start}
durationInFrames={SCENE_TIMING.cta.duration}
>
<Scene4CTA />
</Sequence>
</AbsoluteFill>
);
}
Scene Timing Breakdown
| Scene | Name | Duration | Frames | Start Frame | End Frame |
|---|---|---|---|---|---|
| 1 | Intro | 5s | 150 | 0 | 150 |
| 2 | Features | 10s | 300 | 150 | 450 |
| 3 | Demo | 10s | 300 | 450 | 750 |
| 4 | CTA | 5s | 150 | 750 | 900 |
Total: 30 seconds (900 frames)
Timeline Visualization
Frame: 0 150 450 750 900
Time: 0s 5s 15s 25s 30s
|---------|---------|---------|---------|
Scene: | Intro | Features| Demo | CTA |
|---------|---------|---------|---------|
Next Steps
- Implement scenes via
/remotion-component-gen - Add transitions if needed (crossfades, wipes)
- Integrate constants into composition constants.ts
- Test timing in Remotion preview
- Adjust durations if scenes feel too fast/slow
Checklist
- Scene timing calculated
- Sequence layout defined
- Constants generated
- Timing constants structured
- Scene components implemented (next step)
- Transitions added (if needed)
- Timing tested in preview
## Composition Patterns
### Pattern 1: Sequential Scenes (No Overlap)
Standard sequential layout where scenes don't overlap:
```typescript
<Sequence from={0} durationInFrames={150}>
<Scene1 />
</Sequence>
<Sequence from={150} durationInFrames={300}>
<Scene2 />
</Sequence>
<Sequence from={450} durationInFrames={300}>
<Scene3 />
</Sequence>
Pattern 2: Overlapping Scenes (Crossfade)
Scenes overlap for smooth transitions:
const CROSSFADE = 15; // frames
// Scene 1: Full duration
<Sequence from={0} durationInFrames={150}>
<Scene1 />
</Sequence>
// Scene 2: Starts before Scene 1 ends
<Sequence from={150 - CROSSFADE} durationInFrames={300 + CROSSFADE}>
<Scene2 />
</Sequence>
// Scene 3: Starts before Scene 2 ends
<Sequence from={450 - CROSSFADE} durationInFrames={300 + CROSSFADE}>
<Scene3 />
</Sequence>
Pattern 3: Layered Composition
Background + foreground scenes running simultaneously:
{/* Background layer - runs full duration */}
<Sequence from={0} durationInFrames={900}>
<BackgroundScene />
</Sequence>
{/* Foreground scenes - sequential */}
<Sequence from={0} durationInFrames={150}>
<Scene1 />
</Sequence>
<Sequence from={150} durationInFrames={300}>
<Scene2 />
</Sequence>
Pattern 4: Nested Sequences
Sub-scenes within main scenes:
<Sequence from={0} durationInFrames={300}>
<AbsoluteFill>
{/* Sub-scene 1 */}
<Sequence from={0} durationInFrames={100}>
<Intro />
</Sequence>
{/* Sub-scene 2 */}
<Sequence from={100} durationInFrames={200}>
<MainContent />
</Sequence>
</AbsoluteFill>
</Sequence>
Timing Calculation Helpers
Common frame calculations:
// Convert seconds to frames
const secondsToFrames = (seconds: number, fps: number = 30): number =>
Math.round(seconds * fps);
// Calculate scene timing
interface SceneTiming {
start: number;
end: number;
duration: number;
}
const calculateSceneTiming = (
startSeconds: number,
durationSeconds: number,
fps: number = 30
): SceneTiming => {
const start = secondsToFrames(startSeconds, fps);
const duration = secondsToFrames(durationSeconds, fps);
const end = start + duration;
return { start, end, duration };
};
// Calculate crossfade overlap
const calculateCrossfade = (
scene1Start: number,
scene1Duration: number,
crossfadeDuration: number
) => ({
scene1: {
from: scene1Start,
durationInFrames: scene1Duration,
},
scene2: {
from: scene1Start + scene1Duration - crossfadeDuration,
durationInFrames: crossfadeDuration, // or more if scene is longer
},
});
// Validate total duration
const validateDuration = (
scenes: SceneTiming[],
expectedTotal: number
): boolean => {
const lastScene = scenes[scenes.length - 1];
return lastScene.end === expectedTotal;
};
Scene Timing Generation
Automated timing generation