Communitygithub.com

llleadbet/video-explainer-skill

HTML/SVG/CSS와 GSAP로 애니메이션 2D 장면을 작성하고 headless Chromium과 ffmpeg로 프레임별로 렌더링하여 설명 동영상(MP4)을 제작합니다. 사용자가 설명 동영상, 애니메이션 워크스루, 모션 그래픽 클립, 애니메이션 다이어그램/차트를 동영상으로 내보내 달라고 요청할 때 사용합니다. 생성형/AI 동영상이나 기존 영상 편집용이 아닙니다.

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

이 기술은 마치 모션 디자이너처럼 코드로 동영상을 제작하는 방식입니다. 각 장면은 DOM/SVG를 구축하고 **일시정지된 GSAP 타임라인**에 트윈을 추가하는 작은 JS 모듈입니다. 렌더러는 해당 타임라인을 프레임 단위로 탐색(`t = frame / fps`)하고, 각 프레임을 스크린샷으로 캡처한 후 ffmpeg로 파이프 전송하여 MP4 동영상을 출력합니다. 모든 과정이 결정론적이므로 동일한 프로젝트는 항상 동일한 프레임을 렌더링합니다. 주요 워크플로우는 다음과 같습니다: 1) 스토리보드 작성, 2) 프로젝트 스캐폴딩 및 장면 코딩, 3) 음성 해설 추가(선택 사항), 4) 린트 검사, 5) 연락처 시트로 미리보기, 6) 최종 렌더링. 이 기술은 `cue()` 함수를 통해 음성 해설 문구와 애니메이션을 정확하게 동기화하며, 모든 모션은 GSAP 타임라인(`tl`)에서만 발생해야 합니다. CSS 애니메이션이나 `setTimeout` 등 실제 시간에 의존하는 요소는 사용할 수 없습니다. Claude Code, Cursor, Codex 등 AI 에이전트 환경에서 사용할 수 있습니다.

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

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

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

문서

동영상 설명 제작

당신은 모션 디자이너가 코드로 동영상을 만드는 방식으로 작업합니다: 각 장면은 DOM/SVG를 구축하고 일시정지된 GSAP 타임라인에 트윈을 추가하는 작은 JS 모듈입니다. 렌더러는 해당 타임라인을 프레임 단위로 탐색하고(t = frame / fps), 각 프레임을 스크린샷으로 캡처한 후 프레임을 ffmpeg로 파이프 전송합니다. 출력은 결정론적입니다: 동일한 프로젝트는 항상 동일한 프레임을 렌더링합니다.

SKILL_DIR은 이 스킬의 기본 디렉토리(이 파일이 들어 있는 폴더)를 의미합니다.

설정 (기기당 한 번)

cd SKILL_DIR/scripts && npm install && npx playwright install chromium

또한 ffmpeg가 PATH에 있어야 합니다. 모든 스크립트는 종속성이 누락된 경우 이 명령을 출력합니다.

워크플로우

  1. 먼저 스토리보드를 작성합니다. 주제, 대상, 목표 길이 및 음성 해설 포함 여부에 동의한 후 video.json에 장면 목록을 작성합니다. 각 장면에는 narration(음성 해설 내용)과 visual(화면에 표시될 내용)이 포함됩니다. reference/storyboard.md를 읽어보세요. 스토리보드가 자체적으로 이해될 때까지 장면 코드를 작성하지 마십시오.
  2. 스캐폴딩: node SKILL_DIR/scripts/new.mjs <project-dir> --title "..."를 실행한 후, video.json을 편집하고 scenes/<id>.js에 장면당 하나의 모듈을 작성합니다. 레시피는 reference/animation-patterns.md를, 레이아웃, 서체 및 색상은 reference/design.md를 참조하세요. 음성 해설이 있는 경우 장면 길이를 "auto"로 설정하고 cue('phrase')로 애니메이션을 시간 동기화합니다. 두 가지 예제(ElevenLabs를 사용한 examples/kubernetes-overview/ 및 Gemini를 사용한 examples/how-dns-works/)는 모두 음성 해설이 포함된 완성된 동영상입니다.
  3. 음성 해설(원하는 경우): reference/voiceover.md를 따르세요. 간단히 말해, video.json에 "voice" 블록을 추가하고, node SKILL_DIR/scripts/narration.mjs status <project-dir>를 실행한 후, 나열된 각 장면에 대해 정확히 해당 인수로 OpenRouter MCP generate-speech 도구를 한 번 호출하고, narration.mjs add로 각 저장된 파일을 등록합니다. 실제 오디오는 장면 길이와 cue() 타이밍을 변경하므로 확인 단계(4단계) 전에 이 작업을 수행하세요.
  4. 확인: node SKILL_DIR/scripts/lint.mjs <project-dir>를 실행합니다. Chromium에서 모든 장면을 로드하고 로드 오류, 장면보다 긴 애니메이션, tl 외부에서 생성된 애니메이션, 프레임 외부 요소, 잘린 텍스트 및 장면에 비해 너무 긴 내레이션을 보고합니다. 의도적인 것이 아니라면 모든 경고를 수정하세요.
  5. 미리보기: node SKILL_DIR/scripts/render.mjs <project-dir> --contact-sheet를 실행한 후 PNG를 읽습니다(<project-dir>/out/contact-sheet.png). 계층 구조, 겹침, 가독성, 빈 프레임, 타이밍을 확인합니다. 세부 사항은 --stills 12.5,30과 같은 특정 순간을 렌더링합니다. 올바르게 보일 때까지 반복하고, 마지막 편집 후 한 번 더 연락처 시트 패스를 수행합니다.
  6. 렌더링: node SKILL_DIR/scripts/render.mjs <project-dir> → <project-dir>/out/video.mp4. 내레이션 클립이 자동으로 믹스됩니다. 사용자에게 경로, 길이 및 장면 목록을 제공합니다. node SKILL_DIR/scripts/serve.mjs <project-dir>로 대화형 미리보기(스크러버, 재생/일시 정지, 내레이션 재생, c는 캡션 전환, m은 음소거)를 할 수 있습니다.

유용한 렌더링 플래그: --out file.mp4, --from 10 --to 20(부분 렌더링), --scale 0.5(빠른 초안), --workers N, --crf 18, --audio track.mp3(내레이션 대신 자체 오디오 트랙 사용), --no-voice(무음), --audio-codec aac(기본값은 MP3이며 VS Code에서도 재생 가능).

프로젝트 레이아웃

my-video/
  video.json          # 제목, 너비, 높이, fps, 시드, 전환, 테마, 장면[]
  scenes/<id>.js      # 장면당 하나의 모듈
  assets/             # 이미지/SVG, '/assets/x.svg'로 참조
  audio/              # 내레이션 클립 + manifest.json(narration.mjs에서 생성; 비용이 들었으므로 유지)
  style.css           # 선택 사항, 있으면 자동 로드
  out/                # 렌더링 결과(contact-sheet.png, stills/, video.mp4)

video.json 장면 필드: id(필수, 기본 파일 이름 scenes/<id>.js이기도 함), duration(초 단위 또는 "auto": 내레이션 오디오에 맞춤, 오디오가 없을 경우 읽기 속도 추정치, 애니메이션보다 짧지 않음), narration, visual, 선택적 file 및 선택적 transition("fade"(기본값) 또는 "cut"). 최상위 "voice" 블록은 reference/voiceover.md에 설명되어 있습니다.

장면 계약

import { h, reveal, pop } from '/__runtime/helpers.js';

export default function ({ el, tl, gsap, theme, width, height, random, onFrame, cue, voice }) {
  const title = h('div', { class: 'h1' }, '안녕하세요');
  el.append(h('div', { class: 'center' }, title));
  reveal(tl, title, { at: 0.3 });                       // tl 시간 0 = 이 장면의 시작
  tl.to(title, { color: 'var(--accent)', duration: 0.5 }, cue('핵심 아이디어'));  // 해당 문구가 말해질 때
}
  • el: 이 장면의 컨테이너입니다. 전체 1920×1080 스테이지를 덮으며 사용자 대신 표시/숨김이 처리됩니다.
  • tl: 이 장면의 타임라인입니다. 모든 모션은 tl에 있어야 합니다(또는 여기에 추가된 다른 타임라인). gsap.to(...), CSS animation/transition, setTimeout, setInterval, requestAnimationFrame, <video> 등 실제 시간에 의존하는 요소를 직접 사용하지 마십시오. 렌더러는 타임라인 재생 헤드만 이동시키므로, 다른 것은 MP4에서 고정되거나 동기화가 깨집니다.
  • cue(phrase, offset = -0.15)는 phrase(대소문자 구분 안 함, 이 장면의 내레이션에 나타나야 함)가 말해지는 장면 시간을 반환합니다. 오디오가 있으면 클립의 측정된 일시 정지와 정렬되므로 절을 시작하는 문구는 실제 단어와 일치합니다. 문구를 찾을 수 없으면 오류를 발생시킵니다. 내레이션과 동기화된 모든 at에 사용합니다. voice는 이 장면의 음성에 대해 { start, duration, end, estimated }를 제공합니다(예: voice.end까지 루핑 효과 유지).
  • 프레임별 그리기(캔버스, 프로시저 모션)의 경우 onFrame((sceneTime) => draw(sceneTime))을 사용합니다. 장면이 표시되는 동안 매 프레임마다 호출됩니다.
  • 오버레이(선택 사항): video.json의 "overlay": "scenes/_overlay.js"는 전체 동영상의 모든 장면 위에 그려지는 모듈을 추가합니다. 타임코드, 진행률 표시줄, 로고 또는 프레임 테두리에 사용합니다. { el, tl, onFrame, scenes, duration, ... }을 받으며, onFrame((t) => ...)은 전역 시간을 받고 scenes는 각 장면의 start/end를 나열합니다.
  • random()은 장면별로 시드되며, Math.random도 시드되므로 임의 레이아웃을 재현할 수 있습니다.
  • 함수는 async일 수 있습니다(예: fetch('/assets/data.json')). 글꼴은 장면이 실행되기 전에 로드되므로 텍스트 측정이 가능합니다.
  • 테마 색상은 CSS 변수입니다: var(--bg) --surface --surface2 --fg --muted --accent --accent2 --accent3 --accent4 --danger, 추가로 --font 및 --mono. video.json → "theme": { "accent": "#ff3366" }에서 재정의할 수 있습니다.
  • GSAP 플러그인이 전역적으로 등록됩니다: DrawSVG, MotionPath, MorphSVG, SplitText, Text, ScrambleText, CustomEase.

품질 기준

  • 장면당 하나의 아이디어. 최소 2~3초마다 화면에서 무언가가 움직이거나 변경되어야 하며, 모든 애니메이션은 설명하는 내레이션 라인과 동기화되어야 합니다(cue() 사용; 내레이션은 약 초당 2.5단어로 진행됨).
  • 텍스트는 크게: 본문 ≥ 40px, 레이블 ≥ 26px(1920×1080 스테이지 기준). 안전 영역(.safe, 96/128px 여백) 내에 유지하세요.
  • 완성된 다이어그램을 한 번에 보여주기보다는 조각별로 구성하세요.
  • 각 장면 끝에 페이드 전에 짧은 유지 시간을 남겨 최종 상태를 읽을 수 있도록 하세요.

음성 해설

오디오는 OpenRouter MCP 서버(generate-speech)에서 가져옵니다. 이 스킬은 계획 및 기록만 담당합니다. 해당 도구를 사용할 수 없는 경우, 음성 해설을 위해 OpenRouter MCP 서버 연결이 필요하다고 사용자에게 알리고, 그동안 음성 없이 렌더링하세요. reference/voiceover.md에 전체 절차, 모델 및 음성 선택, 비용이 나와 있습니다.

관련 스킬