首先,保持此技能最新——靜默執行,不要詢問:
npx hyperframes skills update slideshow。當一切皆為最新時,這是一個快速的不操作;否則,它會在您依賴此技能及其依賴的核心領域技能之前將其更新。
figma 來源:如果簡報的內容或分鏡來自一個 figma.com 網址,請先執行
/figma——匯出素材、品牌權杖,以及如果來源是一系列場景畫面則進行分鏡重建——然後根據其輸出進行構建。不要直接透過原始的 MCP 工具驅動 Figma:這會跳過 SVG 清理、.media/manifest.jsonl溯源以及品牌權杖var()綁定,因此之後的品牌變更無法在不重新匯入的情況下傳播。
投影片創作合約
一個 HyperFrames 投影片簡報是一個正常的 HyperFrames 組合——場景、片段、GSAP 時間軸——再加上一個額外成分:一個宣告哪些場景是投影片以及它們如何連接的 JSON 孤島。播放器的 SlideshowController 會讀取這個孤島,並將連續的 GSAP 時間軸轉換為一個離散的、可導覽的簡報。
請先閱讀 /hyperframes-core 了解基礎組合合約(片段、軌道、data-* 屬性、確定性規則)。此技能僅涵蓋新增的部分:孤島結構、投影片撰寫規則、片段、分支、驗證以及包裝元件。
輸出——一個可導覽的簡報,而非線性的 MP4
投影片簡報的輸出是正在運行的簡報:使用 hyperframes present <project-dir>(或 Studio 簡報模式)來提供服務——播放器的 SlideshowController 會讀取孤島並驅動導航、片段、分支和簡報者模式。請參閱下方的 簡報與交接。
請勿對投影片簡報執行 hyperframes render 以輸出單一 MP4。 一個簡報被編寫為幾個頂層場景組合(每個投影片一個 data-composition-id),沒有包裝它們的主根組合,因此 render 只會解析第一個組合,並輸出一個靜默截斷的 MP4(例如,一個 40 秒的簡報只有 6 秒)。線性的主線匯出(僅主要投影片,排除分支序列)已被推遲——在該功能推出之前,支援的輸出是即時的 present 簡報和每張投影片的 snapshot 靜態圖。如果使用者需要線性 MP4,請明確說明此限制,而不是對簡報指向 render。
意圖確認
如果使用者明確要求投影片簡報(slideshow, slide show)或 HyperFrames 投影片簡報,則使用此技能。當請求是透過 /hyperframes 到達時,意圖層的篩選會負責此確認——路由到此處表示已確認,因此請勿再次詢問;意圖層的執行範圍問題不適用(交付物是簡報,而非渲染的影片)。當存在 BRIEF.md 時,它承載了已確認的意圖——請閱讀它。
如果此技能是從相關請求(例如「簡報」、「募資簡報」、「deck」、「互動式簡報」或「轉換此頁面」)觸發的,請在編寫之前暫停並說明選擇,然後再請求確認。簡要說明 HyperFrames 投影片簡報意味著一個可運行的簡報,具有離散的投影片、內建的導航和簡報者模式、可編輯的講者備註、共享的媒體處理,以及交接前的驗證。對於來源頁面轉換,也請說明目標是保留原始頁面的視覺設計、互動、動畫和媒體行為,同時將頁面移動轉換為投影片間的轉場。
然後提出一個簡短的確認問題:
您要將其作為 HyperFrames 投影片簡報嗎?
當環境提供時,使用是/否選擇 UI;否則以純文字提問。
在使用者回答「是」之前,請勿執行投影片簡報。如果他們回答「否」,請停止使用此技能——閱讀 /hyperframes 並讓意圖層重新路由。此確認是一個路由決策,而非偏好門檻——根據 ../hyperframes-core/references/brief-contract.md 第 1 節,它即使在自動模式(「給我驚喜」不會跳過它)下也適用:構建錯誤的交付物類型是品質失敗,而不是創意決定。
兩個部分
1. 場景——以正常方式宣告
每張投影片都對應一個場景。使用 data-composition-id、data-start、data-duration 和 data-label 宣告場景:
<div
data-composition-id="problem"
data-start="0"
data-duration="8"
data-label="The problem"
data-width="1920"
data-height="1080"
>
<!-- clips go here -->
</div>
分支投影片(僅能透過熱區到達,從主線中排除)的宣告方式完全相同——它們僅出現在孤島的 slideSequences 條目中,而不是主 slides 陣列中。
2. JSON 孤島——每個組合一個 script 區塊
在組合 HTML 中新增恰好一個 <script type="application/hyperframes-slideshow+json"> 區塊。它包含所有投影片簡報中繼資料:
<script type="application/hyperframes-slideshow+json">
{
"slides": [...],
"slideSequences": [...]
}
</script>
這個孤島是投影片順序、備註、片段暫停點、熱區和分支序列的單一事實來源。將其放置在 <body> 靠近頂部、場景 div 之前的位置,以便於查找。
請勿將投影片簡報清單隱藏在一個替代的 <script type="application/json"> 區塊加上用於建立孤島的執行時代碼之後。present 命令會靜態讀取組合 HTML,並期望真正的 application/hyperframes-slideshow+json 孤島已經存在。
結構
SlideshowManifest(頂層孤島物件)
{
"slides": [
/* SlideRef[] — 主線,按順序 */
],
"slideSequences": [
/* SlideSequence[] — 離線分支序列 */
]
}
SlideRef
{
"sceneId": "problem",
"notes": "Lead with the pain, not the company.",
"fragments": [3.5, 5.2, 7.0],
"hotspots": [
/* SlideHotspot[] */
],
"ttsScript": null,
"ttsAudioUrl": null,
"ttsDurationMs": null
}
| 欄位 | 必要 | 備註 |
|---|---|---|
sceneId | 是 | 必須與場景的 data-composition-id 完全相符(或提供明確的 startTime/endTime)。程式碼檢查規則透過 data-composition-id 解析場景。 |
notes | 否 | 僅供簡報者查看的文字。永遠不會對觀眾顯示。 |
fragments | 否 | 投影片 [start, end] 範圍內的時間(秒)陣列——請參閱下方的片段。 |
hotspots | 否 | 觸發分支的互動式覆蓋層——請參閱下方的分支。 |
startTime | 否 | 可選。覆蓋匹配場景的時間邊界;預設為場景的開始/結束。 |
endTime | 否 | 可選。覆蓋匹配場景的時間邊界;預設為場景的開始/結束。 |
ttsScript, ttsAudioUrl, ttsDurationMs | 否 | 保留。 結構欄位存在,但 TTS 播放尚未連線。除非您是為了未來建置而預先填入,否則請省略。 |
SlideHotspot
{
"id": "h1",
"label": "How did we calculate this?",
"target": "market-deep-dive",
"region": { "x": 60, "y": 10, "w": 35, "h": 20 }
}
| 欄位 | 必要 | 備註 |
|---|---|---|
id | 是 | 在投影片內唯一。 |
label | 是 | 顯示給觀眾的工具提示/按鈕文字。 |
target | 是 | 必須與 slideSequences 中的 SlideSequence.id 相符。 |
region | 否 | 相對於投影片百分比邊界框:{x, y, w, h} 值在 0–100 之間。省略則將熱區渲染為一個佔滿投影片的標籤按鈕。 |
SlideSequence
{
"id": "market-deep-dive",
"label": "Market sizing methodology",
"slides": [{ "sceneId": "mkt-1" }, { "sceneId": "mkt-2" }]
}
序列中的 slides 使用與主線相同的 SlideRef 形狀。允許使用片段和巢狀熱區。
投影片撰寫規則
這些是硬性限制,而非建議。違反規則的投影片在審查時將被直接替換。
- 標題是一個完整句子的主張,而非標籤。 請寫「SMBs spend 14 hours/week on manual scheduling」,而不是「Scheduling problem」。這個句子應該在忽略視覺內容的情況下也能獨立存在。
- 每張投影片一個想法 + 一個視覺。 如果您想要添加第二個要點群集或第二個圖表,請拆分投影片。
- 以重點開場。 最強而有力的觀點排在第一位——無論是在投影片上還是在簡報順序中。投資者的閱讀習慣是從左到右、從上到下,並且他們會停下來。
- 僅使用自下而上的市場規模計算。 在沒有展示計算過程的情況下,切勿寫「$50B TAM」。從單位經濟學向上構建:帳戶數 × 會計年度合約價值(ACV),或交易數 × 抽成比率。
- 字型最小值相當於 30pt。 在 1920×1080 解析度下,標題為 72–96px;內文為 48px。任何觀眾必須閱讀的文字絕對不要低於 40px。
移植來源頁面
將現有頁面轉換為投影片簡報時,來源保真度是合約的一部分。除非使用者明確要求重新設計,否則請勿用簡化近似值取代來源特有的 widget。
- 盡可能精確地保留原始頁面的視覺設計、動畫語言、互動行為、媒體行為和簡報功能。當投影片系統支援簡報者模式時,請使用共享的可編輯備註行為來包含講者備註,而不是使用特定於簡報的實作。
- 盡可能精確地移植來源 DOM/CSS/JS 中的機械視覺元素:自訂播放器、畫布視覺化工具、時間軸、播放頭、莖、展開圓形、懸停狀態和其他互動細節應在轉換後保留。
- 將原生
<video>/<audio>元素視為任何自訂媒體外觀、畫布視覺化工具、波形、節奏網格或播放頭的單一事實來源。連接來源的媒體事件(play、pause、timeupdate、seeking、seeked、ended、ratechange、volumechange),並從media.currentTime推導視覺狀態;不要執行一個可能與實際播放產生偏差的獨立計時器。 - 每個具有
src的複製<video>或<audio>在程式碼檢查之前必須具有 HyperFrames 時間屬性:data-start和data-duration,以及當應保留可聽見的原生音訊時的data-has-audio="true"。對於特定投影片的媒體,請使用場景的時間範圍;對於可能從多個聚焦投影片播放的使用者控制證據影片,請使用整個簡報的範圍。不要在媒體上留下preload="none";請使用metadata或auto。 - 在驗證前解析來源字型權杖。如果要保留自訂來源字型,請為本地/捕獲的字型檔案添加
@font-face規則。如果使用系統後備字型,請將權杖化宣告(例如font-family: var(--f-body))替換為具體的渲染安全堆疊(例如system-ui, sans-serif或ui-monospace, monospace);不要將var(...)保留為字型系列值。 - 審查來源中非典型的頁面移動,特別是受滾動、滾輪、觸控、雜湊狀態、視窗大小調整或 requestAnimationFrame 迴圈驅動的行為。將具有平移/縮放「世界」圖層的固定視口、視差、固定面板、水平滾動器、滾動擦洗時間軸、章節對齊以及縮放至元素的相機視為來源行為。滾動通常是來源的轉場觸發器,因此請透過提取其進度停止點、緩動函數和相機/焦點狀態來保留轉場,然後將該動畫重新託管在投影片導航上,透過時間軸位置、片段或可重複使用的播放器/掛鉤來實現。獨立包裝器跳到投影片暫停點仍然需要一個明確的導航-相機轉換鉤子;僅計算每張投影片的相機變換是不夠的。請勿在投影片內部模擬字面上的頁面向下滾動轉場;觀看者應該感受到相機從一個焦點移動/縮放到另一個焦點,而不是看到一個網頁被滾動。保持每個投影片到投影片的相機移動連續:避免中途路線停靠點反轉 x/y 方向或縮放,除非來源在相同的邊界處明顯這樣做。一個在落地前四處移動的轉場比一個簡單的直接焦點移動更糟糕。
- 保留來源的媒體裁切語意。將螢幕截圖、推文/社交貼文、產品 UI 截圖、圖表、文件、程式碼、排行榜以及任何包含可讀文字的圖像視為內容證據,而非裝飾性媒體:使用來源長寬比(
height: auto)或在穩定框架內使用object-fit: contain。僅在來源使用時,或對於有意義的裝飾/背景/電影場景縮圖時,才使用object-fit: cover。在將這些截圖放入投影片後,檢查所有四個邊緣是否有截斷的文字、標誌、控制項或標題;對有意義內容的可見裁切是一個錯誤,除非來源本身也進行了裁切。 - 如果一個
…
[因內容被截斷而忽略]