Communitygithub.com

YahyaLendani/motionbrief

HTML 또는 React로 모션 그래픽과 짧은 비디오(타이틀 카드, 로고 스팅, 키네틱 타이포그래피, 숫자 카운트업, 통계 공개, 하단 써드, 투명 오버레이, 기능 몽타주)를 생성합니다. 자연어 요청을 검증된 브리프로 컴파일한 후 렌더링하며, 하나의 브리프로 여러 비디오를 배치로 제작합니다. HyperFrames(HTML + GSAP)와 Remotion(React + TypeScript)을 모두 지원합니다.

motionbrief란 무엇인가요?

이 스킬은 개발자와 AI 에이전트가 자연어 요청만으로 전문적인 모션 그래픽 비디오를 생성할 수 있게 해줍니다. 로고 스팅, 숫자 카운트업, 하단 써드, 타이틀 카드 등 다양한 유형의 영상을 제작할 수 있으며, HyperFrames(HTML + GSAP, Apache 2.0 라이선스)와 Remotion(React + TypeScript) 두 가지 렌더링 엔진을 모두 지원합니다. 사용자는 단순히 "/motion 6초짜리 Inkwell 로고 스팅"과 같이 원하는 내용을 설명하기만 하면, 스킬이 자동으로 상세 브리프(brief.json), 비트 시트, 그리고 실제 비디오를 생성합니다. 주요 특징으로는 브리프 기반 반복 작업(하나의 필드만 수정하여 빠르게 개선), 사일런트 실패 감지(등록되지 않은 타임라인, 잘못된 보간 등), 프레임별 검증(정적 검사 및 런타임 검사), 그리고 배치 렌더링 기능이 있습니다. 이 스킬은 Claude Code, Cursor, Codex와 같은 AI 코딩 에이전트와 함께 사용하도록 설계되었으며, 체계적이고 반복 가능한 비디오 제작 워크플로우를 제공합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/YahyaLendani/motionbrief-claude-skills/tree/main/skills/motionbrief

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

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

문서

모션 그래픽

렌더러가 프레임별로 탐색하는 웹 페이지를 작성하여 비디오를 생성합니다. 아래 두 경로는 동일한 작업을 수행합니다. 차이점은 작성하는 코드입니다.

  • HyperFrames — 하나의 HTML 파일, CSS로 디자인, 일시 중지된 GSAP 타임라인으로 모션을 구현합니다. node scripts/hf.mjs는 고정된(pinned) 버전을 실행하고, 한 번만 설치합니다. Apache 2.0.
  • Remotion — React 컴포넌트. useCurrentFrame()으로 프레임을 가져오고, 나머지는 직접 계산합니다. 성숙하고 타입이 지정되어 있으며, 최대 3명까지 무료로 사용할 수 있습니다.

컴포지션 코드를 작성하기 전에 해당하는 참조를 로드하세요. 프레임워크 규칙은 추측할 수 없으며, 대부분의 실패는 조용히 발생합니다. 타임라인을 등록하지 않은 HyperFrames 파일은 오류 없이 정지 프레임을 렌더링합니다.


쉬운 방법

사용자가 원하는 것을 어떤 말로든 설명합니다. 사용자는 절대 브리프, 스펙, 비트 시트를 작성하지 않습니다. — Claude가 하나로 컴파일합니다.

/motion 6초짜리 Inkwell 로고 스팅을 만들어 줘

이것이 전체 입력입니다. 내부적으로는:

  1. 컴파일: 요청을 brief.json으로 변환 — 기간, 크기, fps, 비트(타이밍 포함), 복사할 텍스트, 이징, 색상 팔레트, 가정 목록. 모든 빈 값은 references/brief.md의 테이블에서 기본값을 가져옵니다.
  2. 표시: 간결한 요약(하나의 테이블, 약 12줄)을 보여주고 같은 턴에 빌드합니다. 승인 단계가 없습니다.
  3. 빌드: 템플릿에서 빌드, 검증, 렌더링, 프레임 확인.

반복은 재빌드가 아닌 필드 수정으로 이루어집니다. "더 강렬하게"는 feel.ease와 두 개의 기간을 변경합니다. kind나 motion이 변경되지 않는 한 코드는 움직이지 않습니다.

브리프는 이 모든 것을 효율적으로 만드는 아티팩트입니다. 컴포지션 옆의 디스크에 저장되므로, 수정은 diff이고, 재렌더링은 하나의 명령어로 수행됩니다.


경로 선택

신호경로
새로운 빌드, 프레임워크 미지정HyperFrames
재사용할 기존 HTML/CSS/GSAP/LottieHyperFrames
node_modules 없음, 빌드 단계 불필요HyperFrames
3명 이상의 팀HyperFrames (라이선스)
사용자가 Remotion을 언급하거나, 저장소가 React/TSRemotion
디자인 시스템, 차트 라이브러리, 복잡한 컴포넌트 필요Remotion
기존 Remotion 프로젝트 이식Remotion (이식 비용이 절약보다 클 수 있음)

사용자가 두 가지를 모두 언급하면 HyperFrames로 빌드하고, Remotion 이식은 요청 시 가능하다고 한 줄로 말합니다. 동일한 작품을 두 번 완전히 빌드하는 것은 비교를 요청하지 않는 한 낭비입니다.


작업 루프

1. 브리프 컴파일

코드를 작성하기 전에 요청을 brief.json으로 변환합니다. 스키마, kind/motion 문법, 기본값 테이블, 반복 레버는 references/brief.md에 있습니다.

node scripts/brief.mjs brief.json          # 검증 + 요약 테이블
node scripts/brief.mjs brief.json --json   # 기계 판독 가능 결과

요약을 사용자에게 출력하고, ERROR가 있으면 수정한 후 같은 턴에 계속 진행합니다. 경고는 판단의 문제입니다 — 수락한 경고는 assumptions에 기록됩니다.

브리프는 또한 점수를 전달합니다. audio.bpm을 선택하여 비트 그리드가 컷을 나누도록 합니다. bpm에서 비트는 60 / bpm초이고 모든 beats[].start는 비트 위에 위치해야 합니다. 120 BPM은 0.5초마다 비트를 제공하며 대부분의 짧은 작품에 적합합니다. brief.mjs가 off_beat_grid를 보고하면 컷을 이동하거나 템포를 변경합니다. 무시하지 마세요. 이것이 작품이 잘 맞는 것과 미묘하게 어긋나는 것의 차이입니다.

완료 조건: brief.mjs가 0으로 종료되고, 모든 비트에 시간 범위, 종류, 모션 및 정확한 텍스트가 있으며, 어떤 컷도 비트 그리드에서 벗어나지 않습니다.

2. 스캐폴드

빈 파일 대신 이 스킬의 템플릿에서 시작하세요. 두 계약에 대해 정확하며, 실패하기 쉬운 두 단계(타임라인 등록, 시퀀스 타이밍)를 절약할 수 있습니다.

# HyperFrames — 일반 HTML. 고정된 엔진은 한 번 설치되며, 네트워크가 필요합니다.
cp -R assets/hyperframes/. ./my-video/
node scripts/hf.mjs lint ./my-video

# Remotion — React 프로젝트, 고정된 의존성을 한 번 설치해야 합니다.
cp -R assets/remotion/. ./my-video/
cd my-video && npm ci
# PowerShell
Copy-Item -Recurse -Force assets\hyperframes\* .\my-video\
Copy-Item -Recurse -Force assets\remotion\* .\my-video\

완료 조건: node scripts/hf.mjs lint가 통과하거나, npx remotion compositions src/index.tsx가 컴포지션 ID를 나열합니다.

3. 비트 빌드

비트당 하나의 파일. 타임라인을 평평하게 유지하세요 — HyperFrames에서는 절대 시간, Remotion에서는 <Sequence> 프레임. 빌드가 타이밍을 변경하면 비트 시트를 업데이트하고, 총 기간을 다시 확인하세요.

각 장면을 비트 이름으로 지정하세요. 검사가 찾는 방식이기 때문입니다. HyperFrames 호스트에서는 data-brief-beat="<id>", Remotion에서는 <Sequence name="<id>">. Remotion Sequence가 타이밍을 계산하는 경우, 그 안의 요소에도 data-brief-beat="<id>"를 추가하여 타이밍을 측정할 수 있게 합니다.

완료 조건: 시트의 모든 비트가 코드에 존재하고, 컴포지션 길이가 시트와 일치하며, TODO, 스텁, 또는 대체 텍스트가 없습니다.

4. 모션 확인

정지 이미지는 타이밍에 대해 속입니다. 프레임을 보고, 그 다음 렌더링을 확인하세요.

node scripts/check-contract.mjs --dir ./my-video --preflight   # 정적 검사, 설치 불필요
node scripts/check-contract.mjs --dir ./my-video --runtime     # 브라우저에서 검사

node scripts/hf.mjs check ./my-video                # 레이아웃, 모션, 대비
node scripts/hf.mjs snapshot ./my-video --review    # 비트 및 이음새 프레임을 PNG로 캡처
node scripts/hf.mjs keyframes ./my-video --selector "#card" --shot motion.png

npx remotion still src/index.tsx LaunchCard out/f.png --frame=45
npx remotion studio src/index.tsx              # 1배속으로 보기

check-contract.mjs는 아무것도 설치하지 않고 조용한 실패를 잡아냅니다: 등록되지 않은 타임라인, 일치하지 않는 window.__timelines 키, 일시 중지되지 않은 타임라인, 누락된 기간, 컴포지션 내 Math.random(), 클램핑되지 않은 interpolate. 실제 린터를 대체하는 것이 아니라 사전 점검입니다.

brief.json이 프로젝트에 있거나 --brief가 이를 가리키면, 빌드와 브리프를 비교합니다. 모든 요구 사항은 verified, failed 또는 unverified 상태가 됩니다. unverified는 통과가 아니며, 렌더링을 차단합니다.

코드상태의미
brief_format_mismatch실패너비, 높이, fps 또는 길이가 format과 다름
brief_scene_count, brief_scene_unmapped실패비트에 해당 ID를 선언하는 장면이 없거나, 장면에 해당 비트가 없음. 위치가 정체성은 아님
brief_timing_mismatch실패장면이 브리프가 지정한 시간에 시작하거나 지속되지 않음 (프레임 이내)
brief_copy_missing실패텍스트가 장면에 없음. 주석과 사용되지 않은 변수는 계산하지 않음
brief_copy_wrong_scene실패텍스트가 다른 장면에만 있음
copy_not_visible실패런타임: DOM에 있지만 숨겨져 있음, 투명함, 화면 밖, 잘림, 흐림 또는 가려짐
copy_hold_short실패런타임: beats[].hold보다 짧은 시간 동안만 읽을 수 있음
first_frame_empty실패런타임: visibleAtStart이 설정되었지만 비트의 어떤 내용도 그려지지 않음
first_frame_unverified미확인런타임: 첫 번째 프레임에 그래픽만 있거나 비트에 텍스트가 없음. 프레임을 확인하세요
brief_timing_unverified, brief_format_unverified미확인소스가 계산함. 런타임이 결정할 수 있음
brief_copy_dynamic, brief_copy_unverified미확인표시 여부는 런타임 문제임. Remotion 텍스트는 런타임까지 항상 이 상태임

일치는 대소문자와 공백을 무시하고, 둥근 따옴표를 접습니다. 다른 구두점은 중요하며, "12,480"은 12480에 도달하는 카운트업과 일치합니다. 요구 사항이 미확인 상태로 남아 있으면, 어떤 것인지 말하고, 수락하기 전에 측정 가능하게 만들려고 노력하세요. 하나를 수락한다는 것은 --allow-unverified "beat.lines.copy[0].visible"과 같이 이름을 지정하고 사용자에게 보고하는 것을 의미합니다. 포괄적인 패턴은 절대 허용하지 않으며, 실패는 전혀 수락할 수 없습니다. 정확한 규칙과 한계는 references/validation.md를 읽으세요.

드리프트는 코드에서 수정하거나, 의도적으로 브리프를 변경하고 brief.mjs를 다시 실행하세요. 둘이 불일치하도록 절대 두지 마세요.

프레임 검토 — 모든 검사가 통과해도 영화가 깨질 수 있습니다

계약 통과는 타이밍과 텍스트가 일치하고 텍스트를 읽을 수 있다는 것을 의미합니다. 팔레트, 이징, 전환, 또는 영화가 제대로 작동하는지에 대해서는 아무것도 말해주지 않습니다. Lint, 레이아웃, 모션, 대비 및 제작 품질 검사는 이 스킬의 자체 템플릿에서 모든 비트가 검은 화면으로 전환되고 숫자가 도착하자마자 카운트업을 종료하는 동안에도 통과했습니다. 프레임을 보는 것만이 이를 발견했습니다. 다음과 같이 캡처하세요:

# HyperFrames: 비트 프레임, 모든 컷 주변의 5프레임 스트립, 폰 시트
node scripts/motion-render.mjs --brief ./my-video/brief.json --snapshot --no-render

# Remotion: 각 컷 c(프레임)에 대해 c-6, c 및 c+6을 캡처하고 각 비트의 중간도 캡처
# (템플릿은 75, 210 및 270에서 컷)
node scripts/motion-render.mjs --dir ./my-video --no-render \
  --stills 37,69,75,81,142,204,210,216,240,264,270,276,315

그런 다음 이미지를 읽고 각 질문에 답하세요. 코드를 수정하고, 다시 캡처하고, 다시 확인하세요:

  • 컷이 검은 화면인가요? 컷 주변에 둘 이상의 빈 프레임이 있으면 이전 동작이 일찍 끝나고 다음 비트가 무(無)에서 페이드 인된다는 의미입니다. 이전 동작이 컷에서 끝나도록 이동하세요 (start = beat duration − exit duration).
  • 결과가 유지되나요? 카운트업의 최종 숫자 또는 줄의 마지막 단어가 화면에 최소 한 비트(60 / bpm초) 동안 정지해 있다가 사라져야 합니다. 숫자가 도착하자마자 사라지면 절대 읽을 수 없습니다.
  • 휴대폰에서 읽을 수 있나요? review-phone.jpg를 확인하거나, 프레임을 360px 너비로 상상해보세요. 1080p에서 약 40px 미만의 레이블과 태그라인은 일반적으로 실패합니다.
  • 브리프의 글꼴인가요? Segoe UI나 Arial과 같은 대체 글꼴은 글꼴이 로드되지 않았음을 의미하며, 다른 기기에서는 다른 영화가 렌더링됩니다. --runtime은 font_fallback으로 경고하고, 보고서는 실제로 그려진 글꼴을 기록합니다. Remotion은 @fontsource/*(템플릿 선택) 또는 로컬 파일의 경우 @remotion/fonts가 필요합니다.
  • 브리프의 전환 방식인가요? feel.transition이 각 컷 주변의 프레임에 나타나며, 검은 화면으로의 딥(dip)이 아닙니다.

완료 조건: 비트 프레임과 모든 이음새 스트립을 읽고, 위의 각 질문에 답했으며, "출시 체크리스트"의 모든 항목이 충족되었습니다.

5. 렌더링

node scripts/motion-render.mjs --brief ./my-video/brief.json
node scripts/motion-render.mjs --brief ./my-video/brief.json --batch rows.json --no-audio

래퍼는 브리프에서 경로, 형식, fps 및 슬러그를 읽고, 브리프, 정적 검사, 도구, 에셋 또는 런타임 검사에서 문제가 있으면 렌더링 시간을 소비하기 전에 중단합니다. 실패 시 1, 미확인 요구 사항 시 3으로 종료됩니다. --no-checks는 검증을 건너뛰고 이를 보고서에 기록합니다. 그런 다음 린트, 렌더링, ffprobe로 파일 측정, <out>.report.json을 작성합니다.

audio.policy가 generated인 경우, 두 경로 모두에서 music.mjs로 배경 음악을 합성하고, 비디오 전용으로 픽처를 렌더링한 후 하나의 ffmpeg 호출로 두 개를 믹싱합니다. 따라서 컴포지션은 엔진의 오디오 믹서에 의존하지 않습니다. 그런 다음 파일에 오디오 스트림이 있고 무음이 아닌지 측정합니다.

투명성의 경우: --format webm 또는 --format mov — H.264는 알파 채널을 지원할 수 없습니다. --no-audio는 배경 음악을 건너뛰고 오디오 스트림이 없는 파일을 생성합니다. GIF는 오디오를 전달할 수 없으므로, 배경 음악이 있는 브리프는 --no-audio를 전달하지 않는 한 GIF에 대해 거부됩니다.

--batch를 사용하면, 하나의 브리프와 행 파일이 N개의 비디오가 됩니다. HyperFrames는 행을 기본적으로 렌더링하고, Remotion은 행당 하나의 props 파일을 얻습니다. 배치는 비디오 전용이며, 배경 음악이 있는 브리프는 --no-audio를 전달하지 않는 한 거부됩니다.

완료 조건: 파일이 존재하고, 보고서가 rendered라고 말하며, notVerified 목록이 비어 있거나 사용자에게 무엇이 있는지 알렸고, 첫 번째 및 마지막 프레임이 의도적입니다.


조용히 깨지는 계약

HyperFrames — 네 가지, 모두 필수:

  1. 루트 요소는 data-composition-id, data-width, data-height, data-duration, data-start="0"을 가져야 합니다.
  2. 모든 시간 기반 요소는 id + data-start + data-duration을 가져야 합니다.
  3. GSAP 타임라인은 { paused: true }로 작성되어야 합니다.
  4. window.__timelines[<data-composition-id>] = tl — 동일한 키. 트윈이 추가된 후에. 이 작업을 놓치면 오류 없이 정지 프레임이 생성됩니다.

Remotion — 세 가지:

  1. 진입 파일에 registerRoot(), 루트 컴포넌트에 <Composition>.
  2. interpolate(..., { extrapolateLeft: "clamp", extrapolateRight: "clamp" }) — 매번 양쪽 끝을 클램프합니다.
  3. 컴포지션 내에 Math.random(), Date.now() 없음. random(seed)를 사용하세요.

저렴해 보이는지 결정하는 네 가지 규칙

가장 자주 잘못 사용되는 규칙입니다. 전체 규칙과 코드는 references/motion-craft.md에 있습니다.

  1. 움직이는 것만 움직이세요. 고정된 것은 그대로 둡니다. 유휴 "호흡" 스케일은 기계 생성처럼 읽힙니다.
  2. 겹치게 하고, 대기시키지 마세요. 요소 자체 지속 시간의 약 15–30%를 겹칩니다. 다음 것이 이전 것이 아직 안정되기 전에 시작됩니다.
  3. 타입에는 바운스를 사용하지 마세요. 오버슈트는 질량이 있는 객체(카드, 플랩, 캐릭터)에 사용합니다. 텍스트, 숫자, UI 레이블은 power3.out / expo.out을 사용하고 절대 오버슈트하지 않습니다.
  4. 움직임당 하나의 아이디어. y + opacity는 "도착"입니다. 회전과 스케일을 추가하면 단어가 비행 중에 읽을 수 없게 됩니다.

또한: 전환은 퇴장입니다. 페이드 아웃 후 페이드 인이 아닙니다. 그렇게 하면 중간이 딥인 점프 컷처럼 보입니다.


출시 체크리스트

  • brief.json 검증: 타이밍 타일, 첫 번째 프레임 의도적, 마지막 홀드 ≥ 2초.
  • check-contract.mjs --runtime이 verified라고 말하거나, 미확인 ID가 이름으로 수락되고 사용자에게 보고됨.
  • 텍스트, 숫자, 핸들, URL이 작성된 그대로 — 로렘 입숨, 플레이스홀더 없음.
  • 타임라인이 컴포지션 ID로 등록됨(HyperFrames) 또는 npx remotion compositions에 의해 컴포지션이 나열됨(Remotion).
  • Lint/검사가 깨끗함.
  • <out>.report.json이 rendered라고 말하고, 예상된 크기, fps, 길이 및 오디오를 가짐.
  • 프레임 검사됨: 모든 비트, 모든 이음새, 폰 너비 — 컷에서 검은 화면 없음,

… (원문과 동일하게 유지되며, 더 이상의 내용은 원문에 없으므로 번역을 중단합니다.)

관련 스킬