# @json-render/remotion
Remotion video renderer for json-render. Turn JSON timeline specs into video compositions.
## Installation
```bash
npm install @json-render/remotion @json-render/core remotion @remotion/player zod
```
## Quick Start
### 1. Create a Catalog
```typescript
import { defineCatalog } from "@json-render/core";
import {
schema,
standardComponentDefinitions,
standardTransitionDefinitions,
standardEffectDefinitions,
} from "@json-render/remotion";
// Use standard definitions or add your own
export const videoCatalog = defineCatalog(schema, {
components: {
...standardComponentDefinitions,
// Add custom components here
},
transitions: standardTransitionDefinitions,
effects: standardEffectDefinitions,
});
```
### 2. Render with the Player
```tsx
import { Player } from "@remotion/player";
import { Renderer } from "@json-render/remotion";
function VideoPlayer({ spec }) {
return (
);
}
```
## Timeline Spec Format
```typescript
interface TimelineSpec {
composition: {
id: string;
fps: number;
width: number;
height: number;
durationInFrames: number;
};
tracks: Array<{
id: string;
name: string;
type: "video" | "overlay" | "audio";
enabled: boolean;
}>;
clips: Array<{
id: string;
trackId: string;
component: string; // Component name from catalog
props: object; // Component-specific props
from: number; // Start frame
durationInFrames: number;
transitionIn?: {
type: string;
durationInFrames: number;
};
transitionOut?: {
type: string;
durationInFrames: number;
};
}>;
audio: {
tracks: Array<{
id: string;
src: string;
from: number;
durationInFrames: number;
volume?: number;
}>;
};
}
```
Example spec:
```json
{
"composition": {
"id": "intro-video",
"fps": 30,
"width": 1920,
"height": 1080,
"durationInFrames": 300
},
"tracks": [
{ "id": "main", "name": "Main Video", "type": "video", "enabled": true },
{ "id": "overlay", "name": "Overlays", "type": "overlay", "enabled": true }
],
"clips": [
{
"id": "clip-1",
"trackId": "main",
"component": "TitleCard",
"props": {
"title": "Welcome",
"subtitle": "To the future",
"backgroundColor": "#1a1a1a",
"textColor": "#ffffff"
},
"from": 0,
"durationInFrames": 90,
"transitionIn": { "type": "fade", "durationInFrames": 15 },
"transitionOut": { "type": "fade", "durationInFrames": 15 }
}
],
"audio": { "tracks": [] }
}
```
## Standard Components
The package includes pre-built video components:
| Component | Description | Key Props |
|-----------|-------------|-----------|
| `TitleCard` | Full-screen title with subtitle | `title`, `subtitle`, `backgroundColor`, `textColor` |
| `ImageSlide` | Full-screen image display | `src`, `alt`, `fit` |
| `SplitScreen` | Two-column layout | `leftTitle`, `rightTitle`, `leftContent`, `rightContent` |
| `QuoteCard` | Quote with attribution | `quote`, `author`, `role` |
| `StatCard` | Large statistic display | `value`, `label`, `trend` |
| `LowerThird` | Name/title overlay | `name`, `title` |
| `TextOverlay` | Centered text | `text`, `fontSize`, `fontFamily` |
| `TypingText` | Terminal typing effect | `text`, `charsPerSecond`, `showCursor` |
| `LogoBug` | Corner logo overlay | `src`, `position`, `size` |
| `VideoClip` | Video playback | `src` |
## Standard Transitions
| Transition | Description |
|------------|-------------|
| `fade` | Opacity fade in/out |
| `slideLeft` | Slide from right |
| `slideRight` | Slide from left |
| `slideUp` | Slide from bottom |
| `slideDown` | Slide from top |
| `zoom` | Scale zoom in/out |
| `wipe` | Horizontal wipe |
## Custom Components
Add custom components to the Renderer:
```tsx
import { Renderer, standardComponents, ClipWrapper } from "@json-render/remotion";
import type { Clip } from "@json-render/remotion";
// Define a custom component
function CustomOverlay({ clip }: { clip: Clip }) {
return (
{clip.props.message}
);
}
// Merge with standard components
const customComponents = {
...standardComponents,
CustomOverlay,
};
// Pass to Renderer
```
## Hooks and Utilities
### useTransition
Calculate transition styles for a clip:
```tsx
import { useTransition } from "@json-render/remotion";
import { useCurrentFrame } from "remotion";
function MyComponent({ clip }: { clip: Clip }) {
const frame = useCurrentFrame();
const transition = useTransition(clip, frame);
return (
Content
);
}
```
### ClipWrapper
Apply transitions automatically:
```tsx
import { ClipWrapper } from "@json-render/remotion";
function MyComponent({ clip }: { clip: Clip }) {
return (
{/* Content gets transition styles applied */}
My content
);
}
```
## Generate AI Prompts
```typescript
const systemPrompt = videoCatalog.prompt();
// Returns detailed prompt with:
// - Component descriptions and props
// - Transition types
// - Effect definitions
// - Timeline spec format requirements
```
## Exports
### Components
```typescript
import {
// Main renderer
Renderer,
standardComponents,
// Standard components
TitleCard,
ImageSlide,
SplitScreen,
QuoteCard,
StatCard,
LowerThird,
TextOverlay,
TypingText,
LogoBug,
VideoClip,
// Utilities
ClipWrapper,
useTransition,
} from "@json-render/remotion";
```
### Types
```typescript
import type {
Clip,
TimelineSpec,
AudioTrack,
TransitionStyles,
ClipComponent,
ComponentRegistry,
} from "@json-render/remotion";
```
### Schema and Catalog Definitions
```typescript
import {
schema,
standardComponentDefinitions,
standardTransitionDefinitions,
standardEffectDefinitions,
} from "@json-render/remotion";
```
## Why Different from React?
| Feature | @json-render/react | @json-render/remotion |
|---------|-------------------|----------------------|
| Spec Format | Element tree (nested components) | Timeline (tracks + clips) |
| Components | UI components (Button, Card) | Video components (scenes, overlays) |
| Timing | User interactions | Frame-based animations |
| Output | React DOM | Remotion video |
json-render is "JSON to render" - the spec format and components are completely flexible per renderer.