Communitygithub.com

jblxo/programmatic-video-skill

코드만으로 60fps 1080p MP4 애니메이션 비디오, 모션 그래픽, 릴리스 리캡, 제품 데모 및 데이터 기반 'Wrapped' 스타일 비디오를 제작하고 렌더링합니다.

programmatic-video-skill란 무엇인가요?

이 스킬은 AI 코딩 에이전트(Claude Code, Cursor, Codex 등)가 HTML5 Canvas/SVG, Playwright 프레임 스테핑(windwo.__setFrame), 멀티모달 접촉 시트 시각적 자체 검토, 절차적 Python/NumPy 오디오 합성, WAV SFX 큐 믹싱 및 FFmpeg를 사용하여 결정론적 60fps 1080p MP4 애니메이션 비디오를 구축하고 렌더링할 수 있는 완전한 워크플로우를 제공합니다. 실시간 화면 녹화(MediaRecorder)나 CSS 애니메이션의 벽시계 시간에 의존하지 않고 프레임 인덱스의 순수 함수로 모든 장면을 구동하여 프레임 드롭, 오디오/비디오 동기화 불일치 및 비결정적 동작을 방지합니다. 전체 렌더링 전에 8-12개의 주요 타임스탬프를 캡처하여 단일 contact-sheet.png로 구성하고 시각적 결함(텍스트 오버플로, 겹침, 낮은 대비)을 검토하여 수정하므로 수천 프레임의 낭비를 방지합니다. 또한 샘플 정확도의 WAV 사운드트랙을 합성하고 FFmpeg 파이프로 직접 스트리밍하여 디스크 블로트 없이 완벽한 동기화된 최종 비디오를 생성합니다.

지원 대상✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI✓OpenCode
npx skills add https://github.com/jblxo/programmatic-video-skill/tree/HEAD/skills/programmatic-video

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

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

문서

프로그래매틱 비디오 생성 스킬

AI 코딩 에이전트가 단일 HTML5 Canvas/SVG 파일, Python 절차적 오디오 스크립트, 헤드리스 Playwright → FFmpeg 파이프를 통해 60fps 1080p MP4 애니메이션 비디오를 설계, 시각적 QA, 점수 매기기 및 렌더링할 수 있는 결정론적이고 설정이 필요 없는 워크플로우입니다.

경로. ${CLAUDE_SKILL_DIR}은 이 SKILL.md가 포함된 디렉터리입니다. Claude Code에서는 자동으로 확장됩니다. Cursor, Codex, OpenCode 또는 다른 에이전트에서는 ${CLAUDE_SKILL_DIR}을 skills/programmatic-video/의 확인된 경로로 바꾸세요.


결정론적 프레임 스테핑이 필요한 이유

AI 에이전트로 비디오를 생성할 때 실시간 브라우저 화면 녹화(MediaRecorder, requestAnimationFrame 벽시계 캡처 또는 실시간 CSS 전환)를 절대 사용하지 마세요:

  1. 벽시계 캡처는 CPU 부하가 급증할 때 프레임을 드롭하여 오디오/비디오 드리프트 및 끊김 현상을 유발합니다.
  2. CSS 애니메이션은 벽시계 시간으로 실행되므로 t = 14.20s로 탐색하여 즉각적인 시각적 QA를 수행할 수 없습니다.
  3. 블라인드 렌더링은 시간을 낭비합니다: 제목이 카드를 넘칠지 확인하기 전에 5,000프레임을 렌더링하면 작업 낭비가 보장됩니다.

대신, 이 스킬로 제작된 모든 비디오는 세 가지 규칙을 따릅니다:

  • 규칙 1 — 프레임 인덱스의 순수 함수: 전체 장면은 window.__setFrame(frameIndex, timeSeconds, fps)에 의해 구동되며, 여기서 t = frameIndex / fps입니다. 모든 위치, 불투명도, 카운터 및 입자는 t의 결정론적 수학 함수입니다(시드된 PRNG(예: mulberry32) 사용, Math.random() 절대 사용 금지).
  • 규칙 2 — 전체 렌더링 전 멀티모달 접촉 시트 QA: 전체 60fps MP4를 인코딩하기 전에 8-12개의 주요 타임스탬프를 캡처(render.mjs --timestamps ...), 단일 contact-sheet.png로 스티치(contact-sheet.py), 멀티모달 읽기/보기 도구를 사용하여 텍스트 클리핑, 겹침 또는 낮은 대비를 수정합니다.
  • 규칙 3 — 샘플 정확한 오디오 + 제로 디스크 블로트 FFmpeg 파이프: 다중 세그먼트 스테레오 WAV 사운드트랙 + 타임스탬프 SFX 큐를 생성(synth-audio.py)한 다음 Playwright에서 PNG 버퍼를 ffmpeg -f image2pipe로 직접 스트리밍합니다(render.mjs).

종단 간 에이전트 워크플로우 (6단계)

1단계: 스토리보드 및 장면 예산

코드를 작성하기 전에 구체적인 타임라인 표를 설계하세요. 비디오를 4-8초 장면으로 그룹화하고 scene.html과 synth-audio.py가 공유하는 명시적인 전환 타임스탬프(T_cut)를 포함하세요:

장면시간 (t)프레임 (60fps)시각적 초점오디오 / SFX 큐
01 — 훅 / 알림0.0s – 7.0s0 – 420CRT 터미널 부팅, 타자기 로그, 2.7s CTA 버튼 클릭서브 펄스 + 2.7s UI 클릭/잠금 해제 큐, 3.4s 라이저
02 — 히어로 메트릭7.0s – 15.0s420 – 9003D 원근 신스웨이브 그리드 + 3개의 스프링 물리 카운터 카드7.0s 전체 124 BPM 신스웨이브 베이스 + 스테레오 아르페지에이터 드롭
03 — 딥 텔레메트리15.0s – 23.0s900 – 1380분할 화면 진행률 표시줄 + 애니메이션 반원형 게이지필터 스위프 + 하이햇 드라이브, 15.0s 서브 임팩트
04 — 호명 및 피날레23.0s – 30.0s1380 – 1800기여자 카드의 벤토 그리드 + "JOB'S DONE!" 배너 및 폭죽25.2s 피날레 코드 + 음성/SFX 큐, 28.5–30.0s 마스터 페이드 아웃

2단계: window.__setFrame(f, t, fps)로 scene.html 작성

HTML5 <canvas>(및/또는 인라인 <svg> + DOM 오버레이)를 사용하여 자체 포함된 1920x1080 HTML 파일을 작성하고 다음을 노출하세요:

window.__setFrame = function(frameIndex, timeSeconds, fps = 60) {
  if (window.__rafId) {
    cancelAnimationFrame(window.__rafId);
    window.__rafId = null;
  }
  const t = typeof timeSeconds === 'number' ? timeSeconds : frameIndex / fps;
  renderSceneAtTime(frameIndex, t);
};
  • 별, 입자, 폭죽 또는 노이즈에 대해 항상 시드된 PRNG(mulberry32(seed))를 포함하여 프레임 f가 실행 간에 비트 단위로 동일하도록 합니다.
  • document.fonts.ready를 기다립니다(render.mjs에서 자동 처리).
  • 복사 가능한 레시피(3D 원근 그리드, 스프링 카운터, CRT 터미널, 게이지, 벤토 카드, 폭죽 물리)는 references/visual-patterns.md를 참조하세요.

3단계: 빠른 타임스탬프 스냅샷 실행 및 contact-sheet.png 구축

절대 먼저 전체 60fps 렌더링을 실행하지 마세요. 장면당 1-2개의 타임스탬프(전환 중간점 포함)를 샘플링하고 단일 접촉 시트를 구축하세요:

# 1. ~3초 안에 9개의 키프레임 PNG 캡처
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --timestamps 1.8,3.0,5.2,8.5,12.5,16.5,20.5,24.5,28.0 \
  --out-dir ./qa-frames

# 2. 레이블이 지정된 그리드 이미지로 스티치
python3 "${CLAUDE_SKILL_DIR}/scripts/contact-sheet.py" \
  --dir ./qa-frames \
  --cols 3 \
  --thumb-width 560 \
  --title "VISUAL QA CONTACT SHEET" \
  --out ./contact-sheet.png

4단계: 멀티모달 자체 검토 루프 (필수!)

./contact-sheet.png(및 밀도가 높아 보이는 개별 ./qa-frames/t-*.png)에서 이미지 Read / View 도구를 호출하세요. references/visual-qa-loop.md의 체크리스트에 대해 모든 타일을 확인하세요:

  • 텍스트가 카드 테두리, 배지 또는 진행률 표시줄을 넘치거나 충돌합니까?
  • 모든 숫자, 레이블 및 HUD 헤더가 1080p에서 고대비이고 읽기 쉽습니까?
  • 모든 장면 전환이 의도하지 않은 빈/검은 프레임 없이 깔끔하게 전환됩니까?

contact-sheet.png에서 문제를 발견하면 scene.html을 수정하고 다음 단계로 진행하기 전에 3단계를 다시 실행하세요.

5단계: 절차적 사운드트랙 합성 및 WAV SFX 큐 믹싱

전환 라이저 및 SFX 큐가 scene.html의 정확한 타임스탬프와 일치하는 스테레오 44.1kHz WAV 사운드트랙을 생성하세요:

python3 "${CLAUDE_SKILL_DIR}/scripts/synth-audio.py" \
  --duration 30.0 \
  --bpm 124 \
  --style synthwave \
  --transitions 3.4,7.0,15.0,23.0,25.2 \
  --cue "25.2:./sfx/jobs-done.wav:+1.5" \
  --out ./soundtrack.wav

사용자 정의 다중 세그먼트 작곡 또는 테마 사운드 팩(예: jblxo/claude-code-sound-packs) 통합에 대한 자세한 내용은 references/audio-synthesis.md를 읽으세요.

6단계: FFmpeg 파이프를 통해 최종 60fps H.264 MP4 렌더링

시각적 QA 및 오디오 합성이 통과되면 전체 파이프 모드에서 render.mjs를 실행하세요:

node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --duration 30 \
  --fps 60 \
  --audio ./soundtrack.wav \
  --crf 18 \
  --out ./final-video.mp4

ffprobe로 출력 컨테이너를 확인하세요:

ffprobe -v error -show_entries format=duration,size:stream=codec_name,width,height,r_frame_rate -of default=noprint_wrappers=1 ./final-video.mp4

참조 플레이북 (요청 시 로드)

주제참조 파일
Canvas/SVG 시각적 프리미티브, 이징 함수, 시드된 PRNG, 3D 신스웨이브 그리드, 게이지, 벤토 카드references/visual-patterns.md
멀티모달 접촉 시트 QA 루프, 일반적인 레이아웃 결함, 타임스탬프 선택 전략references/visual-qa-loop.md
절차적 Python/NumPy 오디오 합성, 코드 진행, 라이저, 덕킹, WAV SFX 큐 믹싱references/audio-synthesis.md

관련 스킬