scrapbook-editor:將原始自拍轉為剪貼簿短影音
使用者提供 一段他們自己說話的直式自拍影片。此技能會剪除其中所有停頓,然後將畫面轉變為一個說話者對著說話的剪貼簿,剪輯方式如同動態設計師在 After Effects 中的操作:參考風格的標題使用兩種字體(白色字,重點字則為彩色的漂亮襯線字,並有紙上線條)與貼紙作為鉤子;網路反應迷因會以拍立得形式貼在說話者臉上;僅標題與非常重要的詞彙會使用紙片;紅色馬克筆會隨說話內容畫圖;他們列舉的物品會有對應貼紙;他們提到的真實畫面會顯示出來;字幕低位於畫面中,逐字顯示;配有背景音樂,且每個落地的東西都有對應音效。
此風格已獲驗證(使用者,2026-10-05):請精確複製它。 § 剪貼簿語言(請見下方流程)即是已驗證剪輯的外觀(workspace/videos/scrapbook-dev-sales.mp4,其規劃:example/plan.mjs):在任何輸入影片上,使用相同的圖形、相同的大小與位置、相同的字體、紙片、動態、音效與音量。它始於一個真實編輯的「測量」(一個 72.7 秒的列表影片「7 個 Claude 技能」,由使用者為客戶編輯:example/README.md 是其完整解剖),並經過六次審查才定案(§ 使用者的決定)。init.sh 會建立此架構;切勿發明其他外觀,也切勿偏離使用者未曾要求變更的任何細節。
此技能運行於 short-editor 技能的引擎之上。 其轉錄、渲染、混音、預覽、建置與驗證都是相同的檔案:請閱讀 ../short-editor/SKILL.md § 先決條件、§ 檔案位置 以及 § 4 到 § 6 一次;它們在此處同樣適用,而此檔案僅說明不同之處。在第一次剪輯前,每次運行時請閱讀:
scripts/example/README.md:參考編輯,逐拍分析,以及開發剪輯../../references/pitfalls.md§ 轉錄與字幕、§ 工作方法:編輯中常見的陷阱(其他章節則在需要時閱讀:§ 音訊(在手動測量音效之前)、§ ffmpeg 與 § Shell(在執行自訂指令之前);引擎工具則遵循其餘章節)
在需要特定步驟時閱讀:../../references/audio-spec.md 關於音量(響度標準,以及如何測量聽到的音量)。引擎的數值:node plugins/video/skills/short-editor/scripts/api.mjs <module> [figure],切勿使用其原始來源。
我無法觀看或聆聽影片。 何處有停頓、人臉位置、音效落地音量:每個都是經過測量的(
tighten.py、face.mjs、measure.mjs),然後檢視合成幀(preview.mjs)以及逐幀檢視動態瞬間(build.sh --slice)。verify.mjs是「準備完成」與損毀檔案之間的最後防線。請勿跳過它。
以下所有路徑相對於 GTM by Pipecorn 資料夾的根目錄。$K 代表 plugins/video/skills/scrapbook-editor/scripts(此技能),$E 代表 plugins/video/skills/short-editor/scripts(引擎)。請使用絕對路徑執行兩者。
先決條件(執行前檢查:在任何工作前確認)
引擎所需:PATH 上需有 ffmpeg + ffprobe(brew install ffmpeg)以及 python3(Xcode Command Line Tools);若缺少任一項目,請停止並顯示安裝指令。其他所有項目會自動準備:$K/py.sh 會執行引擎的 bootstrap.mjs(node 套件、語音轉文字虛擬環境與 numpy);init.sh 會將三種字型(Archivo、Fraunces 以及紙張的手寫字體,預設為 Gochi Hand:Google Fonts,OFL)擷取到專案的 assets/fonts/(或在 ~/Library/Fonts 中尋找),而 sounds.mjs 會擷取紙張音效(八個 Mixkit 錄音,每台機器一次,放入 plugins/video/assets/sfx/paper/,不可提交:Mixkit 授權允許在影片中使用,但不允許重新散佈),並將其準備並測量到專案的 assets/sfx-paper/,並從 shelf 複製 Motionix 包(plugins/video/assets/sfx/motionix/,由 explainer 風格準備;套件中未說明授權:在發布任何內容前請閱讀其 README)到 assets/sfx-motionix/。不會安裝任何系統級套件。
選擇性項目,若缺少則會提示(絕不阻擋流程):
swiftc(Xcode Command Line Tools):face.mjs會使用 Apple Vision 尋找臉部,以便拍立得能精準落在臉上,貼紙則環繞頭部。若無此工具,請在預覽幀上讀取臉部位置,並設定 project.json 中的face({x, y, w, h},為畫面的比例)。.env.local中的GIPHY_API_KEY:已驗證風格所需的真實反應 GIF(gif.mjs)。免費:developers.giphy.com → 建立應用程式 → 選擇 API(非 GIPHY 推薦的 SDK;SDK 是用於顯示 GIPHY 自己挑選器的應用程式;gif.mjs是呼叫 API),每小時 100 次呼叫,對編輯工作來說非常充足。若無此金鑰:使用使用者提供的 GIF(media.mjs),或產生的反應圖片;請告知使用者。.env.local中的GEMINI_API_KEY:用於產生的插圖與反應圖片(picture.mjs,Nano Banana 2,1K 解析度約 $0.07 美元)。- /Applications 中的 Google Chrome(或 Chromium、Brave、Edge):用於擷取說話者提到的公開網頁畫面(
capture.mjs),當使用者沒有自己的畫面時使用。
檔案位置
如引擎所述,且只能依此方式:每個編輯一個工作目錄,位於 workspace/projects/<slug>/,slug 不可與其他專案重複;完成檔案為 workspace/videos/<slug>.mp4;即使使用相同的原始影片,也絕不可使用其他專案的檔案;暫存檔案位於專案的 tmp/,絕不可放在 /tmp。技能本身的 scripts/ 目錄保持唯讀。編輯的圖片則位於其 assets/media/ 中。
流程
0. 設定工作目錄
$K/init.sh workspace/projects/<slug> <source.mp4> workspace/videos/<slug>.mp4
引擎的 scaffolding(project.json 從檔案讀取、subs.config.json、cut.mjs),然後是此技能的 plan.mjs 與 edl.mjs(語言中的每個圖形,皆有註解,準備好供填寫)、project.json 中的語言鍵值(style: "scrapbook"、accent、captionKeep)、人臉資訊,以及音效,並根據此原始影片的聲音進行校準(voiceM,語音的瞬時中位數,以及 sfxMasterDb 設為 0:每個角色接著在 LU 中設定於語音之下,如同實際聽到的)。之後所有指令請在此目錄內執行。
0.2. 先詢問,且僅問一個問題
這些資訊屬於使用者,無法自行猜測;請將它們集中在一個 AskUserQuestion 中詢問:
- 音樂。 預設為背景音樂(第三次審查:「它值得加一段背景音樂」):首先提供 Hip Hop 02(Mixkit,Lily J:已驗證剪輯使用的,也是此風格的預設;Mixkit 授權允許在發布的影片中使用),然後是 Convergence(其他風格的內建配樂),以及 shelf 中其他的選項(
plugins/video/assets/music/,及其 README),最後是「無音樂」。若要透過聆聽選擇,可使用一個選單(同一段 12 秒的片段,搭配每首曲目,音量相同):在建置後執行node $K/music-board.mjs --to 12 mixkit-hip-hop-02-738.mp3@0 [email protected] …(它會在最後將專案原本的音樂放回)。音樂音量設置在語音下方 15 LU($K/music.mjs,§ 外觀)。請告知使用者,非 Mixkit 的曲目(Convergence、ridgeclub)可能會阻擋影片的營利。 - 品牌顏色(project.json 中的
accent;若重點字顏色應不同,則為wordColor;若已設定 Your brand 的強調色,則位於workspace/brand/,請參閱plugins/video/references/brand-kit.md§ Your brand,設定一次):Fraunces 字體的重點字,以及正在說的那個字幕字。預設為黃色 #FFD43B(Pipecorn 的)。請在原始影片上檢查:它會覆蓋在頭髮、皮膚和牆壁上(在開發用的原始影片上,珊瑚色和橙色在說話者的頭髮和臉上消失,而黃色則到處都可讀)。以及字幕必須正確書寫的名稱(captionKeep:品牌、產品、人名、「Station F」)。 - 真實素材:他們提到的內容的螢幕截圖或螢幕錄影(他們的產品、儲存庫、頁面)、他們的標誌。若無此素材,會擷取公開頁面(
capture.mjs);絕不發明私人畫面的內容。 - Pipecorn 通用結尾:每個風格的額外功能,每次都詢問,預設不啟用(
plugins/video/references/pipecorn-generic.md):約 6 秒,位於影片最尾端,顯示 Pipecorn,然後其價值觀在一個區域中輪流顯示,最後再次顯示 Pipecorn,無音樂。選項:不要 · 要,並選擇哪些價值觀(1 到 4 個;node $E/generic.mjs --list;預設為電話覆蓋率、連接成功率、管道)。 - 讓您的聲音更好聽:一個額外功能,每次都詢問,預設不啟用(
plugins/video/references/voice-clean.md):ElevenLabs 的聲音隔離器會去除原始影片中的房間迴音和噪音。選項:不要 · 要,讓我的聲音更好聽。此功能需要 ElevenLabs 連接器:若無金鑰,請用一行說明它存在(設定 › 連接器 › 新增金鑰)然後繼續。若選擇「要」,請在步驟 1 之前執行:node plugins/video/motion/voice.mjs clean <source>,然後更新 project.json 中的source為<…>-voice.<ext>(長度相同,畫面不變)。
請從 GTM by Pipecorn 頁面執行,第一則訊息的簡報會回答此問題;請勿重複詢問。
1. 逐字轉錄
$E/transcribe.sh --lang en # 實際使用的語言;絕不翻譯
words.json,基於原始影片的時間碼。如果原始影片是連拍(同一句話嘗試多次),請先使用引擎的 rough-cut.mjs(請見 short-editor/SKILL.md § 0.7)進行組合,然後轉錄組合後的影片。接著執行 node $E/words.mjs(引擎的):產生 words-fixed.json,每個詞的開始時間從靜音中移至語音起始處,結束時間則在停頓之前,並列出有疑問的詞;使用 words.mjs env|end|say 來讀取其中一個(請見 short-editor/SKILL.md § 1)。請勿為此自行編寫腳本。
2. 剪除所有停頓:跳接剪輯
$K/py.sh tighten.py --dry-run # 顯示將剪除的內容
$K/py.sh tighten.py # source/tight.mov;更新 project.json、words.json、shots.json
$K/py.sh tighten.py --keep 0.10 --min-pause 0.16 # 預設值,根據參考影片測量
會移除 0.16 秒或更長的所有靜音,連接處保留 0.10 秒(最後一個聲音後 0.06 秒,下一個聲音前 0.04 秒);開頭和結尾的靜音也會移除。在參考影片中,沒有留下來的停頓長於 0.32 秒,且連接處大約每 2 到 3 秒出現一次:說話者在螢幕上從不喘氣。每個連接處都是一個跳接:沒有淡入淡出或音效遮蓋它;鏡頭透過在剪輯點上交替寬景/特寫來標記它(§ 外觀)。
語音停止的位置是 測量 出來的(使用 10 毫秒的包絡線,滯後閾值為室溫 +12 / 室溫 +5 dB),絕非透過 Whisper 讀取。Whisper 的語音起始點會與此測量結果進行比對:若一個語音起始點落在測量到的靜音內,且下方有微弱的聲音(室溫 +9 dB),則會在該起始點前 50 毫秒處停止剪輯;若起始點落在室溫噪音中,則表示 Whisper 過早判斷(在開發用原始影片中曾發生三次,早了 0.35 秒),並會將其移至語音實際開始的位置。它會報告這兩種情況。
保留的片段會一次性寫入 source/tight.mov,以完整幀為單位(每個片段的畫面與聲音長度完全相同:未經捨入處理;13 個連接處曾導致嘴型落後聲音兩幀),使用原始影片的位元深度與色彩標籤(絕不重新調色)。然後,如同引擎的 rough-cut.mjs --adopt 所做的一樣,project.json 會指向它(source;原始影片保留在 rawSource),words.json 會根據它的時間碼重新對應(原始影片的轉錄保留在 words.raw.json),而 shots.json 會列出連接處之間的片段。不使用引擎的即時 cuts:包含 cuts 的專案無法透過片段渲染,而片段正是用來檢視動態瞬間的方式。tighten.py 總是重新從原始影片開始,因此執行兩次是安全的;使用者想要保留的剪輯(重拍、口誤)應放入 project.json 的 manualCuts(原始影片的秒數),然後再次執行 tighten.py。
原始影片內部的 場景 變換(結尾的預告鏡頭、另一個房間)不會出現在 shots.json 中:請透過畫面的亮度跳躍來尋找(使用 ffmpeg … signalstats 逐幀分析 YAVG),並將其提供給規劃(SCENE):鏡頭會在該處變寬,並以紙片動畫帶入。
3. 人臉位置
node $K/face.mjs # assets/faces.json,每秒 5 個偵測點,基於輸出時間軸
使用 Apple Vision,跨越所有剪輯點。規劃透過鏡頭讀取它(faces(P, camera(STEPS))):F.slot() 是影片中每個拍立得圖片的位置(畫面的中心線,低於人臉中位數中心 0.08,範圍 0.44-0.50:畫面中央),F.faceLine() 是人臉本身的線條(其中位數中心,範圍 0.36-0.50),用於寫在人臉上的關鍵想法與重點詞句,F.top(t) 是頭頂上方的高度,用於關鍵字,F.around(t0, t1, n) 是環繞頭部的點位,F.over(t0, t1) 是人臉方框。每次執行 tighten.py 後都需再次執行此步驟。
4. 閱讀轉錄並決定圖片:判斷步驟
閱讀整段原始影片,並賦予它參考風格的密度:每 1-3 秒畫面出現一個新東西(參考風格:72.7 秒內有 50 個圖形;開發剪輯:47.1 秒內有 49 個)。針對每個句子,從 § 外觀 中選擇最能說明它的圖形:
- 鉤子(第一句話):使用參考風格的三行標題(一條白線;承諾中最重要的詞以彩色呈現,旁邊是白色文字;紙上線條),如果句子列舉或暗示角色、工具、團隊,則在頭部周圍加上貼紙;
- 感受、成本、失敗、誇飾、比較:使用真實的反應 GIF 拍立得(已驗證剪輯中:Pepe Silvia 用於「搜尋數千個平台」,Key & Peele 流汗用於「老實說,我不是最厲害的」,Buddy the Elf 打電話用於「在電話上要說什麼」,「Let's get ready to rumble」用於「對決」),其字幕位於下巴位置,一個短片中約使用四到五個;
- 隨口提到的列表(「好的、壞的、失敗的……」)以及旁白(地點、「一個系列」、「敬請期待」):使用貼紙,每個詞一個(並非每個關鍵字都使用紙片;字幕已經說出了這些詞,「l'effet papier」:紙片是為了視覺趣味和重量感,就像在筆記本頁邊空白處書寫);
- 數字與統計資料:它們自己的紙片(如果它們是關鍵句子,例如「72.7 秒內的 50 個圖形」),或一個螢幕截圖;
- 產品、儲存庫、網站的畫面:使用者提供的素材,或公開頁面的擷取(
capture.mjs); - 章節(「首先」、「其次」——任何將影片結構化的段落):一個新的紙片,從左側或右側搖擺入鏡(
paper.mjs --swing),上面有該章節的標題;一條小線條或一個圖釘固定它;相機在章節邊界處切換為寬景。
針對所選的每個圖形,在 plan.mjs 中填入其時間碼($node plan.mjs 會以 JSON 形式輸出規劃,供 edl.mjs 讀取)。edl.mjs 是靜態的:它描述了圖形的外觀、位置和動畫;規劃告訴它何時發生。
5. 產生素材
node $K/gif.mjs # assets/gifs/:反應 GIF 作為拍立得
node $K/sticker.mjs # assets/stickers/:鏤空貼紙 emoji
node $K/paper.mjs # assets/papers/:紙片(章節、標題、重要詞句)
node $K/picture.mjs # assets/pictures/:產生的插圖(若需要)
node $K/capture.mjs # assets/captures/:公開頁面截圖
node $K/sounds.mjs # assets/sfx-paper/、assets/sfx-motionix/:已測量的音效
每個素材都會被測量:其位置(座標,佔畫面的比例)、持續時間、出現/消失動畫的時間點。這些測量值會存入 project.json 的 figures 陣列。
6. 渲染
node $E/render.mjs # 產生幀序列
使用引擎的渲染器,結合所有圖層:原始影片、字幕、紙片、貼紙、GIF、插圖、螢幕截圖、音樂與音效。輸出為 source/composite/ 中的一系列 PNG 幀。
7. 混音
node $K/mix.mjs # 混音音軌,使用引擎的混音器
將原始音訊、字幕、音樂與音效混合。所有音效音量皆已測量(measure.mjs),並設定在語音下方。音樂為 -15 LU。
8. 建置最終影片
node $E/build.mjs # 產生最終 MP4
將幀序列與混音音軌結合,輸出為 workspace/videos/<slug>.mp4。
9. 驗證
node $E/verify.mjs # 檢查:長度、解析度、影格率、碼率、色彩
確保輸出符合引擎的規格。如果驗證失敗,請修正問題並重新建置。
外觀
此處定義了已驗證風格的視覺語言。所有測量值皆相對於畫面尺寸(16:9 裁剪為 9:16 後的 1080×1920)。
字幕
- 位置:y = 0.82(從畫面底部算起),置中對齊。
- 字型:Archivo Black,白色。
- 大小:56 px。
- 樣式:一次三個字。正在說的字以
accent顏色(預設為黃色 #FFD43B)顯示。 - 動畫:淡入,每個群組停留 1.5 秒,然後淡出。
鉤子(第一句話)
- 三行:
- 一條水平白線(y = 0.30)。
- 文字:「THE」在左側,「WORD」在中間(白色 Archivo),「PROMISE」在右側(Fraunces,
accent顏色)。使用 project.json 中的hookText。 - 另一條水平白線(y = 0.40)。
- 動畫:從上方滑入,停留 3 秒,然後淡出。
紙片
- 材質:來自
assets/papers/的 PNG,模擬筆記本紙片(白色,帶橫線)。 - 字型:Gochi Hand,32 px,黑色。
- 位置:根據
plan.mjs中的position鍵值。 - 動畫:從左側或右側搖擺入鏡(
paper.mjs --swing),停留,然後摺疊離場。落地時播放紙張音效。
反應 GIF 拍立得
- 大小:畫面寬度的 0.80(864 px),置中。
- 位置:y = 0.44-0.50(與
F.slot()相同)。 - 邊框:白色拍立得邊框(10 px)。
- 動畫:從上方丟入(帶有彈跳效果),停留 2-3 秒,然後從上方撥開離場。落地時播放相機音效。
貼紙
- 來源:
assets/stickers/中的 PNG(從 GIPHY 或使用者提供的素材裁剪)。 - 大小:頭部周圍,每個貼紙約 120×120 px。
- 位置:使用
F.around(t0, t1, n)計算的點位。 - 動畫:從各自位置淡入,停留,然後淡出。
音樂
- 音量:語音下方 15 LU(由
measure.mjs測量)。 - 淡入:0.5 秒。淡出:1 秒。
音效
- 紙張:落地時播放(來自
assets/sfx-paper/,已測量)。 - 相機:GIF 拍立得落地時播放(來自
assets/sfx-motionix/)。 - 所有音效音量:語音下方 12 LU(由
measure.mjs測量)。
使用者的決定
此風格已與使用者進行了六次審查才定案。以下記錄了每次審查的變更:
- 初始剪輯:建立第一個版本。
- 字幕位置:從畫面中央移至底部。
- 音樂:加入預設背景音樂(Hip Hop 02)。
- 紙片動畫:從簡單淡入改為搖擺入鏡。
- GIF 拍立得大小:從 0.60 增加至 0.80 畫面寬度。
- 貼紙位置:從隨機改為環繞頭部。
未來任何變更必須再次經過使用者驗證。