overlays:與語音同步的圖形,放置在 Premiere 中
兩種技能,一個工作坊
這裡 (overlays):放置與編輯 | 工作坊 (motion-design):製作 |
|---|---|
轉錄稿、.prproj 的時間線、以短語錨點編寫的計畫 | 唯一的 Remotion 專案:motion-design/src/,src/illustration/ 中的疊加合成 (BrandedVideo, LowerThirdTrack, Screencast, Scene, FondAnime) |
素材尋找:照片、B-roll、GIF (gifs.py)、網頁截圖、電子郵件卡片 (mail-cards.py) | public/:字型、scenes/<video>/(場景媒體)、sfx/(音效) |
網站展示的錄製 (screencast-record.py) | 主題 (src/illustration/theme.ts)、聲音調色盤 (reference/sound-palette.md、scripts/make-sfx.py、scripts/son.py) |
render-segments.py、screencast-render.py、montage-tella.py:在工作坊內部開始渲染,然後將所有內容放置到 Premiere XML 中 | 音樂、混音 |
這兩個資料夾必須是相鄰的(<skills>/overlays 和 <skills>/motion-design):腳本會透過 ../motion-design 找到工作坊。新的場景元件應寫在 motion-design/src/illustration/scenes/ 中;新的音效應放入工作坊的合成配方中。
安裝(每台機器一次,外掛安裝):bash "${CLAUDE_PLUGIN_ROOT}/install.sh" --data "${CLAUDE_PLUGIN_DATA}"。
手動安裝:將四個技能資料夾並排複製,然後從工具包根目錄執行 bash install.sh。外掛更新後,工作坊的 node_modules 連結會消失:重新執行設定行。詳細資訊請參閱工具包的 INSTALL.md。
編輯黃金法則(預設設定,請根據頻道調整)
影片由語音主導。圖形不會重述所說內容:它們錨定那些僅靠感覺無法捕捉的事物(如專有名詞、引言、地點、標題、數字),或者它們展示正在被談論的內容(如文件、網站、圖表)。
兩個裝飾層級:
- 輕量:每章 1 個高級疊加 + 每 45 到 60 秒 1 個下方三分之一,在開頭(0-30 秒)和結尾之外;
- 密集(示範、調查或教學影片):動畫場景覆蓋畫面 60% 到 70% 的區域,每個場景與語音同步,沒有場景連續 3 秒以上無動畫。說話人頭保持其位置。
如果未說明,請詢問所需的層級。預設情況下不要動畫化:開頭(觀眾決定是否留下)、親密的軼事(動畫會破壞情感)、營造懸念的問題、結尾和行動呼籲、形容詞列表。
在鏡頭上說出的與腳本不符的內容(如數字、術語、近似值)應在螢幕上修正:粗剪會在其報告中標記它,計畫會將正確的值放到語音上,無需要求重新拍攝。
零號規則:參考時間線是 Premiere 專案的,絕非粗剪的
順序永遠是:粗剪 (rough-cut) -> 編輯者在 Premiere 中審查並修改剪輯 -> 疊加層。在這兩者之間,剪輯點會移動、片段會被刪除、持續時間會改變:基於粗剪計算的時間會偏差 30 秒到 1 分鐘,並且元素會出現在影片結束之後。
在粗剪之後硬性停止,即使用戶說「粗剪然後疊加層,由你決定」:交付粗剪 XML,然後等待用戶說他們已在 Premiere 中驗證了它。在此之前,不制定計畫、不計算時間、不進行放置。只有不依賴時間的工作可以繼續(例如尋找圖片和 GIF)。
python3 scripts/timeline-from-prproj.py "/path/clip.MOV" --list # 哪些序列包含此片段
python3 scripts/timeline-from-prproj.py "/path/clip.MOV" --sequence "Derush_v1"
# -> <clip>_transcription.json(SEQUENCE 時間內的詞語)+ <clip>_timeline.json(片段 -> 序列映射)
它會讀取所選序列中片段的素材(ticks = 254016000000/s),並帶入 <clip>_Derush_vN_work/words_premiere.json(專案的轉錄稿,已由粗剪重新對齊)的詞語。如果多個序列包含該片段:它會拒絕猜測(代碼 2),請詢問是哪一個。如果一個序列中有多個片段:按順序全部傳入(A.MOV B.MOV --sequence "...");每個時間條目和每個詞語都帶有 media,輸出將採用第一個片段的名稱。一個被剪斷的詞語,如果它開始於該片段內(在剪輯點前至少 80 毫秒),則保留;一個真正被切斷的詞語會破壞指向它的錨點:將錨點移動到前一個詞語 + offset。檢查最後放置的元素是否保持在序列實際結束之前。
切勿重複使用來自粗剪的 cuts_final.json 或映射。如果沒有 Premiere 專案(僅有片段):python3 scripts/transcribe.py "/path/clip.mp4"(本地 whisper.cpp,在 Apple Silicon 上處理 15 分鐘的素材約需 5 分鐘)。
當用戶交回剪輯時,首先進行比較:他們在 Premiere 中所做的更改是最可靠的回饋。將他們的序列與粗剪 XML 進行比較,將每個重複出現的差距轉變為修復、檢查或規則,然後才編寫疊加層計畫。當用戶驗證最終剪輯時,對已交付的疊加層 XML 執行相同操作:他們刪除、移動(超過 2 幀)、調整大小或添加的內容(他們自己貼上在 V1 上的素材不計入)將成為修復、檢查或規則。沒有刪除或移動任何東西意味著該交付的方法是正確的:保留它。
流程
0.(可選)B-roll
在片段旁邊建立一個 Brolls/ 資料夾,檔案命名為 NN_description_K.mp4(編號、描述、變體):
python3 scripts/match-brolls.py "/path/clip.mp4" # -> <clip>_broll-script.json 待完成
對於每個 B-roll:變體(file)、時間(timecode MM:SS,在轉錄稿中檢查)、durationSec(null = 原始長度)。放置在 V2 上。在網站展示之前執行它(--force 會覆蓋檔案)。在選擇之前查看變體的聯絡表(每個變體 3 幀):檔案名稱經常誤導(例如「street-photography-portrait」可能是夜間城市空拍)。切勿將 B-roll 放在說話者未實際展示的句子上,並且在 B-roll 播放時不要有疊加層音效。
0 bis.(可選)插圖照片
對於引用人物、作品、書籍、地點的影片:
- 清單:根據影片腳本,按出現順序列出實體 ->
illustrations-manifest.json:參考腳本可以是任何格式(文字、Markdown、文件):它提供正確的拼寫和要顯示的內容。{"version": 1, "dest": "Illustrations", "items": [ {"n": 1, "categorie": "reference", "nom": "First Last", "sujet": "portrait", "url": "https://...", "fallback_urls": [], "note": "source: ..."}]} - URL:首先使用免費來源(維基共享資源、官方網站、開放取用博物館),然後使用
python3 scripts/serp_images.py "Name Title" --num 5 --min-width 1200(透過 SerpAPI 搜尋 Google 圖片,需要金鑰SERPAPI_API_KEY)。檢查圖片是否正確(查看縮圖,而不僅僅是頁面標題;拍賣頁面可能是陷阱)。如果影片是出售的,請檢查版權。 - 下載:
python3 scripts/source-illustrations.py illustrations-manifest.json->Illustrations/NN-category-name-subject.ext(檢查位元組、測量寬度;如果缺少 URL 則退出代碼 1)。 - 時間安排:
python3 scripts/match-photos.py "/path/clip.mp4"-><clip>_photos-script.json,時間由名稱在轉錄稿中的模糊搜尋預填(語音辨識會破壞專有名詞)。始終手動針對轉錄稿重新檢查每個時間(模糊匹配可能會取用後來的提及而非第一個);enabled: false會刪除照片。照片放在 V3 上,優先於 B-roll(與照片重疊的 B-roll 將從 XML 中刪除並記錄)。
照片處理:切勿裁剪(保持原始比例,垂直照片保持垂直);照片放置在純色背景上,四邊留有邊距(約占畫面 86%),而不是接觸頂部和底部邊緣的全幀包含。清單中不要有 .webp(Premiere 在 XML 中將其解讀為零長度媒體:使用 sips -s format jpeg 轉換)。寬度低於 800 px 的照片會顯得模糊:render-segments.py 會列印 LOW RES 警告,在交付前列出這些照片。由場景顯示的書籍封面是從網路上取得的出版商視覺(他們的網站、HD 模型),切勿從說話者自己的素材中提取圖像。
當說話者展示一個物體時,沒有任何東西能遮蓋它。 掃描轉錄稿中在提及作品附近出現的「這裡」、「如你所見」、「這個」、「看」:說話者正在將書或相機拿到鏡頭前。在那個視窗上不要有全螢幕照片(編輯者在已交付的剪輯中移除了每一個這樣的封面);封面應放在示範之前或之後,或者根本不放。
0 ter. GIF 和迷因(基本功能,非選項)
每 2 到 4 分鐘一個 GIF,放在情緒或自嘲的時刻(「這非常難搞」、「我全是在胡扯」),絕不在開頭,也絕不用於逐字說明技術句子。一個 gif 場景(疊加層、白色邊框、循環播放)在詞語出現時到達,並帶有音效。
python3 scripts/gifs.py chercher "that's a bug" --planche gifs-sheet.jpg # 列出 + 編號的聯絡表
python3 scripts/gifs.py prendre <id> --nom bug --public <video> # 來源 MP4 + 場景的資料
在選擇之前查看聯絡表(GIPHY 標題不能說明顯示的內容;用英文搜尋通常效果更好)。prendre 將 MP4(而不是 .gif)下載到 Illustrations/gifs/,保留 gifs.json(每個 GIF 的來源),將其複製到 motion-design/public/scenes/<video>/gifs/ 並列印 gif 場景的 data(src、srcW、srcH、loopSec)。需要金鑰 GIPHY_API_KEY(免費)。GIF 經常重複使用受保護的作品:對於出售的影片,請避免使用。
1. 片格的幀率和格式(至關重要)
ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate,width,height -of csv=p=0 "/path/clip.mp4"
當 JSON 未提供時,render-segments.py 會讀取片格的速率和尺寸。如果 JSON 是 30 fps 而片格是 60 fps,所有內容都會偏移 2 倍。在 29.97 fps 時,n 個序列幀持續 n x 1.001 / 30 秒,並且每個渲染必須覆蓋其片格(tailFrames 和 TenirFin 元件會處理)。片格以其 MEDIA 的速率寫入:Premiere 以 29.97(<file> 的速率)讀取 <in>,而不是片格的 <rate>;腳本會寫入 in = round(t x fps x 1000/1001) 並設定 <ntsc>TRUE。
垂直 9:16(Reels):相同的流程,相同的 JSON。下方三分之一會偵測到垂直方向並向上移動以避開字幕區域;照片保持完整(背景上有一條帶);16:9 的 B-roll 會獲得一個填滿寬度的縮放。Reels 規則(來自與最終剪輯的比較交付):照片 2 到 3 秒(預設 2.5),下方三分之一與其相關聯的肖像照片持續時間相同並與之同時開始,除非要求否則不使用庫存 B-roll,說話者展示物體時不要有覆蓋。始終將一個下方三分之一渲染為靜止幀並將其合成在灰色幀上,以在系列開始前檢查垂直佈局。
2. 在提出之前先閱讀
閱讀整個轉錄稿。找出:人名(下方三分之一「nom」)、作品標題(「oeuvre」)、地點(「lieu」)、術語或運動(「term」)、強有力的引言(高級 quote-full)、章節公告(section-title 或章節卡)、引人注目的數字(stat 場景)、被談論的文件、交流記錄和網站(證明場景、示範)。每個被引用的名稱、作品或書籍都在某處被展示(懸浮場景、照片、卡片),或者寫下不展示的原因。使用說話者自己的詞語(在轉錄稿中重新閱讀)閱讀每個圖表的內容,切勿自行解讀:錯誤的圖表(例如將個人資料放在漏斗錯誤層級上)來自於轉述。
3. 每個高級疊加都用一句話構思
「我想看到的:大字體的句子、斜體、左側的強調線、小字體的署名。」如果描述是「文字出現」,則它不是高級疊加:那就是下方三分之一,或者什麼都沒有。
4. 基本目錄
| 類型 | 元件 / 種類 | 軌道 | 資料 | 持續時間 |
|---|---|---|---|---|
motion(全螢幕高級) | quote-full | V5 不透明 | text、author?、source? | 10-14 秒 |
lower-third | lower-third-nom | V6 Alpha | name、years?、tag? | 6 秒 |
lower-third | lower-third-oeuvre | V6 | title、author、year? | 6 秒 |
lower-third | lower-third-lieu | V6 | place、date | 6 秒 |
lower-third | lower-third-term | V6 | term、subtitle? | 6 秒 |
section-title | V6 | eyebrow?、title | 4 秒 | |
scene | 請參閱「動畫場景」 | V5 / V6 / V7 | data、cues | 跟隨語音 |
如果在 10 秒內同時引用一個名字及其作品:使用單一的「nom」下方三分之一,並將作品放入 tag。如果是說話者自己的引言:quote-full 不加 author(他們的語音即為署名)。動畫在最後 18 幀內以自動淡出結束。
5. 時間精確到詞語(至關重要)
切勿估算:在 <clip>_transcription.json 中查找該詞語並使用其 start。元素在詞語開始時出現(下方三分之一最多可以提前 0.5 秒;與句子的開始同步會讓人感覺公告來得太早)。render-segments.py 會拒絕沒有有效時間的片段,並檢查每個時間是否與轉錄稿匹配(OK / WARN / UNKNOWN)。同時檢查 JSON 中的幀率(步驟 1)。
6. 在編寫之前呈現計畫
| # | 時間 | 持續時間 | 類型 | 元件 | 原因 |
|---|-------|--------|-------------|-------------------|--------------------------------|
| 1 | 01:24 | 6 秒 | lower-third | lower-third-nom | First Last 的首次提及 |
| 2 | 02:14 | 12 秒 | motion | quote-full | 第 1 部分的關鍵引言 |
在編寫 JSON 和渲染之前等待批准。
7. 渲染和匯入
(cd ../motion-design && npm ci) # 執行一次
python3 scripts/render-segments.py "/path/clip.mp4" # 全部:渲染 + XML
python3 scripts/render-segments.py "/path/clip.mp4" --lower-thirds-only
python3 scripts/render-segments.py "/path/clip.mp4" --scenes-only
一個場景的啟動可能需要 motion-design/public/scenes/<video>/ 中的素材,再加上 scripts/son.py 中的聲音(內部合成)。XML 在幀邊界處放置片段,跟隨時間和轉錄稿。匯入的軌道映射到 Premiere:V5 不透明(全螢幕)、V6 具有 Alpha 通道(下方三分之一 + 章節標題)、V7 用於浮動場景。匯入後,在導出前重新計時所有內容。
Premier Pro 中的疊加層工作流程
專用於說話人頭影片(評論、教學、Reels)的疊加層,具有前部透明度的軌道,由腳本渲染並通過 XML 匯入。
對於 Reel(9:16):
- 在 Premiere 中建立序列(V3 用於照片,V2 用於 B-roll),基於
motion-design/public/scenes/中的模型。 - 始終將一個疊加層渲染為靜止幀以測試佈局。
- 避免在密集的 B-roll 部分使用疊加層。
管道集成
render-segments.py 輸出一個 .xml 文件,該文件...(原文截斷)