Communitygithub.com

product-demo-video

Esta skill deve ser usada quando o usuário pedir para “criar um vídeo de demonstração de produto”, “criar um vídeo de demonstração de app”, “criar um vídeo de anúncio de funcionalidade”, “fazer uma demonstração de SaaS”, “criar um vídeo de walkthrough de interface”, “animar capturas de tela de produto em uma demonstração”, “adicionar cursor/click animado a uma captura de tela” ou “ampliar uma parte de uma interface”. Cobre a transformação de capturas de tela estáticas/designs (não gravações de tela) em uma demonstração animada limpa: molduras de dispositivo/navegador, cursor animado + ripple de clique, zoom/pan para a interface focal, anotações de chamada, ritmo de etapas, transições entre telas e legendas de funcionalidades.

O que é product-demo-video?

Esta skill transforma capturas de tela estáticas de produtos ou designs em vídeos de demonstração animados e profissionais, sem necessidade de gravador de tela. Ela é ideal para criar demos de apps/SaaS, anúncios de funcionalidades, walkthroughs de integração e vídeos de demonstração de produtos com duração de 15 a 90 segundos. Ao contrário de gravações de tela reais, que sofrem com cursor trêmulo, versões de UI desatualizadas e necessidade de regravação completa para corrigir um passo, esta skill usa código para gerar cada quadro de forma determinística: insere cada captura de tela em uma moldura de navegador ou dispositivo, anima um cursor sintético ao longo de um caminho suavizado até um pixel exato, dispara um ripple de clique no quadro correto, aplica zoom (até 2×) para destacar uma região focal, adiciona anotações de chamada e legendas de benefício, e realiza transições consistentes entre telas. O resultado é um MP4 (via Remotion) onde cada valor de movimento é uma função pura do número do quadro, garantindo que, se uma captura de tela for substituída, a demo seja re-renderizada de forma idêntica. A skill também inclui scripts de verificação para validar quadros estáticos antes da renderização final, evitando retrabalho.

Funciona com~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/2233admin/design-pipeline/tree/HEAD/skill/references/iart-motion-skills/upstream/ecommerce-video-skills/skills/product-demo-video

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Product Demo Video (Vídeo de Demonstração de Produto)

Transforme capturas de tela estáticas ou designs de produtos em uma demonstração animada e polida — sem gravador de tela, sem cursor real trêmulo, sem desvio de versão da UI. Moldura cada tela, deslize um cursor sintético até o pixel exato, faça o ripple do clique, amplie a parte que importa e legende a funcionalidade. Como a entrada é estática e o movimento é código, cada valor é determinístico e re-renderiza identicamente quando a captura de tela muda.

Quando usar

  • Demo de app / SaaS, anúncio de funcionalidade, walkthrough de integração (15–90s).
  • Mostrar um caminho de clique por uma UI da qual você só tem capturas de tela/designs.
  • Destacar uma região focal de um painel denso (zoom-na-região + chamada).

Por que capturas de tela vencem gravações de tela

Gravação de telaBaseada em captura de tela (esta skill)
Cursor real deriva, ultrapassa, tremeCursor segue um caminho suavizado até um alvo exato
Regravar toda a tomada para corrigir um passoTroque um PNG, re-renderize o mesmo código
UI muda no meio da tomada, mouse procuraCada tela é um ativo limpo e de estado final
Difícil ampliar sem pixelizaçãoExporte capturas de tela em 2× (DPR 2) → zooms nítidos

Capture as entradas com o dobro do tamanho de exibição (retina / deviceScaleFactor: 2) para que um zoom de 2× permaneça nítido. Consulte references/screenshot-demo.md para um script de captura com Playwright.

O loop da demonstração

Cada demonstração segue o mesmo ritmo, repetido por funcionalidade. Segure o tempo suficiente para ler, mova com intenção, execute o clique, revele o resultado.

RitmoDuraçãoFunção
Pousar na tela0,5–1sDeixe o espectador se orientar antes que algo se mova
Cursor viaja ao alvo0,4–0,8sMovimento suavizado (ease-in-out), não linear
Ripple de clique + mudança de estado0,2–0,3sFeedback tátil; a tela reage no mesmo quadro
Zoom para região focal1–2s para entrar, segurar 2–4s2× é o ponto ideal — detalhe suficiente, mantém o contexto
Legendar a funcionalidadesegurar junto com o zoomUma frase de benefício, ex. "Exportação com um clique"

Mova a câmera ou o cursor, raramente ambos ao mesmo tempo — dois movimentos simultâneos dividem a atenção.

Moldura a captura de tela

Uma captura de tela crua parece um relatório de bug; uma emoldurada parece produto. Envolva cada tela em uma moldura de navegador ou dispositivo sobre um fundo com marca.

// Moldura de navegador — coloque uma captura de tela, obtenha uma janela crível
const BrowserFrame = ({ url, children }) => (
  <div style={{ borderRadius: 12, overflow: "hidden", background: "#1e1e22",
                boxShadow: "0 40px 80px rgba(0,0,0,.35)" }}>
    <div style={{ height: 40, display: "flex", alignItems: "center", gap: 8, padding: "0 14px" }}>
      {["#ff5f57", "#febc2e", "#28c840"].map((c) => (
        <span key={c} style={{ width: 12, height: 12, borderRadius: "50%", background: c }} />
      ))}
      <div style={{ marginLeft: 12, flex: 1, height: 24, borderRadius: 6, background: "#2b2b30",
                    color: "#9aa", fontSize: 13, display: "flex", alignItems: "center", padding: "0 10px" }}>
        {url}
      </div>
    </div>
    <div style={{ background: "#fff" }}>{children}</div>
  </div>
);

Coloque uma URL real na barra de endereços (autenticidade), adicione uma sombra suave e um fundo gradiente. Para dispositivos móveis, troque para uma moldura de telefone com notch e cantos arredondados. Mantenha o estilo da moldura em um único objeto de tema para que todas as telas combinem.

Cursor animado + ripple de clique (o movimento central)

Direcione a posição a partir do quadro atual, nunca de uma transição CSS ou relógio de parede — um renderizador de vídeo precisa que cada quadro seja uma função pura do número do quadro, ou o cursor dessincroniza e pisca.

import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";

// Viagem suavizada de `from` para `to` entre startFrame e startFrame+dur
const useCursor = (from, to, startFrame, dur) => {
  const frame = useCurrentFrame();
  const t = interpolate(frame, [startFrame, startFrame + dur], [0, 1],
    { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: (x) => x * x * (3 - 2 * x) }); // smoothstep
  return { x: from.x + (to.x - from.x) * t, y: from.y + (to.y - from.y) * t };
};

export const Cursor = ({ from, to, startFrame, dur, clickAt }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const { x, y } = useCursor(from, to, startFrame, dur);

  // O ripple se expande uma vez, no quadro do clique
  const since = frame - clickAt;
  const showRipple = since >= 0 && since < 18;
  const r = spring({ frame: since, fps, config: { damping: 18 }, durationInFrames: 18 });

  return (
    <>
      {showRipple && (
        <div style={{ position: "absolute", left: x, top: y, transform: "translate(-50%,-50%)",
          width: 12 + r * 60, height: 12 + r * 60, borderRadius: "50%",
          border: "2px solid rgba(80,140,255,.9)", opacity: 1 - r }} />
      )}
      <svg width="28" height="28" viewBox="0 0 28 28"
           style={{ position: "absolute", left: x, top: y, filter: "drop-shadow(0 2px 3px rgba(0,0,0,.4))" }}>
        <path d="M3 2 L3 21 L9 15 L13 24 L16 23 L12 14 L20 14 Z" fill="#fff" stroke="#222" strokeWidth="1.4" />
      </svg>
    </>
  );
};

O cursor usa smoothstep para acelerar a partir do repouso e desacelerar até o alvo (um cursor linear parece robótico). Dispare o ripple e a mudança de estado da tela no mesmo quadro clickAt para que causa e efeito coincidam. Consulte references/screenshot-demo.md para a composição completa conectando múltiplos cliques em múltiplas telas.

Zoom para uma região (Ken Burns para UI)

Para ampliar um elemento focal, escale a tela e defina transform-origin para o centro desse elemento, para que o zoom convirja para ele em vez do centro do quadro.

const ZoomToRegion = ({ target, scale = 2, startFrame, dur, children }) => {
  const frame = useCurrentFrame();
  const s = interpolate(frame, [startFrame, startFrame + dur], [1, scale],
    { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: (x) => 1 - Math.pow(1 - x, 3) }); // easeOutCubic
  return (
    <div style={{ transform: `scale(${s})`, transformOrigin: `${target.x}px ${target.y}px`,
                  willChange: "transform" }}>
      {children}
    </div>
  );
};

Limite o zoom a cerca de 2× (acima de 3× perde contexto e desorienta). Segure o estado ampliado por 2–4s — tempo suficiente para ler o detalhe — depois saia suavemente antes de passar para a próxima tela. Acompanhe o zoom com uma chamada, nunca sem.

Anotações de chamada e legendas de funcionalidades

Anote o ponto de inflexão, depois deixe-o limpar. Uma chamada é um rótulo + um conector (seta, círculo ou sublinhado) que aponta para o elemento focal.

  • Destaque o elemento com um anel suave ou um entorno escurecido (box-shadow: 0 0 0 9999px rgba(0,0,0,.45) abre um buraco de holofote).
  • Legende um benefício por batida — frase nominal curta ("Analytics em tempo real"), não uma sentença. Entre no zoom, saia antes do próximo passo.
  • Mantenha as legendas no terço inferior e dentro da área segura para título, para que sobrevivam a cortes para 9:16.

Consulte references/annotation-and-transitions.md para máscaras de holofote, conectores de seta/círculo e uma trilha de legendas digitadas.

Transições entre telas

Entre as etapas, mova as telas com uma linguagem consistente. Escolha uma e mantenha-a:

TransiçãoSensaçãoUso
Empurrar / deslizarMovimento "próximo passo" para frenteWalkthroughs lineares
Cross-zoomMomentum, estilo appEntrando em uma visualização de detalhes
CrossfadeCalmo, neutroMudando de contexto (configurações → painel)
Match-cut em um elemento compartilhadoContínuoMesmo cartão persiste entre telas

Segure a tela de saída até que seu clique seja resolvido, depois faça a transição — nunca corte no meio do movimento. Consulte references/annotation-and-transitions.md.

Lista de verificação de saída

  • Entradas capturadas em 2× (DPR 2); zooms permanecem nítidos em 2×.
  • Cada valor de cursor/zoom é uma função pura de useCurrentFrame() — sem transições CSS para estado animado.
  • Cursor viaja em um caminho suavizado (smoothstep); ripple e mudança de estado disparam no mesmo quadro de clique.
  • Cada tela emoldurada (navegador/dispositivo) com uma URL real e tema consistente.
  • Um movimento por vez (câmera ou cursor); zoom ≤ 2×, segurado 2–4s.
  • Uma legenda de benefício por batida, no terço inferior seguro para título; transições usam uma linguagem consistente.

Entregue e verifique (quadros estáticos renderizados → MP4)

Helper empacotado (scripts/): organize seus quadros estáticos com scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png, depois verifique a codificação com scripts/probe-mp4.sh out.mp4 [WxH] [fps]. Consulte scripts/README.md.

Este é um nível pesado: a entrega é um MP4, não uma página ao vivo. A demonstração consome ativos do usuário — capturas de tela/designs, logotipo opcional — então a verificação é principalmente a imagem correta realmente carregou e pousou no quadro.

Contrato de saída:

  • Um projeto Remotion com a composição registrada (<Composition> + esquema zod + defaultProps); cada valor de cursor/zoom/transição é uma função pura de useCurrentFrame() (sem transições CSS, temporizadores, Date.now()).
  • Capturas de tela carregadas via staticFile(), controladas com delayRender/continueRender para que o PNG 2× (e qualquer fonte web) esteja presente antes da renderização do quadro — caso contrário, a tela surge em branco no meio da demonstração.
  • Entregável = o out/*.mp4 renderizado mais o projeto (re-renderize quando a captura de tela mudar).

Loop de verificação — renderize quadros estáticos → inspecione → codifique. PNGs baratos primeiro, vídeo apenas quando estiverem corretos.

# Quadros estáticos exatos COM AS PROPS QUE VOCÊ VAI ENVIAR (caminhos reais de captura de tela), não defaultProps
npx remotion still ProductDemo out/f-settle.png --frame=15  --props=demo.json   # tela emoldurada, antes do movimento
npx remotion still ProductDemo out/f-click.png  --frame=90  --props=demo.json   # cursor no alvo + ripple
npx remotion still ProductDemo out/f-zoom.png   --frame=150 --props=demo.json   # ampliou para região focal + legenda
# quadro final = durationInFrames - 1 (npx remotion compositions lê isso)

Inspecione cada PNG quanto a fidelidade (captura de tela correta carregada; cursor no pixel exato; ripple de clique e mudança de estado no mesmo quadro; texto da legenda correto) E artefatos (imagem em branco/não carregada, tela fora da área de trabalho, zoom pixelizado ou ultrapassando o quadro, legenda fora do terço inferior seguro para título, proporção incorreta/letterboxing).

# Apenas depois que os quadros estáticos estiverem limpos:
npx remotion render ProductDemo out/demo.mp4 --props=demo.json
npx remotion render ProductDemo out/demo.gif --props=demo.json --codec=gif   # Prova da primeira tela para o README

Lote (um modelo, muitos produtos): ao re-skinizar a demonstração por produto, verifique as props de UM produto representativo por meio de quadros estáticos antes de renderizar em lote o catálogo — pegue um bug de imagem em branco ou fora da área de trabalho uma vez, não N vezes.

Antes de finalizar:

  1. Quadros estáticos renderizam limpos no pouso / clique / fim — sem erros, capturas de tela realmente carregadas (não em branco).
  2. Cursor pousa no alvo exato; ripple + mudança de estado no mesmo quadro; texto da legenda correto e no terço inferior seguro para título.
  3. Todo movimento é orientado a quadro — sem transições CSS / temporizadores / Date.now() / Math.random().
  4. As props enviadas (caminhos reais de captura de tela) renderizam corretamente, não apenas defaultProps.
  5. MP4 completo codificado e reproduzido; (opcional) GIF renderizado para o README.

Arquivos de referência

  • references/screenshot-demo.md — uma demonstração Remotion completa e executável: capturando capturas de tela em 2× com Playwright, os componentes de moldura de navegador/telefone, uma composição de várias etapas que percorre um cursor por várias telas com ripples de clique e um comando de renderização.
  • references/annotation-and-transitions.md — máscaras de holofote, conectores de seta/círculo, uma trilha de legendas de funcionalidades digitadas e as quatro transições entre telas com implementações orientadas a quadro e notas de área segura para múltiplas proporções (16:9 / 9:16).

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Habilidades Relacionadas