givemotion: HTML 입력, 비디오 출력
컴포지션은 하나의 HTML 파일입니다. 모든 프레임은 해당 페이지의 특정 시점의 모습입니다. CSS 애니메이션, 전환, Web Animations, 타이머, requestAnimationFrame, 캔버스 및 WebGL이 가상 클럭에서 실행되므로, 작성한 내용이 프레임 단위로 정확하고 매번 동일하게 렌더링됩니다. 스크립트 태그나 임포트는 필요하지 않습니다: 런타임(window.gm)과 사전 설정된 스타일시트가 자동으로 주입됩니다.
이 파일이 핵심입니다 (전체를 읽으세요). 그런 다음 비디오에 필요한 기술 레시피 1-3개만 읽으세요 (표는 마지막에 있습니다): 각 레시피는 전문가가 해당 효과를 어떻게 구축하는지 숫자와 실제 예제와 함께 보여줍니다. 다른 것이 필요할 때 찾아보세요.
루프
- 직접. 코드를 작성하기 전에, 최고의 스튜디오가 이 브리프를 어떻게 제작할지 결정하세요: 장르를 조사하세요 (가능하면 실제 예제를 웹에서 검색하고, 그렇지 않으면 기억에서 떠올리세요). 그런 다음 HTML 상단에 다음을 작성하세요: 말로 표현한 디자인, 타입 시스템, 모션 언어(이징 패밀리, 리듬, 장면 전환 방식), 샷 리스트(순간당 한 줄: 시간, 화면에 보이는 것, 움직임, 전환). 방법:
references/direction.md. - 스타일 프레임. 먼저 핵심 정지 장면 2-3개를 만들어 스틸 상태로 두고
still로 각각 판단하세요: 포스터처럼 평가하세요 (하나의 초점, 계층, 여백). 그런 다음 애니메이션을 적용하세요. - 모션을 작성하세요; 작업하면서
npx givemotion check video.html을 실행하세요: 모든 ✖를 수정하세요; ⚠는 의도하지 않은 경우 실제 결함입니다; ℹ는 스타일 힌트입니다. - 두 번 검토하세요.
npx givemotion review video.html은 시청자가 보는 내용을 기록하고(개요, 사람들이 읽는 프레임, 바쁜 순간의 모션 스트립),review/REVIEW.md를 생성합니다: 엄격하게 점수를 매기고, 가장 나쁜 다섯 가지 문제를 수정한 후 다시 검토하세요. 새로운 시각이 더 많은 것을 발견합니다: 서브 에이전트에게 브리프와 리뷰 폴더만 제공하세요. 브리프의 시간을data-expect에 넣으세요. - 렌더링:
npx givemotion render video.html -o out/video.mp4.
--json은 기계 출력용, <command> --help는 옵션 확인용입니다. still video.html -t 3.2 -o f.png는 한 순간을 렌더링하고, inspect --at 4.5 --el "#logo"는 요소의 위치를 알려줍니다.
여기서 좋은 모션이 어떻게 만들어지는가
엔진은 모든 HTML/CSS/SVG/캔버스와 프레임 정확한 타임라인을 제공합니다; 디자인은 어떻게 안무하느냐에 따라 결정됩니다. 블라인드 시청자는 모든 요소를 수동으로 안무한 비디오를 한 단어 프리셋으로 만든 비디오보다 선호했습니다.
- 수동으로 안무하세요. 중요한 모든 것에
gm.timeline을 사용하세요: 명시적 시작 시간, 움직임별 이징(빠른expo.out, 부드러운sine.inOut드리프트,back.out(1.6)착지), 관련 부분 간 40-120ms 오프셋. 프리셋(data-enter,data-camera)은 작은 보조 요소에 적합합니다. - 모든 히어로 순간에 세 개의 레이어: 주요 움직임; 이를 돋보이게 하는 2차 디테일(빠를 때 블러, 글로우, 커지는 그림자, 후속 동작, 임팩트 시 링 또는 파티클); 프레임이 얼어붙지 않도록 하는 주변 모션(떠다니는 배경, 느린 카메라 푸시).
- 타이밍의 대비. 빠른 진입, 느린 안정; 무언가 착지한 후 0.4-1초의 고정; 퇴장은 진입보다 짧음. 같은 속도와 곡선으로 모든 것을 움직이지 마세요.
- 브리프를 정확히 따르세요 색상, 폰트, 카피, 크기 및 타이밍; 당신의 기술은 내용이 아닌 움직임 방식에 들어갑니다.
- 프레임 0이 훅입니다. 프레임 가장자리에 잘리는 것이 없고, 텍스트는 큽니다(타이틀 96-200 px, 본문 1080p에서 ≥ 36 px), 순간당 하나의 히어로, 장면은 페이드 대신 서로 흘러들어갑니다(푸시, 휩, 모프, 매치 컷).
- 것들은 것들로부터 나옵니다. 새로운 요소는 이미 화면에 있는 요소에서 태어나며, 갑자기 나타나지 않습니다: 세 개의 원이 주 원에서 짜내져 나옵니다; 화면에 있는 직사각형 중 하나가 옆으로 미끄러져 밑줄이 됩니다; 카드는 클릭된 버튼에서 자라납니다; 로고의 마크가 엔드 카드의 마크가 됩니다. 추가하기 전에 재사용하고 변형하세요. 다음 세트를 미리 심어두세요: 이 비트가 재생되는 동안 이미 세계에 존재(작고 희미하게)하므로 카메라가 그것을 드러냅니다.
- 카메라 움직임은 "여길 봐"를 의미합니다. 시청자가 다음에 읽어야 할 무언가를 향해서만 푸시 인하세요. 빈 공간이나 이전 장면으로의 전환 방식으로 줌하지 마세요: 장면을 떠나려면 옆으로 이동(푸시, 휩, 와이프)하거나 요소를 가져가세요(모프, 위 규칙).
transform/translate/scale/rotate/opacity/filter/clip-path를 애니메이션하고,width/top/left는 사용하지 마세요.- 모든 요소는 계획된 수명을 가집니다: 진입, 읽을 수 있는 고정(~1초 + 단어당 0.25초), 그 다음 퇴장 또는 전환. 샷 리스트가 각 고정 시간을 제공합니다.
계층 구조: 한 번에 한 가지가 중요하다
시청자는 눈이 항상 어디를 봐야 하는지 알 수 있는 비디오를 선호했습니다.
- 모든 줄에는 핵심 단어가 있습니다. 의미를 전달하는 단어에 대비를 주세요(강조 색상, 더 무거운 두께, 더 큰 크기, 또는 그 위에 그려진 하이라이트); 나머지는 더 조용하게 유지하세요. 줄당 하나, 화면당 최대 둘입니다. 모든 것이 강조되면 아무것도 강조되지 않습니다.
- 모든 순간에는 하나의 히어로가 있습니다: 가장 크고 가장 밝으며 가장 많은 움직임을 가진 것. 지원 요소는 더 작고(히어로 ≥ 다음 크기의 1.6배, 최대 세 레벨), 더 어둡고(뮤트 또는 50-70% 불투명도), 히어로 이후에 도착하며 덜 움직입니다. 효과(링, 스파크)는 히어로를 감싸고 절대 교차하지 않습니다.
- 순서대로 눈을 이끄세요: 히어로가 먼저 착지합니다; 핵심 단어는 줄이 안정된 후 0.2-0.4초 후에 색상이나 밑줄을 얻습니다; 지원 요소가 따릅니다. 카메라나 콜아웃이 무언가에 초점을 맞출 때, 나머지는 어둡게 하세요.
- 팔레트 역할을 엄격히: 강조는 강조에만 사용, 뮤트는 보조 텍스트용.
이징: 곡선을 움직임에 맞추기
- 진입은 감속합니다(ease-out:
expo.out,power3.out, 또는 무게를 가지고 착지할 때back.out(1.4)). - 퇴장은 가속합니다(ease-in:
power2.in), 진입보다 짧습니다(60-70%). - 보이는 상태에서 A에서 B로 이동, 카메라 움직임, 이미 화면에 있는 것의 크기 변화: ease-in-out(
power2.inOut,sine.inOut): 부드럽게 시작하고 부드럽게 끝납니다. - 주변 드리프트: 긴
sine.inOut;linear는 루프(회전, 티커)에만 사용합니다. 화면에서 시작하거나 멈추는 것은 선형으로 움직이지 않습니다. ease를 비워두면 엔진이 이미 이 작업을 수행합니다(진입은 스프링 인, 이동은 이즈 인/아웃, 퇴장은 이즈 인); 하나를 설정할 때 위 규칙을 따르세요.
최소 구성
<!doctype html>
<html data-width="1920" data-height="1080" data-fps="30" data-duration="2.5">
<head>
<style>
:root { --bg: #0b0d12; --ink: #fff; --accent: #7c9cff; }
body { background: var(--bg); color: var(--ink); font-family: Inter, sans-serif; }
.scene { display: grid; place-items: center; } /* .scene은 이미 absolute + 전체 프레임 */
h1 { font-size: 160px; letter-spacing: -0.03em; margin: 0; }
.glow { position: absolute; width: 900px; height: 900px; border-radius: 50%; background: var(--accent); filter: blur(160px); opacity: .25; }
</style>
</head>
<body>
<section class="scene">
<div class="glow"></div>
<h1 id="t" data-split="chars">Hello</h1>
</section>
<script>
gm.timeline('.scene')
.from('.glow', { scale: 0.6, opacity: 0, duration: 1.2, ease: 'sine.out' }, 0) // 주변: 빛이 피어오름…
.to('.glow', { x: 220, y: -90, duration: 2.5, ease: 'sine.inOut' }, 0) // …계속 떠다님
.from('#t .gm-char', { y: 140, opacity: 0, filter: 'blur(12px)', duration: 0.7, ease: 'expo.out', stagger: 0.05 }, 0.2) // 주요: 빠른 진입, 빠를 때 블러
.fromTo('#t', { letterSpacing: '0.12em' }, { letterSpacing: '-0.03em', duration: 2.4, ease: 'expo.out' }, 0.2) // 디테일: 트래킹 조임
.to('#t', { scale: 1.06, duration: 1.9, ease: 'sine.inOut' }, 0.6); // 고정이 계속 숨쉼
</script>
</body>
</html>
내장 폰트: Inter, JetBrains Mono, Playfair Display, Space Grotesk, Bebas Neue, Nunito, Caveat; 다른 폰트는 @font-face를 통해 사용.
타이밍 모델 (이것을 읽으세요)
- 설정은
<html>에 있습니다:data-width,data-height(짝수),data-fps(기본 30), 선택적data-duration, 선택적data-background. - 시간은 초 단위:
1.5,1.5s,500ms,45f(프레임),1:02.5. - 클립.
data-start,data-duration또는data-end가 있는 요소는 시작부터 시작+지속 시간 동안만 존재합니다(display됨). 시간은 부모 클립을 기준으로 합니다. 타이밍이 없는 요소는 항상 있습니다. - 비디오 길이 =
<html>의data-duration, 그렇지 않으면 마지막 클립의 끝. - 시퀀스. 컨테이너의
data-sequence는 자식을 하나씩 재생합니다. 모든 자식에data-duration이 필요하거나, 컨테이너에data-cuts="0 2.13 4.27"(각 자식이 시작하는 시간, 또한"beats: 0 4 8"/"bars: 0 1 2")를 제공합니다.data-gap="0.2"(음수 = 오버랩).data-transition="<이름> <초> [이징]"은 이웃을 오버랩하고 변경을 애니메이션합니다; 자식은 자체data-transition(자신이 어떻게 들어오는지)을 설정할 수 있습니다. 각 전환은 그 길이만큼 전체 길이에서 뺍니다: 4초 장면 3개에fade 0.5가 있으면 총 11초입니다. 비트에 맞춘 컷,data-cut-align, 장면의 시간 0이 위치하는 곳:references/timeline.md. - 전환:
push-/cover-/whip-/wipe-+left/right/up/down(푸시: 새 것이 옛 것을 밀어냄; 커버: 새 것이 위로 슬라이드; 휩: 빠르고 블러 있음)diagonalclockiriszoomzoom-through(옛 장면이 날아감)flip(3D)dip(검정을 통해)blurfade-upfade, 그리고morph: 두 장면에서 같은data-morph="이름"을 가진 요소가 나머지는 크로스페이드되는 동안 옛 위치에서 새 위치로 날아가며 크기가 조정됩니다. 로고, 카드 또는 숫자를 가로지릅니다; 한 장면에서는gm.fly를 사용하세요. - CSS 애니메이션은 클립 시간으로 실행됩니다.
animation: fade-up .6s .4s both는 클립이 나타난 후 .4초에 시작됩니다. 요소가 지연 전에 숨겨지도록both(또는backwards) 채우기를 사용하세요. - 긴 장면 내부에 나중에 나타나는 것 (하나의 카메라 세계, 하나의 화이트보드):
data-enter의 지연은 요소의 클립 시작부터 계산되므로,data-enter="write 0.8 11.9"는 장면 시작 후 11.9초에 레이블을 쓰고 그때까지 숨깁니다. 추가 클립이 필요하지 않습니다. gm.onFrame(fn)은 장면 내에서도 비디오의 시간을 가져옵니다;gm.onFrame('#s', (local, info, el) => …)는gm.timeline('#s')처럼#s의 시작부터 계산합니다.- 타이머,
requestAnimationFrame,Date.now(),performance.now()는 가상이며Math.random()은 시드됩니다. 일반 웹 애니메이션 코드가 작동합니다.
타임라인: 정밀한 안무 (GSAP 스타일, 내장)
움직이는 부분이 몇 개 이상인 모든 것에 대해 gm.timeline을 사용하세요: 당신이 알고 있는 GSAP API이며, 시간에서 계산됩니다(프레임 정확, 병렬). 시간은 범위를 포함하는 클립을 기준으로 한 초입니다.
gm.timeline('#scene2') // 범위: 선택자는 그 안에서 조회됨
.from('.title .gm-word', { y: 120, opacity: 0, rotate: 8, stagger: 0.06 }) // 이징 없음: 스프링 인
.to('.card', { x: 400, y: -60, scale: 1.2 }, '+=0.3') // 호를 그리며, 거리에 따라 크기 조정
.fromTo('.bar', { scaleY: 0 }, { scaleY: 1, stagger: { each: 0.08, from: 'center' } }, '<')
.to('#line', { draw: 1, duration: 1.5 }, 2) // SVG 스트로크 그리기
.to('.price', { textContent: 249, duration: 1.5 }, 2.5); // 숫자 카운트
gm.fly('#event', { from: '#slot2', at: 7.5, duration: 0.8 }); // 다른 요소의 박스에서 자신의 위치로 날아가기
from()/fromTo()는 클립 시작부터 시작 값을 보여줍니다(진입 전까지 숨겨짐). 한 속성에 겹치는 트윈: 가장 최근 시작이 우선합니다. 위치, 모든 속성과 옵션, 레이블, 키프레임, gm.fly 및 SVG 주의 사항: references/timeline.md.
또한 내장됨(references/api.md의 표): data-enter/data-exit 프리셋, data-split, data-stagger, data-count (-roll), data-type(타자기), data-scramble, data-camera(푸시, 플로트, 쉐이크…), data-parallax, data-morph, data-fit, data-pulse, 이징 이름(GSAP 이름 작동), 프리셋 CSS 키프레임 및 var(--px), 그리고 미리 만들어진 블록(npx givemotion blocks: 자막, 코드 창, 커서, 브라우저 창, 차트…).
기술 레시피 (비디오에 필요한 것을 읽으세요)
| 비디오에 다음이 있는 경우… | 읽을 것 |
|---|---|
| 로고, 브랜드 스팅, 인트로 또는 엔드 카드 | references/techniques/logo-reveal.md |
| 크게 부딪히고, 쌓이고, 회전하는 큰 타입; 헤드라인이 주역 | references/techniques/kinetic-type.md |
| 텍스트 공개: 단어/문자, 타자기, 쓰기, 스크램블, 하이라이트 | references/techniques/text-reveals.md |
| 카메라 움직임: 푸시, 팔로우, 휩, 뱅크, 디테일로 줌, 쉐이크 | references/techniques/camera-moves.md |
| 여러 장면 전환(푸시, 휩, 모프, 셰이프 와이프) | references/techniques/scene-transitions.md |
| 글로우, 라이트 스윕, 그라디언트, 그레인, 블러, 깊이 | references/techniques/light-and-depth.md |
| 숫자, 카운터, 막대/선 차트, 콜아웃 | references/techniques/numbers-and-charts.md |
| 그려지는 선, 경로, 지도, 핀, 경로를 따라 이동하는 것 | references/techniques/paths-and-maps.md |
| 평면 도형: 성장, 스쿼시, 분할, 궤도, 모프 | references/techniques/shapes-and-motion-graphics.md |
| 커서, 클릭, 타이핑, 목록이 있는 앱/UI | references/techniques/ui-demo.md |
| 편집기 안의 코드, 타이핑, 라인 하이라이트 | references/techniques/code-on-screen.md |
| 충격과 에너지: 슬램, 쉐이크, 버스트, 음악 비트 | references/techniques/impacts-and-energy.md |
| 단어별 자막, 세로 9:16 클립 | references/techniques/captions-vertical.md |
| 화이트보드, 스케치, 손으로 그린 | references/techniques/hand-drawn.md |
| 모든 것 뒤에 있는 살아있는 배경 | references/techniques/backgrounds-and-ambient.md |
API 참조 (필요할 때 찾아보기)
| 다음 경우… | 읽을 것 |
|---|---|
| 속성, 프리셋, 이징 이름, 프리셋 CSS 또는 블록 | references/api.md |
gm.timeline 전체: 위치, 키프레임, 레이블, gm.fly, SVG | references/timeline.md |
gm.camera 세계, 샷, gm.path.travel, 라이딩, 패럴랙스 | references/camera.md |
gm.chart.*, 차트 블록 | references/charts.md |
다이어그램, 화살표, data-sketch, gm.connect, gm.shape, 경로 모프 | references/diagrams.md |
음악, 비트, 음성 해설 + givemotion words, 비디오 클립, 자막 | references/media-audio.md |
| 데이터/템플릿, `<gm-in |