프로그래매틱 비디오 생성 스킬
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 전환)를 절대 사용하지 마세요:
- 벽시계 캡처는 CPU 부하가 급증할 때 프레임을 드롭하여 오디오/비디오 드리프트 및 끊김 현상을 유발합니다.
- CSS 애니메이션은 벽시계 시간으로 실행되므로
t = 14.20s로 탐색하여 즉각적인 시각적 QA를 수행할 수 없습니다. - 블라인드 렌더링은 시간을 낭비합니다: 제목이 카드를 넘칠지 확인하기 전에 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.0s | 0 – 420 | CRT 터미널 부팅, 타자기 로그, 2.7s CTA 버튼 클릭 | 서브 펄스 + 2.7s UI 클릭/잠금 해제 큐, 3.4s 라이저 |
| 02 — 히어로 메트릭 | 7.0s – 15.0s | 420 – 900 | 3D 원근 신스웨이브 그리드 + 3개의 스프링 물리 카운터 카드 | 7.0s 전체 124 BPM 신스웨이브 베이스 + 스테레오 아르페지에이터 드롭 |
| 03 — 딥 텔레메트리 | 15.0s – 23.0s | 900 – 1380 | 분할 화면 진행률 표시줄 + 애니메이션 반원형 게이지 | 필터 스위프 + 하이햇 드라이브, 15.0s 서브 임팩트 |
| 04 — 호명 및 피날레 | 23.0s – 30.0s | 1380 – 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 |