Communitygithub.com

Landing Flyover: 어떤 랜딩도 14.5초 3D 필름으로

어떤 랜딩 페이지 URL이든 코드만으로 14.5초짜리 3D 플라이오버 필름(1440x1152, 60fps MP4)으로 만듭니다. 아주 얕은 심도로 카메라 하나가 페이지를 따라 미끄러지고 카드와 사진이 떠오르며, 위로 올라 전체를 보여준 뒤 히어로로 다이브해 두 줄 타이틀 아래에 착지하고, 음악의 드롭이 타이틀에 맞춰 터집니다.

Landing Flyover: 어떤 랜딩도 14.5초 3D 필름으로란 무엇인가요?

「랜딩 페이지에서 런칭 필름까지」 레시피 2단계(페이지 촬영). 출처는 arjunkshah12345-hash/landing-flyover(MIT, 샘플 MP4와 스틸 포함). 에이전트는 먼저 URL, 브랜드명과 로고, 두 부분으로 된 마무리 문구, 선택 사항인 15초 음악(없으면 Mixkit 로열티 프리 곡 제안)을 한 번에 묻습니다. inspect.mjs가 섹션 트리를 뽑으면 에이전트가 역할별(버튼, 칩, 목업, 카드, 사진, 후기)로 띄울 요소 15–35개를 고르고, capture.mjs가 Playwright로 한 번 스크롤해 애니메이션을 끝내고 영상을 멈추고 스크롤 고정 섹션을 접은 뒤 페이지 플레이트를 저장합니다. 모든 프레임이 seek(t)인 WebGL2 필름이 스틸과 컨택트 시트, 30fps 미리보기, 16개 모션 블러 서브프레임을 쓴 60fps 최종본을 렌더링합니다. flow.py는 옵티컬 플로로 카메라가 멈추지 않는지 확인하고, score.py는 드롭을 9.97초에 맞추고 휙 소리를 넣습니다. Node 18+, ffmpeg, numpy가 있는 Python, GPU가 필요합니다.

지원 대상✓Claude Code✓Codex CLI✓Cursor
npx skills add https://github.com/arjunkshah12345-hash/landing-flyover/tree/HEAD/skills/landing-flyover

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

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

문서

Landing fly-over

랜딩 페이지의 고정된 아트 디렉션 영화입니다. 모든 프레임은 시간의 순수 함수(seek(t) in WebGL2)이며, Playwright로 캡처하고, 실제 GPU에서 16-서브프레임 모션 블러로 렌더링하며, ffmpeg로 인코딩합니다. 비디오 편집기, 타임라인, 컷이 없습니다.

사용자 머신에서 코드를 실행해야 합니다. 실행할 수 없는 경우(채팅 전용 환경), 바로 알리세요: 영화를 설명할 수는 있지만, MP4 파일을 만들기 위해서는 셸이 있는 코딩 에이전트(Claude Code, Codex, Cursor…)가 필요합니다.

0. 입력 요청

한 번에 하나의 메시지로 요청하세요:

  1. 랜딩 페이지 링크.
  2. 브랜드 이름과 로고 마크(정사각형 PNG/SVG 경로; 먼저 레포지토리에서 찾아보세요: logo*, favicon*, brand*).
  3. 두 부분으로 된 클로징 라인: 짧은 문장, 그 다음 짧은 이탤릭체 꼬리. 첫 번째 줄은 22자 이내로 유지하세요(1440px 프레임에서 74px로 설정됨). 페이지의 원문에서 23개의 옵션을 제공하세요.
  4. 15초 트랙(선택 사항). 없으면 로열티 프리 음악을 찾아 제공하세요(Mixkit의 무료 라이선스는 출처 표시 없이 상업적 사용을 허용함; https://assets.mixkit.co/music/<id>/<id>.mp3에서 다운로드). 다운로드한 트랙을 레포지토리에 커밋하지 마세요; 렌더링된 MP4만 커밋하세요.

1. 설정

cp -R <this-skill-dir>/engine ./flyover && cd flyover
npm install && npx playwright install chromium   # 설치된 Chrome이 있을 경우 자동으로 선호됨
cp config.example.json config.json

Node 18+, PATH에 ffmpeg, 점수 계산을 위한 Python 3와 numpy가 필요합니다(흐름 검사를 위해 opencv-python-headless 필요). 로고를 config.json 옆에 두고 url, brand, logo, title을 설정하세요.

2. 검사 후, 떠오를 요소 선택

node inspect.mjs        # → dom.txt (페이지 위치와 함께 섹션 트리) + inspect.png

dom.txt를 읽고 config.json을 채우세요:

  • hero.section: 히어로 섹션. hero.mockup: 히어로의 핸드폰/제품/비디오 프레임(영화가 이 부분에 초점을 맞추며 시작하고, 엔드 카드는 이 바로 아래를 자릅니다). hero.tileAnchor: 히어로의 마지막 버튼(네 개의 로고 타일이 그 옆에서 시작됩니다). hero.footerTitle: 푸터 바로 전의 마지막 큰 제목(8.0초에 선명해집니다).
  • layers: 떠오르는 조각들, { "sel", "role" } 형식, 선택적으로 z(기본 리프트), zMax(카메라가 지나갈 때 리프트), stand(렌즈 쪽으로 서는 각도)를 재정의할 수 있습니다. 역할과 기본값:
역할용도z → zMax · stand
button히어로 / CTA 버튼6 → 28 · 0°
chip배지, 알약, 탭, 작은 로고4 → 64 · 30°
mockup히어로 핸드폰 / 제품 / 비디오 프레임10 → 24 · 0°
card기능 카드, 표, 터미널, 메트릭 셀6 → 30 · 0°
photo카드 내부 이미지, 스크린샷, 코드 샘플8 → 115 · 46°
flychip프레임 가장자리를 스쳐 지나가는 1-2개의 작은 칩4 → 200 · 54°
testimonial하나의 인용문/터미널 카드; 34px 흰색 가장자리 표시22 → 112 · 30°

대부분의 리프트는 작게 유지하세요(20–40px). 전체 페이지에 걸쳐 15–35개 조각, 섹션당 몇 개씩. 중첩된 조각도 괜찮습니다: 내부 조각(photo)을 카드 앞에 나열하세요.

  • waitFor: API에서 제공하는 실시간 숫자(방문자 카운터, 토큰 미터)의 선택자. 캡처는 페이지를 고정하기 전에 각각 0이 아닌 숫자가 표시될 때까지 기다립니다; 그렇지 않으면 "0"으로 촬영될 수 있습니다.
  • hide: 쿠키 배너, 채팅 위젯, 팝업. css: 스크롤 기반 효과의 최종 상태를 강제하는 추가 CSS(예: 스크롤 시 밝아지는 단어). routes: [{ "match": "**/broken.jpg*", "file": "/abs/local/copy.jpg" }] 라이브 사이트가 제공에 실패하는 에셋용.

3. 페이지 캡처 및 고정

node capture.mjs

이것은 한 번 아래로 스크롤하여(지연 로딩 이미지, 카운터, 리빌), 애니메이션을 완료하고, 비디오를 한 프레임(또는 포스터)에 고정시키고, 스크롤 고정 "런웨이" 섹션을 축소(고정 + 200vh 스크롤 스페이서는 그렇지 않으면 빈 공간으로 촬영됨)하고, 고정된 바를 해제한 다음, 기본 플레이트를 4096px 청크로 저장하고(Chrome은 한 번에 16384 장치 픽셀까지만 캡처: 더 큰 캡처는 페이지 상단을 조용히 반복함), 투명 배경에 28px 패딩이 있는 각 리프트 조각을 개별적으로 저장하며, 모든 위치가 있는 capture/layers.json을 저장합니다.

타이밍을 정하기 전에 캡처를 확인하세요: capture/page_*.png와 몇 개의 layer_*.png를 엽니다. 빈 비디오 프레임, 반쯤 드러난 텍스트, 중복된 영역, 팝업이 있는지 확인하세요. css/hide/routes로 수정하고 다시 캡처하세요. 타이밍 전에 페이지를 고정하세요: 섹션 높이가 변경되면 이후 모든 것이 이동합니다.

4. 승인용 스틸

node render.mjs stills 0,1.6,2.5,5,6.5,9.3,11      # → stills/contact_sheet.png

사용자에게 콘택트 시트를 보여주고 최종 렌더링 전에 승인을 기다리세요. 각 스틸이 보여줘야 하는 것:

  • 0초: 히어로 위를 낮게, 목업 선명, 버튼 옆에 32px 로고 타일 네 개.
  • 1.6초: 히어로가 뒤로 넘어가고, 두 번째 섹션의 제목이 중앙을 가로지르며, 가까운 콘텐츠가 녹아내림.
  • 2.5초: 해당 섹션의 사진이 세워져 렌즈 근처에서 흐려짐; 플라이칩이 가장자리를 떠남.
  • 5초 / 6.5초: 안정적인 글라이드; 한 섹션이 중앙에서 선명하고, 아래는 부드럽게; 증언 카드가 흰색 가장자리와 함께 올라옴.
  • 9.3초: 바로 위에서, 전체 페이지가 하나의 중앙 스트립으로.
  • 11초: 엔드 카드: 배지 알약, 1번 라인은 Geist 500, 회색 Instrument Serif 이탤릭 꼬리, 히어로가 1018px 카드로, 모서리에 로고 타일, 아래쪽에 두 개의 부드러운 블러.

5. 모션 확인

node render.mjs video preview30.mp4 30 1 && node render.mjs cam
python3 flow.py preview30.mp4     # PASS = 글라이드가 멈추거나 역전되지 않고, 비행이 확대되지 않음

6. 점수 및 렌더링

python3 score.py track.mp3 auto     # 드롭을 찾아 9.97초에 배치; 8.66초와 9.80초에 워시 → audio/score.wav
node render.mjs video flyover.mp4 60 16   # → flyover.mp4, audio/score.wav가 있으면 flyover-audio.mp4도 생성됨

Apple M 시리즈 GPU에서 프레임당 약 0.1–0.2초(총 870 프레임). 하네스는 macOS에서 ANGLE Metal, Windows에서 D3D11, Linux에서 Vulkan을 선택합니다; SwiftShader/llvmpipe가 보고되면 소프트웨어 래스터라이저에서 실행 중이며 느릴 것입니다.

영화 (고정: 페이지별로 다시 타이밍하지 마세요)

  • 14.5초, 60fps, 1440x1152. 비행 0–8.2초 · 상승 7.75–9.25초 · 상공 9.25–9.47초 · 다이브 9.47–9.97초 · 타이틀 카드 9.97–14.5초.
  • 하나의 카메라, 컷 없음. 초점 거리 1880px, 56° 기울기, 거리 이징 아웃 1360→1700px, 회전하지 않음. 페이지 아래로의 속도는 하나의 통합 곡선(순항 비율): 0 → 0.6초까지 0.5, 1.25초까지 유지, 1.6초까지 1.0, 7.3초까지 유지, 8.3초까지 0.12로 이징. 순항은 푸터 제목이 8.0초에 선명하도록 조정되므로 긴 페이지는 더 빠르게 글라이드합니다.
  • 픽셀당 피사계 심도: 전경 블러 = 75·(초점−깊이)/깊이, 배경 블러 = 6·(깊이−초점)/깊이, 최대 120px; 밉 레벨에서 40 황금각 탭, 모션 블러 서브프레임마다 회전; 근거리 블러가 팽창되어 초점이 맞지 않은 전경이 선명한 배경 위로 흘러나옴.
  • 리프트된 조각은 자신의 중앙을 기준으로 세워지고(상단 가장자리가 렌즈 쪽으로) 그림자를 드리움: 동일한 그림자 평면 #1a2133, 오프셋 (0.10z, 4+0.36z), 블러 7+0.5z, 26%.
  • 상승: 사다리꼴 속도에 로그 스케일 줌, 8.15–8.95초에 기울기 평탄화, 프레임 하단 가장자리를 상단에서 42px 위에 고정하는 카메라로 전환. 다이브: 상단 가장자리가 고정된 로그 스케일의 2차 이징 인-아웃, 그런 다음 y 283으로 드롭; 둥근 직사각형 마스크가 24px → 38px 모서리로 변환. 히어로 아래 콘텐츠는 먼저 헤이즈 색상으로 페이드 아웃된 다음 투명하게 자름.
  • 타이틀: 배지 알약 10.02초에 페이드 인 (y 44); 1번 라인 10.12초부터 단어당 0.06초; 꼬리 10.36초부터 단어당 0.05초; 각 단어는 12px 블러에서 16px 위로 0.34초에 걸쳐 상승. 2% 크립으로 유지.

금지: 컷, 크로스페이드, 글라이드의 정지 또는 급등, 카메라 회전 또는 측면 흔들림, 비행 중 줌 인, 광선 효과, 엔드 카드 전에 페이지 위에 텍스트.

주의사항

  • 거대한 페이지: 기본 플레이트는 청크로 분할되며, 하나의 스크린샷이 아닙니다. 히어로가 중간쯤에 반복되면 캡처가 16384 장치 픽셀을 초과한 것입니다.
  • 스크롤 기반 사이트: 고정 런웨이는 자동으로 축소됩니다; 단어별 스크롤 하이라이트는 전체 불투명도를 강제하는 css 규칙이 필요합니다.
  • 비디오: videoTime 초에 고정됩니다. 라이브 사이트의 비디오가 404면 검은 카드가 표시됩니다; routes를 통해 로컬 포스터를 제공하세요.
  • 페이딩 카드는 뒤에 있는 것을 보여주므로 먼저 헤이즈 색상으로 페이드 아웃하세요(엔진이 히어로 아래의 모든 것에 대해 이 작업을 수행).
  • 1번 라인이 너무 긺: 단어가 74px에서 프레임 밖으로 나갑니다. 글자 크기를 줄이지 말고 라인을 짧게 하세요.
  • 라이선싱: 음악은 사용자의 책임입니다; 상업용 비디오를 포함하는 라이선스의 트랙을 선호하세요.

관련 스킬