Motion Frames — 프레임 기반 모션 디자인 시스템
전문가 수준의 모션 디자인을 비디오 소프트웨어 없이 제작하는 완전한 방법: 전체 애니메이션은 장면이 프레임 번호의 순수 함수인 HTML 페이지이며, 헤드리스 Chromium으로 프레임 단위로 캡처하고 ffmpeg로 MP4로 조립합니다. 모든 것이 결정적입니다. 동일한 입력, 동일한 픽셀 — 병렬 렌더링, 모든 프레임에서 재개, 1/60초 정밀도의 사운드 및 이미지 싱크가 가능합니다.
1. 불가침의 규칙: 프레임의 순수 함수
- 전체 장면은
renderFrame(n)에 존재하며,n은 프레임 번호(60fps)입니다. - 금지: 시계(
Date.now,performance.now,requestAnimationFrame을 통한 누적 상태) 및 시드 없는 난수: 난수는 인덱스/프레임의 결정적hash(i)를 통해서만 허용됩니다. - 모션 = 이벤트 시작 이후 경과 시간의 폐쇄형 공식:
- 분석적 스프링(저감쇠):
spring(t, freq, damp)— 오버슈트 포함, 모든 것의 기본 물리(진입, 팝, 스택). - 명명된 이징:
easeOutCubic,easeInOutCubic,easeOutBack. - 세그먼트:
seg(n, a, b)= 프레임 구간의 진행률 0→1;clamp,lerp로 모든 값(위치, 색상, 모프 형상) 보간.
- 분석적 스프링(저감쇠):
- 기본 형식: 1080×1920, 60fps. 지속 시간은 콘텐츠에 따라 결정(빠른 테스트: 8초 = 480프레임).
2. 파이프라인(이 스킬의 pipeline/ 폴더)
| 파일 | 설명 |
|---|---|
pipeline/template.html | 헬퍼(T, seg, spring, 이징, hash)와 renderFrame(n) 스켈레톤이 포함된 기본 페이지 |
pipeline/render.mjs | 종속성 없는 CDP 렌더러: node render.mjs <page.html> <dir> <num_frames> 1080 1920 [start_frame] |
pipeline/preview.mjs | 선택한 프레임만 PNG로 렌더링: node preview.mjs <page.html> <dir> "0,60,160,300" <total> 1080 1920 |
pipeline/sfx_kit.py | 프레임 번호에 연결된 합성 효과음 키트(numpy/scipy) |
- Chromium: 렌더러는
CHROME_BIN을 찾고, 그 다음 스크립트 옆의chrome-headless-shell, 그 다음 작업 공간의 알려진 경로를 찾습니다. 모든 Chromium이 작동하는 것은 아닙니다. 도메인/WebGL 정책이 있는 빌드(예: Hatch가 관리하는 Chromium)는 독립 실행 실행을 거부합니다. 별도의chrome-headless-shell을 사용하세요. - 속도:
FMT=jpeg(품질 90)는 PNG보다 약 2배 빠르며 결과에서 구별할 수 없습니다. PNG는 프리뷰 전용입니다. - 샤드: 긴 비디오는 2개의 병렬 프로세스(간격의 절반,
start_frame인수 사용)로 렌더링되며, 각각 고유한PORT(CDP)를 사용합니다. ~8GB 머신에서는 최대 2개 병렬 — 3개는 RAM을 초과합니다. - 조립:
ffmpeg -framerate 60 -i dir/f%04d.jpg -i audio.wav -c:v libx264 -pix_fmt yuv420p -crf 18 -c:a aac -b:a 192k -movflags +faststart out.mp4. - 로컬 폰트 및 이미지: HTML에 상대 경로로 참조(
file://을 통해 작동). 브랜드 폰트:.woff2를 다운로드하고 로컬@font-faceCSS를 생성하세요. 렌더링 시간에 네트워크에 의존하지 마십시오. 장면에 사용된 이미지: 페이지 본문에 숨겨진<img>프리로드를 포함하세요. 그렇지 않으면 첫 번째 프레임에 이미지가 없습니다.
3. 제작 워크플로(이 순서대로)
- 대본 및 참고 자료: 각 장면의 문구를 정의합니다. 참고 자료를 프레임 단위로 연구(ffmpeg로 연락처 시트 추출)하고 문법을 기록합니다. 표면을 복사하지 마십시오.
- 오디오 우선(내레이션이 있는 경우): 무음 감지(
ffmpeg -af silencedetect) 후 잘라낼 위치를 결정합니다. faster-whisper로 전사합니다(small,word_timestamps=True, 오디오를 16k WAV에서 읽은 numpy 배열로 전달 — faster-whisper의 내부 디코딩은 일부 PyAV 버전에서 손상됨). 키워드 시간을 프레임 랜드마크(second × 60)로 변환합니다. 말하기 지속 시간을 절대 임의로 정하지 마십시오. - 브랜드 조사(제품 비디오의 경우): 실제 아이덴티티를 가져옵니다. 사이트의 HTML/CSS를 다운로드하고 로고(이미지 파일), 팔레트(CSS에서 가장 빈번한 16진수) 및 폰트를 추출합니다. 비디오에 공식 로고와 폰트를 사용합니다.
- 장면별 디자인: 장면당 하나의 함수(
s1(n),s2(n)...), 경계는 음성 랜드마크에 있습니다. 각 장면은 이미 동기화된 주요 이벤트와 함께 시작됩니다. - 필수 프리뷰:
preview.mjs로 15–30프레임의 연락처 시트를 만들어 리듬과 구성을 확인합니다. 그리고 항상 2~3개의 키 프레임을 실제 크기로 확인합니다: 연락처 시트는 속임수입니다(텍스트 충돌, 너비 오버플로 및 작은 세부 사항을 숨깁니다). - 마이크로 이벤트별 SFX(섹션 8), 애니메이션과 동일한 프레임 번호 사용.
- 샤드 렌더링 + 조립 + QA: 최종 MP4에서 프레임을 추출(개별 프레임이 아님)하고 전달하기 전에 확인합니다.
4. 모션 언어(전문가와 평범함을 구분하는 것)
- 영화 같은 오프닝: 첫 1초는 제목입니다. 큰 타이포그래피가 스프링과 카메라로 진입하고, 배경에 깊이가 있습니다. 정적 화면은 없습니다.
- 카메라는 절대 멈추지 않음: 모든 샷에서 천천히 드리프트하는 스케일(1→1.03–1.09); 레이어 간 시차를 동반한 움직임(돌리/줌/팬)으로 컷을 위장.
- 밀도: 0.5–1.5초마다 마이크로 이벤트. 2초 동안 아무 일도 일어나지 않는 구간이 있으면 잘못된 것입니다.
- 모든 것에 물리: 오버슈트가 있는 스프링, 낙하 및 바운스의 스쿼시 & 스트레치, 주요 움직임 전의 예비 동작. 선형 모션은 기본적으로 금지됩니다.
- 전환은 이벤트이지 컷이 아님: 객체 모프(알약이 막대로, 막대가 카드로), 블러가 있는 줌-스루, 또는 줌-펀치(장면 경계에서 약 18프레임의 크로스페이드와 함께 스케일 1→1.09 교차).
- 적은 팔레트: 한 계열의 배경 + 글로우가 있는 하나의 강조 색상; 무거운 타이포그래피; 많은 여백.
5. 배경: 절대 평범하지 않게, 항상 살아있게
평범한 검은색 배경(또는 어떤 단색 배경)은 금지됩니다. 배경은 그 자체의 생명, 흐름 및 배경/중간/전경 사이의 시차를 가지고 있습니다. 세 가지 입증된 레시피:
- 라이브 스튜디오(어두운 프로모션): 강조 색상의 물감 그라데이션, 천천히 움직이는 2개의 흐릿한 컬러 블롭, 상단의 라이트 콘, 떠다니는 보케 입자(결정적 해시), 원근법의 점 그리드 바닥 + 빛나는 수평선 + 중앙 요소 아래 반사.
- 리퀴드 오로라(연속 장면): 3–4개의 길쭉한 방사형 그라데이션 리본,
mix-blend-mode: screen, 강한 블러, Lissajous 곡선으로 움직이며 천천히 회전; 명령이 장면의 "색상"을 변경할 때 크로스페이드가 있는 두 팔레트; 위에 입자 먼지. - 브랜드 아이스(밝은 키네틱): 브랜드 색상의 밝은 그라데이션, 흐르는 민트 실크(오로라와 동일한 기술, 밝게), 미묘한 점 그리드 및 먼지 — 깨끗하지만 숨 쉬는.
6. 진정한 3D(신경 쓰세요 — 비디오가 참고 자료에 가장 뒤처지는 부분입니다)
- CSS
perspective+rotateX/rotateY를 전화기, 카드 및 대시보드에 사용; 요소는 기울기에 반응하는 살아있는 그림자와 함께 떠 있습니다. - 진정한 시차: 모든 줌/팬에서 배경, 중간 및 전경이 다른 속도로 움직입니다.
- CSS로 3D 큐브 및 상자: 각 면은
translateZ = 너비/높이의 절반으로 배치된 div입니다(이것을 틀리면 가장자리가 벌어집니다). - 올라가는 등각 사다리/블록, 깊이가 있는 스택, 유리(뒤의 배경이 단순할 때
backdrop-filter), 그리고 스윕하는 반사 하이라이트. - 경험 법칙: 장면이 "텍스트 + 평면 사각형"으로 설명될 수 있다면 3D가 부족한 것입니다. 사진처럼 보일 때까지 기울기, 레이어 또는 깊이를 추가하십시오.
7. 네 가지 문법(샷별 구조)
A. 시네마/모프(오프닝 및 스타일 테스트)
영화 타이틀 → 점선 궤적을 따라 스쿼시 & 스트레치가 있는 객체 → 카메라가 다이빙하고 객체가 모프(원→알약→화면) → 3D 요소가 회전하며 면이 확대됨 → 손으로 그린 원이 있는 키네틱 타이포그래피 → 스프링으로 움직이는 그래프가 있는 유리 패널 → 시작점으로 돌아가는 종료(완벽한 루프, 해당하는 경우).
B. 프리미엄 앱 프로모션(Opal/Qwix 같은 참고 자료)
- 라이브 앰비언트 배경 + 스포트라이트; 글로우/블룸이 있는 하나의 강조 색상.
- 오프닝: 3D 원근감으로 떠 있는 UI/전화기, 풀 포커스가 있는 돌리-인(흐릿하게 시작, 초점 맞춤).
- 카메라가 세부 사항(그래프 막대)으로 다이빙하여 다음 샷이 됩니다.
- 아이콘 + 카운팅 숫자(easeOut) + 레이블이 있는 유리 알약; 가장자리에 빛의 호가 흐르는 테두리.
- 집계: 알약에서 지지선이 그려져 ▲가 있는 거대한 숫자로 수렴.
- 앱 아이콘이 모프 + 입자 폭발.
- 앱 시트 + 커다란 CTA 알약 버튼에 빛 스윕.
- 로고 공개: 기호가 그려짐(SVG dash) + 워드마크 + 작은 URL.
C. 연속 대화형 장면("Built with Claude" 참고 자료)
하나의 장면, 컷 없음, 리퀴드 오로라 위: 기호가 그려짐 → 명령 알약이 진입 → 커서가 이동하여 알약을 클릭 → 알약이 모프하여 프롬프트 막대가 됨 → 프롬프트가 단어별로 입력됨(깜빡이는 캐럿, 마지막 단어 강조) → 막대가 모프하여 결과가 됨(내부에서 구성되는 카드: 링, 막대, 재생, 진행률 %) → 두 번째 명령이 입력되어 전체 배경색 변경 → 기호 + 서명으로 종료. 이야기는 "누군가가 제품을 사용하는 것"입니다.
D. 밝은 키네틱 타입(타이포그래피 PT-BR 광고)
브랜드 아이스 배경; 브랜드 폰트의 무거운 타이포그래피가 주역, 음성 비트에 단어별로, 키워드는 강조 색상, 유령 같은 컬러 그림자 및 손으로 그린 낙서(그어 긋기, 원, 스우시 — SVG dash). 실제 UI를 인터리브하여 이야기를 전달: 물리로 쌓이는 알림, 비교 막대, 로고 주위의 궤도 노드 시스템, 채팅 거품, 그래프가 있는 상태 카드, 거대한 카운터. 장면 경계는 줌-펀치; 중간에 어두운 반전 비트("그리고 거기서 끝이 아닙니다!"); 아이콘이 있는 3회 슬로건; 커서가 클릭한 로고 + CTA + URL로 종료.
8. 사운드: 마이크로 이벤트별 SFX
sfx_kit.py에서 구성된 트랙: 각 사운드 이벤트는 시각적 이벤트와 동일한 프레임 번호를 사용합니다.- 어휘:
pop(클릭, 카드, 큰 단어),tick(타이핑, 막대, 카운터),whoosh(전환 및 모프),shimmer(확인, 공개),pad(모든 것 아래의 미묘한 하모닉 패드). - 비디오와 동일한 밀도: 시각적 마이크로 이벤트가 있으면 사운드가 있습니다. 내레이션 아래에서는 트랙을 ~0.5로 믹싱하고 음성이 지배하도록 합니다.
- 사용자 음성을 생성하거나 대체하지 마십시오. 내레이션은 항상 사용자의 것이며, 그대로 유지됩니다(무음 제거는 오디오를 분석하고 동기화를 다시 수행한 후에만).
9. 비-제네릭 체크리스트(전달하기 전에 확인)
- 타이포그래피가 주역입니까, 아니면 단순한 UI 레이블입니까? (주역이어야 함)
- 모든 장면에서 0.5–1.5초마다 마이크로 이벤트가 있습니까?
- 어떤 것이 물리로 쌓이거나, 떨어지거나, 충돌합니까? 아니면 모든 것이 고립되어 떠 있습니까?
- 상호 작용(커서 클릭, 프롬프트 입력, 제품 사용)이 있습니까?
- 손으로 그린 낙서 레이어(원, 밑줄, 화살표, 그어 긋기)가 있습니까?
- 적어도 하나의 전환은 객체 모프입니까, 아니면 단순한 줌입니까?
- 배경이 그 자체의 생명으로 흐르고 레이어 간 시차가 있습니까?
- UI에 추상적인 플레이스홀더 대신 이야기를 전달하는 "실제" 콘텐츠(값, 대화, 이름)가 있습니까?
- 궤도 시스템, 경로 위의 텍스트 또는 다른 "시그니처" 요소가 있습니까?
- 3D가 섹션 6의 테스트를 통과합니까?
- 모든 마이크로 이벤트에 SFX가 있습니까?
10. 상업적 진실(숫자를 지어내지 마십시오)
- 상업적 약속이 되는 숫자(비율 %, 승인율 %, 가격)는 지어내지 않습니다: 브랜드가 공개하지 않으면 숫자 없는 시각적 비교(높은 막대 × 낮은 막대), 모션 기법으로서의 볼륨/성장 카운터 및 질적 언어("높음", "훨씬 낮음")를 사용합니다.
- 제품에 대한 불확실한 사실은 대본 작성 전에 신호를 보내야 하며, 렌더링 후에는 절대 안 됩니다.
11. 이미 발생한 오류(반복하지 마십시오)
- 연락처 시트는 속임수: 미리보기는 텍스트 충돌 및 너비 오버플로를 숨깁니다. 항상 키 프레임을 실제 크기로 검증하십시오.
- SVG의 중복 속성: 동일한 요소에 두 개의
stroke-dasharray— 첫 번째가 우선하고 draw-on이 조용히 죽습니다. 요소당 하나의 속성. - 하드코딩된 장면 인덱스: 고정 장면을 반환하는 함수(
return 5)는 장면 수가 변경될 때 마지막 장면을 깨뜨립니다. 경계 배열에서 파생시키십시오. - 열린 3D 큐브: 잘못된
translateZ(≠ 차원의 절반)를 가진 면은 가장자리에 틈을 남깁니다. - 병렬 3개의 샤드 = OOM 소형 머신에서. 최대 2개.
- 시스템 Chromium은 작동하지 않을 수 있음(도메인/WebGL 정책): 별도의 chrome-headless-shell을 사용하십시오.
- 프리로드 없는 이미지는 첫 번째 프레임 후에만 나타납니다: 본문에 숨겨진
<img>가 해결합니다. - "거의 맞는" 장면: 큰 폰트로 텍스트 너비를 측정하십시오. 118px 슬로건 문구는 1080px를 초과하여 심하게 깨질 수 있습니다. 큰 프리뷰에서 실제 너비를 확인하십시오.
12. 예제 프로젝트(이 시스템의 실제 제작물)
~/workspace/motion-frames/teste_8s.mp4— 문법 A: 공/모프/큐브/타이포그래피 루프, 8초.~/workspace/iphone18/iphone18_pro.mp4— 단어별 동기화된 내레이션(53초), CSS로 만든 iPhone 3D.~/workspace/kalo/kalo_app_v2.mp4— 라이브 스튜디오 배경 + AI 식사 스캔 장면이 있는 문법 B, 15초.~/workspace/kalo/feito_com_muse.mp4— 문법 C: 연속 장면, 커서, 프롬프트 입력, 모프, 크로스페이드가 있는 오로라, 14초.~/workspace/turtle/turtlepags.mp4— 내레이션이 있는 완전한 문법 D, 실제 브랜드 아이덴티티(사이트의 로고/팔레트/폰트), 53초.