Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds
Volver a colecciones
Guide18 min read

Remotion - Tworzenie Wideo za Pomocą Reacta

Remotion is a framework for programmatic video creation using React. React components, TypeScript, CSS, Canvas, and WebGL for generating professional animations and videos.

Remotion - Tworzenie Wideo za Pomocą Reacta

Czym jest Remotion?

Remotion to framework umożliwiający tworzenie wideo za pomocą technologii webowych - Reacta, TypeScriptu, CSS, Canvas i WebGL. Zamiast używać After Effects czy Premiere Pro, piszesz kod, który generuje profesjonalne animacje i filmy.

Wyobraź sobie, że możesz:

  • Tworzyć animowane intro używając komponentów React
  • Generować spersonalizowane wideo dla tysięcy użytkowników
  • Automatyzować produkcję video marketingu
  • Budować interaktywne wizualizacje danych

Remotion sprawia, że video production staje się programowaniem.

Główne zalety

  • React - Używaj komponentów, hooks, state
  • TypeScript - Pełna typizacja
  • Technologie web - CSS, Canvas, SVG, WebGL
  • Programmatic - Zmienne, funkcje, algorytmy
  • Renderowanie - MP4, WebM, GIF

GitHub

Repository: github.com/remotion-dev/remotion

Dokumentacja: remotion.dev/docs

Status: 31k+ GitHub stars | TypeScript | Aktywny development

Dlaczego Remotion?

Problem z tradycyjną produkcją wideo

  1. Ręczna praca - After Effects wymaga ręcznej edycji
  2. Brak skalowalności - Nie możesz wygenerować 1000 spersonalizowanych wideo
  3. Trudna automatyzacja - Skrypty ExtendScript są ograniczone
  4. Brak wersjonowania - Trudno śledzić zmiany w projektach
  5. Kosztowne narzędzia - Adobe CC to $55/miesiąc

Rozwiązanie Remotion

Code
TEXT
┌─────────────────────────────────────────────────────────────┐
│                     REMOTION WORKFLOW                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   React Components  ->  Video Preview  ->  MP4/WebM/GIF     │
│                                                              │
│   ┌────────────┐    ┌────────────┐    ┌────────────┐        │
│   │   Code     │    │   Live     │    │   Export   │        │
│   │  (React)   │ -> │  Preview   │ -> │   Video    │        │
│   └────────────┘    └────────────┘    └────────────┘        │
│                                                              │
│   Benefits:                                                  │
│   - Version control (Git)                                    │
│   - Reusable components                                      │
│   - Data-driven generation                                   │
│   - API integration                                          │
│   - CI/CD rendering                                          │
└─────────────────────────────────────────────────────────────┘

Kluczowe zalety

  1. React ecosystem - Komponenty, hooks, npm packages
  2. Programmatic - Logika, warunki, pętle
  3. Data-driven - Generuj wideo z danych
  4. Scalable - Tysiące wideo automatycznie
  5. Version control - Git, code review, CI/CD
  6. Free to use - Open-source (z licencją dla firm)

Instalacja

Nowy projekt

Code
Bash
# Utwórz nowy projekt Remotion
npx create-video@latest

# Struktura projektu:
# my-video/
# ├── src/
# │   ├── Composition.tsx    # Główna kompozycja
# │   ├── Video.tsx          # Root component
# │   └── index.tsx          # Entry point
# ├── package.json
# └── remotion.config.ts

Uruchomienie preview

Code
Bash
cd my-video

# Start development server
npm start

# Otwiera się Remotion Studio na localhost:3000

Renderowanie wideo

Code
Bash
# Render do MP4
npx remotion render src/index.tsx MyComposition out/video.mp4

# Render do GIF
npx remotion render src/index.tsx MyComposition out/animation.gif

# Render z custom settings
npx remotion render src/index.tsx MyComposition out/video.mp4 \
  --codec h264 \
  --quality 100 \
  --frames 0-300

Podstawy Remotion

Kompozycja

TSsrc/Root.tsx
TypeScript
// src/Root.tsx
import { Composition } from 'remotion'
import { MyVideo } from './MyVideo'

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyVideo"
      component={MyVideo}
      durationInFrames={150}  // 5 sekund przy 30fps
      fps={30}
      width={1920}
      height={1080}
    />
  )
}

Podstawowy komponent wideo

TSsrc/MyVideo.tsx
TypeScript
// src/MyVideo.tsx
import { useCurrentFrame, useVideoConfig, interpolate } from 'remotion'

export const MyVideo = () => {
  const frame = useCurrentFrame()
  const { durationInFrames } = useVideoConfig()

  // Animacja opacity: 0 -> 1 przez pierwsze 30 klatek
  const opacity = interpolate(
    frame,
    [0, 30],
    [0, 1],
    { extrapolateRight: 'clamp' }
  )

  // Animacja pozycji
  const translateY = interpolate(
    frame,
    [0, 30],
    [50, 0],
    { extrapolateRight: 'clamp' }
  )

  return (
    <div style={{
      flex: 1,
      backgroundColor: '#0f0f0f',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center'
    }}>
      <h1 style={{
        fontSize: 100,
        color: 'white',
        opacity,
        transform: `translateY(${translateY}px)`
      }}>
        Hello Remotion!
      </h1>
    </div>
  )
}

Sekwencje

TSsrc/VideoWithSequences.tsx
TypeScript
// src/VideoWithSequences.tsx
import { Sequence, useCurrentFrame } from 'remotion'
import { Intro } from './Intro'
import { MainContent } from './MainContent'
import { Outro } from './Outro'

export const VideoWithSequences = () => {
  return (
    <>
      {/* Intro: klatki 0-60 (2 sekundy) */}
      <Sequence from={0} durationInFrames={60}>
        <Intro />
      </Sequence>

      {/* Main content: klatki 60-240 (6 sekund) */}
      <Sequence from={60} durationInFrames={180}>
        <MainContent />
      </Sequence>

      {/* Outro: klatki 240-300 (2 sekundy) */}
      <Sequence from={240} durationInFrames={60}>
        <Outro />
      </Sequence>
    </>
  )
}

Animacje z spring

Code
TypeScript
import { spring, useCurrentFrame, useVideoConfig } from 'remotion'

export const SpringAnimation = () => {
  const frame = useCurrentFrame()
  const { fps } = useVideoConfig()

  // Spring animation dla naturalnego ruchu
  const scale = spring({
    frame,
    fps,
    config: {
      damping: 10,
      stiffness: 100,
      mass: 1
    }
  })

  return (
    <div style={{
      transform: `scale(${scale})`,
      width: 200,
      height: 200,
      backgroundColor: '#3b82f6',
      borderRadius: 20
    }} />
  )
}

Zaawansowane funkcje

Ładowanie zewnętrznych danych

TSsrc/DataDrivenVideo.tsx
TypeScript
// src/DataDrivenVideo.tsx
import { delayRender, continueRender } from 'remotion'
import { useEffect, useState } from 'react'

export const DataDrivenVideo = () => {
  const [data, setData] = useState(null)
  const [handle] = useState(() => delayRender())

  useEffect(() => {
    fetch('/api/video-data')
      .then(res => res.json())
      .then(json => {
        setData(json)
        continueRender(handle)
      })
  }, [handle])

  if (!data) return null

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.description}</p>
    </div>
  )
}

Wideo z audio

Code
TypeScript
import { Audio, Sequence, staticFile } from 'remotion'

export const VideoWithAudio = () => {
  return (
    <>
      {/* Background music */}
      <Audio src={staticFile('background-music.mp3')} volume={0.5} />

      {/* Sound effect na 60 klatce */}
      <Sequence from={60}>
        <Audio src={staticFile('whoosh.mp3')} />
      </Sequence>

      {/* Voice over */}
      <Sequence from={30}>
        <Audio src={staticFile('voiceover.mp3')} />
      </Sequence>

      {/* Visual content */}
      <YourVisualContent />
    </>
  )
}

Obrazy i wideo jako źródło

Code
TypeScript
import { Img, Video, staticFile, OffthreadVideo } from 'remotion'

export const MediaComposition = () => {
  return (
    <>
      {/* Statyczny obraz */}
      <Img src={staticFile('logo.png')} style={{ width: 200 }} />

      {/* Wideo jako tło */}
      <OffthreadVideo src={staticFile('background.mp4')} />

      {/* Wideo z zewnętrznego URL */}
      <Video src="https://example.com/video.mp4" />
    </>
  )
}

Lottie animations

Code
TypeScript
import { Lottie } from '@remotion/lottie'
import animationData from './animation.json'

export const LottieVideo = () => {
  return (
    <Lottie
      animationData={animationData}
      style={{ width: 500, height: 500 }}
    />
  )
}

Three.js / WebGL

Code
TypeScript
import { ThreeCanvas } from '@remotion/three'
import { useCurrentFrame } from 'remotion'

export const ThreeDVideo = () => {
  const frame = useCurrentFrame()
  const rotation = (frame / 60) * Math.PI * 2 // Pełny obrót co 60 klatek

  return (
    <ThreeCanvas>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} />
      <mesh rotation={[0, rotation, 0]}>
        <boxGeometry args={[2, 2, 2]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>
    </ThreeCanvas>
  )
}

Programowe generowanie wideo

Personalizowane wideo

TSsrc/PersonalizedVideo.tsx
TypeScript
// src/PersonalizedVideo.tsx
interface VideoProps {
  userName: string
  userAvatar: string
  stats: {
    commits: number
    pullRequests: number
    reviews: number
  }
}

export const PersonalizedVideo: React.FC<VideoProps> = ({
  userName,
  userAvatar,
  stats
}) => {
  return (
    <div className="video-container">
      <Intro userName={userName} avatar={userAvatar} />
      <StatsReveal stats={stats} />
      <Outro />
    </div>
  )
}

Batch rendering

TSscripts/render-batch.ts
TypeScript
// scripts/render-batch.ts
import { bundle } from '@remotion/bundler'
import { renderMedia, selectComposition } from '@remotion/renderer'

const users = await fetch('/api/users').then(r => r.json())

for (const user of users) {
  const bundled = await bundle('./src/index.tsx')

  const composition = await selectComposition({
    serveUrl: bundled,
    id: 'PersonalizedVideo',
    inputProps: {
      userName: user.name,
      userAvatar: user.avatar,
      stats: user.stats
    }
  })

  await renderMedia({
    composition,
    serveUrl: bundled,
    codec: 'h264',
    outputLocation: `out/${user.id}.mp4`
  })

  console.log(`Rendered video for ${user.name}`)
}

API Integration

TSapi/render-video.ts
TypeScript
// api/render-video.ts
import { renderMedia, selectComposition, bundle } from '@remotion/renderer'

export async function POST(request: Request) {
  const { userId, data } = await request.json()

  const bundled = await bundle('./src/index.tsx')

  const composition = await selectComposition({
    serveUrl: bundled,
    id: 'DynamicVideo',
    inputProps: data
  })

  const outputPath = `/tmp/${userId}.mp4`

  await renderMedia({
    composition,
    serveUrl: bundled,
    codec: 'h264',
    outputLocation: outputPath
  })

  // Upload to S3 or return path
  const videoUrl = await uploadToS3(outputPath)

  return Response.json({ videoUrl })
}

Przypadki użycia

GitHub Unwrapped

GitHub używa Remotion do generowania spersonalizowanych podsumowań roku dla milionów użytkowników:

Code
TypeScript
// Uproszczony przykład
export const GitHubUnwrapped = ({ user }) => {
  return (
    <>
      <Sequence from={0} durationInFrames={90}>
        <Intro username={user.name} avatar={user.avatar} />
      </Sequence>

      <Sequence from={90} durationInFrames={120}>
        <CommitStats
          totalCommits={user.commits}
          topLanguages={user.languages}
        />
      </Sequence>

      <Sequence from={210} durationInFrames={120}>
        <ContributionGraph data={user.contributions} />
      </Sequence>

      <Sequence from={330} durationInFrames={90}>
        <Outro year={2024} />
      </Sequence>
    </>
  )
}

Marketing automation

Code
TypeScript
// Generowanie reklam produktowych
export const ProductAd = ({ product }) => {
  return (
    <>
      <ProductShowcase
        image={product.image}
        name={product.name}
        price={product.price}
      />
      <FeatureHighlights features={product.features} />
      <CallToAction discount={product.discount} />
    </>
  )
}

// Wygeneruj dla wszystkich produktów
for (const product of products) {
  await renderVideo({
    component: ProductAd,
    props: { product },
    output: `ads/${product.id}.mp4`
  })
}

Data visualization

Code
TypeScript
// Animowana wizualizacja danych
export const DataVisualization = ({ data }) => {
  const frame = useCurrentFrame()

  // Animuj słupki wykresu
  const animatedData = data.map((d, i) => ({
    ...d,
    height: interpolate(
      frame,
      [i * 10, i * 10 + 30],
      [0, d.value],
      { extrapolateRight: 'clamp' }
    )
  }))

  return (
    <BarChart data={animatedData} />
  )
}

Licencjonowanie

Ważne: Remotion ma specyficzny model licencyjny:

  • Free - Dla projektów open-source i personal use
  • Company License - Wymagana dla firm (zależy od revenue)
  • Enterprise - Custom pricing dla dużych organizacji

Sprawdź remotion.dev/license przed użyciem komercyjnym.

Remotion vs alternatywy

CechaRemotionAfter EffectsFFmpegMotion Canvas
JęzykReact/TSExtendScriptCLITypeScript
Learning curveŚredniaWysokaNiskaŚrednia
ProgrammaticOgraniczone
Scalability
Preview✅ Live✅ Live
EkosystemnpmAdobe-npm
KosztFree/Paid$55/moFreeFree

FAQ - Najczęściej zadawane pytania

Czy Remotion jest darmowy?

Dla projektów osobistych i open-source - tak. Firmy muszą zakupić licencję.

Jakie formaty wyjściowe są wspierane?

MP4 (H.264, H.265), WebM (VP8, VP9), GIF, PNG sequence.

Czy mogę używać zewnętrznych bibliotek React?

Tak! Framer Motion, styled-components, Tailwind - wszystko działa.

Jak wydajne jest renderowanie?

Remotion renderuje każdą klatkę osobno, więc może być wolniejsze niż natywne edytory. Dla dużych projektów używaj Remotion Lambda (AWS) lub własnego clustera.

Czy mogę używać wideo jako źródła?

Tak, Remotion obsługuje import wideo, audio i obrazów.

Podsumowanie

Remotion rewolucjonizuje produkcję wideo:

  • React - Twórz wideo jak aplikacje
  • Programmatic - Zmienne, funkcje, API
  • Scalable - Tysiące wideo automatycznie
  • Version control - Git, code review
  • Ecosystem - Cały npm w zasięgu
  • Modern - TypeScript, hooks, components

Remotion to idealne narzędzie dla programistów chcących tworzyć profesjonalne wideo bez opuszczania swojego IDE.


Remotion - Create Videos with React

What is Remotion?

Remotion is a framework that enables video creation using web technologies - React, TypeScript, CSS, Canvas, and WebGL. Instead of using After Effects or Premiere Pro, you write code that generates professional animations and videos.

Imagine being able to:

  • Create animated intros using React components
  • Generate personalized videos for thousands of users
  • Automate video marketing production
  • Build interactive data visualizations

Remotion turns video production into programming.

Key advantages

  • React - Use components, hooks, state
  • TypeScript - Full typing support
  • Web technologies - CSS, Canvas, SVG, WebGL
  • Programmatic - Variables, functions, algorithms
  • Rendering - MP4, WebM, GIF output

GitHub

Repository: github.com/remotion-dev/remotion

Documentation: remotion.dev/docs

Status: 31k+ GitHub stars | TypeScript | Active development

Why Remotion?

The problem with traditional video production

  1. Manual work - After Effects requires manual editing
  2. Lack of scalability - You cannot generate 1000 personalized videos
  3. Difficult automation - ExtendScript scripts are limited
  4. No version control - Hard to track changes in projects
  5. Expensive tools - Adobe CC costs $55/month

The Remotion solution

Code
TEXT
┌─────────────────────────────────────────────────────────────┐
│                     REMOTION WORKFLOW                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   React Components  ->  Video Preview  ->  MP4/WebM/GIF     │
│                                                              │
│   ┌────────────┐    ┌────────────┐    ┌────────────┐        │
│   │   Code     │    │   Live     │    │   Export   │        │
│   │  (React)   │ -> │  Preview   │ -> │   Video    │        │
│   └────────────┘    └────────────┘    └────────────┘        │
│                                                              │
│   Benefits:                                                  │
│   - Version control (Git)                                    │
│   - Reusable components                                      │
│   - Data-driven generation                                   │
│   - API integration                                          │
│   - CI/CD rendering                                          │
└─────────────────────────────────────────────────────────────┘

Key advantages

  1. React ecosystem - Components, hooks, npm packages
  2. Programmatic - Logic, conditions, loops
  3. Data-driven - Generate video from data
  4. Scalable - Thousands of videos automatically
  5. Version control - Git, code review, CI/CD
  6. Free to use - Open-source (with license for companies)

Installation

New project

Code
Bash
# Create a new Remotion project
npx create-video@latest

# Project structure:
# my-video/
# ├── src/
# │   ├── Composition.tsx    # Main composition
# │   ├── Video.tsx          # Root component
# │   └── index.tsx          # Entry point
# ├── package.json
# └── remotion.config.ts

Running preview

Code
Bash
cd my-video

# Start development server
npm start

# Opens Remotion Studio at localhost:3000

Rendering video

Code
Bash
# Render to MP4
npx remotion render src/index.tsx MyComposition out/video.mp4

# Render to GIF
npx remotion render src/index.tsx MyComposition out/animation.gif

# Render with custom settings
npx remotion render src/index.tsx MyComposition out/video.mp4 \
  --codec h264 \
  --quality 100 \
  --frames 0-300

Remotion basics

Composition

TSsrc/Root.tsx
TypeScript
// src/Root.tsx
import { Composition } from 'remotion'
import { MyVideo } from './MyVideo'

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyVideo"
      component={MyVideo}
      durationInFrames={150}  // 5 seconds at 30fps
      fps={30}
      width={1920}
      height={1080}
    />
  )
}

Basic video component

TSsrc/MyVideo.tsx
TypeScript
// src/MyVideo.tsx
import { useCurrentFrame, useVideoConfig, interpolate } from 'remotion'

export const MyVideo = () => {
  const frame = useCurrentFrame()
  const { durationInFrames } = useVideoConfig()

  // Opacity animation: 0 -> 1 over first 30 frames
  const opacity = interpolate(
    frame,
    [0, 30],
    [0, 1],
    { extrapolateRight: 'clamp' }
  )

  // Position animation
  const translateY = interpolate(
    frame,
    [0, 30],
    [50, 0],
    { extrapolateRight: 'clamp' }
  )

  return (
    <div style={{
      flex: 1,
      backgroundColor: '#0f0f0f',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center'
    }}>
      <h1 style={{
        fontSize: 100,
        color: 'white',
        opacity,
        transform: `translateY(${translateY}px)`
      }}>
        Hello Remotion!
      </h1>
    </div>
  )
}

Sequences

TSsrc/VideoWithSequences.tsx
TypeScript
// src/VideoWithSequences.tsx
import { Sequence, useCurrentFrame } from 'remotion'
import { Intro } from './Intro'
import { MainContent } from './MainContent'
import { Outro } from './Outro'

export const VideoWithSequences = () => {
  return (
    <>
      {/* Intro: frames 0-60 (2 seconds) */}
      <Sequence from={0} durationInFrames={60}>
        <Intro />
      </Sequence>

      {/* Main content: frames 60-240 (6 seconds) */}
      <Sequence from={60} durationInFrames={180}>
        <MainContent />
      </Sequence>

      {/* Outro: frames 240-300 (2 seconds) */}
      <Sequence from={240} durationInFrames={60}>
        <Outro />
      </Sequence>
    </>
  )
}

Spring animations

Code
TypeScript
import { spring, useCurrentFrame, useVideoConfig } from 'remotion'

export const SpringAnimation = () => {
  const frame = useCurrentFrame()
  const { fps } = useVideoConfig()

  // Spring animation for natural movement
  const scale = spring({
    frame,
    fps,
    config: {
      damping: 10,
      stiffness: 100,
      mass: 1
    }
  })

  return (
    <div style={{
      transform: `scale(${scale})`,
      width: 200,
      height: 200,
      backgroundColor: '#3b82f6',
      borderRadius: 20
    }} />
  )
}

Advanced features

Loading external data

TSsrc/DataDrivenVideo.tsx
TypeScript
// src/DataDrivenVideo.tsx
import { delayRender, continueRender } from 'remotion'
import { useEffect, useState } from 'react'

export const DataDrivenVideo = () => {
  const [data, setData] = useState(null)
  const [handle] = useState(() => delayRender())

  useEffect(() => {
    fetch('/api/video-data')
      .then(res => res.json())
      .then(json => {
        setData(json)
        continueRender(handle)
      })
  }, [handle])

  if (!data) return null

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.description}</p>
    </div>
  )
}

Video with audio

Code
TypeScript
import { Audio, Sequence, staticFile } from 'remotion'

export const VideoWithAudio = () => {
  return (
    <>
      {/* Background music */}
      <Audio src={staticFile('background-music.mp3')} volume={0.5} />

      {/* Sound effect at frame 60 */}
      <Sequence from={60}>
        <Audio src={staticFile('whoosh.mp3')} />
      </Sequence>

      {/* Voice over */}
      <Sequence from={30}>
        <Audio src={staticFile('voiceover.mp3')} />
      </Sequence>

      {/* Visual content */}
      <YourVisualContent />
    </>
  )
}

Images and video as source

Code
TypeScript
import { Img, Video, staticFile, OffthreadVideo } from 'remotion'

export const MediaComposition = () => {
  return (
    <>
      {/* Static image */}
      <Img src={staticFile('logo.png')} style={{ width: 200 }} />

      {/* Video as background */}
      <OffthreadVideo src={staticFile('background.mp4')} />

      {/* Video from external URL */}
      <Video src="https://example.com/video.mp4" />
    </>
  )
}

Lottie animations

Code
TypeScript
import { Lottie } from '@remotion/lottie'
import animationData from './animation.json'

export const LottieVideo = () => {
  return (
    <Lottie
      animationData={animationData}
      style={{ width: 500, height: 500 }}
    />
  )
}

Three.js / WebGL

Code
TypeScript
import { ThreeCanvas } from '@remotion/three'
import { useCurrentFrame } from 'remotion'

export const ThreeDVideo = () => {
  const frame = useCurrentFrame()
  const rotation = (frame / 60) * Math.PI * 2 // Full rotation every 60 frames

  return (
    <ThreeCanvas>
      <ambientLight intensity={0.5} />
      <pointLight position={[10, 10, 10]} />
      <mesh rotation={[0, rotation, 0]}>
        <boxGeometry args={[2, 2, 2]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>
    </ThreeCanvas>
  )
}

Programmatic video generation

Personalized video

TSsrc/PersonalizedVideo.tsx
TypeScript
// src/PersonalizedVideo.tsx
interface VideoProps {
  userName: string
  userAvatar: string
  stats: {
    commits: number
    pullRequests: number
    reviews: number
  }
}

export const PersonalizedVideo: React.FC<VideoProps> = ({
  userName,
  userAvatar,
  stats
}) => {
  return (
    <div className="video-container">
      <Intro userName={userName} avatar={userAvatar} />
      <StatsReveal stats={stats} />
      <Outro />
    </div>
  )
}

Batch rendering

TSscripts/render-batch.ts
TypeScript
// scripts/render-batch.ts
import { bundle } from '@remotion/bundler'
import { renderMedia, selectComposition } from '@remotion/renderer'

const users = await fetch('/api/users').then(r => r.json())

for (const user of users) {
  const bundled = await bundle('./src/index.tsx')

  const composition = await selectComposition({
    serveUrl: bundled,
    id: 'PersonalizedVideo',
    inputProps: {
      userName: user.name,
      userAvatar: user.avatar,
      stats: user.stats
    }
  })

  await renderMedia({
    composition,
    serveUrl: bundled,
    codec: 'h264',
    outputLocation: `out/${user.id}.mp4`
  })

  console.log(`Rendered video for ${user.name}`)
}

API integration

TSapi/render-video.ts
TypeScript
// api/render-video.ts
import { renderMedia, selectComposition, bundle } from '@remotion/renderer'

export async function POST(request: Request) {
  const { userId, data } = await request.json()

  const bundled = await bundle('./src/index.tsx')

  const composition = await selectComposition({
    serveUrl: bundled,
    id: 'DynamicVideo',
    inputProps: data
  })

  const outputPath = `/tmp/${userId}.mp4`

  await renderMedia({
    composition,
    serveUrl: bundled,
    codec: 'h264',
    outputLocation: outputPath
  })

  // Upload to S3 or return path
  const videoUrl = await uploadToS3(outputPath)

  return Response.json({ videoUrl })
}

Use cases

GitHub Unwrapped

GitHub uses Remotion to generate personalized year-end summaries for millions of users:

Code
TypeScript
// Simplified example
export const GitHubUnwrapped = ({ user }) => {
  return (
    <>
      <Sequence from={0} durationInFrames={90}>
        <Intro username={user.name} avatar={user.avatar} />
      </Sequence>

      <Sequence from={90} durationInFrames={120}>
        <CommitStats
          totalCommits={user.commits}
          topLanguages={user.languages}
        />
      </Sequence>

      <Sequence from={210} durationInFrames={120}>
        <ContributionGraph data={user.contributions} />
      </Sequence>

      <Sequence from={330} durationInFrames={90}>
        <Outro year={2024} />
      </Sequence>
    </>
  )
}

Marketing automation

Code
TypeScript
// Generating product ads
export const ProductAd = ({ product }) => {
  return (
    <>
      <ProductShowcase
        image={product.image}
        name={product.name}
        price={product.price}
      />
      <FeatureHighlights features={product.features} />
      <CallToAction discount={product.discount} />
    </>
  )
}

// Generate for all products
for (const product of products) {
  await renderVideo({
    component: ProductAd,
    props: { product },
    output: `ads/${product.id}.mp4`
  })
}

Data visualization

Code
TypeScript
// Animated data visualization
export const DataVisualization = ({ data }) => {
  const frame = useCurrentFrame()

  // Animate chart bars
  const animatedData = data.map((d, i) => ({
    ...d,
    height: interpolate(
      frame,
      [i * 10, i * 10 + 30],
      [0, d.value],
      { extrapolateRight: 'clamp' }
    )
  }))

  return (
    <BarChart data={animatedData} />
  )
}

Licensing

Important: Remotion has a specific licensing model:

  • Free - For open-source projects and personal use
  • Company License - Required for companies (depends on revenue)
  • Enterprise - Custom pricing for large organizations

Check remotion.dev/license before commercial use.

Remotion vs alternatives

FeatureRemotionAfter EffectsFFmpegMotion Canvas
LanguageReact/TSExtendScriptCLITypeScript
Learning curveMediumHighLowMedium
ProgrammaticYesLimitedYesYes
ScalabilityYesNoYesYes
PreviewLiveYesNoLive
EcosystemnpmAdobe-npm
CostFree/Paid$55/moFreeFree

FAQ - Frequently asked questions

Is Remotion free?

For personal projects and open-source - yes. Companies must purchase a license.

What output formats are supported?

MP4 (H.264, H.265), WebM (VP8, VP9), GIF, PNG sequence.

Can I use external React libraries?

Yes! Framer Motion, styled-components, Tailwind - everything works.

How efficient is rendering?

Remotion renders each frame separately, so it can be slower than native editors. For large projects, use Remotion Lambda (AWS) or your own cluster.

Can I use video as a source?

Yes, Remotion supports importing video, audio, and images.

Summary

Remotion revolutionizes video production:

  • React - Create videos like applications
  • Programmatic - Variables, functions, API
  • Scalable - Thousands of videos automatically
  • Version control - Git, code review
  • Ecosystem - All of npm at your fingertips
  • Modern - TypeScript, hooks, components

Remotion is the ideal tool for developers who want to create professional videos without leaving their IDE.