Communitygithub.com

Opus Visual Motion Engine

규율 있는 모션 그래픽 파이프라인: 코드 기반 비디오/UI, 결정론적 seek(t), 자동화된 렌더 QA, MP4 내보내기 — 텍스트 전용 모델에서도 작동합니다.

Opus Visual Motion Engine란 무엇인가요?

Opus Visual Motion Engine은 텍스트 전용 AI 모델로 고품질의 모션 그래픽과 비디오를 제작할 수 있게 해주는 엄격한 파이프라인입니다. 이 스킬은 `plan → build from the template → render → QA → fix → export`의 단계를 강제하며, 각 단계는 생략할 수 없습니다. 1920×1080 캔버스, 결정론적 `seek(t)` 함수, 표준화된 장면 관리 등이 포함된 `composition-template.html`을 제공하여, 동일한 입력에 대해 항상 동일한 프레임을 생성합니다. Claude Code, Cursor, Codex 등 다양한 AI 에이전트에서 사용할 수 있으며, `qa.mjs` 스크립트를 통한 자동화된 QA로 오류를 차단하고, 피드백 루프를 통해 2~3회의 반복 생성을 거쳐 최종 결과물의 품질을 보장합니다. 특히 텍스트 전용 모델에 최적화되어 있어, 비주얼 콘텐츠를 직접 '볼' 수 없는 환경에서도 정확한 결과물을 얻을 수 있습니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add Lob0Garou/opus-visual-motion-engine

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

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

문서

Opus Visual Motion Engine은(는) 무엇을 하나요?

시각적 결과물을 위한 규율 있는 파이프라인: 계획 → 템플릿에서 구축 → 렌더 → QA → 수정 → 내보내기. 품질은 취향이 아니라 렌더 전후에 적용되는 게이트에서 나옵니다. 순서대로 단계를 따르세요. 작업이 "단순해 보인다"고 단계를 건너뛰지 마세요.

아래의 경로는 이 스킬의 디렉토리(제공된 skill_resources 베이스)를 기준으로 합니다. 이를 $SKILL이라고 부릅니다.

0. 먼저 읽기 (무조건)

코드를 작성하기 전에, 결과물과 일치하는 참고 자료를 읽으십시오. 해당 주제에 대해 권위 있는 자료입니다:

결과물읽을 자료
비디오, 모션 그래픽, 설명 영상, 제품 비디오references/video-generation.md, references/motion-design.md, references/javascript-animation.md
키네틱 타이포그래피 / 타이포 중심 작품위의 비디오 세트 + references/typography.md
랜딩 페이지, 대시보드, 목업, UIreferences/visual-design.md, references/typography.md
다이어그램, 개략도, 데이터 시각화references/visual-design.md §4
프레이밍 / 카메라 결정references/cinematography.md
지속 시간 및 이징references/animation-primitives.md
동기화할 음악 또는 음성SKILL.md §10 + references/video-generation.md §6

작업 예제는 examples/*.md에 있습니다. 브리핑과 가장 가까운 예제를 읽으십시오.

1. 코드 전에 계획 (작성하기)

HTML을 생성하기 전에 계획을 답변(또는 출력물 옆의 PLAN.md)에 작성하십시오. 머릿속에만 있는 계획은 카운트되지 않습니다.

UI / 페이지

  1. 핵심 메시지: 한 문장. 시청자가 3초 안에 이해해야 하는 것은?
  2. 명명된 방향: 이름, 4–6개의 명명된 16진수 토큰(의미 할당됨), 역할이 있는 서체, 형태 처리. 주제의 산업, 재료 및 관용구에서 파생하십시오. 장난감 가게와 핀테크 대시보드는 절대 방향을 공유하지 않습니다.
  3. 계층 구조: 모든 블록에 PRIMARY / SECONDARY / TERTIARY 태그를 지정하십시오. PRIMARY만이 하나의 대담한 동작을 얻습니다.
  4. 섹션 진행: 섹션당 한 줄로, 해당 섹션의 역할과 다음 섹션으로 전환하는 방법을 설명합니다.
  5. 렌더 전 수학: 텍스트 너비 ≈ chars × 0.55 × font-size (산세리프) 또는 × 0.5 (세리프); 상자 너비 = max(title_chars × 8, subtitle_chars × 7) + 24 (14px 기준); 행 맞춤 = Σ너비 + 간격 ≤ 컨테이너. 모든 연결선을 모든 상자와 대조하여 추적하십시오. 상자와 교차하면 L자형 경로를 만드십시오.

비디오 / 모션 그래픽

  1. 핵심 메시지: 한 문장. 두 문장이 필요하다면 두 개의 비디오가 있는 것입니다.
  2. 비트: 3–7개. 각 비트는 "시청자가 이제 무엇을 알게 되었는가?"에 답합니다.
  3. 비트당 장면 카드: 시작/종료 (초), 구도, 카메라, 유형 크기, 기본 요소 (2–4), 종료. references/motion-design.md §2의 템플릿을 사용하십시오.
  4. 시그니처 모멘트: 메커니즘이 표시되는(레이블이 아닌) 하나의 프레임 이름을 지정하십시오(예: 잡음이 신호로 필터링됨). 스토리가 캡션에서만 작동한다면 비트를 재설계하십시오.
  5. 전체 타임라인: 절대 타임스탬프. 장면의 EXIT는 다음 장면이 공간을 차지하기 전에 완료되어야 합니다. DURATION을 실제 종료 시간(기본 10–20초, 내레이션이 있는 경우에만 30–45초)으로 설정하십시오.

카드가 없는 장면은 비디오에 속하지 않습니다.

2. 템플릿에서 구축 (비디오)

assets/composition-template.html을 결과물 옆에 복사하고 EDIT 블록을 채우십시오. ENGINE 블록을 다시 작성하지 마십시오. 이미 다음을 제공합니다:

  • 1920×1080 #stage (STAGE_W/H를 1080×1920 또는 1080×1080으로 변경 가능), 모든 창에 맞춤;
  • window.DURATION, window.seek(t), window.render(t), window.SCENES: 캡처/내보내기 계약 (QA는 SCENES에서 모든 장면을 캡처함);
  • at(), ease.*, lerp, mulberry32 (시드 PRNG), 그리고 가시성 및 EXIT를 위한 layer();
  • window.AUDIO (§10)를 읽고 없으면 0을 반환하는 오디오 헬퍼 audioAt(t, "rms"|"low"), since(t, list), hit(t, list, dur);
  • 캡처 및 축소 동작 아래에서 자동으로 꺼지는 미리보기 플레이어 (space, ←/→, Home/End);
  • 필요한 3개 레이어(밝음, prefers-color-scheme 보호, [data-theme])의 색상 토큰.

페이지의 경우, §6에 따라 일반 단일 파일 HTML을 작성하십시오.

3. 결정론적 시간 (비디오)

  • render(t)는 유일한 상태 드라이버입니다. 모든 위치, 불투명도, 크기, 숫자 및 dashoffset은 초 단위 t에서 계산됩니다. seek(x)는 이전에 렌더링된 것과 관계없이 동일한 프레임을 렌더링합니다.
  • t는 초 단위입니다. t를 [0, DURATION]으로 고정하고, 절대 [0, 1]로 고정하지 마십시오: 초를 0..1로 고정하면 전체 타임라인이 조용히 멈춥니다.
  • 금지: setTimeout, setInterval, 타임라인으로서의 CSS 애니메이션/전환, 시드되지 않은 Math.random(), 상태의 Date.now(). requestAnimationFrame은 재생 시계만 진행하고 render(clock)을 호출할 수 있습니다. 템플릿이 이미 이 작업을 수행합니다.
  • 무작위성: render 내부가 아닌, 빌드 시 mulberry32(seed)에서 생성하십시오.
  • SVG 그리기에는 세 가지 모두 필요합니다: pathLength="1", stroke-dasharray="1", 그리고 1에서 0까지의 stroke-dashoffset. dasharray가 없으면 프레임 0부터 선이 완전히 그려진 것처럼 나타납니다.
  • inline-block 단어 범위는 후행 공백을 삼킵니다. 간격은 margin-right에 두십시오.

4. 모션 문법

각각 하나의 작업을 가진 다섯 가지 동작. 어떤 동작이 이 중 어느 것에도 해당하지 않으면 삭제하십시오.

  • ENTER: 페이지 또는 장면당 하나의 오케스트레이션된 시퀀스, 읽기 순서로, 형제는 60–120ms 간격으로 시작됨. 모든 섹션에서 위로 페이드하는 것은 AI의 전형적인 징후입니다.
  • EMPHASIS: 한 번에 한 요소: 스케일 팽창 (≤1.2), 광선 또는 의미를 전달하는 색상 변경.
  • TRANSITION: 상태 변경. 변경된 부분만 움직입니다. 나머지는 정지. 0.2–0.6초.
  • CAMERA: 무대 수준의 스케일/이동, 장면당 최대 한 번, 0.8–1.2초, 텍스트 읽기 중에는 절대 안 됨.
  • EXIT: 0.3–0.5초, 완전히 완료됨. 어떤 요소도 장면 경계를 넘어 중간 상태로 남아 있지 않아야 합니다. 단, 동일하게 유지되거나 변형되는 의도적인 연속성 앵커는 예외입니다(동일한 객체의 상태 변경은 가장 강력한 전환입니다).

전환은 의미를 전달합니다: 하드 컷 = 카테고리 변경, 변형 = 같은 것이 변경됨, 팬 = 횡단. 절대 모든 곳에 기본 크로스페이드를 사용하지 마십시오. 지속 시간과 이징은 references/animation-primitives.md에 있습니다. 함께 움직이는 이웃은 다른 지속 시간 또는 오프셋을 얻습니다.

5. 스택 결정

상황스택
페이지 마이크로 모션transform/opacity에 대한 CSS 전환, 0.2–0.6초; @media (prefers-reduced-motion: no-preference) 내부 ≤2초 루프
비디오 / 모션 그래픽 / 키네틱 타입템플릿 + 바닐라 render(t) (기본값)
6개 이상의 엇갈린 트랙 또는 SVG 변형 오케스트레이션고정된 GSAP UMD, 하나의 일시 중지된 마스터 타임라인, seek(t) → tl.seek(t)
차트인라인 SVG (기본값) 또는 animation:false가 있는 Chart.js UMD, 16진수 색상 (캔버스는 CSS 변수를 읽을 수 없음)
생성 예술randomSeed/noiseSeed가 있는 p5.js
3D, 3D가 메시지인 경우에만고정된 Three.js UMD; render(t)에서 스크립트된 카메라

목표에 도달하는 가장 간단한 스택을 사용하십시오. 외부 스크립트는 cdnjs.cloudflare.com 또는 cdn.jsdelivr.net의 정확한 고정 버전이어야 합니다. 다른 모든 것은 인라인으로 처리하십시오. 모든 글꼴은 실제 대체 스택을 가져야 합니다.

6. 기술적 바닥 (협상 불가)

  1. CSS와 JS가 인라인된 단일 .html, 16MB 미만, 이미지/데이터는 data: URI 사용.
  2. :root 토큰으로 색상 지정; :root:not([data-theme="light"])로 보호된 @media (prefers-color-scheme: dark) 아래 어두운 레이어 및 :root[data-theme="dark"] 아래 반복; 명시적인 body 배경색.
  3. viewport-fit=cover가 있는 meta viewport; env(safe-area-inset-*) 패딩; html/body에 height:100%, 100vh 사용 금지; 넓은 블록은 자체 overflow-x:auto 내에서 스크롤; 그리드는 minmax(0,1fr) 사용.
  4. 표시된 계산된 숫자는 Math.round, toFixed 또는 Intl.NumberFormat을 통과해야 합니다. 카운트업은 최종 값에 정확히 도달해야 합니다.
  5. 접근성: 명도 대비 ≥4.5:1 (≥24px 텍스트의 경우 ≥3:1), 눈에 보이는 포커스, prefers-reduced-motion 준수 (템플릿은 최종 프레임을 표시함).
  6. 읽기 쉬운 유형: 1080p 비디오 프레임에서 20px 미만의 텍스트 없음 (H/54). 모바일 페이지에서 14px 미만의 본문 텍스트 없음.
  7. 브라우저 저장소는 타임라인 상태를 절대 보유하지 않습니다. 저장소를 사용하는 경우 try/catch로 감쌉니다.

7. 일반적인 AI 디자인 피하기

브리핑에 자유가 있을 때, 이러한 기본값에 절대 사용하지 마십시오 (qa.mjs는 여러 가지를 자동으로 플래그 지정합니다):

특징수정
크림색 #F4F1EA 계열 + 세리프 디스플레이 + 테라코타 #D97757 계열 강조주제 자체 자료에서 가져온 팔레트
거의 검은색 + 하나의 산성 강조, 주제에 관계없이 사용방향이 서면으로 정당화되는 경우에만 허용
동일한 둥근 카드, 모든 곳에서 하나의 반경, 동일한 부드러운 그림자계층 구조별 반경 토큰; 카드는 경계가 있는 객체만
장식으로서의 그라데이션, 보라색 그라데이션, 글래스모피즘평면 채우기; 연속적인 물리적 속성에 대해서만 최대 하나의 그라데이션
추적된 대문자 눈썹, 중간 점 메타 문자열, 링크의 "→"문장 케이스; 내용을 반복하는 레이블 삭제
기본값 Inter / 시스템 글꼴이 주제에 대해 선택된 서체, 대체 스택 포함
헤드라인에서 강조된 단일 단어강조 색상이 작품의 다른 곳에서 동일한 의미로 사용되는 의미 토큰인 경우에만 허용 (예: 산호 = 잡음)
일반적인 히어로: 헤드라인 + 부제목 + CTA + 스크린샷주제 세계에서 가장 특징적인 것으로 시작
모든 것 가운데 정렬, 모든 섹션에서 동일한 그리드 리듬섹션별 정렬 시스템; 리듬 변경
모든 것이 한 번에 애니메이션, 모든 곳에서 300ms지속 시간 맵 + 스태거 (§4)

한 곳에서 대담함을 투자한 다음, 하나의 액세서리를 제거하십시오.

8. 렌더 + QA (전달 전 필수)

자동화된 QA를 실행하십시오. 파일을 헤드리스로 렌더링하고 증거와 판정을 기록합니다. Node ≥18이 필요합니다. 스킬의 새 복사본에서 첫 번째 실행은 $SKILL/scripts에서 npm install이 필요합니다 (scripts/node_modules가 존재하면 건너뛰십시오).

node "$SKILL/scripts/qa.mjs" path/to/deliverable.html

Windows의 DSH에서는 pwsh 도구를 사용하여 동일한 명령으로 실행하십시오. 옵션: --step 0.25 (빠른 장면에 대한 더 미세한 그리드), --out <dir>, --mode page|video.

비디오 모드 (DURATION + seek가 존재할 때 자동)는 단계마다 프레임을 캡처하고 다음을 확인합니다: 금지된 API, 순서가 잘못된 재방문에 대한 결정론, 고정된 타임라인, 데드 에어, 거의 빈 범위, 해결되지 않은 최종 프레임, 텍스트 충돌, 다른 그래픽 위의 텍스트, 클리핑, 명도 대비, 최소 글꼴 크기, 절대 그려지지 않는 dash-offset 선, 축소 모션 루프, 콘솔/페이지 오류 및 템플릿 특징. 페이지 모드는 데스크톱 1440, 모바일 390 및 어두운 스킴을 렌더링하고, 동일한 레이아웃 규칙과 모바일 가로 오버플로를 확인합니다.

출력은 qa-<name>/에 저장됩니다: report.md (판정 및 결과), report.json (프레임별 잉크 범위 및 변경), contact-sheet.png (모든 프레임을 하나의 이미지에), moments.png (각 장면의 시작, 중간 및 끝, window.SCENES에서 가져옴), key_000..100.png 및 frames/.

  • 시그니처 모멘트 및 동기화 지점을 명시적으로 전달하십시오: --at 5.4,9.1.
  • 의도적인 레이어링 (의도적으로 쌓은 키네틱 타입, 푸티지 위의 제목)은 data-qa-allow-overlap 속성이 있는 요소 내부에 있어야 합니다. 해당 서브트리에 대해서만 충돌 및 텍스트-오버-그래픽 검사를 건너뜁니다. 우발적 충돌을 무음 처리하는 데 절대 사용하지 마십시오.
  • font WARN은 선택한 패밀리가 로드되지 않았고 텍스트가 대체 글꼴에 있음을 의미합니다. 모든 너비가 잘못되었으므로 레이아웃을 판단하기 전에 수정하십시오.

종료 코드 0 = FAIL 없음. FAIL은 차단입니다. 모든 WARN은 수정되거나 비평에서 한 줄로 정당화되어야 합니다.

9. 비평 루프

  1. 모델이 이미지를 읽을 수 있는 경우: contact-sheet.png를 연 다음, 잘못 보이는 key_*.png를 여십시오. 의도가 아닌 픽셀을 판단하십시오.
  2. 모델이 텍스트 전용인 경우: report.md와 report.json의 프레임별 테이블을 사용하십시오. coverage < 0.015는 프레임이 비어 있음을 의미합니다. 장면 전체에 걸친 diff 0은 아무것도 움직이지 않음을 의미합니다. diff의 급증은 컷을 표시합니다. 모든 장면 카드의 타임스탬프를 이러한 숫자와 교차 확인하십시오.
  3. 각 질문에 "✓"가 아닌 구체적인 관찰로 답하십시오:
    • 구성: 각 키 프레임에서 눈이 가장 먼저 가는 곳은 어디입니까? 그것이 메시지입니까?
    • 계층 구조: PRIMARY가 명확합니까? 프레임당 정확히 하나의 중요한 움직이는 것이 있습니까?
    • 메커니즘: 시그니처 모멘트가 캡션을 제거한 상태에서 아이디어를 보여줍니까?
    • 연속성: 모든 핸드오프가 깔끔합니까? 경계에서 중간 상태인 것이 없고 앵커가 동일하거나 변형되고 있습니까?
    • 타이밍: 오프셋이 있고, 기본 지속 시간이 없으며, 읽기 시간이 8단어당 ≥1.2초입니까?
    • 타이포그래피 / 명도 대비 / 밀도: 계획당 크기, 프레임당 ≤5개의 경쟁 요소, 다크 모드에서 읽기 가능?
    • 내러티브: 시청자가 한 번 본 후 핵심 메시지를 반복할 수 있습니까?
  4. 수정 → qa.mjs 재실행 → 재비평. QA가 통과하고 비평에 열린 항목이 없을 때까지 반복하십시오.
  5. 최종 질문, 정직하게 답변: "이것이 의도적으로 디자인된 것처럼 보입니까, 아니면 단지 생성된 것처럼 보입니까?" "생성된" 경우: 무엇이 일반적인지 이름을 지정하고, 계획을 수정하고 (§1), 재구축하십시오. 첫 번째 렌더는 거의 최종 결과물이 아닙니다. 2–3회 생성을 예상하십시오.

10. 오디오 동기화 (음악 또는 음성이 있는 경우)

절대 귀로 타이밍을 추측하지 마십시오. 오디오를 데이터로 변환하고 render(t)가 이를 읽도록 하십시오:

node "$SKILL/scripts/audio-data.mjs" music.mp3 --inject composition.html   # window.AUDIO를 HTML에 기록
  • AUDIO.beats (추정된 템포의 균일한 간격 그리드), AUDIO.onsets (히트, 음표, 음절), 및 프레임별 AUDIO.rms / AUDIO.low (0..1; low는 <150 Hz 킥/베이스 밴드).
  • 템플릿 헬퍼로 모션 구동: 비트 펄스(EMPHASIS)를 위한 hit(t, AUDIO.beats, 0.2), 킥 반응 스케일을 위한 audioAt(t, "low"), 히트당 공개를 위한 since(t, AUDIO.onsets). 비트에 장면 컷 배치: AUDIO.beats에서 장면 시작 선택.
  • 동기화는 구성상 프레임 정확함: 펄스는 해당 비트 또는 그 이후의 첫 번째 프레임에 도달합니다 (≤1 프레임, 30fps에서 ≤33ms). 오디오가 t=0보다 늦게 시작하면 --offset <s>를 전달하십시오.
  • 수준은 누군가 듣기 전에 확인됩니다. 클리핑된 샘플은 종료 코드 1을 반환합니다. 샘플 피크가 -1 dBFS를 초과하면 경고합니다. AAC 인코딩이 클리핑하기 때문입니다. -18..-12 LUFS 밖의 음량은 보고됩니다 (플랫폼은 약 -14로 정규화).
  • --bpm은 템포 감지를 무시하고 제공된 BPM을 사용합니다.
  • 미리보기: $SKILL/scripts/audio-data.mjs를 --preview music.mp3 없이 실행하여 music.html을 만든 다음 브라우저에서 엽니다. 비트, onsets 및 RMS 파형이 타임라인에 표시되며, 음소거/솔로 및 재생/마커가 포함됩니다.
  • 오프닝에만 적합한 오디오는 0초보다 큰 audioOffset을 설정합니다. DURATION은 여기에 포함되지 않지만 오디오가 재생되는 프레임만 나타냅니다.

11. 내보내기

생성된 HTML을 비디오로 변환합니다:

node "$SKILL/scripts/export.mjs" path/to/deliverable.html --fps 30 --out video.mp4
  • FFmpeg가 설치되어 있어야 합니다 (가장 가까운 FFmpeg가 PATH에 있어야 함). --ffmpeg-binary로 재정의할 수 있습니다.
  • 기본 fps 30, crf 17, h264. WebP 가져오기가 --fps 60을 초과하지 않습니다.
  • 이미지 시퀀스의 경우 --format png.
  • --frames N,M은 N에서 M까지의 프레임만 캡처합니다.
  • --audio music.mp3는 출력에 오디오 트랙을 믹스합니다. --audio-delay 및 --audio-volume도 사용 가능합니다.
  • 렌더는 QA가 요구 사항을 전달한 후에만 실행하십시오. 미리 내보내지 마십시오.

"

관련 스킬