longtake 是做什麼的?
基於 Patrick 的 onetake,針對垂直(9:16)短視頻平台進行修改。 變更內容與原因:
CHANGES.md。垂直方法:references/vertical.md。
關於產品的短動效影片,由產品本身構建而成。它不是影片編輯器,也不是幻燈片生成器:而是一個組合(一個 HTML 檔案,window.__seek(t))、一個動作庫(lib/motion.js)、從真實事物錄製的素材、一個共用同一空間的聲音調色盤,以及一個預言機,可在人類觀看之前判斷剪輯是否有節奏感、是否具有承接性。
六部影片教會了它。motion-web 用了三個剪輯版本:第一個和第二個因為「PPT 式一個一個展示」而被否決,原因是節奏均勻 — 這是節奏的一半問題。Pocket Weather Club 有節奏,但仍然是 PPT:它的 v1 通過了所有節奏檢查卻被否決,因為每個節拍都取代了前一個。v3 在每個節拍都從前一個節拍生長出來後才被接受 — 角色降落在標題上,頁面從其卡片中長出,一個舞台從角色中打開。這是承接的另一半。One dot 加入了操作者:使用靜止攝影機時,結果是「就缺靈動的跟踪運鏡」;使用追逐每個節拍所框定畫面(滯後、傾斜、穩定)的攝影機後,結果是「運鏡、鏡頭和物理都沒問題」。knockon 透過因果關係承接:一個輕型桌面機器,每個節拍都是引發下一個節拍的碰撞。clearing 透過規模承接:一個鏡頭從一年到空閒的半小時再返回,攝影機追逐螢幕上的錨點,使其在 1 倍和 300 倍時都能穩定定位。overlap 是關於意義的教訓:它的第一個剪輯版本是「美術挺棒但沒看出來啥意思」,加入標籤化的游標後變得更糟;只有在將概念嵌入藝術作品本身後(一個隱藏在兩個噪點板中的 & 符號,在通道對齊的瞬間出現)才被理解。這裡的一切都是為了讓下一部影片能從這些影片結束的地方開始。
協議無法提供的內容(請先閱讀)
以下規則主要是被否決的原因的記錄:它們防止影片變成幻燈片。它們是基礎門檻。一部影片可以通過所有規則和所有預言機的評估,但仍然死氣沉沉 — W1(一個垂直宣傳片,2026-11)就是如此:承接度 1.00,判定「通過」,但最終判定是「很死板,沒到參考片的 70%」。它缺少的是那些被接受的影片所擁有的東西:
- 每個節拍中都有值得觀看的素材。 Onetake 發布片(常見的參考片)是 v8:三個提示,每個都變成一個完整的、擁有自己調色盤和動作語言的設計短片。觀眾觀看的是作品,而不是關於作品的標籤。首先問:我們擁有最美麗的東西是什麼(素材、完成的影片、真實 UI)?基於這些,用全螢幕構建影片。用卡片和晶片解釋過程的概念是圖表,而移動得很好的圖表仍然是圖表。
- 一個時鐘。 每個強大的案例都會跟隨音樂網格進行剪輯 — 在重拍上發送,在 Drop 處進行最快速的部分,在靜止的節拍上停止。沒有旁白時,音樂就是時間線,而不是裝飾。根據「足夠長到可以閱讀」來定時節拍會產生均勻的節奏,看起來僵硬。如果使用者的專案禁止使用音樂,請說明這會造成的損失並提出詢問。
- 一個故事弧線。 密度和速度向一個高峰發展,然後釋放。五個相等的站點就是一個列表。
- 將變化作為內容。 在參考片中,事物本身會轉變(視窗重新排列成手機,橫條打開變成影片)。僅在靜態節拍之間移動的動畫是過渡環繞的幻燈片。
- 多輪審視。 參考片經過八次審查剪輯。在首次渲染之前展示鉤子和高峰的靜止畫面,在拋光之前展示草稿;切勿將一個未經審查的版本作為最終版本呈現。
何時使用此技能,何時不使用
- 為應用程式、頁面、技能、功能製作的發布/預告/介紹短片 — 是。
- 有旁白的功能展示(30–60 秒),展示產品正在被使用,可能包含多種語言 — 是:重建 UI 而不是錄製它(§4,
references/product-demo.md)。 - 使用者有一個他們想要感覺的參考短片 — 是,從 §1 開始。
- 長篇、談話性節目、編輯現有素材並加入轉場 — 否。
- 使用者明確提到了 HyperFrames 或 Remotion — 使用他們命名的工具。否則使用此流程。
協議 — 按此順序執行,不得跳過
1 · 在接觸任何東西之前解構參考片(硬規則)
python3 scripts/analyze_ref.py ref.mp4 --out ana/ # 能量圖、剪輯、靜止度、聯絡表、運動線
閱讀能量圖和靜止畫面,並寫下影片必須匹配的數字。能量圖說明了影片在何時移動;motion: 行說明了如何移動 — 中位數 t80(快照或 S 曲線)和動態模糊(渲染時是否帶有運動模糊)。決定 motion-web 影片的因素:參考片34 % 完全靜止,有7 次硬剪輯分佈在兩個爆發點,並且保持每個元素很小且帶有大量留白。這些都不是觀看一次就能明顯看出來的,而未經測量就構建的影片出現了兩次均勻的節奏。references/reference-deconstruction.md。
參考片的數字優先於下面的類型規則。「小元素,大空間」和「三分之一時間靜止」是從 motion-web 測量得出的。Onetake 發布片大約有 10% 的靜止時間且大部分是滿框;W1 遵循了針對它的類型規則(靜止 0.50,空白空間),結果變得空洞而緩慢。記錄靜止百分比、畫面填充比例、剪輯次數以及最密集片段的位置,並匹配這些。同時注意參考片的節拍是由什麼構成的(完成的設計片段?真實 UI?文字?)以及它是否跟隨音樂剪輯 — 這是 §2 的輸入。
2 · 概念 — 在任何節拍表之前,三個核心想法(硬規則)
一個概念是關於畫面的一句話,而不是關於產品:構成影片的單一想法。寫三個在想法上不同的概念 — 而不是用相同卡片講述的三個故事:
- 一個元素貫穿所有內容進行轉化 — 一個點是游標,分裂成技能列表,空心化成加載環,展開成彈簧曲線,最終作為單詞標誌中 i 上的點落下;
- 一個跨越縮放比例的攝影機移動 — 從游標內部開始,拉出到輸入框,穿過發送按鈕進入作品,從完成的影片中出來(
cases/clearing-15s:一年 → 一天 → 半小時 → 返回); - 一個前/後分割 — 左側是幻燈片風格的相同節拍,右側是承接的節拍,直到右側打破到左側;
- 一個連鎖反應 — 每個節拍都是引發下一個節拍的碰撞(
cases/knockon-15s); - 或者一個物理隱喻、一個連續的表面、一個文字系統…
對於每個概念:鉤子畫面、承接每個邊界的方式、它排除了什麼(沒有卡片?沒有剪輯?),以及它的外觀 — 來自 looks/ 的預設(python3 scripts/look.py sheet → gallery/sheets/looks.png:紙、黃昏、桌面、群青、Riso、餘燼,每個都從一部被接受的影片中測量得出)、產品自己的顏色(look.py from-shot shots/*.png --out look.json),或者為此影片專門製作的外觀。讓使用者選擇三個概念。模板的故事 — 動態文字 → 打字提示 → 勾選清單 → 結果 → 斷奏節拍 → 黑色文字標誌 — 只是一個概念,永遠不是預設:一個基於它的操作演示通過了所有預言機評估(承接度 1.00),但被退回,理由是「和 motion web 很像…沒有創造力」。上面列表中的範例以及每個案例也是如此:選擇「one dot」因為它是第一個範例是在複製,而不是一個概念(W1 就是這麼做的,結果看起來像圖表)。用兩個問題測試每個概念:在畫面最繁忙的那一秒,觀看者在看什麼?(它必須是美麗的東西,而不是一個標籤)以及事物本身會變成什麼?
垂直(9:16)影片不是旋轉的橫向影片:畫面是一個高柱,所以要從上到下填充,讓素材溢出邊緣,並保持平台的安全區域(字幕和按鈕覆蓋底部約 20% 和右邊緣)。stills.py --width 1080 --height 1920 在其靜止畫面中保持寬高比。方法,包括嵌套式入口潛入及其數字:references/vertical.md,案例 cases/huazhong-dongtian-22s/。
3 · 將故事板作為節奏 和 承接
將所選概念寫成節拍表:t · 節拍 · 移動什麼 · 靜止什麼 · 承接什麼到下一節拍。
節奏。 變化鏡頭長度,相差 ≥ 4 倍(0.25 秒的文字與 2.5 秒的停頓交替)。至少有一段在畫面和聲音上都接近靜止。一個故事 — 概念的故事 — 而不是目錄。元素大小和空間遵循參考片(§1)。
弧線和時鐘。 在節拍表之前選擇音樂,找到它的重拍、靜音間隙和 Drop(scripts/beat_grid.py),並將表格中的每個 t 寫成該曲目的一個節拍。畫面的高峰應位於 Drop 處。
承接。 在每個章節邊界,命名存活下來並移動的事物:手、主體、一個成為下一個場景的容器(morphRect)、一個從主體打開的舞台(iris)、一個推入卡片直到其成為場景的攝影機(zoomThrough)、一個折疊成最終標誌的演員陣容(gather → seal)。如果沒有事物存活下來,那就是幻燈片切換,無論節奏如何。裸剪輯屬於打擊樂的爆發和結束卡片,當概念需要它們時。references/rhythm.md。
4 · 來自真實事物的素材 — 或從截圖重建的 UI
python3 scripts/record_footage.py footage.json --out footage/
由 Playwright 即時驅動的真實頁面(以牆上時鐘速度進行的滑動、滾輪步驟、點擊),以你將要顯示的大小錄製,並在輸入開始的瞬間注入品紅色標記,以便之後可以找到動作影格。影格以 30 fps 的 JPEG 格式輸出;指針路徑被保存下來,以便組合可以重新繪製手部 — 觀看者必須看到原因,而不僅僅是效果。配置格式在腳本的 docstring 中。
或者重建它。 當影片逐步展示應用程式的功能時(尤其當它包含語音或其他語言時),使用者只截圖或錄製參考鏡頭,而 UI 則在參考片本身的像素影格中用 HTML 重建。每個字串都存放在一個表格中,每個狀態都由一個純 set(state) 函數寫入,而副本則放置在攝影機可以任意縮放逼近的平面上。高亮從其 DOM 測量(lib/ui_kit.js)。旁白來自 scripts/vo_tools.py:試聽、台詞、單詞時間、字幕。第二語言是同一組合上的 ?lang=,其 VO 通過 UIK.timeWarp 在意思相同的單詞上映射到作者的時間線,並使用 scripts/frame_diff.py 檢查來源語言是否像素一致。內容保持產品的真實輸出。方法、數字及相關細節:references/product-demo.md。這是一種技術,而不是一種外觀:調色盤、舞台、攝影機語法和轉場在每次 §2 中都重新選定。
5 · 組合 — 單個檔案、時間的純函數、來自庫的動作
mkdir -p cases/my-film && cp templates/comp.html lib/motion.js cases/my-film/ # 模板加載 motion.js → window.OM
python3 scripts/probe.py my-film/comp.html # 只要它能完整播放:每個邊界承接什麼,每個動作的曲線
通過查看 gallery/sheets/<move>.png 來選擇動作 — 在動作的速度曲線上的六個影格。庫中有 39 個動作:入場、承接、接觸和實時模擬、攝影機及其投影輔助,以及一個流體集(光場、漣漪、絲綢、皮帶、SwiftUI 彈簧);每個都是返回 DOM 變換或 Canvas 調用所需數字的時間函數。永遠不要用固定常數重新推導彈簧或緩動。模板是 motion-web 影片(動態文字、打字提示、勾選清單、飛越、實時模擬、停頓、斷奏節拍、每個模擬都讀取的一個連續手部路徑) — 僅當在 §2 中選擇了該概念時才複製它的節拍;否則保留它的合約和輔助函數,並撰寫概念自己的節拍。一切都是 f(t);模擬預先以 240 Hz 模擬一次然後取樣。預覽使用 ?play,定格使用 ?t=6.4&hud。references/motion-library.md,references/composition.md。
外觀隨組合一起交付。 python3 scripts/look.py apply ember cases/my-film/comp.html(或一個 look.json)在其旁邊寫入 look.js:八種顏色作為 CSS 變數和 LOOK.color,三個 OFL 字型子集化為組合所使用的字符並內聯,以便在 file:// 渲染時獲得真實文字。在組合腳本之前加載它,對照 var(--ink) / var(--display) 或 LOOK.font('display', 96) 編寫,並在 LOOK.ready 上鏈接 window.__ready。在文案更改後重新運行它;它會命名任何字型缺少的字符(中文/日文/韓文使用 --cjk <font>)。
攝影機:關鍵幀設定,但需要操作。 OM.camera(t, keys) 將攝影機放在每個節拍需要的地方;操作員的感覺來自於關鍵幀的放置方式:將主體關鍵幀設定在大約 0.1 秒前的 sineInOut 以跟隨它,將著陸點關鍵幀設定在快照之前的 expoInOut 以甩到該點,添加一隻手(一個緩慢的雙正弦浮動,在停頓時歸零)和 OM.shake 在每個著陸點。在更遠的地方繪製一個模糊的 OM.lattice,否則在空白空間上,移動無法被感知。使用攝影機時,__track 返回螢幕框(OM.projectBox),__motion 將移動路徑傳遞給 render.py,而 __meta.inFrame 指定了永遠不能離開影格的內容。方法,代碼:references/composition.md → 攝影機。
6 · 渲染 — 通過後才輸出 1080p30 草稿,4K60
python3 scripts/stills.py comp.html --times 0.7,2.4,3.8,6.2,9.9,12.7 --out stills.png # 先看再渲染
python3 scripts/render.py comp.html --out draft.mp4 --sfx sfx.wav # 1920×1080 · 30 fps · 180° 快門
python3 scripts/render.py comp.html --out film.mp4 --final --sfx sfx.wav # 3840×2160 · 60 fps,一旦剪輯被接受才執行
快門是真實的動態模糊:每個移動的影格是在快門打開期間多次尋求的平均值,在線性光中平均;會檢測停頓並跳過它。捕獲是 Chrome 的螢幕截圖(約 150 毫秒;頁面本身在 1 毫秒內繪製),因此 render.py 在多個瀏覽器中並行運行 --workers(預設為核心數減 2,最多 8 個)。