Communitygithub.com

erencalik/motion-graphics-video-generator-claude

단일 요청으로 애니메이션 MP4 모션 그래픽 비디오(9:16 릴스 또는 16:9)를 생성하며, HTML/CSS/JS 애니메이션을 프레임 단위로 렌더링하고 ffmpeg로 결합합니다. 모션 그래픽, 키네틱 타이포그래피, 애니메이션 통계, 릴스 애니메이션에 사용하세요.

motion-graphics-video-generator-claude란 무엇인가요?

이 스킬은 Claude의 코드 실행 환경 내에서 별도의 편집 소프트웨어나 스톡 푸티지 없이 엔드투엔드 MP4 모션 그래픽 비디오를 생성합니다. 사용자가 단일 요청만 하면 HTML/CSS/JS로 애니메이션을 작성하고, Playwright로 헤드리스 Chrome에서 각 프레임을 캡처한 후 ffmpeg로 비디오로 결합합니다. 또한 코드로 음악을 합성하여 비디오와 동기화합니다. claude.ai, Cursor, GitHub Copilot 등 코드 실행과 파일 생성을 지원하는 모든 플랫폼에서 작동합니다. 키네틱 타이포그래피, 애니메이션 인포그래픽, 입자 효과, 하프톤, 지도, 카운터 등 다양한 스타일을 지원하며, 로고와 브랜드 자료를 업로드하여 맞춤형 브랜드 비디오를 제작할 수 있습니다. 이 스킬은 Michael Ly의 가이드를 기반으로 하여 신뢰성과 재현성을 보장하는 결정론적 프레임워크를 사용합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erencalik/motion-graphics-video-generator-claude/tree/HEAD

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

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

문서

모션 그래픽 비디오

Claude의 코드 환경 내에서 편집 소프트웨어나 스톡 푸티지 없이 MP4를 엔드투엔드로 생성합니다. 코드 실행 및 파일 생성이 필요합니다(claude.ai: 설정 > 기능). 브랜드 비디오의 경우 로고, 사진, 색상 및 글꼴을 업로드하거나 브랜드 스타일 파일을 지정하세요. 사용자의 언어로 응답합니다.

작동 방식

  1. 애니메이션은 단일 HTML 페이지로 작성됩니다. 모든 요소의 위치, 크기, 색상 및 불투명도는 프레임 번호(window.renderFrame(f))로부터 계산됩니다. CSS 전환, setTimeout 또는 requestAnimationFrame은 사용되지 않습니다. 이렇게 하면 렌더링이 결정론적이 됩니다.
  2. 헤드리스 Chrome(Playwright)이 모든 프레임을 캡처합니다. 20초 × 60fps = 1,200프레임.
  3. ffmpeg가 프레임을 MP4(H.264, yuv420p)로 변환합니다.
  4. 음악은 코드로 합성되며, 전환에 맞춰 타이밍이 조정되고 비디오에 추가됩니다.

요청 체크리스트 (누락된 항목이 있으면 한 번에 질문)

  1. 길이: 15~20초가 이상적입니다.
  2. 형식: Reels/TikTok/Shorts용 9:16(1080×1920), YouTube/포트폴리오용 16:9(1920×1080).
  3. 소스 자료: 웹사이트, 업로드된 사진, 로고 또는 없음.
  4. 스타일: 기술 이름을 지정하세요: 키네틱 타이포그래피, 애니메이션 인포그래픽/통계, 입자, 하프톤, 지도/지형, 카운터, 타임라인. 이름이 지정된 기술이 더 안정적인 결과를 제공합니다.
  5. 규칙 및 제외 사항: 일치시킬 색상, 제외할 사항(예: 가격, 추가 텍스트).
  6. 열정: 사용자가 "최선을 다해주세요"라고 말하면 Claude가 컨셉, 팔레트 및 음악을 직접 선택하고 더 과감하게 진행합니다.

스토리 릴스를 위한 기성 구조: 로고/훅 인트로(0~2초) → 키네틱 타입의 스토리 문장 → 카운터에서 증가하는 숫자 → 타임라인 또는 지도 → 클로징 카드(계정 핸들). 화면 텍스트는 Reels 안전 영역(상단 210px, 하단 310px, 오른쪽 84px 여백) 안에 유지하세요. 숫자와 날짜는 출처가 있어야 하며, 가상의 숫자를 애니메이션하지 마십시오.

제작 단계

  1. 초 단위로 장면 계획을 작성하고(표: 시간 | 화면 내용 | 전환 | 오디오 히트) 표시합니다.
  2. scene.html을 작성합니다. 규칙: 고정 픽셀 크기, window.TOTAL(총 프레임 수) 및 window.renderFrame(f) 정의; 이징 함수로 보간; 글꼴은 base64 woff2(환경이 Google Fonts에 도달하지 못할 수 있음)로, 이미지는 base64로 포함합니다.
  3. 먼저 3~4개의 PNG 프레임을 캡처하고 직접 검사합니다(텍스트 넘침, 잘못된 글꼴, 빈 프레임). 그런 다음 전체 렌더링을 수행합니다.
  4. audio.py로 음악을 합성하고 장면 전환에 히트를 배치합니다. 사용자가 자신의 음악을 업로드하면 그 음악을 사용합니다.
  5. 결합, ffprobe로 길이/해상도 확인, 중간 프레임을 시각적으로 확인하고 MP4를 전달합니다.

렌더링 시간: 60fps에서 20초는 약 8~10분이 소요됩니다. 빠른 초안에는 30fps를, 최종본에는 60fps를 사용하세요. 시간 코드로 수정 요청을 받습니다("0:07의 카운터를 더 느리게").

템플릿 (테스트 완료, 이 SKILL.md 옆에 파일로도 제공됨)

scene.html (스켈레톤)

<!doctype html><html><head><meta charset="utf-8"><style>
html,body{margin:0;width:1080px;height:1920px;overflow:hidden;background:#0E0E10;font-family:'Montserrat',Arial,sans-serif}
#s{position:relative;width:1080px;height:1920px}
.t{position:absolute;left:90px;right:90px;color:#F5F1E8;font-weight:800;line-height:1.05}
</style></head><body><div id="s">
<div class="t" id="a" style="top:520px;font-size:120px">5,126</div>
<div class="t" id="b" style="top:680px;font-size:64px;color:#FF5A1F">FAILED PROTOTYPES</div>
</div><script>
const FPS=30,DUR=3;window.TOTAL=FPS*DUR;
const clamp=(x,a=0,b=1)=>Math.min(b,Math.max(a,x));
const easeOut=t=>1-Math.pow(1-t,3);
window.renderFrame=f=>{const t=f/FPS;
 const p=easeOut(clamp(t/0.6));a.style.opacity=p;a.style.transform=`translateY(${(1-p)*80}px)`;
 a.textContent=Math.round(5126*easeOut(clamp(t/1.5))).toLocaleString('en-US');
 const q=easeOut(clamp((t-0.8)/0.5));b.style.opacity=q;b.style.transform=`scale(${0.8+0.2*q})`;};
</script></body></html>

render.js: node render.js scene.html video.mp4 30 (Playwright가 없으면: npm i playwright && npx playwright install chromium; 실패하면 Python Playwright로 동일한 루프를 작성)

// node render.js scene.html out.mp4 [fps]
const {chromium}=require('playwright');const {spawn}=require('child_process');const path=require('path');
(async()=>{const [,,html,out,fpsArg]=process.argv;const fps=+(fpsArg||30);
const b=await chromium.launch();const p=await b.newPage({viewport:{width:1080,height:1920}});
await p.goto('file://'+path.resolve(html));await p.evaluate(()=>document.fonts.ready);
const total=await p.evaluate(()=>window.TOTAL);
const ff=spawn('ffmpeg',['-y','-f','image2pipe','-framerate',String(fps),'-i','-','-c:v','libx264','-pix_fmt','yuv420p','-crf','18','-preset','medium',out],{stdio:['pipe','inherit','inherit']});
for(let f=0;f<total;f++){await p.evaluate(f=>window.renderFrame(f),f);ff.stdin.write(await p.screenshot({type:'jpeg',quality:92}));}
ff.stdin.end();await new Promise(r=>ff.on('close',r));await b.close();console.log('frames',total);})();

16:9의 경우 뷰포트와 페이지 크기를 1920×1080으로 변경합니다.

audio.py: python3 audio.py music.wav <초> (numpy 합성: 패드 + 히트)

# python3 audio.py music.wav 3   -> synthesised pad + hits
import sys,wave,numpy as np
out,dur=sys.argv[1],float(sys.argv[2]);sr=44100;t=np.arange(int(sr*dur))/sr
pad=sum(np.sin(2*np.pi*f*t) for f in (110,164.8,220))*0.08*np.minimum(1,t/0.5)
def hit(at,f0=60):
    x=np.zeros_like(t);m=t>=at;tt=t[m]-at;x[m]=np.sin(2*np.pi*f0*tt*(1+3*np.exp(-tt*30)))*np.exp(-tt*8)*0.6;return x
y=pad+hit(0.0)+hit(0.8,90)
y=y/np.max(np.abs(y))*0.8;fade=np.minimum(1,(dur-t)/0.4);y*=fade
w=wave.open(out,'wb');w.setnchannels(1);w.setsampwidth(2);w.setframerate(sr);w.writeframes((y*32767).astype(np.int16).tobytes());w.close()

결합

ffmpeg -y -i video.mp4 -i music.wav -c:v copy -c:a aac -b:a 192k -shortest final.mp4

한계

  • 사진에 효과를 적용할 수 있습니다(입자, 하프톤, 컷아웃). 사람을 애니메이션할 수 없으며 립싱크는 불가능합니다(이를 위해서는 전용 아바타/비디오 모델을 사용하세요).
  • 합성 음악은 전자 음악입니다. 실제 악기나 보컬이 필요하면 오디오 파일을 업로드하세요.
  • 사용자가 소유하지 않은 저작권이 있는 캐릭터나 로고는 사용할 수 없습니다. 실제 회사 로고는 뉴스/논평 맥락에서만 사용하고 출처를 명시하세요.

크레딧: Michael Ly의 가이드 "How to Generate Motion Graphics Videos with Claude"(milleemd.com/guides/motion-graphics-videos)의 방법을 기반으로 합니다. 코드 템플릿은 이 스킬을 위해 작성되었습니다.

관련 스킬