Communitygithub.com

motion: canvas + Web Audio 모션 영상을 MP4로, 모든 비율 지원

모든 종류의 모션 디자인 영상(비네트, 인트로, 애니메이션 설명, 키네틱 텍스트 광고)을 canvas로 그리고 Web Audio로 합성한 사운드트랙을 입혀, 9:16, 4:5, 1:1, 16:9 MP4로 프레임 단위 내보내는 Agent Skill입니다. 내레이션 유무 모두 가능합니다.

motion: canvas + Web Audio 모션 영상을 MP4로, 모든 비율 지원란 무엇인가요?

튜토리얼 영상 레시피 3단계(SNS 티저). Felipeex/motion-skill(2026-10-07 공개, README에 9:16 약 35초 광고 GIF 3개, SaaS 광고 포함). 스킬은 video.html을 작성해 render(t)로 canvas에 모든 프레임을 그리고 Web Audio로 음악과 휙, 팝, 틱 효과음을 만들기 때문에 같은 t는 항상 같은 프레임을 냅니다. export.mjs가 헤드리스 Chrome을 프레임 단위로 구동해 ffmpeg로 넘기고, --quadros로 먼저 검토용 스틸을 뽑습니다. 내레이션이 있으면 trim-audio.mjs가 무음을 잘라 voice.wav를 정규화하고 Whisper로 단어별 타이밍을 잡으며(OpenAI 키는 환경 변수로만), 음악은 목소리 아래로 자동으로 낮아집니다. 규격은 1080x1920, 1080x1350, 1080x1080, 1920x1080이고 브랜드 색상, 폰트, 로고는 프로젝트에서 읽습니다. 최종 MP4는 ffprobe와 ebur128로 약 -14 LUFS를 확인합니다. 숫자, 성과, 추천사는 사용자가 제공해야 하며 절대 지어내지 않습니다. Chrome, ffmpeg, Node 24가 필요하고 npm install은 필요 없습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add Felipeex/motion-skill

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Motion genérico (canvas + Web Audio → MP4)

Um vídeo, sem amarrar formato, marca, nicho ou narração. Se o projeto já tiver um vídeo feito com esta skill, copie a pasta dele para videos/<nome>/ (ou onde o usuário quiser), apague o que é do vídeo antigo (assets/, voice.wav, timings.json, words.json, o MP4) e reescreva as cenas do video.html: o exportador, o servidor local e o buildAudio já funcionam. Se não houver, crie os arquivos abaixo nessa pasta.

ArquivoO que faz
trim-audio.mjs(Só com narração) tira os silêncios → voice.wav normalizada + timings.json
video.htmlA animação: render(t) num canvas + trilha/efeitos em Web Audio. Aberto no Chrome, vira prévia com som
export.mjsChrome sem janela desenha cada quadro → ffmpeg → MP4. --quadros 0.2,9.5,… só tira fotos para revisar
assets/Imagens que o vídeo usa (logo, prints, fotos)

Precisa de: Chrome em C:/Program Files/Google/Chrome/... (ou CHROME=), ffmpeg no PATH, Node 24. Sem npm install.

O que adaptar ao copiar

  • Formato: W, H e <canvas width height> no video.html, o aspect-ratio do CSS do canvas e o --window-size do export.mjs (maior que o canvas). Medidas comuns: 1080x1920 (Reels/Stories/Shorts), 1080x1350 (feed 4:5), 1080x1080 (1:1), 1920x1080 (YouTube/apresentação).
  • Nome da saída: OUT no export.mjs (video-<nome>.mp4) e o prefixo do --user-data-dir.
  • Duração: TOTAL. Com narração, é a duração da voz cortada; sem narração, combine com o usuário (vinheta 3–6s, intro 5–10s, explicativo 30–90s).
  • Sem narração: tire o carregamento de voice.wav e o ducking da música no buildAudio; a trilha fica no volume cheio (≈0,6–0,75). Sem som nenhum: pule o renderAudioWav e exporte só o vídeo (-an).
  • Visual: cores e fontes vêm da marca do usuário (pergunte ou leia do projeto). Defina tudo como constantes no topo (COLORS, FONTS); nada de cor solta no meio das cenas.
  • Zonas seguras: 9:16 → conteúdo entre y≈200 e y≈1600 e 90px nas laterais (interface do Reels). 4:5 e 1:1 → 60px de margem. 16:9 → 5% de margem (title safe).

Fluxo com o usuário (fale simples)

  1. Perguntas, no máximo 6, uma por vez (com a ferramenta de perguntas do agente, se houver, como o AskUserQuestion; 3 opções, a recomendada primeiro). Pergunte só o que não dá para descobrir: formato/onde vai ser postado, tem narração?, duração (se não houver voz), estilo, marca/cores (se não estiverem no projeto), som e chamada final.
  2. Roteiro em tabela (tempo | fala ou texto | o que aparece). Espere o ok antes de desenhar.
  3. Mande fotos de revisão, depois entregue o MP4.

Áudio (quando houver narração)

  • node trim-audio.mjs "<gravação>": silencedetect a -35dB/0,25s, folgas de 0,08s/0,14s e loudnorm. Confira a média da voz perto de -19 dB (volumedetect).
  • Tempo de cada palavra: Whisper (whisper-1, verbose_json, timestamp_granularities[]=word, idioma certo) com a chave que o usuário der, só por variável de ambiente, nunca salva. Palavras rápidas às vezes vêm no mesmo tempo: espalhe à mão.
  • Os textos na tela seguem o que foi falado. Avise quando diferirem do roteiro escrito.

Animação (video.html)

  • Tudo sai de render(t): a mesma t gera sempre o mesmo quadro. Aleatório só com mulberry(seed); nada de Math.random() ou Date no desenho.
  • Tempos em constantes no topo; o som (soundEvents) lê as mesmas constantes, então imagem e som não saem do ritmo.
  • Cenas: SCENES = [[início, fim, fn]], entrada ~0,3s e saída ~0,22s, com uma transição cobrindo a troca. Evite corte seco.
  • Texto palavra por palavra: drawWords. Espaço entre palavras = 0.28 * size (com 0,24, itálico gruda). Ajuste size ao formato: em 16:9 o texto é mais largo e menor.
  • Movimento constante: nenhuma cena parada por mais de 0,5s (luzes do fundo, leve zoom de câmera, granulado).
  • Quadro 0 = capa: algo já visível em t=0 (use entradas com tempo negativo); nada de abrir com tela branca.
  • Fontes: document.fonts.load(...) de cada peso antes do primeiro render; window.ready espera fontes e imagens.
  • Imagens por http, nunca file:// (o canvas fica "sujo" e toDataURL falha). O export.mjs já sobe um servidor local.
  • Logo do cliente sempre como imagem, nunca redesenhada.

Som (Web Audio)

  • buildAudio(ac, voz, t0) serve para a prévia (AudioContext) e para exportar (OfflineAudioContext → WAV).
  • Trilha sintetizada (pad, baixo, bumbo, chimbal); ajuste o BPM ao clima (≈80 calmo, ≈96 padrão, ≈120 energético). Com voz: música a 0,22 sob a voz. Efeitos: whoosh nas transições, pop nas entradas, tic em contagens. Tudo passa por um compressor.
  • Saída com loudnorm=I=-14:TP=-1.5 (redes sociais). Para YouTube/apresentação, -14 também serve.

Exportar e revisar

cd videos/<nome>
node export.mjs --quadros 0,2,5,9   # fotos em review/
node export.mjs                     # MP4
  • Olhe as fotos antes de exportar. Para um mosaico: copie como seq_00.jpg… e use ffmpeg -i seq_%02d.jpg -vf "scale=400:-1,tile=7x2" (glob não funciona no Windows).
  • Checklist: texto cobrindo texto, palavra grudada, conteúdo fora da zona segura, quadro 0 vazio, cena parada, número sem ponto de milhar.
  • Depois do MP4: ffprobe (resolução certa, 30fps, h264+aac), ebur128 (≈ -14 LUFS) e quadros tirados do próprio MP4 (-ss). Diga ao usuário que você mediu o som, mas não ouviu.
  • Não versione mix.wav nem review/ (confira o .gitignore se a pasta for nova).

Conteúdo

  • Prova, números e depoimentos só se forem reais e o usuário fornecer. Nunca invente.
  • Se o vídeo for anúncio, promessa de ganho ("até 4x", "R$ X por dia") pode ser reprovada pelo Meta. Avise.

관련 스킬