← 포트폴리오

044 · 모션그래픽 통합 제작환경

🎬 Motion Stack0에서 시작하는 설치 가이드

Claude Code에 영상·3D·수학애니메이션·제너러티브아트·자막·실사편집 제작 능력을 붙이는 8개 도구의 설치 전 과정이다. 프로그램 정식 명칭, 받는 곳, 설치되는 절대 경로, 검증 명령, 실패 지점까지 전부 적었다. GitHub에 접근할 수 없는 환경을 위한 오프라인 경로도 함께 제공한다.

⚡ 원샷 설치 스크립트
GitHub 도달 여부를 스스로 검사해 경로를 바꾼다. --check로 설치 상태만 볼 수도 있다.
motion-stack-setup.sh · 12KB
📦 스타터 팩
Remotion · HyperFrames 예제 2종. 실제 렌더까지 검증 완료. node_modules 미포함.
motion-stack-starters.zip · 63KB
🔌 오프라인 팩
GitHub 차단 환경용. GitHub에서 받아야 하는 스킬 11종을 라이선스와 함께 동봉.
motion-stack-offline.zip · 4.9MB
이 문서의 전제: 읽는 사람의 컴퓨터에 아무것도 설치돼 있지 않다고 가정한다. "Remotion을 깐다"가 아니라 Remotion이 무엇이고 어디서 오는지부터 적었다. 모든 버전·경로는 2026-10-17에 macOS에서 실제로 설치하고 렌더까지 확인한 값이다.

목차

  1. 무엇이 설치되는가 — 5개 도구의 정체
  2. 네트워크 접근 매트릭스 — GitHub 없이 되는 것/안 되는 것
  3. 설치 경로 지도 — 무엇이 어디에 깔리는가
  4. 원샷 설치 — 스크립트 한 번
  5. 도구별 수동 설치 — 명령 · 검증 · 기대 출력
  6. Blender 수동 3단계 — 자동화 불가 구간
  7. 스타터 코드 전문 — 복사해서 바로 실행
  8. 동작 확인 — 렌더 스모크 테스트
  9. 트러블슈팅 — 실제로 걸렸던 지점
  10. 호출법 · 출처 · 라이선스
  11. 개념 먼저 — 스킬·플러그인·MCP가 뭔가
  12. 도구 선택 결정 트리
  13. 첫 10분 — 도구별 실전 튜토리얼
  14. 에러 사전 — 증상 → 원인 → 조치
  15. 렌더 비용 감각 — 실측값
  16. 제거 · 롤백
  17. 조합 워크플로 레시피 3종
  18. 설치 완료 체크리스트
  19. 확장 도구 3종 — 자막·Lottie·실사편집 (2026-10-21)

01 · 무엇이 설치되는가 — 5개 도구의 정체

정식 명칭만든 곳무엇을 하는 도구인가받는 곳 / 설치 형태
Remotion
v4.0.536
Remotion (remotion.dev) React 컴포넌트로 영상을 만든다. 프레임 번호를 받아 화면을 그리면 그게 영상이 된다. 데이터 기반 영상·자막·차트 애니메이션에 강하다. npm 레지스트리 · 전역 설치 없음, 프로젝트 단위(npx create-video)
HyperFrames
v0.8.167
HeyGen HTML+CSS+GSAP로 영상을 만든다. 헤드리스 크롬으로 그린 뒤 ffmpeg로 mp4를 뽑는다. 웹 지식만으로 영상을 만들 수 있어 Remotion의 대안이 된다. npm(CLI) + Claude Code 플러그인(스킬 9종, GitHub 마켓플레이스)
MCP for Blender
(blender-mcp)
ahujasid Claude가 Blender를 직접 조작한다. 오브젝트 생성·머티리얼·파이썬 실행·Poly Haven/Sketchfab 에셋 로드까지. 3D 장면을 대화로 만든다. PyPI(uvx mcp-for-blender) + Blender 앱(blender.org / brew cask)
Manim CE
v0.22.0
Manim Community 수학·개념 애니메이션. 3Blue1Brown이 쓰는 그 엔진의 커뮤니티판. 수식 전개, 그래프, 알고리즘 시각화. PyPI(pip3 install --user manim) + 스킬은 GitHub
algorithmic-artPardesco 코드로 만드는 제너러티브 아트. 시드 기반 결정론적 생성 — 캔버스·SVG(플로터/레이저용)·WebGL 셰이더·오디오 반응형·루프 영상. GitHub 저장소(스킬 폴더) · MIT
"스킬"이 뭔지 모른다면: Claude Code의 스킬은 ~/.claude/skills/<이름>/SKILL.md에 있는 마크다운 지시문 묶음이다. 설치란 사실상 폴더를 그 위치에 두는 것이고, 그러면 Claude가 관련 요청에서 알아서 그 문서를 읽고 따른다. 실행 파일이 아니라서 오프라인 팩으로 통째 전달해도 그대로 동작한다.

02 · 네트워크 접근 매트릭스 — GitHub 없이 되는 것 / 안 되는 것

사내망 등에서 GitHub이 막혀 있는 경우를 위한 절이다. 결론부터: 5개 중 4개는 GitHub 없이 설치된다. GitHub을 타는 것은 ① 일부 스킬 폴더 ② HyperFrames 플러그인 설치 ③ Remotion 공식 스킬 뿐이고, ①②는 오프라인 팩으로 대체된다.
구성요소GitHub 필요실제로 받는 곳차단 시 대안
Remotion 본체불필요npm 레지스트리—
Remotion 공식 스킬 12종필요GitHub remotion-dev/skills없음. 자체 라이선스라 오프라인 팩에 미포함. 본체만으로도 제작은 가능
HyperFrames CLI불필요npm hyperframes@0.8.167—
HyperFrames 스킬 9종필요하나 대체됨GitHub 마켓플레이스오프라인 팩에 포함(Apache-2.0)
MCP for Blender 서버불필요PyPI uvx mcp-for-blender—
Blender 애드온(270KB)불필요PyPI 패키지에 번들 blender_mcp/bundled/addon.py— (설치본과 번들본 sha256 동일 확인)
Blender 앱불필요blender.org 또는 brew caskblender.org 직접 다운로드
Manim CE불필요PyPI—
manim-skill필요하나 대체됨GitHub awesome-skills/manim-skill오프라인 팩에 포함(MIT)
algorithmic-art필요하나 대체됨GitHub Pardesco/algorithmic-art-skill오프라인 팩에 포함(MIT)
Homebrew 패키지
(ffmpeg·cairo·pango·uv)
간접 의존bottle이 ghcr.io(GitHub 인프라)ffmpeg → ffmpeg.org 공식 빌드
uv → pip3 install --user uv
cairo·pango → conda-forge

오프라인 설치 — 3줄

GitHub 차단 환경 설치 (Cloudflare에서 직접 다운로드)
curl -fsSL https://design-portfolio-7yo.pages.dev/motion-stack-offline.zip -o pack.zip
unzip pack.zip && cd motion-stack-offline
bash install-offline.sh     # 스킬 11종 배치 + Blender MCP 등록(PyPI 경유)
팩에 든 것: skills/ 11종(manim-skill · algorithmic-art · hyperframes 9종) · starters/ 2종 · install-offline.sh · ATTRIBUTION.md(출처·라이선스 전문). 설치 스크립트는 이미 있는 스킬은 건너뛴다(멱등).

03 · 설치 경로 지도 — 무엇이 어디에 깔리는가

경로를 모르면 지우지도 고치지도 못한다. 아래는 이 맥에서 실제로 확인한 절대 경로다. ~는 홈 디렉터리(/Users/<사용자명>).
경로무엇비고
~/.claude/skills/전역 스킬 폴더manim-skill · algorithmic-art · hyperframes 9종이 여기 들어간다. 폴더를 넣고 빼는 것이 설치/제거
~/.claude/plugins/플러그인 캐시·마켓플레이스cache/hyperframes/hyperframes/0.8.167/에 LICENSE 포함
~/Library/Application Support/
Blender/5.2/scripts/addons/blender_mcp.py
Blender 애드온270KB. PyPI 패키지가 자동 배치한다. Blender 버전이 다르면 5.2 부분이 바뀐다
/Applications/Blender.appBlender 본체brew cask 또는 blender.org 설치본
~/Library/Python/3.11/binpip --user 실행파일기본 PATH에 없다 — manim 명령을 못 찾는 가장 흔한 원인(9번 참고)
<프로젝트>/.agents/skills/remotion-*Remotion 공식 스킬전역이 아니라 프로젝트 스코프. 12종, skills-lock.json으로 버전 고정
~/.cache/uv/uvx 패키지 캐시mcp-for-blender 실체가 여기 풀린다

설치 여부 한 번에 확인

설치 상태 점검 (아무것도 바꾸지 않음)
ls ~/.claude/skills/                      # 스킬 폴더 목록
claude plugin list                        # 플러그인(hyperframes@hyperframes)
claude mcp list | grep blender            # MCP 서버 연결 상태
ls "$HOME/Library/Application Support/Blender/5.2/scripts/addons/"
node -v && npm -v                         # v24.14.1 / 11.11.0 에서 검증
ffmpeg -version | head -1                 # 9.0.1
PATH="$HOME/Library/Python/3.11/bin:$PATH" manim --version   # v0.22.0

# 또는 스크립트로 한 번에 (설치는 하지 않음)
bash motion-stack-setup.sh --check

04 · 원샷 설치 — 스크립트 한 번

다운로드 후 실행
curl -fsSL https://design-portfolio-7yo.pages.dev/motion-stack-setup.sh -o setup.sh

bash setup.sh --check    # ① 먼저 현재 상태만 확인 (아무것도 설치/수정하지 않는다)
bash setup.sh            # ② 실제 설치
STEP 0

도달성 검사

GitHub·npm·PyPI 각각에 실제로 붙어보고 이후 경로를 분기한다.

STEP 1

시스템 패키지

ffmpeg·uv·cairo·pango·pkgconf

STEP 2~3

Remotion·HyperFrames

npm 경로. 플러그인은 GitHub 가능할 때만.

STEP 4

Blender MCP

PyPI 서버 등록 + 애드온 자동 배치

STEP 5~6

Manim·아트 스킬

PyPI + 스킬 폴더(차단 시 오프라인 팩 안내)

STEP 7

확인 출력

설치된 버전을 표로 찍어준다.

스크립트가 하지 않는 것: ① Remotion 프로젝트를 임의 위치에 만들지 않는다(어디에 둘지는 사용자 결정) ② Blender GUI 활성화(불가능 — 6번 참고) ③ --check 모드에서는 파일·설정을 일절 건드리지 않는다.

05 · 도구별 수동 설치 — 명령 · 검증 · 기대 출력

사전 요건

0. Homebrew · Node · 시스템 패키지
# Homebrew (없을 때만)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Node — Remotion 요구사항: ^20.19.0 || ^22.13.0 || >=24
brew install node
node -v    # 검증 환경: v24.14.1 / npm 11.11.0

# 시스템 패키지
#  ffmpeg  : 영상 인코딩 (HyperFrames·Remotion·algorithmic-art 공용)
#  uv      : uvx로 Blender MCP 서버 실행
#  cairo·pango·pkgconf : Manim 렌더 백엔드
#  ⚠️ brew 공식 이름은 pkg-config가 아니라 pkgconf 다
brew install ffmpeg uv cairo pango pkgconf

1. Remotion

Remotion — 프로젝트 생성 · 스킬 · 렌더
# 전역 설치할 것이 없다. 프로젝트를 만든다.
npx create-video@latest my-video
cd my-video && npm install

# Claude Code용 공식 스킬 12종 (프로젝트 스코프 → .agents/skills/remotion-*)
# ⚠️ 이 단계만 GitHub(remotion-dev/skills)을 탄다
npx remotion skills add

# 검증
npx remotion studio                              # http://localhost:3000 미리보기
npx remotion render HelloMotion out/hello.mp4    # 스타터 팩 예제

# 기대 출력:  + out/hello.mp4  약 45.9 kB  (1280×720, 30fps, 90프레임)
함정: create-video 기본 스캐폴드의 MyComp는 null을 반환한다. 그대로 렌더하면 완전히 빈 영상이 나오는데 이게 정상 동작이다 — 설치 실패로 오해하기 쉽다. 눈으로 확인하려면 7번의 HelloMotion.tsx를 쓸 것.

2. HyperFrames

HyperFrames — 플러그인(스킬 9종) · CLI
# 방법 A — Claude Code 플러그인 (스킬 9종이 전역으로 붙는다, GitHub 필요)
claude plugin marketplace add heygen-com/hyperframes
claude plugin install hyperframes@hyperframes
claude plugin list        # hyperframes@hyperframes · 0.8.167 · user · enabled

# 방법 B — CLI만 (npm, GitHub 불필요). 스킬 자동 진입은 없지만 제작·렌더는 전부 가능
npx --yes hyperframes@0.8.167 init my-video
cd my-video
npx --yes hyperframes@0.8.167 check     # 린트 + 모션/대비 검증
npx --yes hyperframes@0.8.167 render    # mp4 (헤드리스 크롬 + ffmpeg)

# 설치되는 스킬 9종:
#   hyperframes(라우터) · -animation · -audio · -cli · -core
#   -creative · -keyframes · -registry · -studio

3. MCP for Blender

Blender + MCP 서버 — 전부 GitHub 불필요
# Blender 앱 (검증 버전 5.2.2 LTS)
brew install --cask blender          # 또는 blender.org에서 직접 다운로드

# MCP 서버 등록 — PyPI에서 받는다
claude mcp add -s user blender -- uvx mcp-for-blender

# 검증
claude mcp list | grep blender       # blender: uvx mcp-for-blender - ✔ Connected

# 애드온은 패키지에 번들돼 있어 서버가 직접 배치한다(별도 다운로드 불필요)
ls "$HOME/Library/Application Support/Blender/5.2/scripts/addons/blender_mcp.py"

4. Manim CE · 5. algorithmic-art

Manim · algorithmic-art — PyPI + 스킬 폴더
# Manim 본체 (PyPI)
pip3 install --user manim

# ⚠️ pip --user 실행파일은 기본 PATH에 없다 → 셸 설정에 추가
echo 'export PATH="$HOME/Library/Python/3.11/bin:$PATH"' >> ~/.zshrc
export PATH="$HOME/Library/Python/3.11/bin:$PATH"   # 현재 셸 즉시 적용
manim --version    # Manim Community v0.22.0

# 스킬 2종 — GitHub 가능할 때
git clone https://github.com/awesome-skills/manim-skill.git      ~/.claude/skills/manim-skill
git clone https://github.com/Pardesco/algorithmic-art-skill.git  ~/.claude/skills/algorithmic-art

# GitHub 차단 환경이면 오프라인 팩으로 (동일 내용, MIT)
#   curl -fsSL https://design-portfolio-7yo.pages.dev/motion-stack-offline.zip -o pack.zip
#   unzip pack.zip && cd motion-stack-offline && bash install-offline.sh

06 · Blender 수동 3단계 — 자동화 불가 구간

이 구간만은 스크립트가 대신할 수 없다. Blender의 애드온 활성화와 서버 시작은 GUI 조작이라, 파일을 올바른 경로에 두는 것까지만 자동화된다. 이 3단계를 하지 않으면 Claude가 Blender를 제어하지 못한다 — "설치했는데 안 된다"의 대부분이 여기다.
STEP 1

애드온 활성화

Blender 실행 → Edit → Preferences → Add-ons

  • 검색창에 MCP for Blender 입력
  • "Interface: MCP for Blender" 체크박스 켜기
  • 목록에 안 보이면 애드온 파일 경로 확인(3번 표)
STEP 2

서버 시작

3D 뷰포트에서 N 키 → 사이드바

  • MCP 탭 선택
  • Start MCP Server 클릭
  • Blender를 끄면 서버도 꺼진다 — 쓸 때마다 켜야 한다
STEP 3

연결 확인

Claude Code에서

  • claude mcp list → blender ✔ Connected
  • "블렌더에 큐브 하나 만들어줘"로 실제 조작 확인
  • 가능해지는 것: 오브젝트·머티리얼·파이썬 실행·Poly Haven/Sketchfab 에셋

07 · 스타터 코드 전문 — 복사해서 바로 실행

다운로드가 막혀 있어도 되도록 파일 전체를 적었다. 아래 블록을 그대로 저장하면 스타터 팩과 동일하다.

Remotion — 동작 확인용 컴포지션

이 파일이 필요한 이유: 기본 스캐폴드는 빈 영상을 만든다. 아래 컴포지션은 실제로 렌더해서 화면을 확인한 최소 예제다 — 라임색 "Remotion OK" 텍스트가 페이드인하고 프레임 카운터가 돈다.
remotion-starter/src/HelloMotion.tsx — 렌더 검증 완료
import { AbsoluteFill, interpolate, useCurrentFrame, useVideoConfig } from "remotion";

// 설치가 제대로 됐는지 눈으로 확인하는 용도.
//   npx remotion render HelloMotion out/hello.mp4
export const HelloMotion: React.FC = () => {
  const frame = useCurrentFrame();
  const { durationInFrames } = useVideoConfig();

  const opacity = interpolate(frame, [0, 20], [0, 1], { extrapolateRight: "clamp" });
  const y = interpolate(frame, [0, 24], [28, 0], { extrapolateRight: "clamp" });
  const out = interpolate(frame, [durationInFrames - 15, durationInFrames], [1, 0], {
    extrapolateLeft: "clamp",
  });

  return (
    <AbsoluteFill
      style={{
        backgroundColor: "#0f172a",
        justifyContent: "center",
        alignItems: "center",
        fontFamily: "Pretendard, -apple-system, system-ui, sans-serif",
      }}
    >
      <div
        style={{
          opacity: opacity * out,
          transform: `translateY(${y}px)`,
          color: "#a3e635",
          fontSize: 84,
          fontWeight: 800,
          letterSpacing: "-0.03em",
        }}
      >
        Remotion OK
      </div>
      <div style={{ opacity: opacity * out, color: "#94a3b8", fontSize: 28, marginTop: 14 }}>
        frame {frame} / {durationInFrames}
      </div>
    </AbsoluteFill>
  );
};
remotion-starter/src/Root.tsx — 컴포지션 등록
import { Composition } from "remotion";
import { MyComposition } from "./Composition";
import { HelloMotion } from "./HelloMotion";

export const RemotionRoot: React.FC = () => {
  return (
    <>
      {/* 기본 스캐폴드 컴포지션 (내용 없음 — 빈 영상이 정상이다) */}
      <MyComposition />
      {/* 설치 확인용 동작 예제 */}
      <Composition
        id="HelloMotion"
        component={HelloMotion}
        durationInFrames={90}
        fps={30}
        width={1280}
        height={720}
      />
    </>
  );
};
remotion-starter/package.json + remotion.config.ts + src/index.ts
// ─── package.json ─────────────────────────────────────────────
{
  "name": "remotion-starter",
  "private": true,
  "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" },
  "dependencies": {
    "@remotion/cli": "4.0.536",
    "react": "19.2.3",
    "react-dom": "19.2.3",
    "remotion": "4.0.536"
  },
  "devDependencies": {
    "@remotion/eslint-config-flat": "4.0.536",
    "@types/react": "19.2.7", "@types/web": "0.0.166",
    "eslint": "10.12.0", "prettier": "3.8.1", "typescript": "5.9.3"
  },
  "scripts": {
    "dev": "remotion studio",
    "build": "remotion bundle",
    "lint": "eslint src && tsc"
  }
}

// ─── remotion.config.ts ───────────────────────────────────────
import { Config } from "@remotion/cli/config";
Config.setRspack(true);
Config.setVideoImageFormat("jpeg");
Config.setOverwriteOutput(true);
Config.setDefaultPremountInSeconds(2);

// ─── src/index.ts (엔트리) ────────────────────────────────────
import { registerRoot } from "remotion";
import { RemotionRoot } from "./Root";
registerRoot(RemotionRoot);

HyperFrames — 편집 대상은 index.html 하나뿐

타임라인 계약: data-composition-id / data-start / data-duration / data-track-index 속성이 렌더러가 읽는 계약이고, GSAP 타임라인을 window.__timelines["main"]에 등록하면 렌더러가 프레임마다 그걸 시킹한다(재생이 아니라 시킹이라 결정론적이다).
hyperframes-starter/index.html — 전문
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      html, body {
        margin: 0; width: 1920px; height: 1080px;
        overflow: hidden; background: #0a0a0a;
      }
      #root {
        width: 100%; height: 100%; display: flex;
        align-items: center; justify-content: center;
        font-family: Inter, ui-sans-serif, system-ui, sans-serif;
      }
      #title { color: #f4f4f5; font-size: 72px; font-weight: 600; letter-spacing: -0.03em; }
    </style>
  </head>
  <body>
    <div
      id="root"
      data-composition-id="main"
      data-start="0"
      data-duration="10"
      data-width="1920"
      data-height="1080"
    >
      <h1 id="title" class="clip" data-start="0" data-duration="10" data-track-index="0">Title</h1>
    </div>
    <script>
      const tl = gsap.timeline({ paused: true });
      // 예: tl.fromTo("#title", { opacity: 0, y: 24 }, { opacity: 1, y: 0, duration: 0.6 }, 0);
      window.__timelines["main"] = tl;
      tl.seek(0);
    </script>
  </body>
</html>
hyperframes-starter/package.json + hyperframes.json
// ─── package.json — 전역 설치 없이 npx로 CLI를 고정 버전 호출 ───
{
  "name": "hyperframes-starter",
  "private": true,
  "type": "module",
  "scripts": {
    "dev":     "npx --yes hyperframes@0.8.167 preview",
    "check":   "npx --yes hyperframes@0.8.167 check",
    "render":  "npx --yes hyperframes@0.8.167 render",
    "publish": "npx --yes hyperframes@0.8.167 publish"
  }
}

// ─── hyperframes.json — 레지스트리·경로 설정 ───────────────────
{
  "$schema": "https://hyperframes.heygen.com/schema/hyperframes.json",
  "registry": "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry",
  "paths": {
    "blocks":     "compositions",
    "components": "compositions/components",
    "assets":     "assets"
  },
  "media": { "autoProxy": true }
}

// ⚠️ registry가 raw.githubusercontent.com을 가리킨다 →
//    GitHub 차단 환경에서는 레지스트리 블록 설치(hyperframes add)가 실패한다.
//    직접 작성한 index.html 렌더는 레지스트리 없이도 정상 동작한다.

08 · 동작 확인 — 렌더 스모크 테스트

도구확인 명령성공 기준(실측)
Remotionnpx remotion render HelloMotion out/hello.mp4+ out/hello.mp4 45.9 kB · 1280×720 · 90프레임. 재생 시 라임색 "Remotion OK" + 프레임 카운터
HyperFramesnpm run check → npm run rendercheck 통과 후 renders/에 mp4 생성
Manimmanim --version → 예제 씬 렌더Manim Community v0.22.0, mp4 산출
Blender MCPclaude mcp list | grep blender✔ Connected + GUI에서 서버 시작 후 "큐브 만들어줘"가 실제로 동작
algorithmic-artClaude에게 "코드로 제너러티브 아트 만들어줘"스킬이 자동 진입해 시드 기반 코드 생성
검증 원칙: "렌더 성공" 로그는 의도한 화면이 담겼다는 증거가 아니다. 실제로 이 가이드를 쓰면서 겪은 함정이라, 위 Remotion 예제는 렌더 후 ffmpeg -ss 1.2 -i hello.mp4 -frames:v 1 frame.png로 프레임을 뽑아 눈으로 확인한 뒤 배포했다. 빈 영상(기본 MyComp)도 "성공" 로그를 남기기 때문이다.

09 · 트러블슈팅 — 실제로 걸렸던 지점

01

manim: command not found

pip3 install --user가 넣는 ~/Library/Python/3.11/bin이 기본 PATH에 없다. 셸 설정에 추가하고 새 터미널을 열어야 적용된다. 기존 세션은 export PATH=...로 즉시 적용.

가장 흔함
02

brew install pkg-config 실패

Homebrew의 공식 포뮬러 이름은 pkgconf다. pkg-config는 별칭이라 환경에 따라 혼동을 준다. 설치 확인도 brew list --versions pkgconf로.

이름 함정
03

영상이 완전히 비어 있다

Remotion 기본 스캐폴드의 MyComp는 null 반환이 정상이다. 설치 문제가 아니다. HelloMotion을 렌더해 확인할 것.

오진 유발 1위
04

Blender를 제어하지 못한다

claude mcp list가 Connected여도 Blender GUI에서 Start MCP Server를 누르지 않으면 동작하지 않는다. Blender를 끄면 서버도 꺼지므로 쓸 때마다 다시 켠다.

6번 참고
05

brew가 ghcr.io에서 멈춘다

Homebrew는 미리 빌드된 bottle을 GitHub Container Registry에서 받는다. GitHub이 차단되면 설치가 멈춘다. ffmpeg는 ffmpeg.org 공식 빌드, uv는 pip3 install --user uv, cairo·pango는 conda-forge로 우회.

GitHub 차단 환경
06

hyperframes add가 실패한다

hyperframes.json의 registry가 raw.githubusercontent.com을 가리킨다. 레지스트리 블록 설치만 막히고, 직접 작성한 컴포지션 렌더는 정상이다.

GitHub 차단 환경
07

스킬을 설치했는데 Claude가 모른다

스킬은 ~/.claude/skills/<이름>/SKILL.md 구조여야 인식된다. 압축을 잘못 풀어 ~/.claude/skills/manim-skill/manim-skill/SKILL.md처럼 한 겹 더 들어가면 인식되지 않는다. ls ~/.claude/skills/<이름>/SKILL.md로 확인할 것. 또한 스킬 추가 후에는 Claude Code 세션을 새로 시작해야 반영된다.

오프라인 팩 설치 시 주의

10 · 호출법 · 출처 · 라이선스

설치 후 Claude Code에서 부르는 법

이렇게 말하면이게 동작한다
"Remotion으로 15초 인트로 만들어줘"remotion-* 스킬 12종 (프로젝트 스코프)
"/hyperframes로 제품 소개 영상 만들어줘"
또는 자연어로 영상 요청
hyperframes 라우터 스킬이 자동 진입해 하위 스킬(animation·audio·keyframes…)을 고른다
"매님으로 푸리에 변환 시각화해줘"manim-skill
"코드로 제너러티브 아트 만들어줘"algorithmic-art
"블렌더로 이 장면 만들어줘"blender MCP (GUI에서 서버 시작 후)

출처와 라이선스 — 재배포 조건

자산출처라이선스오프라인 팩 포함
manim-skillawesome-skills/manim-skillMIT포함
algorithmic-artPardesco/algorithmic-art-skillMIT © 2026 Pardesco포함 (node_modules 제외)
HyperFrames 스킬 9종HeyGen HyperFrames v0.8.167Apache-2.0포함 (LICENSE 동봉)
Remotion 공식 스킬remotion-dev/skills자체 라이선스미포함 — 각자 npx remotion skills add
MCP for Blenderahujasid/blender-mcp (PyPI 배포)저장소 표기 따름불필요 — PyPI에서 직접
Remotion을 회사에서 쓸 계획이라면 라이선스를 먼저 확인할 것. npm license 필드가 SEE LICENSE IN LICENSE.md로, 개인·소규모는 무료지만 기업 사용은 별도 조건이 붙는 모델이다. 이 때문에 오프라인 팩에도 Remotion 스킬을 넣지 않았다.
MIT·Apache-2.0 재배포 조건: 둘 다 재배포를 허용하되 저작권 표시와 라이선스 전문을 함께 전달할 것을 요구한다. 오프라인 팩에는 ATTRIBUTION.md와 각 폴더의 원본 LICENSE를 그대로 넣어뒀다 — 이 팩을 다시 배포할 때 제거하지 말 것.

11 · 개념 먼저 — 이 단어들을 모르면 설치해도 못 쓴다

설치가 끝나도 "그래서 이걸 어떻게 부르지?"에서 막히는 경우가 많다. 이 장은 Claude Code를 처음 쓰는 사람 기준으로 등장 용어를 전부 푼다.

스킬 (Skill)

~/.claude/skills/<이름>/SKILL.md에 있는 마크다운 지시문 묶음. 실행 파일이 아니다. Claude가 요청을 보고 "이 스킬이 맞겠다" 싶으면 그 문서를 읽고 따른다.
설치 = 폴더를 그 경로에 두는 것. 그래서 오프라인 팩으로 통째 옮겨도 그대로 동작한다. 인식 안 되면 ① 폴더가 한 겹 더 들어갔는지 ② 세션을 새로 시작했는지 확인.

플러그인 (Plugin)

스킬·에이전트·명령을 묶어 배포하는 단위. claude plugin install로 설치하며 마켓플레이스(대개 GitHub 저장소)에서 받는다.
HyperFrames가 이 방식이고, 설치하면 스킬 9종이 한꺼번에 붙는다. 확인: claude plugin list.

MCP (Model Context Protocol)

Claude가 외부 프로그램과 대화하는 표준 규격. 스킬이 "지시문"이라면 MCP는 "도구 연결"이다.
Blender MCP는 별도 프로세스(서버)가 떠서 Claude의 요청을 Blender 조작으로 번역한다. 그래서 Blender 앱 안에서 서버를 켜야 하고, 앱을 끄면 연결이 끊긴다. 확인: claude mcp list.

uvx / npx

둘 다 "설치하지 않고 바로 실행"하는 도구다. npx는 npm 패키지를, uvx는 Python 패키지를 임시로 받아 실행한다.
그래서 uvx mcp-for-blender는 전역 설치 흔적을 남기지 않고, 캐시는 ~/.cache/uv/에 쌓인다.

헤드리스 렌더

화면 없는 브라우저로 페이지를 그려서 이미지·영상으로 뽑는 방식. HyperFrames가 이 구조다 — HTML/CSS/GSAP로 만든 화면을 프레임 단위로 캡처해 ffmpeg로 mp4를 만든다.
따라서 웹에서 되는 것은 대부분 영상으로도 된다. 반대로 브라우저가 못 그리는 건 영상에도 안 나온다.

컴포지션 (Composition)

"영상 한 편"의 단위. Remotion은 <Composition id durationInFrames fps width height>로 등록하고, HyperFrames는 data-composition-id 속성으로 선언한다.
한 프로젝트에 여러 컴포지션을 두고 이름으로 골라 렌더한다: npx remotion render <id> out.mp4.

시킹 (seeking) vs 재생

영상 렌더링은 재생이 아니라 시킹이다. "0.0초 상태를 그려라 → 캡처 → 0.033초 상태를 그려라 → 캡처" 방식이라 느린 컴퓨터에서도 결과가 똑같다(결정론적).
그래서 HyperFrames는 GSAP 타임라인을 paused: true로 만들어 window.__timelines에 등록한다 — 렌더러가 직접 시킹하기 위해서다.

시드 (seed) · 결정론

제너러티브 아트에서 난수의 출발점. 같은 시드 = 같은 결과물이라, 마음에 든 작품을 다시 만들 수 있다.
시드를 안 고정하면 "아까 그거 다시"가 불가능하다. algorithmic-art가 시드 기반인 이유.

스킬 · 플러그인 · MCP의 관계 한 줄 정리: 스킬은 Claude에게 주는 설명서, 플러그인은 설명서 묶음의 배포 포장, MCP는 Claude와 다른 프로그램을 잇는 전선이다. 이 스택에서 Remotion·Manim·algorithmic-art는 스킬, HyperFrames는 플러그인(=스킬 9종), Blender는 MCP다.

12 · 도구 선택 결정 트리 — 뭘 만들 때 뭘 쓰나

다섯 도구는 대체재가 아니라 레이어다. 겹치는 영역에서 무엇을 고를지가 실패를 가른다.
만들려는 것1순위대안고르는 이유
데이터가 바뀌면 영상도 바뀌어야 함(차트·리포트·주간 요약)Remotion—React라 props로 데이터를 흘려넣고 반복 생성이 쉽다. 자막·차트 라이브러리 생태계가 그대로 쓰인다
브랜드 필름·킨타입·설명 영상(웹 디자인 감각 그대로)HyperFramesRemotionHTML/CSS를 그대로 쓴다. 디자인 토큰·웹폰트·CSS 효과를 영상에 가져오기 가장 빠르다. 대비·모션 검사가 내장
수식 전개·알고리즘·그래프 설명Manim—수학 객체(수식·좌표계·변환)가 1급 시민. 다른 도구로 하면 전부 수작업
3D 장면·제품 렌더·카메라 워크Blender MCP—진짜 3D 엔진이 필요한 영역. 대화로 장면을 조립하고 파이썬으로 세밀 조정
배경 패턴·추상 비주얼·플로터/레이저 출력물algorithmic-artHyperFrames시드 기반 결정론 + SVG 출력(물리 출력 가능)
짧은 인트로 타이틀(5~15초)HyperFramesRemotion둘 다 가능. HTML로 빨리 만들 거면 전자, 컴포넌트 재사용이 목적이면 후자
위 요소들을 섞은 한 편각자 뽑고 ffmpeg로 이어붙인다도구마다 강한 구간이 다르다. 한 도구로 전부 하려다 막히는 경우가 가장 흔하다

⛔ 이렇게 고르면 막힌다

  • "영상이니까 전부 Remotion" → 수식 애니메이션을 직접 구현하다 시간 소모
  • "3D니까 Blender로 자막까지" → 텍스트 레이아웃이 지옥
  • "HyperFrames가 쉬우니 데이터 100건 반복 생성도" → 반복은 Remotion props가 압도적
  • 도구를 먼저 고르고 콘텐츠를 맞춤

✅ 고르는 순서

  • ① 결과물의 성격을 먼저 정한다(설명형/브랜드형/데이터형/3D)
  • ② 그 성격에서 1순위 도구를 쓴다
  • ③ 섞이면 구간별로 나눠 각자 뽑고 ffmpeg로 합친다
  • ④ 애매하면 10분 스파이크를 먼저 돌려본다(13장)
구간별로 뽑아서 이어붙이기 (ffmpeg)
# 1) 각 도구로 구간을 뽑는다 (해상도·fps를 반드시 통일할 것)
#    intro.mp4   ← HyperFrames (1920x1080, 30fps)
#    formula.mp4 ← Manim        (manim -qh 로 1080p 렌더)
#    chart.mp4   ← Remotion     (width/height/fps를 Composition에 명시)

# 2) 목록 파일을 만든다
cat > list.txt <<'EOF'
file 'intro.mp4'
file 'formula.mp4'
file 'chart.mp4'
EOF

# 3) 재인코딩 없이 이어붙이기 (코덱·해상도·fps가 같을 때만 가능)
ffmpeg -f concat -safe 0 -i list.txt -c copy final.mp4

# 사양이 다르면 통일해서 다시 인코딩
ffmpeg -i formula.mp4 -vf "scale=1920:1080,fps=30" -c:v libx264 -crf 18 formula_fixed.mp4

# 확인: 길이·해상도·코덱이 의도대로인지
ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate \
        -show_entries format=duration -of default=nw=1 final.mp4

13 · 첫 10분 — 도구별 실전 튜토리얼 (전부 실제 렌더 검증)

설치 확인용 "Hello"를 넘어 실제로 쓸 수 있는 최소 예제를 도구마다 하나씩 싣는다. 아래 코드는 전부 이 환경에서 직접 렌더해 결과 화면까지 확인한 것이다.

① Manim — 수식·도형 애니메이션 (검증됨)

scene.py — 텍스트 + 도형 + 색 채우기
from manim import *

class HelloManim(Scene):
    def construct(self):
        title  = Text("Motion Stack OK", font_size=56, color=GREEN)
        circle = Circle(radius=1.4, color=BLUE).shift(DOWN * 1.2)

        self.play(Write(title), run_time=1.2)              # 글자가 그려지며 등장
        self.play(title.animate.shift(UP * 1.6), run_time=0.6)  # .animate = 상태 전이
        self.play(Create(circle), run_time=1.0)             # 선이 그려짐
        self.play(circle.animate.set_fill(BLUE, opacity=0.5), run_time=0.8)
        self.wait(0.4)
렌더 · 품질 플래그
# PATH가 안 잡혀 있으면 먼저 (pip --user 설치본)
export PATH="$HOME/Library/Python/3.11/bin:$PATH"

manim -ql --disable_caching scene.py HelloManim   # 빠른 미리보기 480p15
manim -qh scene.py HelloManim                     # 최종 1080p60
manim -qk scene.py HelloManim                     # 4K
manim -ql -s scene.py HelloManim                  # 마지막 프레임만 PNG로

# 출력 위치: ./media/videos/scene/<품질>/HelloManim.mp4
# 실측(이 환경, -ql): 5개 애니메이션 · 4.0초 영상 렌더 완료
Manim 핵심 개념 3개만: ① Scene.construct()가 진입점 ② self.play(...)에 들어가는 것이 애니메이션(Write·Create·FadeIn…) ③ 기존 객체를 바꿀 땐 obj.animate.메서드() — 이 .animate를 빼면 즉시 변경돼 애니메이션이 안 생긴다(가장 흔한 실수).

② HyperFrames — HTML로 만드는 영상 (검증됨)

index.html — 타이틀 등장 + 서브텍스트 지연 등장
<div id="root" data-composition-id="main"
     data-start="0" data-duration="6" data-width="1920" data-height="1080">
  <h1 id="title" class="clip" data-start="0" data-duration="6" data-track-index="0">
    Motion Stack
  </h1>
  <p id="sub" class="clip" data-start="0.6" data-duration="5.4" data-track-index="1">
    HTML · CSS · GSAP
  </p>
</div>

<script>
  const tl = gsap.timeline({ paused: true });   // ★ 반드시 paused

  tl.fromTo("#title",
      { opacity: 0, y: 28 },
      { opacity: 1, y: 0, duration: 0.8, ease: "power3.out" }, 0);
  tl.fromTo("#sub",
      { opacity: 0 },
      { opacity: 1, duration: 0.6 }, 0.6);   // ← 세 번째 인자 = 시작 시각(초)
  tl.to("#title, #sub", { opacity: 0, duration: 0.5 }, 5.2);

  window.__timelines["main"] = tl;   // ★ 렌더러가 이걸 시킹한다
  tl.seek(0);
</script>
검증 · 렌더 — check가 먼저다
npm run check    # 린트 + 모션 + 대비(WCAG) 검사
npm run render   # mp4 (헤드리스 크롬 + ffmpeg)
npm run dev      # 미리보기 서버

# 이 환경에서의 실제 check 출력:
#   ◇ 0 issues across 9 sample(s)
#   Motion     ◇ 0 errors, 0 warnings
#   Contrast   ◇ 59/59 text checks pass WCAG AA
#   ◇ Check passed
HyperFrames에서 반드시 지킬 3가지: ① 타임라인은 paused: true — 자동 재생하면 렌더 결과가 들쭉날쭉해진다 ② 요소마다 data-start/data-duration으로 존재 구간을 선언 ③ window.__timelines["<composition-id>"]에 등록. 셋 중 하나만 빠져도 "화면은 맞는데 영상은 비어 있는" 결과가 나온다.

③ Remotion — 데이터로 움직이는 영상

BarChart.tsx — props로 데이터를 받아 애니메이션
import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";

type Props = { data: { label: string; value: number }[] };

export const BarChart: React.FC<Props> = ({ data }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const max = Math.max(...data.map((d) => d.value));

  return (
    <AbsoluteFill style={{ background: "#0f172a", padding: 80, gap: 18,
                            flexDirection: "column", justifyContent: "center" }}>
      {data.map((d, i) => {
        // 막대마다 4프레임씩 지연 — stagger
        const p = spring({ frame: frame - i * 4, fps, config: { damping: 14 } });
        const w = interpolate(p, [0, 1], [0, (d.value / max) * 100]);
        return (
          <div key={d.label} style={{ display: "flex", alignItems: "center", gap: 16 }}>
            <div style={{ width: 160, color: "#94a3b8", fontSize: 28 }}>{d.label}</div>
            <div style={{ height: 44, width: `${w}%`, background: "#e879f9", borderRadius: 8 }} />
            <div style={{ color: "#e2e8f0", fontSize: 26 }}>
              {Math.round(d.value * p)}
            </div>
          </div>
        );
      })}
    </AbsoluteFill>
  );
};

// Root.tsx 에 등록 — defaultProps로 데이터를 주입한다
<Composition
  id="BarChart" component={BarChart}
  durationInFrames={150} fps={30} width={1920} height={1080}
  defaultProps={{ data: [
    { label: "Remotion", value: 82 },
    { label: "HyperFrames", value: 74 },
    { label: "Manim", value: 61 },
  ] }}
/>
Remotion 핵심 3개: ① useCurrentFrame()이 전부다 — 현재 프레임을 받아 그 시점의 화면을 그리면 된다 ② interpolate(frame, [입력범위], [출력범위])로 값 매핑 ③ 자연스러운 움직임은 spring(). CSS transition·animation은 쓰지 않는다 — 시킹 방식이라 반영되지 않는다.
데이터를 바꿔가며 여러 편 뽑기 (Remotion이 압도적인 지점)
# props를 JSON으로 주입해 같은 컴포지션을 다른 데이터로 렌더
npx remotion render BarChart out/week1.mp4 \
  --props='{"data":[{"label":"A","value":40},{"label":"B","value":90}]}'

# 파일에서 읽어 반복 (주간 리포트 자동화 패턴)
for f in data/week*.json; do
  npx remotion render BarChart "out/$(basename "$f" .json).mp4" --props="$f"
done

④ algorithmic-art — 시드 기반 제너러티브

Claude에게 이렇게 요청한다 (스킬이 자동 진입)
코드로 제너러티브 아트 만들어줘.

조건:
- 플로우 필드 기반, 선 중심 구성
- 캔버스 1080x1080, 배경은 아주 어두운 네이비
- 팔레트는 3색 이내, 라임 계열 강조색 하나
- 시드를 고정해서 같은 결과를 다시 뽑을 수 있게 해줘
- 결과를 PNG로 저장하고, 시드 값을 파일명에 넣어줘

나중에 플로터로 출력할 수도 있으니 SVG 버전도 같이 만들어줘.
왜 시드를 꼭 요구해야 하나: 시드를 고정하지 않으면 매번 다른 결과가 나와서 "아까 그 그림"을 영원히 못 찾는다. 플로터·레이저로 물리 출력할 계획이면 SVG도 함께 요청할 것 — 래스터(PNG)에서 역변환하는 건 훨씬 어렵다.

⑤ Blender MCP — 대화로 3D 장면 만들기

연결 확인 → 조작 순서
[1단계] Blender를 열고 N키 → MCP 탭 → Start MCP Server 를 눌렀는지 먼저 확인
        (이걸 안 하면 claude mcp list가 Connected여도 조작이 안 된다)

[2단계] Claude에게:
  "블렌더에 지름 2짜리 구를 원점에 만들고,
   금속 재질(roughness 0.2)을 입혀줘.
   카메라는 45도 위에서 내려다보게 배치하고,
   HDRI 환경광을 넣어서 1920x1080으로 렌더해줘."

[3단계] 결과를 확인하고 세부 조정:
  "구를 조금 왼쪽으로 옮기고, 바닥에 반사되는 평면을 추가해줘"

※ 복잡한 작업은 한 번에 요청하지 말고 단계로 나눌 것.
   3D는 중간 결과를 봐야 다음 지시가 정확해진다.

14 · 에러 사전 — 증상 → 원인 → 조치

증상 / 에러 메시지원인조치
zsh: command not found: manimpip --user 바이너리 경로가 PATH에 없음export PATH="$HOME/Library/Python/3.11/bin:$PATH" (영구 적용은 ~/.zshrc에 추가 후 새 터미널)
Manim 설치 중 pycairo 빌드 실패cairo·pango 헤더 없음brew install cairo pango pkgconf 후 재설치. brew 이름은 pkg-config가 아니라 pkgconf
Manim 렌더는 되는데 한글이 네모로 나옴기본 폰트에 한글 글리프 없음Text("한글", font="Pretendard")처럼 폰트를 명시(설치된 폰트명이어야 함)
Manim에서 아무 움직임이 없음.animate를 빼고 속성을 직접 바꿈self.play(obj.animate.shift(UP)) 형태로. 직접 대입은 즉시 적용되어 애니메이션이 생기지 않는다
Remotion 렌더 결과가 완전히 검거나 비어 있음기본 스캐폴드 MyComp가 null 반환정상 동작이다. HelloMotion 같은 실제 컴포지션을 렌더할 것
Remotion에서 CSS 애니메이션이 영상에 안 나옴렌더는 재생이 아니라 프레임 시킹이라 CSS 애니메이션이 진행되지 않음useCurrentFrame() + interpolate()/spring()으로 프레임 기반으로 다시 작성
Remotion Cannot find module / 버전 충돌Node 버전 미달^20.19.0 || ^22.13.0 || >=24 필요. node -v 확인 후 brew install node
HyperFrames 렌더 결과가 정지 화면타임라인을 window.__timelines에 등록하지 않음, 또는 paused:true 누락두 가지를 모두 확인. tl.seek(0)까지 호출
HyperFrames check에서 대비 경고텍스트/배경 대비가 WCAG AA 미달색을 조정한다. 영상은 압축으로 대비가 더 떨어지므로 경고를 무시하지 말 것
hyperframes add가 실패레지스트리가 raw.githubusercontent.comGitHub 차단 환경이면 레지스트리 블록은 못 받는다. 직접 작성한 컴포지션 렌더는 정상
Blender: claude mcp list는 Connected인데 조작이 안 됨Blender 안에서 Start MCP Server를 안 누름N키 → MCP 탭 → Start. Blender를 끄면 매번 다시 켜야 한다
Blender Add-ons 목록에 MCP가 안 보임애드온 파일이 해당 Blender 버전 경로에 없음~/Library/Application Support/Blender/<버전>/scripts/addons/ 확인. 버전이 다르면 경로의 숫자가 다르다
uvx: command not founduv 미설치brew install uv 또는 pip3 install --user uv
brew install이 ghcr.io에서 멈춤Homebrew bottle이 GitHub 인프라에서 옴2장의 대안 사용(ffmpeg.org 빌드·conda-forge·pip)
스킬을 넣었는데 Claude가 모름폴더 깊이 오류 또는 세션 미갱신~/.claude/skills/<이름>/SKILL.md 구조 확인 후 새 세션 시작

15 · 렌더 비용 감각 — 얼마나 걸리고 얼마나 커지나

"렌더가 안 끝난다"의 대부분은 고장이 아니라 설정이 과한 것이다. 이 환경에서 측정한 값을 기준점으로 둔다.
작업설정실측메모
Remotion 렌더1280×720 · 30fps · 90프레임(3초)45.9 KB 산출텍스트 위주라 용량이 작다. 영상·이미지가 들어가면 수십 배
Manim 렌더-ql 480p15 · 애니메이션 5개 · 4초즉시 수준-qh(1080p60)는 수 배, -qk(4K)는 수십 배 걸린다. 작업 중엔 항상 -ql
HyperFrames check9 샘플 · 대비 59항목0 issues 통과렌더보다 훨씬 빠르다. 렌더 전에 항상 check
HyperFrames 데모 영상1920×1080 · 10초3.0 MBh264. 웹 삽입용으로 적정
프레임 추출(확인용)ffmpeg 1프레임즉시ffmpeg -ss 1.2 -i a.mp4 -frames:v 1 f.png
01

작업 중엔 저품질

Manim -ql, Remotion은 짧은 durationInFrames로 구조부터 맞춘다. 최종 품질은 마지막에 한 번.

반복 비용 ↓
02

검사 먼저, 렌더 나중

HyperFrames는 check가 렌더보다 훨씬 싸다. 모션·대비 문제를 렌더 전에 거른다.

0 issues 확인
03

결과는 열어서 본다

"렌더 성공" 로그는 내용 보장이 아니다. 프레임을 뽑아 눈으로 확인하는 습관이 가장 싸게 먹힌다.

ffmpeg -frames:v 1

16 · 제거 · 롤백 — 되돌리는 법

설치 가이드에 제거 방법이 없으면 사용자는 실험을 못 한다. 전부 되돌릴 수 있다는 걸 알아야 과감하게 시도한다.
구성요소별 제거
# 스킬 (폴더를 지우면 끝)
rm -rf ~/.claude/skills/manim-skill
rm -rf ~/.claude/skills/algorithmic-art

# 플러그인
claude plugin uninstall hyperframes@hyperframes
claude plugin marketplace remove hyperframes          # 마켓플레이스 등록도 해제

# MCP 서버 등록 해제
claude mcp remove blender -s user
# Blender 애드온은 따로 지운다
rm -f "$HOME/Library/Application Support/Blender/5.2/scripts/addons/blender_mcp.py"

# Manim (PyPI)
pip3 uninstall manim
# ~/.zshrc, ~/.bash_profile 에 추가한 PATH 줄도 직접 삭제

# Blender 앱
brew uninstall --cask blender

# 캐시 정리 (용량 회수)
rm -rf ~/.cache/uv          # uvx 패키지 캐시
npm cache clean --force     # npx 캐시

# 프로젝트는 폴더째 지우면 된다 (전역에 남는 것이 없다)
rm -rf my-video
되돌릴 때 알아둘 것설명
Remotion은 지울 게 거의 없다전역 설치가 없다. 프로젝트 폴더만 지우면 끝(공식 스킬도 프로젝트 안 .agents/에 있다)
스킬 제거는 즉시 반영되지 않는다Claude Code 세션을 새로 시작해야 목록에서 빠진다
Blender 설정은 앱 삭제 후에도 남는다~/Library/Application Support/Blender/ 전체를 지우면 사용자 설정까지 사라지니 주의 — 애드온 파일만 골라 지울 것
brew 제거가 다른 것을 깨뜨릴 수 있다ffmpeg·cairo는 다른 도구도 쓴다. brew uses --installed ffmpeg로 의존을 먼저 확인

17 · 조합 워크플로 레시피 — 실전 3종

한 도구로 끝나는 작업은 드물다. 실제로 자주 나오는 조합 3가지를 단계·산출물·검증 지점까지 적었다.

레시피 A — 기술 설명 영상 (인트로 + 수식 + 데이터)

구간도구산출물이 구간에서 확인할 것
0~5초
인트로
HyperFramesintro.mp4 1920×1080·30fpsnpm run check에서 대비 경고 0건. 타이틀이 5초 안에 완전히 등장·퇴장
5~25초
개념 설명
Manimformula.mp4 — -qh로 1080p수식 전개가 읽을 시간을 주는가(self.wait()). 한글 폰트 명시했는가
25~40초
데이터
Remotionchart.mp4 — props로 실제 수치 주입숫자가 실제 데이터와 일치하는가. 막대 stagger가 과하지 않은가
합치기ffmpegfinal.mp4해상도·fps·코덱 통일 확인 후 -c copy. 다르면 재인코딩
레시피 A 실행 순서
# 1) 각 구간 산출 (해상도·fps를 처음부터 맞춘다 — 나중에 맞추면 재인코딩 손실)
cd intro-hf     && npm run check && npm run render   # → renders/*.mp4
cd ../formula   && manim -qh scene.py Explain          # → media/videos/.../Explain.mp4
cd ../chart-rem && npx remotion render BarChart out/chart.mp4 --props=data.json

# 2) 사양 확인 — 다르면 합치기가 실패하거나 결과가 깨진다
for f in intro.mp4 formula.mp4 chart.mp4; do
  echo -n "$f: "
  ffprobe -v error -select_streams v:0 \
    -show_entries stream=width,height,r_frame_rate,codec_name -of csv=p=0 "$f"
done

# 3) 합치기
printf "file 'intro.mp4'\nfile 'formula.mp4'\nfile 'chart.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy final.mp4

# 4) 결과를 "열어서" 확인 (구간 경계마다 프레임 추출)
for t in 2 10 30; do ffmpeg -y -ss $t -i final.mp4 -frames:v 1 check_$t.png; done

레시피 B — 제품 소개 (3D 렌더 + 텍스트 오버레이)

1

Blender

대화로 장면 구성 → 1920×1080 연속 렌더(PNG 시퀀스 또는 mp4)

2

확인

프레임 추출로 조명·구도 점검. 여기서 틀리면 뒤 작업이 전부 헛일

3

HyperFrames

렌더 결과를 <video>로 깔고 그 위에 HTML 텍스트·로고 오버레이

4

check

영상 위 텍스트는 대비가 떨어지기 쉽다 — WCAG 검사로 거른다

5

render

최종 mp4

왜 오버레이를 Blender에서 하지 않나: 3D 엔진의 텍스트 레이아웃은 웹보다 훨씬 불편하다. 3D는 3D로, 타이포는 HTML로 나누면 수정 비용이 급격히 낮아진다 — 문구를 바꿀 때 3D를 다시 렌더할 필요가 없다.

레시피 C — 주간 리포트 자동화 (데이터 → 영상 N편)

같은 템플릿 · 다른 데이터로 반복 생성
# 전제: Remotion 컴포지션이 props로 데이터를 받도록 작성돼 있다(13장 ③)

# 1) 데이터 준비 — 주차별 JSON
#    data/2026-W41.json, data/2026-W42.json ...

# 2) 일괄 렌더
mkdir -p out
for f in data/*.json; do
  name=$(basename "$f" .json)
  echo "── 렌더: $name"
  npx remotion render BarChart "out/$name.mp4" --props="$f" || echo "❌ 실패: $name"
done

# 3) 산출물 검증 — 파일이 생겼다고 내용이 맞는 건 아니다
for m in out/*.mp4; do
  d=$(ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$m")
  s=$(wc -c < "$m")
  echo "$m  ${d}s  ${s}B"
  # 길이가 0이거나 용량이 비정상적으로 작으면 빈 영상일 가능성
done

# 4) 한 편만 눈으로 확인 (샘플링)
ffmpeg -y -ss 2 -i out/2026-W41.mp4 -frames:v 1 sample.png
자동화에서 가장 흔한 사고: 데이터가 비었는데도 렌더가 "성공"해서 빈 차트 영상이 50편 만들어지는 경우. 컴포지션 안에서 data.length === 0일 때 눈에 띄는 경고 화면을 그리게 해두면 샘플만 봐도 즉시 드러난다.

18 · 설치 완료 체크리스트 — 여기까지 되면 성공

1단계 — 설치 상태 (명령으로 확인)
□ node -v                        → v20.19+ / v22.13+ / v24+
□ ffmpeg -version | head -1      → 버전이 찍힌다
□ uv --version                   → 버전이 찍힌다
□ manim --version                → Manim Community v0.22+
□ ls -d /Applications/Blender.app → 존재
□ claude mcp list | grep blender → ✔ Connected
□ claude plugin list             → hyperframes@hyperframes · enabled
□ ls ~/.claude/skills/           → manim-skill, algorithmic-art, hyperframes* 포함

※ 한 번에: bash motion-stack-setup.sh --check
2단계 — 실제 산출물 (각 도구로 하나씩 뽑아본다)
□ Remotion     : npx remotion render HelloMotion out/hello.mp4
                 → 약 45KB · 재생 시 라임색 "Remotion OK" 보임
□ HyperFrames  : npm run check → "Check passed" / npm run render → mp4 생성
□ Manim        : manim -ql scene.py HelloManim
                 → media/videos/scene/480p15/HelloManim.mp4
□ algorithmic-art : Claude에게 "코드로 제너러티브 아트" 요청 → 시드 포함 PNG
□ Blender      : GUI에서 Start MCP Server 후
                 "큐브 하나 만들어줘" → 뷰포트에 실제로 생성됨

※ 각 산출물을 반드시 "열어서" 확인할 것.
  렌더 성공 로그는 내용이 맞다는 증거가 아니다.
5개 중 4개까지는 명령만으로 끝난다. 유일하게 사람 손이 필요한 건 Blender의 GUI 3단계(6장)다. 설치가 안 된 것처럼 느껴진다면 대개 ① PATH ② Blender 서버 미시작 ③ 세션 미재시작 — 이 셋 중 하나다.

다음 단계 — 더 깊이 가려면

영상 제작 원리

이 스택의 도구는 전부 프레임 시킹 모델이다. 그 개념이 잡히면 도구 전환이 쉬워진다 — 11장의 "시킹 vs 재생"을 다시 읽을 것.

설계 원칙

편집기·출력 파이프라인을 직접 만들 계획이라면 029·042·043 구현 핸드북으로. 단일 데이터 모델·오프스크린 렌더·검증 스위트가 정리돼 있다.

이 환경으로 뭘 만드나

도구별 활용 시나리오와 조합 예시는 044 기능 보드에 사용 예 중심으로 정리돼 있다.

19 · 확장 도구 3종 — 2026-10-21 추가, 5개 → 8개

기존 5개 스택의 공백은 소리·자막·실사 푸티지였다. 전부 "코드로 그리는" 도구뿐이라 말과 소리가 비어 있었다. 아래 3종을 추가해 그 구간을 메웠고, 전부 로컬에서 동작한다(API 키·로그인 불필요).
추가메우는 공백라이선스검증 결과
whisper.cpp + 자체 자막 스킬받아쓰기·자막 — 완전 오프라인MIT (ggml-org)한국어 문장 받아쓰기 정확, SRT 생성 확인. Metal GPU 백엔드 사용
text-to-lottie웹·앱에 심는 벡터 애니메이션(Lottie JSON)MIT스킬 + Skia Skottie 플레이어 프로젝트 설치
OpenMontage실사 푸티지 조립·나레이션 영상 (12개 파이프라인)AGPLv3데모 렌더 완주 — 1920×1080·30fps·25초·3.6MB, 프레임 육안 확인

① whisper.cpp — 로컬 자막

왜 서드파티 스킬을 안 썼나: 자막 스킬을 찾아보니 후보가 전부 별 0~9개였고 설치 과정에서 임의 스크립트를 실행했다. 반면 엔진인 whisper.cpp 자체는 ggml-org 공식에 성숙하다. 그래서 엔진만 설치하고 스킬은 검증된 명령으로 직접 작성했다. 저장소 선정 기준(스타·공식성)을 자막에도 똑같이 적용한 결과다.
설치 — 엔진 + 모델
brew install whisper-cpp          # 1.9.5 (ggml-org 공식)

# 모델은 별도 다운로드. 한국어 정확도를 위해 large-v3-turbo 권장(1.5GB)
mkdir -p ~/.cache/whisper-models && cd ~/.cache/whisper-models
curl -fL -o ggml-large-v3-turbo.bin \
  "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin"

# 가벼운 대안: ggml-small.bin(488MB) · ggml-base.bin(148MB)
사용 — 받아쓰기 · 자막 굽기
# whisper.cpp는 16kHz 모노 WAV만 받는다. 영상은 먼저 변환
ffmpeg -y -i input.mp4 -ar 16000 -ac 1 -c:a pcm_s16le audio.wav

# 받아쓰기 (❌ -l ko 를 빼면 영어로 가정해 엉뚱하게 나온다)
whisper-cli -m ~/.cache/whisper-models/ggml-large-v3-turbo.bin \
  -l ko -f audio.wav -osrt          # -ovtt -otxt -oj 동시 지정 가능

# 소프트 자막(끌 수 있음, 빠름)
ffmpeg -y -i input.mp4 -i audio.wav.srt -c copy -c:s mov_text output.mp4

# 하드 자막(영상에 각인, SNS·발표용)
ffmpeg -y -i input.mp4 -vf "subtitles=audio.wav.srt:force_style='FontName=Pretendard,FontSize=22,BorderStyle=3'" \
  -c:v libx264 -crf 18 -c:a copy output.mp4
부수 효과: whisper.cpp를 깔자 HyperFrames가 자동으로 감지했다(hyperframes doctor → ✓ whisper-cpp /opt/homebrew/bin/whisper-cli). HyperFrames 쪽 자막 기능도 함께 살아난 셈이다.

② text-to-lottie — 웹·앱용 벡터 애니메이션

먼저 알아둘 것: 이건 MP4를 만들지 않는다. 산출물은 Lottie JSON이고, React·iOS·Android·웹에 끼워 넣어 재생하는 형식이다. 영상 파일이 목적이면 Remotion·HyperFrames를 쓰고, 보드·대시보드·앱 UI에 심을 애니메이션이 필요할 때 이걸 쓴다.
설치 — 스킬 + 로컬 플레이어
# 저장소에 스킬과 "Skia Skottie 플레이어" 프로젝트가 함께 들어있다.
# 스킬은 이 플레이어로 결과를 검증하도록 설계돼 있어 둘 다 필요하다.
git clone --depth 1 https://github.com/diffusionstudio/lottie.git /tmp/lottie

# 1) 스킬은 전역 스킬 경로로 (폴더 한 겹 더 들어가지 않게 주의)
cp -R /tmp/lottie/skills/text-to-lottie ~/.claude/skills/text-to-lottie

# 2) 플레이어 프로젝트는 작업 폴더에 둔다
mv /tmp/lottie <프로젝트>/lottie-player
cd <프로젝트>/lottie-player && npm install && npm run dev

③ OpenMontage — 실사 푸티지·나레이션 영상

기존 스택과 겹치지 않는 지점: Remotion·HyperFrames·Manim은 전부 화면을 코드로 그린다. OpenMontage는 이미 존재하는 영상·이미지를 모아 편집하는 쪽이다(아카이브·NASA·Pexels 등 무료 소스). 다큐·트레일러·설명영상 등 12개 파이프라인을 갖는다.
설치 — venv로 격리됨(전역 오염 없음)
git clone --depth 1 https://github.com/calesthio/OpenMontage.git openmontage
cd openmontage
make setup        # .venv 생성 + pip + remotion npm + piper-tts + hyperframes 캐시

# 검증
make hyperframes-doctor
make demo-list                              # zero-key 데모 3종
.venv/bin/python render_demo.py code-to-screen   # 실측: 750프레임 → 3.6MB mp4
⚠️ 라이선스가 다르다 — AGPLv3. 지금까지 번들한 도구들(MIT·Apache-2.0)과 달리 copyleft다. 개인이 로컬에서 쓰는 것은 자유지만, 수정본을 배포하거나 네트워크 서비스로 제공하면 소스 공개 의무가 따른다. 이 사이트의 오프라인 팩에 OpenMontage를 넣지 않은 이유다 — 넣으면 팩 전체의 배포 조건이 달라진다.

같이 들어온 로컬 오디오 — 로그인 없는 나레이션

hyperframes doctor가 알려준 선택 항목 중 로컬 TTS(Kokoro)를 함께 설치했다. 기존 media-use 스킬의 음성·음악은 HeyGen CLI 로그인을 요구하는데, Kokoro는 로컬에서 돌아 로그인도 인터넷도 필요 없다.
로컬 오디오 옵션
# 로컬 TTS — 설치함 (나레이션)
pip3 install --user kokoro-onnx soundfile
#   확인: hyperframes doctor → ✓ TTS (Kokoro) Kokoro deps installed

# 로컬 BGM — 설치하지 않음 (torch 포함 약 2.5GB)
#   필요해지면: pip install transformers torch soundfile numpy

8개 도구 — 무엇을 언제 쓰나

만들려는 것도구비고
데이터가 바뀌면 영상도 바뀜Remotionprops로 반복 생성
브랜드 영상·타이틀·카메라 무브HyperFramesHTML/CSS/GSAP
수식·그래프 설명Manim수학 객체가 1급
3D 장면·제품 렌더Blender MCPGUI에서 서버 시작 필요
배경 패턴·플로터 출력algorithmic-art시드 고정 필수
말을 글로 / 자막whisper.cpp완전 오프라인, 한국어는 -l ko
앱·웹에 심는 애니메이션text-to-lottieMP4 아님, JSON
실사 푸티지 조립·나레이션OpenMontageAGPLv3 주의
이제 가능해진 조합: HyperFrames로 그린 그리드 카메라 영상 → Kokoro로 나레이션 생성 → whisper.cpp로 그 나레이션의 자막 생성 → ffmpeg로 합성. 전 구간이 로컬에서, 로그인 없이 돌아간다. 주간업무 요약 영상처럼 주기적으로 돌려야 하는 작업에 필요한 마지막 조각이 이 둘이었다.