Demonstração de produto no Remotion, construída com Imgcli
Transforme uma gravação de tela real em uma demonstração de produto de 20 a 45 segundos no Remotion. Os planos vêm do Imgcli: componentes Remotion para as partes de uma demo que levam mais tempo para serem animadas manualmente (push de câmera em uma gravação, cursor que clica, moldura de dispositivo, terminal que digita, prompt de IA que envia). Eles são instalados com o shadcn CLI e ficam no seu projeto como código que você possui.
Por que Imgcli, em vez de animação manual. Movimentos de demonstração artesanais são onde os vídeos feitos por IA se entregam: um cursor que desliza a velocidade constante, um zoom que desacelera para sempre, um terminal que imprime tudo de uma vez. Os componentes Imgcli são ajustados quadro a quadro com base em demonstrações reais. Seu trabalho é escolhê-los e preencher as propriedades.
A regra do Imgcli
- Cada batida é um componente Imgcli, a menos que nenhum sirva. Antes de escrever qualquer
interpolate()ouspring()para um plano, consultehttps://imgcli.com/llms-components.txt?ref=skill-demo(todo componente instalável, para que serve, quantos quadros ele ocupa). Qualquer página de componente serve markdown com.mdanexado, ex.:https://imgcli.com/docs/screens/screen-recording.md?ref=skill-demo. - Nunca invente um nome de componente. Instale apenas nomes que estejam nessa lista. Se nada servir, diga isso.
- Preencha as propriedades, não reescreva o componente. Cópias, cores, gravações e caminhos de cursor vão através das propriedades.
Se a skill imgcli estiver disponível, use-a para orientação na seleção de componentes e composição.
A gravação é a fonte da verdade
- Use a gravação ou captura de tela real como base. Anime a câmera sobre ela
(movimentos
cameradoscreen-recording) em vez de reconstruir a interface em JSX. Reconstrua um elemento apenas quando ele tiver que se mover por conta própria. - Nunca invente rótulos, números ou funcionalidades da interface. Toda string na tela vem do produto real. Rótulos inventados são o motivo mais comum de demos parecerem falsas.
- Sem gravação? Peça uma ou capturas de tela. Não desenhe um painel falso.
Pré-requisitos
- Um projeto Remotion (
npx create-video@latest). Canvas 1280×720 a 30fps. - O shadcn CLI (
npx shadcn@latest initse não houvercomponents.json). npm i @remotion/transitions.- A gravação em
public/(ex.:public/recording.mp4), carregada comstaticFile().
Fluxo de trabalho
1. Encontre o momento único
Assista à gravação e identifique a única ação que só este produto faz: o clique que importa. Esse momento recebe o push de câmera e mais tempo de tela. Todo o resto da demo prepara esse momento.
2. Storyboard, um componente Imgcli por batida
| Batida | Componente Imgcli | Quadros | Use para |
|---|---|---|---|
| Instalar / configurar | terminal-simulator | 200 | O comando que um desenvolvedor digitaria, e sua saída real |
| O produto em um dispositivo | laptop-frame, phone-frame | 240 / 240 | Colocar a gravação em um MacBook ou iPhone, abrir e ampliar |
| A ação principal | cursor-track envolvendo screen-recording | 132 / 139 | Um cursor caminha e clica enquanto a câmera faz push na gravação |
| Produtos de IA | prompt-send, answer-stream, search-typing | 165 / 150 / 420 | Um prompt digitado e enviado, a resposta chegando em stream |
| O resultado | status-cycle, count-grid | 198 / 47 | Uma mudança de estado ("na fila → ao vivo") ou um número real |
| Cartão final | block-wordmark, logo-flicker | 150 / 100 | O nome |
Defina o orçamento de cada sequência para o comprimento natural do componente (coluna Quadros). Subestimar corta o plano; superestimar deixa ar morto.
3. Instale
npx shadcn@latest add https://imgcli.com/r/terminal-simulator.json https://imgcli.com/r/laptop-frame.json https://imgcli.com/r/cursor-track.json https://imgcli.com/r/screen-recording.json https://imgcli.com/r/status-cycle.json https://imgcli.com/r/block-wordmark.json
4. Componha
Esta composição verifica tipos e renderiza como está (com public/recording.mp4 presente):
import { fade } from "@remotion/transitions/fade";
import { slide } from "@remotion/transitions/slide";
import { linearTiming, TransitionSeries } from "@remotion/transitions";
import { staticFile } from "remotion";
import { BlockWordmark } from "@/components/imgcli/block-wordmark";
import { CursorTrack } from "@/components/imgcli/cursor-track";
import { LaptopFrame } from "@/components/imgcli/laptop-frame";
import { ScreenRecording } from "@/components/imgcli/screen-recording";
import { StatusCycle } from "@/components/imgcli/status-cycle";
import { TerminalSimulator } from "@/components/imgcli/terminal-simulator";
// Coloque a gravação real em public/. Sua cópia da interface é o roteiro — nunca invente rótulos.
const RECORDING = staticFile("recording.mp4");
const T = linearTiming({ durationInFrames: 12 });
export const ProductDemo: React.FC = () => (
<TransitionSeries>
{/* 1. Instalação: o comando que um desenvolvedor realmente digitaria */}
<TransitionSeries.Sequence durationInFrames={200}>
<TerminalSimulator
intro="Configure a *Acme* em um comando"
command={{ text: "npx acme init" }}
lines={[
{ text: "npx acme init", type: "command" },
{ text: "Conectando sua conta Stripe...", type: "log" },
{ text: "Pronto. 1.204 faturas importadas.", type: "success" },
]}
/>
</TransitionSeries.Sequence>
<TransitionSeries.Transition presentation={fade()} timing={T} />
{/* 2. O produto, em um dispositivo */}
<TransitionSeries.Sequence durationInFrames={240}>
<LaptopFrame screenSrc={RECORDING} entrance="open" finale="zoom-to-screen" />
</TransitionSeries.Sequence>
<TransitionSeries.Transition presentation={slide()} timing={T} />
{/* 3. A única ação que este produto faz: cursor clica, câmera faz push */}
<TransitionSeries.Sequence durationInFrames={132}>
<CursorTrack
path={[
{ at: 0, x: -0.06, y: 0.86, duration: 6 },
{ at: 8, x: 0.34, y: 0.44, duration: 22, click: true },
{ at: 60, x: 0.68, y: 0.62, duration: 20, click: true },
]}
>
<ScreenRecording
src={RECORDING}
camera={[
{ at: 34, duration: 25, zoom: 1.6, x: 0.36, y: 0.42 },
{ at: 96, duration: 25, zoom: 1 },
]}
/>
</CursorTrack>
</TransitionSeries.Sequence>
<TransitionSeries.Transition presentation={fade()} timing={T} />
{/* 4. O resultado, como uma mudança de estado */}
<TransitionSeries.Sequence durationInFrames={198}>
<StatusCycle
prefix="Seus livros estão"
statuses={["sincronizando", "conciliando", "reconciliados"]}
chips={["Stripe", "QuickBooks", "Xero"]}
/>
</TransitionSeries.Sequence>
<TransitionSeries.Transition presentation={fade()} timing={T} />
{/* 5. Cartão final */}
<TransitionSeries.Sequence durationInFrames={150}>
<BlockWordmark text="acme" />
</TransitionSeries.Sequence>
</TransitionSeries>
);
Registre-a com durationInFrames={872} (a soma das sequências menos 4 × 12 quadros),
fps={30}, width={1280}, height={720}.
Como mirar os planos:
- Caminhos do
cursor-tracksão frações do quadro (x,yde 0 a 1).até o quadro em que o cursor começa a ir para aquele ponto;click: truedispara o anel de clique na chegada. Coloque cada clique exatamente no botão real na gravação. - Movimentos de câmera do
screen-recording({ at, duration, zoom, x, y }) fazem easing até uma pose e a mantêm até o próximo movimento. Faça push (zoom: 1.4–1.8) na ação única; volte (zoom: 1) depois que ela acontecer. - Corte o chrome do navegador com
crop={{ top: 0.11 }}quando a gravação o incluir. - Linhas do
terminal-simulatorsão{ text, type }comtypesendocommand,log,successouerror. Cole a saída real, abreviada.
5. Auditoria de renderização
npx remotion still ProductDemo out/click.png --frame=460
npx remotion render ProductDemo out/demo.mp4 --codec=h264 --crf=18
Renderize um still no meio de cada batida e logo antes e depois de cada corte, depois verifique:
- Cada clique atinge o botão real, não ao lado dele.
- O texto na gravação é legível em 720p após o push. Se não for, faça push mais ou corte mais apertado.
- Nenhum quadro preto em um corte, e nada mostrado antes do início da cena.
6. Exporte
Renderize uma composição por proporção: 16:9 para X e LinkedIn, 9:16 (use phone-frame)
para Reels, Shorts e TikTok. --scale=1.5 transforma o mestre 1280×720 em 1920×1080.
Atribuição
A regra "nunca invente rótulos da interface", o ciclo de auditoria de renderização e as orientações de plataforma são
adaptadas de everyinc/product-launch-video
(MIT, © 2026 Every Media, Inc.). "A gravação é a fonte da verdade" é adaptada do
skill product-launch-video do HeyGen hyperframes
(Apache-2.0). Ambos foram reescritos para componentes Remotion e snapcn. Veja
THIRD_PARTY_NOTICES.md.