Visual Guide Video
分析影片並撰寫一個時間軸檔案 (timeline.py),引擎便會以程式碼渲染所有特效、音樂與音效。完全不使用外部編輯工具或音源檔案。
SKILL_DIR = 此 SKILL.md 所在的資料夾。腳本透過 python "$SKILL_DIR/scripts/<name>.py" 執行。
0. 準備
pip install -r "$SKILL_DIR/requirements.txt" # opencv-python imageio-ffmpeg numpy scipy pillow edge-tts
ffmpeg 使用 imageio-ffmpeg 套件。韓文與表情符號字體會自動偵測作業系統預設字型(可透過 VGUIDE_FONT_BOLD/REGULAR/EMOJI 指定)。
工作資料夾應與影片檔案放在一起:project/timeline.py,輸出產物位於 project/build/ 與 project/output/。
1. 影片類型判斷 → 設定檔選擇
python "$SKILL_DIR/scripts/analyze.py" VIDEO --out build/analysis
直接透過 Read 檢視主控台的 類型推測 結果與 build/analysis/sheets/*.jpg 圖片來決定類型。使用 PROFILE 設定檔可切換預設值,而 timeline.py 中設定的值永遠優先。
| PROFILE | 目標 | 預設值 | 核心特效 |
|---|---|---|---|
screen | 螢幕錄製·教學·展示 | pop 音樂、關閉原始音訊、進度條 | SHOTS 縮放、CLICKS、LINKS、HIGHLIGHTS、CARDS、HUD、FLOW |
game | 遊戲實況·頭目戰·精華片段 | epic 音樂(音量較小)、開啟原始音訊、電影級調色、30fps | MAGNIFY、IMPACTS、SPEED/FREEZE、POPS、CALLOUTS(@追蹤對象)、數值條分析 |
vlog | 日常·旅遊·開箱 | chill 音樂、開啟原始音訊、暖色調 | CALLOUTS、STICKERS、SPEED(倍速移動)、字幕、GRADES |
anim | 動畫·角色影片 | cute 音樂、鮮豔調色 | POPS(搞笑)、STICKERS、CALLOUTS、FREEZE |
promo | 廣告·宣傳·旅遊·品牌影片 | epic 音樂(音量較大)、關閉原始音訊、30fps | TYPE(廣告字型·浮水印)、CLEANUP(清除原始文字)、INK 轉場、GLOWS、LETTERBOX、季節粒子、zen 音樂弧線 |
每種類型要說明的重點都不同:
- screen:「現在按了哪裡、有什麼改變」→ 點擊位置放大、變更面板的箭頭、狀態卡片。
- game:「發生了什麼事(攻擊·防禦·受擊·回復·頭目模式)」+ 趣味性 → 打擊感、反應彈窗、遠處目標的放大鏡、關鍵時刻暫停解說、無聊移動片段快轉。
- vlog:「在哪裡、做什麼」+ 情感 → 重於氛圍而非解說。將活動(生日·旅行·畢業)的高潮以慢動作、粒子特效強化,晃動的移動片段則快轉,拍照瞬間暫停並加上拍立得效果,結尾則用照片拼貼作為 Outro。
- anim:強調角色反應 → 可愛彈窗、貼紙、關鍵表情暫停。
- promo:「讓觀眾想去、想買」→ 用簡短的廣告文案(開場 2 行 → 主標題 → 場景章節 → 結尾卡片)取代字幕,場景切換時使用墨跡擴散等標誌性轉場,音樂能量曲線(平靜 → 堆疊 → 高潮 → 餘韻 → 終曲)。若原始畫面有其他語言的文字,則清除並替換為目標語言(國際版)。
通用剪輯原則(使用者最喜歡的部分):不必要的片段(移動·載入·鏡頭晃動的片段)快轉,重要的瞬間則暫停並加上解說或裝飾。分析階段應先將每個片段分類為「核心 / 連接 / 贅飾」再開始。
2. 分析—何時何地發生何事
events.json 中的事件類型:
- 通用:
cut(場景切換)、flash(閃爍)、loud(音量峰值 = 打擊聲·爆炸)、motion(動作峰值) - screen:
switch(點擊·輕觸切換候選)、big-change、scroll - 數值條 (
--bar):bar-drop/bar-big-drop(受擊)、bar-low(危險)、bar-empty(死亡)、bar-rise(回復)
遊戲必須測量 HP 數值條。受擊·回復·死亡的時機可以精確到影格。
python "$SKILL_DIR/scripts/crops.py" VIDEO --t 10,30 --box 200,940,500,100 --step 25 --out build/hp.jpg # 測量數值條座標
python "$SKILL_DIR/scripts/analyze.py" VIDEO --out build/analysis --bar player:337,982,626,988 --bar boss:1015,911,1590,915
- 數值條框選範圍為條內的一行像素 (高度 4~8px)。白色數值條預設為
light,彩色則使用:any。 - 透過 Read 檢視
bar_<名稱>.png(Kymograph:垂直軸=時間)來確認事件是否準確。若受擊瞬間數值條閃爍紅光或特效導致 HUD 消失可能產生誤判,請與graph.png及圖表交叉比對。 - 圖表間隔為 2 秒。戰鬥片段則以 0.3~0.6 秒間隔擷取更多影格,以直接解讀動作(攻擊/翻滾/受擊/變身)。
精確座標:務必使用刻度裁剪測量。
python "$SKILL_DIR/scripts/crops.py" VIDEO --t 7.4,13.5 --box 0,760,420,240 --out build/crops.jpg # 區域,50px 刻度
python "$SKILL_DIR/scripts/crops.py" VIDEO --t 12 --full --out build/grid.jpg # 全畫面,100px 格線
3. 撰寫 timeline.py
從 Recipe 開始。 將符合類型的 Recipe 複製為 timeline.py,並僅填入 [1. 要填寫的值](關鍵時刻的時間·座標·文字),即可自動生成經過驗證的特效結構。接著透過預覽影片,根據內容增減或修改項目。
| Recipe | 目標 | 要填寫的值 |
|---|---|---|
recipes/screen_walkthrough.py | 螢幕錄製教學·展示 | 點擊(時間·座標·文字·變更處·卡片)、要強調的區域、字幕 |
recipes/game_boss_fight.py | 遊戲戰鬥精華片段 | HP 數值條位置、受擊(時間·剩餘 HP)、我方攻擊、頭目倒地、回復、死亡/擊殺、移動片段、解說字幕 |
recipes/event_vlog.py | 生日·紀念日·派對 Vlog | 高潮時間與對象、晃動片段、照片倒數·暫停影格、來賓登場、最後場景 |
recipes/promo_shorts.py | 30 秒直式 Shorts(廣告蒙太奇) | 片段列表(原始片段·輸出長度)、場景平移、季節關鍵字·章節文字、轉場類型 |
recipes/promo_film.py | 廣告·宣傳·旅遊影片 | 開場文案、主·結尾卡片、場景(片段·倍速·章節文字·浮水印·鏡頭·粒子·能量·背景音)、墨跡轉場時間、發光對象、要清除的文字 |
Recipe 的預設值經實際影片驗證,保留原樣即可像範例一樣運作(用於其他影片時務必重新測量)。若缺少 Recipe 中的項目,請參考 templates/timeline_template.py 的完整架構進行新增。若無合適 Recipe,則從模板開始。
處理過的影片其 timeline.py 應放在該影片的資料夾中。技能儲存庫不應包含特定影片的時間軸(人名·個人場景·工作內容) — 可通用的模式應移至 Recipe 或此文件中。
規則:時間永遠是『原始影片時間』,座標永遠是『原始像素』。 即使 SPEED·FREEZE 改變了輸出長度,引擎會自動轉換。
暫停片段內的時間使用 (原始時間,輸出偏移秒數):(49.45, 1.6) = 49.45 秒開始暫停,並在 1.6 秒後。用於在暫停期間依序顯示彈窗、拍立得、Outro。
通用元素(所有設定檔)
| 項目 | 用途 |
|---|---|
TRIM, SPEED, FREEZE | 裁剪片段、倍速·慢動作(標籤徽章,標籤為 None 則無徽章)、暫停畫面(look desat=解說用 / photo=僅快門閃光)。快轉會自動產生動態模糊 (SPEED_BLEND) |
TRACKS | 移動對象的關鍵影格。auto=True(OpenCV 追蹤:人物·動物)/ auto="match"(模板匹配:蛋糕·招牌等形狀固定物體,使用單一關鍵影格追蹤至 until)/ follow="父級"(跟隨父級追蹤的對象,例如:蛋糕上的蠟燭)。其他項目透過 "@名稱"、"@名稱:top" 引用 |
PARTICLES | 粒子 confetti/hearts/sparkle/bokeh/notes/stars/snow/petals/leaves/fireflies(可指定 palette=[6] 顏色)。用於追蹤·座標的 burst(一次性噴發)或 rate(持續),全畫面使用 at="screen" |
PHOTOS | 將原始影格以拍立得效果顯示(標題·角度·掉落進場)。用於暫停畫面·Outro 拼貼 |
SHOTS | 鏡頭:座標縮放 / "full" / "fill"(無黑邊填滿)/ "@追蹤對象" 追蹤縮放 |
MAGNIFY | 放大鏡:將遠處目標以圓形放大 + 連接線 + 標籤 |
CALLOUTS | 指向對象的對話框(會跟隨追蹤移動) |
POPS | 彈窗文字樣式 impact/danger/cool/info/funny/small/party/sweet/count(倒數計時數字) |
STICKERS | 表情符號貼紙(bob/pulse) |
IMPACTS | 打擊感 hit/heavy/crit/damage/block/parry:震動+閃光+縮放衝擊+色差(+自動音效) |
SHAKE, FLASH | 手動震動·閃爍 |
GRADE, GRADES | 調色 cinematic/warm/cool/vivid/mono/sepia/danger/dream/night(片段間轉換) |
SFX, SFX_VOLUME | 音效庫:hit boom clang pop ding scratch sad_trombone heartbeat shutter slowmo crash whoosh riser party_horn twinkle confetti / stamp temple_bell ink gliss gliss_down / 可指定長度的背景音 "waves:8" "wind:6" "water:6" "birds:5" |
SOURCE_AUDIO | 原始音訊(慢動作片段會降低音高,暫停片段為靜音,快轉片段則按 fast_gain 減少音量) |
MUSIC | style pop/epic/chill/cute/zen、arc(zen:場景能量)、start(從此時間開始音樂)、drop、end(+end_fx scratch/fade/cut)、volume |
MASTER_GAIN_DB | 最終混音增益(在限制器之前)。手機影片原始音量較小,可增加 +3~5 dB |
CUSTOM_LAYERS, CUSTOM_FRAME_FX, CUSTOM_SFX | 在 timeline.py 中以函式新增指定的新特效(如下) |
OUTPUT_SIZE, FPS, QUALITY | 輸出解析度(例如 720p (1280, 720))、fps、CRF |
CANVAS, BACKDROP | 設計畫布。直式 Shorts 使用 CANVAS = (1080, 1920) + OUTPUT_SIZE = (1080, 1920)。橫式原始影片會置中顯示,留白處以 BACKDROP("black"、"blur"、dict(kind="blur", tint=(r,g,b), amount=0.5))填充。若要全螢幕,可使用 SHOTS 倍率 ≈ 3.16 (= 1920 / 607.5) 並平移 x 軸 |
SPEED_RAMP | 用於無縫拼接倍速片段(Shorts 蒙太奇):片段之間不會回到 1 倍速,而是平滑過渡指定的秒數 |
廣告·宣傳元素 (scripts/promo.py,所有設定檔皆可用)
| 項目 | 用途 |
|---|---|
CLEANUP | 清除原始畫面中的文字·印章·Logo (t0, t1, (x0,y0,x1,y1), dict(plate=(ta, tb), ref=t))。plate = 同一場景中沒有文字的影格 → 可完整還原背景(若場景平移·縮放,會透過相位相關自動補償移動)。mask="box" 則替換整個方框(靜止背景),若無 plate 則使用 Inpaint(NS + 紙張紋理),live=True 用於移動中的文字(例如滑入的標籤,ink="light") |
TYPE | 廣告字型。"line"(逐詞浮現的文案)、"hero"(字母間距收攏出現的大型標題 + 副標題 + 浮水印)、"chapter"(浮水印蓋下後,Kicker·分隔線·標題接續出現,veil 可在背後添加薄霧帷幕)。座標以 1920x1080 畫布為準,可使用 color 設定顏色,halo 增強可讀性 |
GLOWS | 太陽·月亮·燈光的擴散光暈 + 鏡頭光暈(Streak·Ghost)— 會跟隨追蹤對象移動 |
INK | 墨跡擴散轉場 (t, dict(dur, at)):在 t 時覆蓋畫面最大面積,然後從中央開始散去(自動附加音效) |
TYPE "slam" | Shorts 專用:大字隨著節奏『砰』的一聲出現—即使繪製在墨跡之上,在畫面被覆蓋時依然可見 (over_ink)。浮水印 seal |
LETTERBOX | 電影黑邊 dict(ratio=2.39, range=(t0, t1)) — 進出時平滑。粒子效果也會隱藏於黑邊之下 |
接到新特效指示時 — 自訂 Hook
無需修改引擎,直接在 timeline.py 中撰寫函式。ctx 包含 t(輸出時間)、ts(原始時間)、raw(原始影格)、frame(目前畫布 BGR)、view、cv(疊加畫布)、tl、gfx、fx、W、H、screen("@boss")、window(t0, t1)(原始時間區段 → (alpha, 進度))。
def speed_lines(ctx): # CUSTOM_LAYERS:繪製疊加層(無回傳或回傳新 frame)
w = ctx.window(57.2, 58.4)
if w:
x, y = ctx.screen("@boss")
for k in range(12):
a = k / 12 * 6.283
ctx.fx.draw_line(ctx.cv, (x + 300 * math.cos(a), y + 300 * math.sin(a)),
(x + 700 * math.cos(a), y + 700 * math.sin(a)), (255, 255, 255), 3, w[0] * 0.6)
CUSTOM_LAYERS = [speed_lines]
def red_pulse(ctx): # CUSTOM_FRAME_FX:變形影格 → 回傳新 frame
return ctx.fx._tint(ctx.frame, (255, 0, 0), 0.15) if ctx.window(76, 78) else None
CUSTOM_FRAME_FX = [red_pulse]
def boss_roar(a): # CUSTOM_SFX:a = dict(buf, add, lib, tl, SR)
a["add"](a["buf"], a["lib"]["boom"](), a["tl"].out(14.4), 0.8)
CUSTOM_SFX = [boss_roar]
經常使用的特效之後可移至 fx.py 成為正式項目。
佈局規則(來自實際遇到的問題)
通用
- 表情符號會以彩色渲染。但
▸ ✓ ✕等符號可能會顯示為 □,因此請使用表情符號 (✅ ✖️ 👉 ⏩ ⏸) 或• → ·。 - 字幕每行約 40 字元。關鍵字可用
[方括號]強調。暫停畫面的解說字幕,若將暫停時間設定為起點=終點(tf, tf, "..."),則僅在暫停期間顯示。 - 同一時間點不要重疊超過 3 個彈窗、對話框或貼紙。彈窗持續 0.8~1.2 秒即可。
screen
- 卡片與高亮應錯開時間(卡片 → 高亮)。卡片須在下一次點擊縮放前結束。
- 縮放狀態下高亮若超出畫面則會被裁剪 → 倍率設定為 1.15~1.3。
- 標籤位置
"right"(箭頭)、"above-right"(表格行)、"below"(頂部元素)。HUD 在縮放 1.12 倍以上時進入迷你模式(左側 100px)。
game
- 超寬比例 (21:9) 會以黑邊形式放入 16:9 畫布。上下黑邊處可用於放置倍速徽章·字幕,避免遮擋動作。若想填滿畫面,請在
SHOTS中使用"fill"。 - 數值條高亮使用
"above|nodim"— 若將畫面變暗則無法看到動作。 - 縮放僅限 1.3~1.5 倍。動作太快時過度放大會導致目標移出畫面。如需放大,請使用
MAGNIFY。 - 暫停(FREEZE)持續 1
2 秒,一部影片使用 34 次即可。暫停期間可用 CALLOUTS 指出「誰做了什麼」。 - 移動·載入片段以 2
3 倍速 SPEED 縮短。慢動作 0.30.4 倍僅用於受擊·致命一擊的 0.5~1 秒。 - 追蹤關鍵影格應在目標大幅移動時記錄,在場景變換(Cut)處則寫入兩次相同的值(前後各一),以避免補間產生跳動。可使用
python "$SKILL_DIR/scripts/tracks.py" timeline.py建立圖表確認。 - 透過 HP 事件鎖定受擊時間點,並以影格精確度設定
IMPACTS。受擊 =damage/crit,我方攻擊命中 =hit/heavy。 - 保留原始遊戲音效,BGM 音量調小 (volume 0.3~0.45)。在死亡時間點使用
MUSIC["end"]+end_fx="scratch"中斷音樂,並以sad_trombone等音效製造笑點。
promo(廣告·宣傳·國際版)
- 清除原始文字:選擇文字出現前 0.4 秒以上/消失後的影格作為 plate。淡入淡出中的影格仍殘留有模糊文字 → 使用增強對比的裁剪(減去背景模糊後 ×4)確認。清除後,使用
--preview的原始解析度裁剪檢查殘影·接縫。 - 對於霧氣·水花等形態持續變化的背景,plate 不適用(會產生灰色污漬)→ 不使用 plate 而採用 Inpaint,並在該處疊加帶有
veil的章節字型。 - 紅色印章偵測僅鎖定深紅色(排除夕陽·朱紅天空)。若天空為朱紅色,須確認整個方框不會變色而產生色帶。
- 文案要簡短:開場 2
4 單字 × 2 行、章節標題 25 單字、結尾卡片品牌 + 一行。請勿使用實際機構·品牌的官方標語。 - 字型置於黑邊內側(排除上方 140px·下方 140px 區域)。原始文字所在位置通常為『留白的天空』,適合放置章節標題。
- 音樂:zen 風格使用
arc定義場景能量。調整場景倍速使墨跡轉場時間落在小節邊界 (80 BPM = 3 秒),則轉場·鼓聲·浮水印能與節奏吻合(可透過tl.load輸出時間後調整倍速)。階段音量差異要大(calm −20 / peak −12 dB 左右),高潮才能凸顯。 - 關鍵場景(展開的屏風·日出)使用 0.75
1 倍速,緩慢風景使用 1.52.4 倍速。僅在主要段落(季節·區域)轉換時使用墨跡,同一段落內則保留原始轉場。 - 直式 Shorts (30 秒) (
recipes/promo_shorts.py):96 BPM(一小節 2.5 秒)對應一個場景。使用SEGMENTS = [(原始開始,結束,輸出長度)]拼接,並透過Remap反推算倍速,使轉場精準落在小節上。原始轉場 (Crossfade) 壓縮為 0.2 秒,隱藏在墨跡·閃光之下。- 前 1 秒為 Hook:一行文案 → 小節 1 處品牌標題 + 音樂重擊。開場·結尾使用條狀佈局(中央原始畫面 + 上下字型),本體則為全螢幕直式裁剪 + 主體方向平移(太陽·瀑布·月亮置中,寬闊風景則由左→右)。
- 快轉片段中原始秒數變短,因此字型時間應使用 (TRIM[0],輸出秒) 這種輸出基準寫法。章節透過
pace=0.55快速出現。 - 粒子效果設定
clip=True以隨 Cut 中斷(避免花瓣飄入下一季節)。為避開 Shorts UI,字型應置於上方 260px·下方 420px 內側。
vlog(家族·活動影片)
- 手機影片晃動較多。晃動的移動片段以 3~4 倍速快轉(動態模糊會自動加入使其平滑),原始音訊會自動降低。
- 高潮(吹蠟燭·乾杯·進球)使用 0.4 倍慢動作 + 閃光 + confetti burst + party_horn。音樂從該瞬間開始 (
MUSIC["start"]) — 在此之前保留原始音訊(生日歌·對話)。 - 拍照場景應在快門按下後的未晃動影格暫停 (
look="photo") 並顯示拍立得。務必透過預覽確認暫停影格清晰(相機移動中的影格會模糊)。 - 貼紙·彈窗·愛心不要放在臉上。測量臉部座標後,置於旁邊或上方空白處。若要指向表情(鬼臉·眨眼),請使用 CALLOUTS(
ring=False)從側面指向。 - 若畫面上出現倒數(手機計時器),則使用
count彈窗 3·2·1 對齊該時刻,並加上 pop 音效。 - Outro 是在暫停畫面上疊加 2~3 張拍立得拼貼 + 簡短祝賀文字(透過
OUTRO的top上移,並設定stats=[])。 - 即使沒有字幕·配音也要讓故事能看懂:開場標題 + 每個場景的簡短彈窗一行即可。
4. 重複預覽
python "$SKILL_DIR/scripts/build.py" timeline.py --preview 3.5,7.4,26 # 原始時間
python "$SKILL_DIR/scripts/build.py" timeline.py --preview-out 16.6,36.2 # 輸出時間(確認暫停·慢動作中間)
透過 Read 檢視 build/preview/sheet*.jpg,修正重疊·裁剪·遮擋·座標誤差·文字亂碼。可透過標籤 src ↔ out 確認時間轉換。暫停片段無法以原始時間確認,因此使用 --preview-out。
5. 音訊
- 背景音樂
MUSIC["style"]:pop (126BPM 電子流行)、epic (96BPM 太鼓·斷奏弦樂·銅管·合唱)、chill (82BPM Lo-fi)、cute (132BPM 木琴·撥奏)、zen (80BPM 伽倻琴·大笒·長鼓·鼓·合唱,MUSIC["arc"] = [(原始時間, "calm|flow|pulse|build|peak|hush|finale")])。除 zen 外皆有 intro → A → B → build → drop → outro 結構,於drop秒時高潮爆發。 - 原始音效:game/vlog/anim 預設開啟。若配音員說話則會一同 Ducking (
SOURCE_AUDIO["duck"])。 - 音量檢查:遊戲以原始音效為主。測量各片段的 RMS,使音樂比原始音效小 3~5dB,音效僅在打擊瞬間可聞。
import tl, music, build; t = tl.load("timeline.py"); m = music.build_music(t)[0] * t.music["volume"]; s = build.source_audio(t, m.shape[1]) - 配音(可選)
NARRATION = [(t, "句子")](若無則讀取字幕)。--voice edge(Microsoft 神經網路,線上 — 請注意句子會傳送至 Microsoft)/--voice sapi(Windows 離線)。若build/voice_report.json中 rate 超過 +15% 或 overflow,則縮短句子(韓語 ≈ 7 音節/秒)。
6. 最終渲染與驗證
python "$SKILL_DIR/scripts/build.py" timeline.py [--voice edge] [--workers 8]
將影格拆分給多個處理器平行渲染後拼接(1 分鐘 1080p ≈ 2~3 分鐘,8 workers)。請於背景執行。
完成前確認事項
- 檢查最後一行
[done] ... Ns (expected Ns), N MB中的長度是否一致,以及日誌中是否有 Traceback。 - 從輸出中抽幾張影格確認:
ffmpeg -ss T -i out.mp4 -frames:v 1 f.png - 音樂·音效無法直接聽取,因此透過片段 RMS 確認,並告知使用者自行聆聽。
檔案結構
| 檔案 | 角色 |
|---|---|
scripts/analyze.py | 元數據·類型推測·場景切換·音量峰值·數值條事件·圖表·畫面截圖 |
scripts/crops.py | 原始座標刻度裁剪 |
scripts/tracks.py | 對象追蹤(關鍵影格補間·OpenCV)、驗證圖表 |
scripts/remap.py | 時間重映射 (TRIM·SPEED·FREEZE) |
scripts/build.py | 預覽 / 音訊混合(原始音效重映射·限制器)/ 平行渲染 / SRT |
scripts/tl.py | timeline.py 載入器、設定檔預設值、座標·時間轉換 |
scripts/render.py | 鏡頭(追蹤·晃動)·螢幕錄製層·自訂 Hook |
scripts/fx.py | 通用特效:調色、打擊感、放大鏡、對話框、彈窗、貼紙、徽章、 |
…
[其餘內容因檔案過長已截斷]