Communitygithub.com

product-video

Grave e produz o vídeo de demonstração de um site, app ou funcionalidade com a CLI vos — o agente define o roteiro de cliques (actions.json), a gravação planeja os zooms automaticamente e cada decisão de edição é um dado no doc.json, então correções são edições e re- renderizações, nunca regravações. As renderizações são determinísticas e a exportação é gratuita até 4K sem marca d'água.

O que é product-video?

Esta skill capacita agentes de IA (como Claude Code, Cursor, etc.) a produzirem vídeos de demonstração polidos, capturas de tela e ativos de marketing a partir de páginas web ao vivo, usando a CLI `vos`. Em vez de regravar todo o roteiro de cliques para corrigir o ritmo ou os zooms, a skill transforma cada decisão de edição em dados dentro de um arquivo `doc.json`. O fluxo de trabalho é: o agente explora a página alvo e escreve um roteiro de cliques (`actions.json`), ensaia e grava a interação, ajusta os parâmetros de zoom/tilt/trims no `doc.json` e finalmente renderiza o vídeo final. As renderizações são determinísticas — apenas mudanças no `doc.json` alteram a saída. A exportação pode ser feita gratuitamente até resolução 4K, sem marca d'água. A skill também oferece suporte a cenários atrás de login, usando um 'session ladder' para obter uma sessão de teste antes de iniciar a gravação, e pode converter passeios pré-verificados com `agent-browser` em roteiros de cliques. Um ciclo de qualidade multimodal (guiado por `references/taste.md`) garante que cada quadro seja inspecionado antes da renderização final. Além de vídeos, a skill pode gerar assets de lançamento (capturas para lojas, Product Hunt, redes sociais) através do sub-skill `launch-kit`.

Funciona com~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/vosjs/skills/tree/main/skills/product-video

Perguntar na sua IA favorita

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

Documentação

Product video (e os ativos ao redor dele), do início ao fim

Você está produzindo um ativo de produto pronto para ser enviado — um vídeo polido, um conjunto de stills com tamanhos exatos, ou ambos — a partir de uma página web ativa, com a CLI vos. Tudo são dados: você escreve um script de fluxo, a CLI grava e planeja, você ajusta o JSON, você re-renderiza. Nunca regrave para corrigir ritmo ou zooms — edite doc.json e renderize novamente. Padrão de qualidade: references/taste.md — siga seu ciclo de qualidade e julgue os stills multimodalmente.

Configuração

npm i -D @vosjs/cli

Um comando, um pacote: @vosjs/cli é o binário vos de código aberto (MIT) com os verbos do motor, o pipeline de takes usado aqui (record / plan / frames / render em gravações de tela) e os verbos da plataforma vos.so. (Até a versão 0.9, o pipeline de takes era enviado separadamente como @vosso/vos-plugin; um projeto que ainda o liste pode descartá-lo.) Requisitos:

  • Um Chromium: o Chrome do sistema é encontrado automaticamente; caso contrário, execute npx playwright install chromium ou aponte VOS_BROWSER_PATH para um. Código de saída 3 significa que nenhum navegador foi encontrado.
  • Rede no momento da renderização: a página de renderização carrega three/mediabunny do esm.sh. A gravação também precisa alcançar a URL alvo. Sandboxes totalmente offline não podem renderizar — diga isso em vez de não enviar nada.

Convenções: logs → stderr, resultados → stdout; --json emite NDJSON terminando com {"event":"done",…}; códigos de saída 0 ok / 1 erro / 2 uso ou falha estrita / 3 sem navegador / 4 o gravador encontrou um login em vez da página (uma SESSION ausente ou expirada, nunca um bug de script: references/sessions.md). vos <verb> --help imprime as flags desse verbo (@vosjs/cli 0.41.1 e posteriores).

Passo 0 — escolha o destino (ele decide tudo)

DestinoViewportSaídaExtras
Clipe de página inicial (hero/embed de seção)2560×1440 (2K nativo da filmagem)webm → re-encode VP9 + posterloop silencioso; veja references/destinations.md
Vídeo de lançamento (PH, social, promo de loja)2560×1440 ou 1280×720mp4 (--format mp4, precisa do Chrome do sistema)faixa de música via doc.audio
Stills do kit de lançamento (capturas de loja, tiles, OG)dimensionado para o ativoPNGs frames --frame <t> --size WxH do mesmo takeum take → cada ativo
Demo rápida (issue, PR, chat)1280×720webm, padrõesvelocidade acima do polimento; rascunhos aceitáveis SOMENTE aqui

Dimensões e orçamentos de bytes por canal: references/destinations.md.

O loop principal (todo destino)

  1. Explore a página alvo com suas próprias ferramentas (buscar HTML / Playwright). Identifique os 3–6 momentos que contam UMA história. Colete SELETORES estáveis (a[href='…'], ids, papéis — não cadeias nth-child). Prepare o conteúdo como um cenário: o script deve deixar o produto no estado que uma captura de tela orgulhosa mostraria — rótulos digitados, dados com aparência real, a funcionalidade no meio da história. Uma tela vazia grava rápido e não demonstra nada, e nenhuma composição downstream a resgata.

    Atrás de um login? Resolva a sessão antes do script. Um gravador sem sessão grava a parede (a página de login, ou a página pública que o site envia para um estranho) e o único sintoma é um seletor ignorado. Suba a escada em references/sessions.md de cima para baixo e pare no primeiro degrau que segurar: nenhuma parede (um modo demo, um servidor local com autenticação desligada) → CUNHE uma sessão a partir da autenticação de teste que o projeto já tem (playwright/.auth, um auth.setup.ts, um script de seed: procure antes de perguntar a qualquer pessoa) → faça login fora da câmera com setup em actions.json (a senha de { "env": "NAME" }, nunca um literal) → o humano faz login uma vez (vos session open <url> --name <app>, então --session <app> no record) → o humano grava com a extensão a partir da lista de shots que vos actions script actions.json imprime, e você corta. Cada degrau termina em setup, um arquivo de estado para --storage-state, ou uma sessão nomeada para --session. Nunca digite ou aceite uma senha de produção, mantenha o arquivo de estado fora do diretório do take e fora do git, e grave de uma conta demo: o que a conta mostra é enviado no vídeo.

    Já verificou a funcionalidade com agent-browser? Mantenha esse passeio e pule o segundo script. O resultado --json do agent-browser não diz o que foi executado (scroll responde {scrolled:true}), então envolva cada chamada para que o comando acompanhe seu resultado e depois converta:

    ab() { agent-browser "$@" --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const r=JSON.parse(s);process.stdout.write(JSON.stringify({command:process.argv.slice(1),...r})+"\n")})' -- "$@" >> steps.jsonl; }
    ab open https://target.example; ab snapshot -i -u; ab click @e27
    ab wait 800; ab snapshot -i          # a página mudou: refs renumerados
    ab fill @e2 query; ab press Enter
    vos actions from-agent-browser steps.jsonl --out actions.json
    

    (um caminho inteiro executado como um agent-browser batch … --json > steps.jsonl já tem essa forma). O log é steps.jsonl no diretório onde você está, então caminhe a partir de um diretório. As refs são resolvidas através do último snapshot -i antes delas, e elas RENUMERAM após uma navegação e novamente dentro de um diálogo: tire um novo snapshot depois de qualquer coisa que mude a página e leia as refs antes de nomear uma (-u dá aos links seu href). Clique no controle, não pressione seu atalho: ⌘K abre o diálogo para um humano, mas uma tecla é o único passo que o gravador não pode repetir. Tudo o que ele não pode seguir (uma tecla de atalho, um arrasto, um segundo open) é NOMEADO na saída, nunca descartado: leia as notas, escreva esses passos à mão e grave.

  2. Escreva actions.json:

    {
      "url": "https://target.example",
      "viewport": { "width": 1280, "height": 720 },
      "steps": [
        { "do": "wait", "ms": 800 },
        { "do": "hover", "selector": "a[href='/pricing']", "ms": 700 },
        { "do": "click", "selector": "#cta" },
        { "do": "wait", "ms": 1500 },
        { "do": "scroll", "dy": 400 },
        { "do": "move", "x": 640, "y": 320 },
        { "do": "wait", "ms": 900 }
      ]
    }
    

    Verbos: wait hover click type scroll move drag (type = {do:'type', selector, text, delayMs?, ms?, focus?}: ele clica no campo e depois digita text; focus:false digita no que já está focado, para um Enter de envio) (drag = edições reais: {do:'drag', selector|x,y, tx, ty, ms} — deslize um input de faixa, arraste um elemento canvas, mova um clipe da linha do tempo). O RITMO É o plano do zoom: abra wait ≥700ms; passe o mouse sobre o que importa 700–900ms (pausas se tornam zooms); o ms de um clique é o tempo de LEITURA, contado a partir da última alteração da página (@vosjs/cli 0.47 e posteriores; o gravador paga o tempo de estabilização por conta própria), então dimensione-o como uma batida: cerca de 1000ms após uma navegação, 600ms após um controle, nunca preenchido para uma página lenta; termine estabilizado. Direcione o cursor para longe de menus acionados por hover (taste.md, regras de fluxo). Verifique com vos validate actions.json.

    Em seguida, ENSAIE-O (@vosjs/cli 0.39 e posteriores): vos record --actions actions.json --out take --dry-run. Cada passo é executado na página real, em ordem, porque um seletor posterior geralmente existe apenas após um clique anterior, mas nada é capturado e nada é escrito: um seletor perdido é nomeado em segundos (saída 2) em vez de após um take em tempo real e sua codificação, e um take já em --out mantém sua filmagem e seu corte. Ele imprime o rect de cada passo em px de captura, que é o que uma camada fixada lê. Ensaie novamente após cada edição de script, e grave apenas um script que passe. Um produto com login ensaia da mesma forma: --storage-state e --browser-arg= também se aplicam a ele, e o ensaio termina listando o que o quadro EXPÕE (um endereço, uma chave, um cartão). Esconda-os com mask antes de gravar: references/sessions.md.

  3. Grave: vos record --actions actions.json --out take --strict --json --strict sempre: seletor ignorado / timeout networkidle → saída 2 com skipped[] no evento done. Uma ignorância significa que o fluxo está quebrado — corrija-o, nunca o entregue contornando-o. O take é auto-codificado e auto-planejado automaticamente. (vos create --actions actions.json out.webm --strict é o verbo gravar+renderizar de uma só vez — bom para uma primeira passagem rápida, mas o loop DESTA skill revisa os quadros antes de renderizar, então prefira os verbos separados aqui.)

  4. Ajuste doc.json (o JSON Schema é enviado no pacote npm @vosjs/cli: schema/doc.schema.json):

    • zoom: [{in, out, level, cx, cy, source}], segundos SOURCE; níveis 1.4–2.8; cx/cy NORMALIZADOS [0..1] (0.5,0.5 = centro) — NÃO pixels; defina "source": "manual" nos intervalos que você tocar (sobrevive ao re-planejamento).
    • segments (cortes) · speed (rate 0.1–16) · frame.* · cursor.
    • tilt: [{in, out, rx, ry, source}], segundos SOURCE — o cartão 3D inclina-se para a pose enquanto ativo, retorna ao repouso entre elas. GRAUS (±5..18 lê premium): +rx = borda superior mais próxima, +ry = borda esquerda mais próxima (inclinar em direção a um foco no lado direito = ry negativo). Intervalos ≥ 0.8s; combine com momentos de zoom (mesmo in/out encadeia os movimentos), uma mudança de pose a cada ~5s batida. "source": "manual" nos intervalos que você tocar; tiltStyle: "subtle"|"medium"|"strong" registra a varinha automática.
    • frame.backgroundMedia: um loop de vídeo / imagem atrás do cartão — {"kind":"video","key":"/bg.webm","duration":10,"dim":0.2}. key = um arquivo colocado no diretório do take ("/bg.webm") ou uma URL de mídia; vídeo precisa de duration (modulo loop ancorado na SAÍDA); dim 0..1 tela. Ambiente, não um assunto — escureça-o atrás de uma IU densa.
    • audio: clipes ancorados na SAÍDA; key pode ser um arquivo colocado no diretório do take ("/music.mp3"); ganho/fades/loop. Misturado em renderizações completas (Opus/AAC); --range permanece silencioso; força voo único.
    • export: {"resolution": "720p|1080p|2k|4k", "fps": 30} — nunca acima da filmagem (validate avisa). Então vos validate take --json — as verificações devem passar.
  5. Olhe antes de renderizar (o ciclo de qualidade taste.md):

    • vos frames take --at-zooms --times 0,25%,50%,75%,100% --json → julgue cada still contra taste.md, os ápices de zoom mais fortemente.
    • Itere: edite doc.json → vos render take check.webm --range a..b --draft (segundos, meia res — nunca envie rascunhos) → re-quadre a região alterada.
    • Tentando uma apresentação? Use uma flag, não um script de rascunho. render/frames aceitam substituições do doc — --set <path>=<value> (repetível; JSON-ou-string), --frame <macos|windows|minimal|none> (render), --background <url> — que aplicam patch no doc em memória (doc.json intacto) e são protegidos por lint. Então vos frames take --frame 2.0 --set frame.browserBar.kind=mac-light --set tilt[0].rx=8 pré-visualiza um cartão emoldurado e inclinado sem tocar no arquivo.
  6. Renderização final: vos render take out.webm --json (ou --format mp4). Re-quadre o final (frames --at-zooms) contra taste.md antes de declarar concluído. As renderizações são determinísticas — apenas suas edições alteram a saída.

6b. Rodada de revisão humana (quando a solicitação envolve uma): vos open take serve o take no estúdio — suas edições no doc.json chegam intactas e

Individual skills in this repo

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

launch-kit

Ship the media with the release — one take of the real product becomes YouTube demo, Chrome Web Store screenshots/tiles, Product Hunt gallery, social cuts, and OG cards; verified kit.json manifest.

vos-authoring

Author a vos animation program (VosConfigJson) from scratch or debug one — declarative configs compiling into deterministic Three.js + GSAP-dialect animations on the MIT vos engine (@vosjs/core), validated locally with compileVosConfig. Covers the schema, dialect rules, 2D overlay elements, shaders, and params/presets knobs. Use when asked to write a vos animation program, create a VosConfigJson, make a programmatic motion graphic or logo animation, or fix a config that fails to compile or lint.

vos-create

Create vos programs in the user

vosjs/vos-cut

Cut a screen recording (a vosso take) into the product video it was recorded for, from its evidence, with the vos CLI — read the take's digest (the moments the cursor track says mattered, each with a footage frame and a crop), narrate beats, edit doc.json by exception over the planners, verify with stills, and push an attributed version the human fine-tunes at vos.so; every edit is a data patch, so a re-cut never re-records. Use when asked to edit or cut a recording, make a product video or what's-new clip from a take, cut it like the last one, or cut a series of recordings in one style.

vosjs/vos-footage

Hand a Remotion, HyperFrames, or any video composition a clean captured clip of the real product — recorded and auto-zoomed with the vos CLI, delivered as full-bleed footage with no chrome, and always backed by an editable take on the maker's shelf, which the handoff says. Use when a composition needs real product footage, app or site b-roll, "capture our app for the video", or a screen-recorded segment to drop into another tool's timeline.

vosjs/vos-migrate

Turn an existing Loom, Screen Studio, Cap, or plain mp4/webm screen demo into an editable vosso take — re-encode the file, synthesize the take's metadata, plan, and push, so the old demo becomes a living document you re-cut instead of a file you re-record. Use when asked to "convert this Loom", "migrate our old demos", "re-edit this mp4", "make our Screen Studio recording editable", or to bring any already-recorded demo into vosso.

vos-remix

Remix a vos.so gallery program into your own — fetch its config, edit the declared knobs or code locally, validate with vos check, and push a private copy back with lineage that iterates as versions. Carries the params/Looks doctrine and the GLB 3D-showcase recipe. Use when asked to remix, customize or personalize a gallery animation, swap a 3D model into a showcase, or iterate a fetched program as versions.

Habilidades Relacionadas