短影音垂直影片(Hyperframes)
短影音 = 1080x1920 垂直、10–30 秒、談話頭人臉 + 動態圖形場景疊加 + 卡拉OK字幕。此技能中的所有內容均提煉自 May Shorts 19 迭代屍檢報告(v1 → v4),並應應用於每個新的短影音。
務必先調用 /hyperframes。 此技能建立在它之上——它不會取代框架規則(data-* 屬性、window.__timelines、合成結構)。無論格式為何,這些規則都是不可協商的。
觸發時機
- 「製作一個短影音」、「TikTok 貼文」、「Reels」、「Shorts」、「垂直影片」
- 任何從談話頭錄影 + 腳本/逐字稿開始,目標為社群媒體的建置
- 重新定時、重新剪輯或重新同步現有的短影音
- 為旁白添加同步的卡拉OK字幕
攻略(高層級)
- 音訊是真理的來源。 先編輯音訊(剪掉重錄、停頓)。另存為
<名稱>-edit.mp4。使用ffprobe測量精確長度——這就是合成的data-duration。 - 轉錄編輯後的音訊,使用
npx hyperframes transcribe <edit>.mp4 --model small.en --json;或者,如果重新定時一個已有字幕的現有項目,且字幕中具有shift()函數,則保留現有字幕,僅移動場景起始點。 - 在編輯時間中設定場景邊界——絕不在同一檔案中混用原始時間與編輯時間錨點。請參閱下方「音訊同步協議」。
- 建構合成骨架(4 個圖層:環境背景、接縫處理、字幕、人臉)——請參閱下方「合成骨架」。
- 使用相對於每個場景
data-start的 LOCAL 偏移量來編寫場景。每個場景都是其在compositions/scene<N>-<標籤>.html下的子合成。 - 檢查 → 草稿渲染 → 逐字影格驗證 → 最終渲染。 這是驗證關卡。絕不跳過步驟 3(影格驗證)。
合成骨架(4 個永遠開啟的圖層)
每個短影音垂直影片在 compositions/ 下都有這四個子合成,載入到共享軌道:
index.html (根節點, 1080x1920, data-composition-id="main")
├── ambient-bg.html track-index="3" — 徑向漸層 + 漂移網格 + 粒子 + 暗角
├── face-wrapper + <video> track-index="0" — 談話頭(請參閱人臉模式編排)
├── seam-treatment.html track-index="5" — 羽化 y=960 邊緣(僅限下半部場景)
├── scene1-<標籤>.html track-index="1" — 場景疊加(連續接續,無間隙)
├── scene2-<標籤>.html track-index="1"
├── …
└── captions.html track-index="2" — 卡拉OK字幕,逐字同步
data-duration在根節點、環境背景、接縫處理、人臉影片、人臉音訊、字幕中完全相同。只有場景疊加會隨時間變化。- 人臉的
<audio>是一個單獨的元素(混音器需要它),絕不使用影片本身的音軌。 class="clip"放在定時 div 上——絕不放在<video>或<audio>上。
人臉模式編排(短影音的招牌動作)
人臉位於一個包裝 div 中,其大小為來源的原始橫向尺寸(1920x1080)。GSAP 動畫操作的是包裝器(絕不操作影片元素——操作 <video> 尺寸會凍結影格)。
兩種模式:
const BOTTOM = { x: 0, y: 1136, scale: 0.5625 }; // 下半部,完整橫向內容可見
const FULLSCREEN = { x: -1166.5, y: 0, scale: 1.7778 }; // 裁切覆蓋,填滿 1080x1920
const MODE_DUR = 0.32;
BOTTOM 將 1920x1080 的來源渲染為 1080x607.5,置於底部 960px 區域的中間。FULLSCREEN 水平裁切以填滿直式影格。
在新場景內容出現前 0.15 秒進行過渡,使用 ease: "expo.inOut":
[
{ t: <scene-4-start>, mode: FULLSCREEN },
{ t: <scene-5-start>, mode: BOTTOM },
…
].forEach(({ t, mode }) => {
mainTl.to("#face-wrapper", { ...mode, duration: MODE_DUR, ease: "expo.inOut" }, t - 0.15);
});
瞬間切換模式的人臉是垂直影片中最突兀的影格。務必進行插值。
人臉調色(每個短影音,無例外)
#face-video {
filter: contrast(1.08) saturate(1.08) brightness(0.97);
}
再加上一個在整個持續時間內從 1.00 到 1.025 的細微 Ken Burns 縮放效果(ease: "none")和一個側邊暗角 ::after 偽元素,使人臉融入周圍的海軍藍,而不是與銳利的邊緣相接。
接縫處理(下半部場景必需)
在 y=960 處有一條海軍藍到透明的漸層帶(60–100px),外加一條帶柔和發光的 2px 強調掃描線。在人臉之後繪製它,使其位於頂部;全螢幕場景在接管時會將其覆蓋。銳利的 y=960 切割是 AI 編輯內容的第二大破綻(僅次於背景平坦度)。
音訊同步協議(不可跳過)
問題: 如果音訊已被編輯(移除了重錄/停頓),則來源逐字稿中的時間戳將不再與編輯後的影片匹配。以原始時間設定的場景起始點將會延遲觸發。
規則: 所有時間都基於編輯時間。絕不混用。
任何短影音重新定時的驗證程序:
- 測量兩個音訊檔案:
差值 = 總剪掉時間。ffprobe -v error -show_entries format=duration -of csv=p=0 assets/original.mp4 ffprobe -v error -show_entries format=duration -of csv=p=0 assets/<名稱>-edit.mp4 - 如果在
captions.html中使用shift()函數來對應逐字稿單詞,則將其視為真理來源。shift(originalTime) = editedTime的對應關係也適用於每個場景的data-start。 - 場景內部偏移量(在
compositions/sceneN.html內)是相對於場景data-start的 LOCAL。如果場景的父級data-start在編輯時間中是正確的,則內部偏移量無需修改即可保持正確——除非一個場景跨越了一個剪輯點,在這種情況下,父級持續時間和內部偏移量都會改變。 - 人臉模式過渡陣列時間必須使用編輯時間。它們不會自動偏移。
重新定時的計劃格式(每次使用此表格結構):
| 場景 | 目前起始 | 目前時長 | 新起始 | 新時長 | 理由 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
然後是人臉模式陣列,接著是任何內部偏移量變更,最後是影格驗證清單。
場景編寫
一個場景 = 一個子合成檔案。場景位於同一個 data-track-index 上,連續接續(無間隙)。在每個場景內部:
data-duration與父層級的時間槽完全匹配- 所有 GSAP 錨點都是 LOCAL(從場景起始點開始為 0)
- 使用
tl.set({}, {}, <data-duration>)來填充時間軸,使 GSAPtl.duration()與data-duration匹配
場景節奏規則(來自 10 項原則)
- 無空白影格。 每 100 毫秒至少有 1 個元素在動畫中。將首次入場偏移 0.1–0.3 秒,而非 t=0。
- 重點展示 ≥ 1 秒停留。 場景的「大揭曉」(圖章、數字鎖定、笑點)必須在畫面上停留 ≥ 1 秒,理想為 1.5 秒。根據展現時間而非總時間來預算場景。
- 貫穿整個持續時間的動態。 如果所有入場動畫在一個 4 秒場景的本地時間 2 秒處都已結束,則添加次要動態:底線掃描、勾勾彈出、卡片上的環境漂移、藥丸形狀上的細微振盪發光。死寂節奏 = 滑走。
- 變化緩動函數。 每個場景在不同入場動畫中至少使用 3 種不同的緩動函數。
- 每 5 秒運行時間有一個令人驚嘆的效果。 字體重擊、故障/色差揭示、甩鏡、音訊同步重擊。沒有這些,影片讀起來就像「標籤化的談話頭」——正確但令人難忘。
字幕(卡拉OK 風格)
- Montserrat 900,46–58px(適用於 1080 寬度),100% 白色基底
- 活躍單詞:scale-1.08 彈出 + 顏色變為強調色(AIS 使用
#37bdf8,根據品牌調整) - 透過分層的
text-shadow實現描邊,絕不使用-webkit-text-stroke(在 Chromium 渲染中不一致) - 移除 rgba 背景藥丸——讓描邊來保持可讀性。字幕應像框架上的塗鴉,而非字幕軌道。
- 對於重新定時,在
captions.html內部使用shift()函數來將逐字稿單詞時間戳對應到編輯時間。這使逐字稿 JSON 保持不變,並使重新定時變得機械化。
完整的卡拉OK 實作請參閱 /hyperframes 下的 references/captions.md。簡而言之:每個單詞的 <span> 元素帶有 data-word-start,GSAP 補間作用於每個跨度,緊湊的 0.08–0.12 秒彈出持續時間。
環境背景(絕不輸出純海軍藍)
最小可行的背景堆疊:
- 徑向漸層基底(中心比邊緣亮 15–20%)
- 動態噪點/顆粒疊加,透明度 8–12%
- 4–8 個漂移粒子點或網格軌跡
- 細微暗角
background: #07121c 單獨使用只是一個佔位符,而非設計。對於科技感/控制室美學,使用 feedback_techy_background_layers.md 中的 6 層堆疊(HUD 網格遮罩到暗角 + 電路軌跡 + 脈衝節點 + 掃描光束 + 遙測字幕 + 角落單色標籤)。
音訊反應性
- 標題隨節拍脈衝 3–6%。背景在低音部分可達 10–30%。
- 文字反應性保持細微(3–6%),以便字幕保持可讀性;背景可以推得更用力。
- 使用一個設定了 SEED 的離線分析器(預先計算音訊特徵軌道),使渲染結果具有確定性。請勿在渲染路徑中使用
AnalyserNode——Math.random()和即時音訊節點會破壞確定性。
轉場
- 輪換風格。 沒有兩個相鄰的轉場是相同類型。連續六次硬切是 AI 編輯的第一大破綻。
- 人臉模式過渡(
BOTTOM ↔ FULLSCREEN)在模式於場景之間變化時,可兼作場景轉場。 - 對於純疊加場景到場景,從註冊庫安裝:
push-up、flash-through-white、sdf-iris或完整的著色器轉場包。執行npx hyperframes catalog --type block瀏覽。
驗證關卡(強制執行——未經確認不可發布)
檢查通過 ≠ 設計有效。在您從逐字精確時間戳提取影格並讀取每個 PNG 之前,絕不報告短影音渲染完成。
步驟 1 — 草稿渲染
cd video-projects/<slug>
npx hyperframes lint
npx hyperframes render --quality draft --output renders/<slug>-vN-draft.mp4
步驟 2 — 逐字影格提取
挑選 8–15 個時間戳,每個時間戳對應一個口語單詞,並且在該時間點應該有一個特定的視覺元素在畫面上。不要取整數。不要取場景中間。要精確到單詞。
mkdir -p renders/frames-vN
for pair in "<t>:<label>" "<t>:<label>" ...; do
t="${pair%%:*}"; label="${pair##*:}"
ffmpeg -y -ss "$t" -i renders/<slug>-vN-draft.mp4 \
-frames:v 1 -q:v 2 "renders/frames-vN/t${t}-${label}.png"
done
步驟 3 — 讀取每個 PNG
對每個 PNG 調用 Read,以便將圖像載入到上下文中。不要只列出檔名。對於每個影格確認:
- 預期的視覺元素在預期的時刻顯示在畫面上(不是晚 1 秒,也不是提早)
- 在任何下半部場景中,說話者的臉部都沒有被裁切
- 全螢幕 vs 下半部人臉模式對於該場景是正確的
- 字幕符合品牌形象、可讀、未溢出
- 無空白影格、無意外重疊、無文字超出畫布
步驟 4 — 如果任何項目失敗,修正並重新驗證。絕不發布有問題的內容。
步驟 5 — 最終渲染
npx hyperframes render --quality standard --output renders/<slug>-vN.mp4
從最終渲染中抽查 3–4 個影格(相同時間戳,不同資料夾 frames-vN-final/),以確認標準品質編碼沒有改變任何內容。
11 條規則(品質檢查清單——在首次草稿前執行)
每個短影音建置。在編寫過程中執行此清單,而非之後。
- 無空白影格。 每 100 毫秒有一個正在動畫的元素。
- 場景重點展示 ≥ 1 秒停留。 根據展現時間而非總時間預算。
- 人臉是一個角色。 調色 + Ken Burns 效果 + 側邊暗角。
- 無硬接縫。 使用漸層 + 掃描線羽化 y=960。
- 每 5 秒一個令人驚嘆的效果。 字體重擊、故障、甩鏡、音訊重擊。
- 音訊反應性不可協商。 文字 3–6%,背景 10–30%。
- 輪換轉場風格。 沒有兩個相鄰的相同。
- 字幕要突出,而非禮貌地標註。 使用描邊而非藥丸形狀。活躍單詞使用縮放 + 顏色。
- 貫穿整個場景持續時間的動態。 如果入場動畫提早結束,則使用次要動態。
- 背景是一個圖層,而非一種顏色。 至少需要徑向 + 噪點 + 粒子 + 暗角。
- 重擊/圖章疊加在目標文字完全可見之後才出現。 揭示邏輯 > 單詞同步。圖章
t≥ 目標可見t+ 0.10–0.25 秒。否則,笑點會在鋪墊之前出現。
專案結構(每個短影音專案)
video-projects/<slug>/
├── hyperframes.json
├── meta.json (id, name, 尺寸 1080x1920, fps 30)
├── index.html (根合成, 4 層骨架)
├── compositions/
│ ├── ambient-bg.html
│ ├── seam-treatment.html
│ ├── captions.html (重新定時時包含 shift() 函數)
│ ├── scene1-<標籤>.html
│ ├── scene2-<標籤>.html
│ └── ...
├── assets/
│ ├── <名稱>.mp4 (原始錄影)
│ ├── <名稱>-edit.mp4 (編輯後 — 已移除剪輯 — 合成使用此檔案)
│ ├── transcript.json (whisper 輸出)
│ └── 品牌資產 (logo, brand-tokens.css, 背景音樂)
└── renders/
├── <slug>-v1-draft.mp4
├── frames-v1/
├── <slug>-v1.mp4
└── ...
重新定時協議(當音訊被重新編輯或時間戳漂移時)
- 使用
ffprobe測量新舊編輯後音訊的持續時間。差值 = 總剪掉時間。 - 識別剪輯視窗:哪些秒數被移除,從哪裡移除。
- 編寫計劃表:每個場景的
data-start、data-duration,每個臉部模式過渡的t,以及任何內部偏移量跨越剪輯點的場景。 - 對於每個跨越剪輯點內部偏移量的場景:...(原文此處截斷)