Communitygithub.com

Landing Flyover:把任何落地頁變成 14.5 秒 3D 影片

把任何落地頁網址變成一支 14.5 秒的 3D 飛越影片(1440x1152、60fps MP4),全部以程式完成:一個連續鏡頭帶著極淺景深滑過頁面,卡片與圖片浮起立向鏡頭,升空俯瞰全頁,再俯衝進首屏,停在兩行標題下,配樂的 drop 剛好落在標題上。

Landing Flyover:把任何落地頁變成 14.5 秒 3D 影片 是什麼?

「落地頁到發表片」配方第 2 步(把頁面拍成片),來自 arjunkshah12345-hash/landing-flyover(MIT,倉庫附樣片 MP4 與截圖)。agent 先一次問清:頁面網址、品牌名與 logo、兩段式結尾文案、可選的 15 秒配樂(沒有的話可推薦 Mixkit 免版稅曲目)。inspect.mjs 匯出頁面區塊樹,agent 依角色(按鈕、標籤、樣機、卡片、圖片、評價卡)挑 15–35 個要浮起的元素;capture.mjs 用 Playwright 捲動一次、跑完動畫、凍結影片、收合捲動固定區塊並存下整頁底圖;WebGL2 影片每一格都是 seek(t) 的純函數,先產出截圖與聯絡表、30fps 預覽,再產出含 16 個動態模糊子幀的 60fps 成片。flow.py 以光流檢查鏡頭從不停頓,score.py 把音樂 drop 對到 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 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Landing fly-over

一個固定的、經過藝術指導的著陸頁影片。每一幀都是時間的純函數(WebGL2 的 seek(t)),使用 Playwright 擷取,在真實 GPU 上以 16 子幀動態模糊渲染,並以 ffmpeg 編碼。沒有影片編輯器、沒有時間軸、沒有剪接。

你需要在使用者的機器上執行程式碼。 如果你無法做到(例如僅限聊天的環境),請直接說明:你可以描述影片,但 MP4 需要一個具有 shell 存取權限的編碼代理(Claude Code、Codex、Cursor……)。

0. 詢問輸入項目

一次詢問,在一則訊息中提出:

  1. 著陸頁連結。
  2. 品牌名稱與標誌圖案(一個方形的 PNG/SVG 路徑;先在 repo 中尋找:logo*、favicon*、brand*)。
  3. 兩部分結尾文案:一句簡短陳述,加上一句斜體結尾。第一行請維持在約 22 個字元內(它在 1440px 畫面上以 74px 字級呈現)。從頁面本身的文案中提供 2–3 個選項。
  4. 一段 15 秒的音樂(可選)。如果他們沒有,提議尋找免版稅音樂(Mixkit 的免費授權允許商業使用無須署名;從 https://assets.mixkit.co/music/<id>/<id>.mp3 下載)。切勿將下載的音樂提交到 repo 中;僅提交渲染後的 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+、ffmpeg 在 PATH 中、以及 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°
flychip1–2 個飛越畫面邊緣的小元件4 → 200 · 54°
testimonial一則引言 / 終端機卡片;顯示 34px 白色邊框22 → 112 · 30°

大部分浮起高度保持極小(20–40px)。整個頁面目標約 15–35 個元件,每個區塊幾個。巢狀元件可以:將內部元件(photo)列在它的卡片之前。

  • waitFor:由 API 提供的即時數字選擇器(訪客計數器、代幣計量表)。擷取會等到每個選擇器顯示非零數字後才凍結頁面;否則它們可能顯示為「0」。
  • hide:Cookie 橫幅、聊天小工具、彈出視窗。css:任何額外的 CSS 以強制捲動驅動效果的最終狀態(例如文字在捲動時亮起)。routes:[{ "match": "**/broken.jpg*", "file": "/abs/local/copy.jpg" }] 用於即時網站無法提供的靜態資源。

3. 擷取並鎖定頁面

node capture.mjs

這會向下捲動一次(觸發懶載入圖片、計數器、揭露效果),完成動畫,將影片凍結在某個影格(或其預覽圖),收合捲動固定的「跑道」區塊(sticky + 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

向使用者展示聯絡表,等待確認後再進行最終渲染。每個靜態畫面應顯示的內容:

  • 0s:低角度在英雄區上方,mockup 清晰,四個 32px 標誌拼貼在按鈕旁邊。
  • 1.6s:英雄區逐漸落在後方,第二個區塊的標題穿過畫面中央,附近的內容開始融化模糊。
  • 2.5s:該區塊的照片立起並在鏡頭附近模糊;一個飛出元件離開畫面邊緣。
  • 5s / 6.5s:穩定滑行;一個區塊在畫面中央清晰,下方柔和;使用者評價區塊升起並顯示白色邊框。
  • 9.3s:正上方俯瞰,整個頁面呈現為一條置中的長條。
  • 11s:結束卡片:徽章藥丸、第一行使用 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.97s;8.66s 和 9.80s 有呼嘯聲 → 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.5 在 0.6 秒內,維持至 1.25 秒,1.0 在 1.6 秒內,維持至 7.3 秒,在 8.3 秒內緩和至 0.12。巡航速度經計算使頁尾標題在 8.0 秒時清晰,因此較長的頁面會滑行得更快。
  • 每個像素的景深:前緣模糊 = 75·(focus−depth)/depth,後緣模糊 = 6·(depth−focus)/depth,上限 120px;從 mip 層級進行 40 個黃金角取樣,每個動態模糊子幀旋轉;近場模糊進行膨脹,使失焦的前景物體能覆蓋清晰的背景。
  • 浮起的元件繞其自身中心立起(頂部邊緣朝向鏡頭)並產生陰影:同一圖案以純色 #1a2133 繪製,偏移 (0.10z, 4+0.36z),模糊 7+0.5z,透明度 26%。
  • 上升:以對數尺度對梯形速度進行縮放,傾斜角度在 8.15–8.95 秒內變平,移交給一個將頁面底部邊緣固定在畫面上方 42px 處的相機。潛入:以對數尺度進行二次進出緩動,頁面頂部邊緣固定,然後下降至 y 283;一個圓角矩形遮罩從 24px 變形至 38px 圓角。英雄區以下的內容先淡入霧色,然後切為透明。
  • 標題:徽章藥丸在 10.02 秒淡入(y 44);第一行從 10.12 秒開始,每 0.06 秒出現一個詞;結尾從 10.36 秒開始,每 0.05 秒出現一個詞;每個詞從 12px 模糊中上升 16px,歷時 0.34 秒。保持 2% 的緩慢蠕動。

禁止:剪接、交叉淡入淡出、滑行中的停止或加速、鏡頭轉向或橫向擺動、飛行期間放大、發光效果、結束卡片之前頁面上出現任何文字。

注意事項

  • 超大頁面:基底圖以區塊儲存,從不使用單張螢幕截圖。如果在頁面中段看到英雄區重複,表示一次擷取超過了 16384 裝置像素。
  • 捲動驅動的網站:粘性跑道會自動收合;逐詞滾動高亮效果需要 css 規則強制設定為完全不透明。
  • 影片:它們會凍結在 videoTime 秒。如果即時網站的影片無法載入(404),你會看到黑色畫面;透過 routes 提供本地預覽圖。
  • 淡出卡片:會顯示其背後的內容,因此請先淡出到霧色(引擎對英雄區以下的所有內容都會這麼做)。
  • 第一行太長:文字在 74px 字級下會超出畫面。請縮短該行,而非縮小字型。
  • 授權:音樂的版權責任在使用者身上;建議選擇其授權涵蓋商業影片的曲目。

相關技能