Anual Pague anualmente e ganhe 2 meses grátis em qualquer plano pago. Ver planos
Entrar Comece grátis

Vídeos explicativos animados e narrados com o ToRun MCP e o Remotion

Última atualização: 11 nov. 2026

O que pode criar

Um agente de programação que executa comandos no seu computador, como o Claude Code, o opencode ou o Cursor, pode criar com o ToRun um vídeo explicativo curto e narrado. O agente escreve o guião, pede ao ToRun as imagens das cenas, a narração e a música de fundo, e renderiza o vídeo no seu computador com o Remotion, uma biblioteca que transforma componentes React em vídeo.

O que precisa

  • Uma ferramenta de programação ligada ao servidor MCP do ToRun que consiga executar comandos e escrever ficheiros numa pasta: opencode, Claude Code ou Cursor.
  • Node.js 18 ou posterior. A primeira renderização transfere o browser com que o Remotion renderiza.
  • A quota de um plano pago ou saldo na carteira: as chamadas à API nunca utilizam a quota gratuita. Consulte como as chamadas são pagas.

O Remotion tem a sua própria licença: é gratuito para particulares e empresas muito pequenas, e as empresas maiores precisam de uma licença empresarial. Consulte remotion.dev/license antes de o utilizar para trabalho.

O projeto inicial

Quatro ficheiros. Peça ao seu agente que os crie numa pasta vazia, ou copie-os você mesmo, e depois execute npm install nessa pasta. Os ficheiros gerados vão para uma pasta public ao lado de 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 contém o vídeo inteiro. Cada cena tem uma caption mostrada no ecrã, o texto de narração say, o prompt da imagem, os nomes dos ficheiros da sua imagem e da sua narração, e a sua duração em 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 reproduz as cenas uma após a outra. Cada imagem aproxima-se lentamente, a legenda surge a subir, a narração da cena começa com ela e a música toca baixinho durante todo o vídeo:

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

Como o agente cria o vídeo

  1. Guião. O agente escreve as cenas em video.json: uma ideia por cena, uma legenda de poucas palavras, uma ou duas frases para dizer. Peça-lhe que lhe mostre o guião antes de gerar o que quer que seja.

  2. Saldo. Chama account_balance para ver o que a conta pode gastar. Esta chamada é gratuita.

  3. Imagens. Para cada cena, chama image_generate com o prompt da cena e size 1792x1024, e guarda a imagem como public/scene-1.png, public/scene-2.png e assim por diante. Se uma imagem não estiver pronta dentro do tempo de espera, a ferramenta devolve um id de tarefa, e o agente consulta job_status até a imagem estar pronta.

  4. Narração. Para cada cena, chama tts_generate com o texto say da cena e uma voz, por exemplo nova, e guarda o áudio como public/scene-1.mp3 e assim por diante.

  5. Tempos. Define os seconds de cada cena como a duração da sua narração mais cerca de meio segundo. tts_generate devolve essa duração como duration_seconds, medida a partir do ficheiro de áudio. Se a resposta também disser duration_estimated: true, a duração só pôde ser estimada a partir do texto, por isso o agente mede o ficheiro. Para verificar um ficheiro você mesmo:

    npx remotion ffprobe -v error -show_entries format=duration -of csv=p=0 public/scene-1.mp3
    
  6. Música (opcional). Chama music_generate com um prompt como «calm instrumental background, soft piano», with_vocals definido como false e duration_seconds próximo da duração do vídeo. A ferramenta devolve um id de tarefa; o agente consulta job_status até a faixa estar pronta e guarda-a como public/music.mp3. Sem música, remova a linha music de video.json.

  7. Pré-visualização e renderização. npm run studio abre uma pré-visualização no seu browser. npm run render escreve out/explainer.mp4.

Todas as ligações para ficheiros que uma ferramenta devolve transferem-se sem iniciar sessão. Mantenha a ligação completa, incluindo a parte depois do ponto de interrogação:

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

Peça ao seu agente

Cria um vídeo explicativo de 30 segundos sobre como funciona a sincronização da nossa aplicação, com o projeto inicial do Remotion de torun.ai/docs/mcp-motion-explainers. Quatro cenas. Mostra-me primeiro o guião em video.json. Depois gera uma imagem por cena sem texto, narra cada cena com a voz nova, adiciona música instrumental suave, acerta o tempo de cada cena pela sua narração e renderiza.

Para um vídeo vertical, peça width 1080 e height 1920 em video.json, e imagens com size 1024x1792.

Quanto custa

  • image_generate, tts_generate e music_generate são chamadas pagas, cobradas em Runs aos mesmos preços que na aplicação. Um vídeo com quatro cenas e música são quatro imagens, quatro narrações e uma faixa.
  • account_balance e job_status são gratuitas.
  • A renderização é feita no seu computador. Alterar as legendas, os tempos ou o movimento e renderizar de novo não custa nada no ToRun; gerar de novo uma imagem ou uma narração é uma nova chamada paga.
  • Quando uma única geração custaria mais do que o limiar da chave, a ferramenta responde primeiro com o preço, e o seu agente pergunta-lhe antes de executar a chamada.
  • Tudo o que o agente gera também é guardado na sua biblioteca ToRun.

Dicas

  • Peça imagens sem texto. A legenda leva as palavras, e os modelos de imagem escrevem muitas vezes o texto com erros.
  • Limite cada cena a uma ideia e a uma ou duas frases de narração.
  • Escolha uma voz e mantenha-a durante todo o vídeo.
  • Mantenha o volume da música entre 0.1 e 0.15, para que a narração se ouça com clareza.
Ficou preso? O fórum costuma responder em poucas horas; o suporte, em 24 horas. Pergunte no fórum Contactar o suporte