Yearly Pay yearly and get 2 months free on every paid plan. See plans
Zaloguj się Zacznij za darmo

Animowane filmy objaśniające z narracją dzięki ToRun MCP i Remotion

Ostatnia aktualizacja: 11 lis 2026

Co możesz zrobić

Agent programistyczny, który uruchamia polecenia na Twoim komputerze, taki jak Claude Code, opencode czy Cursor, może zrobić z ToRun krótki film objaśniający z narracją. Agent pisze scenariusz, prosi ToRun o obrazy do scen, narrację i muzykę w tle, a następnie renderuje wideo na Twoim komputerze za pomocą Remotion, biblioteki, która zamienia komponenty React w wideo.

Czego potrzebujesz

  • Narzędzia programistycznego połączonego z serwerem MCP ToRun, które potrafi uruchamiać polecenia i zapisywać pliki w folderze: opencode, Claude Code lub Cursor.
  • Node.js 18 lub nowszego. Pierwsze renderowanie pobiera przeglądarkę, za pomocą której renderuje Remotion.
  • Limitu płatnego planu lub salda w portfelu: wywołania API nigdy nie korzystają z darmowego limitu. Zobacz jak opłacane są wywołania.

Remotion ma własną licencję: jest darmowy dla osób prywatnych i bardzo małych firm, a większe firmy potrzebują licencji firmowej. Zanim użyjesz go w pracy, sprawdź remotion.dev/license.

Projekt startowy

Cztery pliki. Poproś agenta, aby utworzył je w pustym folderze, albo skopiuj je sam, a potem uruchom tam npm install. Wygenerowane pliki trafiają do folderu public obok package.json.

package.json:

{
  "name": "motion-explainer",
  "private": true,
  "scripts": {
    "studio": "remotion studio src/index.ts",
    "render": "remotion render src/index.ts Explainer out/explainer.mp4"
  },
  "dependencies": {
    "@remotion/cli": "4.0.539",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "remotion": "4.0.539"
  }
}

video.json opisuje całe wideo. Każda scena ma caption wyświetlany na ekranie, tekst narracji say, prompt obrazu, nazwy plików swojego obrazu i narracji oraz swoją długość w seconds:

{
  "width": 1920,
  "height": 1080,
  "fps": 30,
  "music": { "file": "music.mp3", "volume": 0.12 },
  "scenes": [
    {
      "caption": "Every team has a backlog.",
      "say": "Every team has a backlog, and it only grows.",
      "prompt": "flat illustration of a wall covered in sticky notes, soft morning light, no text",
      "image": "scene-1.png",
      "narration": "scene-1.mp3",
      "seconds": 5.5
    },
    {
      "caption": "Sort it by what users feel.",
      "say": "Sort it by what your users feel, not by what is loudest.",
      "prompt": "flat illustration of hands arranging cards into three columns on a desk, no text",
      "image": "scene-2.png",
      "narration": "scene-2.mp3",
      "seconds": 6
    },
    {
      "caption": "Ship the top one this week.",
      "say": "Then ship the top one this week.",
      "prompt": "flat illustration of a small paper boat leaving a harbour at sunrise, no text",
      "image": "scene-3.png",
      "narration": "scene-3.mp3",
      "seconds": 5
    }
  ]
}

src/index.ts:

import {registerRoot} from 'remotion';
import {Root} from './Root';

registerRoot(Root);

src/Root.tsx odtwarza sceny jedna po drugiej. Każdy obraz powoli się przybliża, podpis wsuwa się od dołu, narracja sceny zaczyna się razem z nią, a muzyka gra cicho pod całym wideo:

import React from 'react';
import {AbsoluteFill, Composition, Html5Audio, Img, interpolate, Series, staticFile, useCurrentFrame} from 'remotion';
import data from '../video.json';

// "say" and "prompt" are the script: the narration text and the image prompt. Rendering reads the rest.
type Scene = {image: string; narration?: string; seconds: number; caption?: string; say?: string; prompt?: string};
type Video = {width: number; height: number; fps: number; music?: {file: string; volume: number}; scenes: Scene[]};

const video = data as Video;
const clamp = {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'} as const;
const framesOf = (scene: Scene) => Math.round(scene.seconds * video.fps);

// One scene: the image slowly zooms in, the caption rises in, the narration plays from the scene's start.
const SceneView: React.FC<{scene: Scene; frames: number}> = ({scene, frames}) => {
  const frame = useCurrentFrame();
  const fade = interpolate(frame, [0, 10, frames - 10, frames], [0, 1, 1, 0], clamp);
  const zoom = interpolate(frame, [0, frames], [1, 1.08]);
  const rise = interpolate(frame, [8, 26], [40, 0], clamp);
  return (
    <AbsoluteFill style={{backgroundColor: 'black', opacity: fade}}>
      <Img src={staticFile(scene.image)} style={{width: '100%', height: '100%', objectFit: 'cover', transform: `scale(${zoom})`}} />
      {scene.caption ? (
        <div
          style={{
            position: 'absolute', left: '6%', right: '6%', bottom: '8%', transform: `translateY(${rise}px)`,
            color: 'white', fontFamily: 'Arial, sans-serif', fontSize: video.height / 18, fontWeight: 700,
            textShadow: '0 2px 16px rgba(0,0,0,0.7)',
          }}
        >
          {scene.caption}
        </div>
      ) : null}
      {scene.narration ? <Html5Audio src={staticFile(scene.narration)} /> : null}
    </AbsoluteFill>
  );
};

const Explainer: React.FC = () => (
  <AbsoluteFill style={{backgroundColor: 'black'}}>
    <Series>
      {video.scenes.map((scene, i) => (
        <Series.Sequence key={i} durationInFrames={framesOf(scene)}>
          <SceneView scene={scene} frames={framesOf(scene)} />
        </Series.Sequence>
      ))}
    </Series>
    {video.music ? <Html5Audio src={staticFile(video.music.file)} volume={video.music.volume} loop /> : null}
  </AbsoluteFill>
);

export const Root: React.FC = () => (
  <Composition
    id="Explainer"
    component={Explainer}
    width={video.width}
    height={video.height}
    fps={video.fps}
    durationInFrames={video.scenes.reduce((sum, scene) => sum + framesOf(scene), 0)}
  />
);

Jak agent robi wideo

  1. Scenariusz. Agent zapisuje sceny w video.json: jeden pomysł na scenę, podpis z kilku słów, jedno lub dwa zdania do powiedzenia. Poproś, aby pokazał Ci scenariusz, zanim cokolwiek wygeneruje.

  2. Saldo. Wywołuje account_balance, aby sprawdzić, ile konto może wydać. To wywołanie jest bezpłatne.

  3. Obrazy. Dla każdej sceny wywołuje image_generate z prompt sceny i size 1792x1024 i zapisuje obraz jako public/scene-1.png, public/scene-2.png i tak dalej. Jeśli obraz nie jest gotowy w czasie oczekiwania, narzędzie zwraca identyfikator zadania, a agent odpytuje job_status, aż obraz będzie gotowy.

  4. Narracja. Dla każdej sceny wywołuje tts_generate z tekstem say sceny i głosem, na przykład nova, i zapisuje audio jako public/scene-1.mp3 i tak dalej.

  5. Czas. Ustawia seconds każdej sceny na długość jej narracji plus około pół sekundy. tts_generate zwraca tę długość jako duration_seconds, zmierzoną na podstawie pliku audio. Jeśli odpowiedź zawiera też duration_estimated: true, długość dało się tylko oszacować na podstawie tekstu, więc agent mierzy plik. Aby samodzielnie sprawdzić plik:

    npx remotion ffprobe -v error -show_entries format=duration -of csv=p=0 public/scene-1.mp3
    
  6. Muzyka (opcjonalnie). Wywołuje music_generate z promptem takim jak „calm instrumental background, soft piano”, with_vocals ustawionym na false i duration_seconds zbliżonym do długości wideo. Narzędzie zwraca identyfikator zadania; agent odpytuje job_status, aż utwór będzie gotowy, i zapisuje go jako public/music.mp3. Bez muzyki usuń wiersz music z video.json.

  7. Podgląd i renderowanie. npm run studio otwiera podgląd w przeglądarce. npm run render zapisuje out/explainer.mp4.

Każdy link do pliku zwrócony przez narzędzie da się pobrać bez logowania. Zachowaj cały link, łącznie z częścią po znaku zapytania:

curl -L -o public/scene-1.png "<the image link>"

Poproś agenta

Zrób 30-sekundowy film objaśniający, jak działa synchronizacja w naszej aplikacji, na podstawie projektu startowego Remotion z torun.ai/docs/mcp-motion-explainers. Cztery sceny. Najpierw pokaż mi scenariusz w video.json. Potem wygeneruj po jednym obrazie na scenę bez tekstu, nagraj narrację każdej sceny głosem nova, dodaj cichą muzykę instrumentalną, dopasuj długość każdej sceny do jej narracji i wyrenderuj.

Aby uzyskać pionowe wideo, poproś o width 1080 i height 1920 w video.json oraz o obrazy z size 1024x1792.

Ile to kosztuje

  • image_generate, tts_generate i music_generate to płatne wywołania, rozliczane w Runs po tych samych cenach co w aplikacji. Wideo z czterema scenami i muzyką to cztery obrazy, cztery narracje i jeden utwór.
  • account_balance i job_status są bezpłatne.
  • Renderowanie odbywa się na Twoim komputerze. Zmiana podpisów, czasu lub animacji i ponowne renderowanie nic nie kosztuje w ToRun; ponowne wygenerowanie obrazu lub narracji to nowe płatne wywołanie.
  • Gdy jedno generowanie kosztowałoby więcej niż próg klucza, narzędzie najpierw odpowiada ceną, a agent pyta Cię, zanim wykona wywołanie.
  • Wszystko, co agent wygeneruje, jest też zapisywane w Twojej bibliotece ToRun.

Wskazówki

  • Proś o obrazy bez tekstu. Słowa niesie podpis, a modele obrazów często piszą tekst z błędami.
  • Ogranicz każdą scenę do jednego pomysłu i jednego lub dwóch zdań narracji.
  • Wybierz jeden głos i trzymaj się go przez całe wideo.
  • Utrzymuj głośność muzyki między 0.1 a 0.15, aby narracja pozostała wyraźna.
Utknąłeś? Forum zwykle odpowiada w ciągu kilku godzin, wsparcie — w ciągu 24 godzin. Zapytaj na forum Skontaktuj się z pomocą