Godišnje Plaćajte godišnje i dobijte 2 mjeseca besplatno uz svaki plaćeni paket. Pogledajte pakete
Prijava Počni besplatno

Animirani objašnjavajući videozapisi s naracijom uz ToRun MCP i Remotion

Zadnje ažuriranje: 11 stu 2026

Što možete izraditi

Agent za programiranje koji pokreće naredbe na vašem računalu, poput Claude Code, opencode ili Cursor, može s ToRun izraditi kratki objašnjavajući video s naracijom. Agent piše scenarij, traži od ToRun slike scena, naraciju i pozadinsku glazbu te renderira video na vašem računalu pomoću Remotion, biblioteke koja React komponente pretvara u video.

Što vam treba

  • Alat za programiranje povezan s ToRun MCP poslužiteljem koji može pokretati naredbe i zapisivati datoteke u mapu: opencode, Claude Code ili Cursor.
  • Node.js 18 ili noviji. Prvo renderiranje preuzima preglednik kojim Remotion renderira.
  • Kvota plaćenog plana ili saldo novčanika: API pozivi nikad ne koriste besplatnu kvotu. Pogledajte kako se pozivi plaćaju.

Remotion ima vlastitu licencu: besplatan je za pojedince i vrlo male tvrtke, a veće tvrtke trebaju tvrtkinu licencu. Prije upotrebe za posao provjerite remotion.dev/license.

Početni projekt

Četiri datoteke. Zamolite agenta da ih izradi u praznoj mapi ili ih sami kopirajte, a zatim ondje pokrenite npm install. Generirane datoteke idu u mapu public pokraj 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 sadrži cijeli video. Svaka scena ima caption koji se prikazuje na zaslonu, tekst naracije say, prompt slike, nazive datoteka svoje slike i naracije te svoje trajanje u 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 reproducira scene jednu za drugom. Svaka se slika polako približava, natpis se podiže odozdo, naracija scene počinje s njom, a glazba tiho svira ispod cijelog videa:

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)}
  />
);

Kako agent izrađuje video

  1. Scenarij. Agent zapisuje scene u video.json: jedna ideja po sceni, natpis od nekoliko riječi, jedna ili dvije rečenice za izgovoriti. Zamolite ga da vam pokaže scenarij prije nego što bilo što generira.

  2. Saldo. Poziva account_balance da vidi koliko račun može potrošiti. Ovaj je poziv besplatan.

  3. Slike. Za svaku scenu poziva image_generate s prompt scene i size 1792x1024 te sprema sliku kao public/scene-1.png, public/scene-2.png i tako dalje. Ako slika nije gotova unutar vremena čekanja, alat vraća ID zadatka, a agent pita job_status dok slika ne bude gotova.

  4. Naracija. Za svaku scenu poziva tts_generate s tekstom say scene i glasom, primjerice nova, te sprema zvuk kao public/scene-1.mp3 i tako dalje.

  5. Vremenski raspored. Postavlja seconds svake scene na trajanje njezine naracije uz otprilike pola sekunde. tts_generate vraća to trajanje kao duration_seconds, izmjereno iz audiodatoteke. Ako odgovor sadrži i duration_estimated: true, trajanje se moglo samo procijeniti iz teksta, pa agent mjeri datoteku. Da biste sami provjerili datoteku:

    npx remotion ffprobe -v error -show_entries format=duration -of csv=p=0 public/scene-1.mp3
    
  6. Glazba (neobavezno). Poziva music_generate s promptom poput „calm instrumental background, soft piano”, with_vocals postavljenim na false i duration_seconds blizu trajanja videa. Alat vraća ID zadatka; agent pita job_status dok skladba ne bude gotova i sprema je kao public/music.mp3. Bez glazbe uklonite redak music iz video.json.

  7. Pregled i renderiranje. npm run studio otvara pregled u vašem pregledniku. npm run render zapisuje out/explainer.mp4.

Svaka poveznica na datoteku koju alat vrati preuzima se bez prijave. Sačuvajte cijelu poveznicu, uključujući dio iza upitnika:

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

Zamolite svojeg agenta

Izradi objašnjavajući video od 30 sekundi o tome kako radi sinkronizacija u našoj aplikaciji, s početnim Remotion projektom s torun.ai/docs/mcp-motion-explainers. Četiri scene. Najprije mi pokaži scenarij u video.json. Zatim generiraj jednu sliku po sceni bez teksta, svakoj sceni dodaj naraciju glasom nova, dodaj tihu instrumentalnu glazbu, uskladi trajanje svake scene s njezinom naracijom i renderiraj.

Za okomiti video zatražite width 1080 i height 1920 u video.json te slike sa size 1024x1792.

Koliko to košta

  • image_generate, tts_generate i music_generate plaćeni su pozivi, koji se naplaćuju u Runs po istim cijenama kao u aplikaciji. Video s četiri scene i glazbom znači četiri slike, četiri naracije i jednu skladbu.
  • account_balance i job_status besplatni su.
  • Renderiranje se odvija na vašem računalu. Promjena natpisa, vremenskog rasporeda ili pokreta i ponovno renderiranje na ToRun ne košta ništa; ponovno generiranje slike ili naracije novi je plaćeni poziv.
  • Kad bi jedno generiranje stajalo više od praga ključa, alat najprije odgovara cijenom, a vaš agent vas pita prije nego što izvrši poziv.
  • Sve što agent generira sprema se i u vašu ToRun knjižnicu.

Savjeti

  • Tražite slike bez teksta. Riječi nosi natpis, a modeli za slike često pogrešno pišu tekst.
  • Ograničite svaku scenu na jednu ideju i jednu ili dvije rečenice naracije.
  • Odaberite jedan glas i zadržite ga kroz cijeli video.
  • Držite glasnoću glazbe između 0.1 i 0.15 kako bi naracija ostala jasna.
Zapeli ste? Forum obično odgovara unutar nekoliko sati, podrška unutar 24 sata. Pitajte na forumu Kontaktiraj podršku