華爾街式解讀片 (wallstreet-explainer)
講一筆大帳:真的人、真的新聞、真的畫面作證據,圖形舞台把數字和關係演出來;每一鏡都接住上一鏡的東西往下走,觀眾始終知道「現在在看什麼、為什麼看這個」。 動的是鏡頭和世界,不是元素自己演:鏡頭在有前後層的舞台裡推、拉、搖,去找正在說的那個東西;東西在原地換狀態。每一下動作都對著那句話的意思。
這份 skill 是什麼
-
是:一套設計思路(每一鏡放什麼、為什麼、憑什麼接下一鏡)、一套動效原理(從三條同類參考片逐幀量出來:為什麼它不像 PPT、不像 AI,手法清單和量化目標)、一套風格語言(舞台、巨字、摳像、圓盤、數字、圖表、原文高亮的具體做法,外加一份開頭鉤子選單),以及一套工具。
-
不是模板。沒有能複製的畫面工程,也沒有固定的鏡頭順序。每條片的畫面都要從它自己的文案和素材裡現想。
examples/ai-burn-money/記錄的是一條片子怎麼想出來、在哪裡摔過跤,不要照搬它的鏡頭。 -
慢推、數字滾動、實拍上壓字,參考片都在用。廉價的不是這些手法,是做法。判斷用三句話:刪掉它觀眾少懂了什麼?是鏡頭在動、東西在換狀態,還是元素自己在演出場?這一層是真的、具體的嗎?
動手前先讀 references/thinking.md 和 references/motion.md,再按需求讀其他幾份。
流程:每一站停下來給用戶看
審美由用戶把關。不要一口氣出成片;每站給出具體的東西,等他點頭再往下走。
| 站 | 做什麼 | 給用戶看什麼 |
|---|---|---|
| 0 選題 | 題目要同時滿足「現在熱」和「看完能帶走點什麼」 | 兩三個題目,每個附一句鉤子 |
| 1 文案 | 口語、第一人稱,句句往下接;插原聲的地方先寫鋪墊句(references/audio.md) | 全文。點頭之前不做正式配音 |
| 2 導演表 | 見下面「導演表」一節 | 要點:開頭怎麼抓人、每處怎麼接、要不要加鋪墊句 |
| 3 素材 | 官方高清片 → 新聞原文 → 當事人原聲 → 當事人摳像用的整段實拍(沒有切點、有對得上台詞的動作)。先拼聯繫表看過,再定入點,逐幀查切點(references/sourcing.md) | 關鍵素材(可選) |
| 4 配音和時間線 | scripts/temp_voice.py:先用臨時語音排出時間線,畫面全部掛在字上 | — |
| 5 開頭 | 先挑 3 個機制不同的鉤子,各做 5–8 秒粗剪給用戶選(references/opening.md);選中的再做成從 0 秒到第一個換段處的小樣(15–20 秒,帶聲音) | 3 個鉤子粗剪 → 選中後的開頭小樣 |
| 6 全片 720p | 按導演表鋪完;每寫兩三鏡截靜幀看,關鍵動作看連續幀(strip.py);交片前跑 motion_check.py | 720p 全片、抽幀圖,再點出兩三處請他重點看 |
| 7 成片 | 改到滿意;換正式配音;出 1080p,只渲一次 | 1080p |
每次交付都要做到:
- 用
ffprobe驗證檔案能打開。 - 自己逐鏡看過靜幀和聯繫表,關鍵動作看過連續幀。
- 放進一個固定的審閱資料夾,用編號加中文名命名,舊版本加
舊_前綴。 - 說清楚這版改了什麼、哪些量過、哪些要用戶自己聽或看。
導演表
全片只有這一份計劃。用戶拿它核對畫面,做的時候照它做,審片時拿它對照。每一鏡寫這幾列:
| 鏡 | 時間 | 文案 | 屏上是什麼,在幹什麼 → 停下來時留下什麼 | 觀眾多懂了什麼 | 承擔 | 讀懂時刻 + 停留 | 承接 |
|---|
- 觀眾多懂了什麼:一句具體的話,和上一鏡的不一樣。寫不出來,這一鏡就該刪或者重想。
- 承擔:這一鏡靠什麼讓人看懂。人物 / 實證(真素材、原文)/ 構造(圓盤、圖表)/ 文字(大字、結論)/ 混合。
- 承接:上一鏡留下的哪樣東西被這一鏡接住,接法寫成
續 / 切 / 帶過 / 推近 / 展開 / 換章加上那樣東西。第一鏡寫—。 - 在「屏上」一列裡順手寫清鏡頭怎麼走:每次移動的落點是誰(推到誰、搖去找誰、什麼時候拉回看全),以及哪幾鏡用當事人摳像。
- 文案一字不改;一鏡可以覆蓋好幾句話;時刻掛在詞上(「說到『七千』的那一刻」)。
寫完做一次「讀表」檢查:遮住文案和「多懂了什麼」兩列,只讀「屏上」一列,看還講不講得通。再查有沒有連續好幾處硬切、有沒有停不夠的鏡頭。示例見 examples/ai-burn-money/director.md。
讀哪份
| 在做什麼 | 讀 |
|---|---|
| 想一鏡該放什麼、為什麼、憑什麼接下一鏡 | references/thinking.md |
| 動起來:為什麼不像 PPT/AI、手法清單、量化目標、相機和摳像的程式碼手感 | references/motion.md |
| 畫面長什麼樣:舞台、巨字、摳像、圓盤、數字、圖表、片名、字幕、實拍畫框 | references/style.md |
| 兩鏡之間怎麼接、運鏡和動作的手感 | references/grammar.md |
| 開頭 | references/opening.md |
| 找片、下片、挑入點、摳人、新聞原文、原聲 | references/sourcing.md |
| 文案、配音、原聲剪口、音效、混音 | references/audio.md |
| 交付前自檢 | references/review.md |
| 實踐中踩過的坑 | references/lessons.md |
工具(scripts/)
| 腳本 | 幹什麼 |
|---|---|
footage.py | search 搜片 / get 下載(可只下一段、只下音訊)/ sheet 帶時間碼的聯繫表 / scenes 鏡頭切點 / extract 抽 30fps 幀序列 / wave 看原聲剪口的響度 |
snap_news.mjs | 新聞和報告原文截圖:攔廣告、去浮層、等字體載入完再量關鍵詞的框 |
matte.py | 實拍逐幀摳人(GPU 上 ISNet 約 0.25 秒/幀),提示藏著的切點,只存人物外框那一塊 |
matte_clean.py | 摳像後處理:去細線零碎、整列抹掉貼著的椅背、寫出每幀頭肩中心(放人時跟住他) |
stage25d.js | 頁面裡用的小工具:分層相機、方向運動模糊、景深、摳像跟人、巨字、眉題、實拍退成底、按十億取整。只是工具函數,不是鏡頭 |
temp_voice.py | script.json → 臨時配音(edge-tts)和 timeline.json(每個字的時刻、原聲插段、片名位置);有正式配音時自動換上,--asr 重新對齊 |
render.mjs | 逐幀渲染:--stills 看幀、--video --range 渲一段、--h 1080 出成片 |
strip.py | 連續幀拼圖:一個動作 8 張,查靜幀看不出來的穿幫;也用來拆參考片的動作 |
motion_check.py | 鏡頭運動自檢:畫面完全不動的時間、定住次數、鏡頭在動的時間、前後層、推拉比,和參考片的區間比 |
mix.py | 配音、原聲、音效、配樂(配樂給人聲讓路)→ -14 LUFS;--check 量各段響度 |
依賴:ffmpeg、yt-dlp、Python(edge-tts、numpy、opencv-python、Pillow;可選 faster-whisper;摳人要 onnxruntime-gpu 和 rembg 下載的模型)、Node 和 Playwright。安裝方法見 README。
配音:先用臨時語音
- 先用
temp_voice.py出 edge-tts 臨時配音,排出時間線,畫面照它做。 - 文案和畫面都定了,再換正式配音(任何 TTS、複製音色或真人錄音都可以):每句存成
voice/<id>.final.wav,跑temp_voice.py script.json --asr。 - 配音一律:切掉首尾靜音、保持原速、句間停頓只由
gap決定。不要事後用 atempo 加速,切掉靜音以後再加速會很急促。
片子怎麼搭(骨架,不是拿來抄的)
- 一個片子目錄:
index.html、film.css、film.js、timeline.json、assets/(實拍幀在assets/clips/<名>/,摳像在assets/cut/<名>/)。要用相機小工具就把scripts/stage25d.js拷進來,先於 film.js 載入。 film.js暴露window.ready和window.seek(t)。seek找到 t 所在的鏡頭(shot(t0, t1, fn)),呼叫fn(t)返回這一幀的 HTML,並等圖片解碼和字體載入完。同一個 t 永遠畫出同一幀,不依賴 CSS 動畫和播放時鐘。- 時刻一律寫成
cue(句id, '詞'),從時間線裡取,不寫死秒數。換了配音,全片自動順延。 - 實拍抽成幀序列,按 t 取幀,不用
<video>。幀數要登記,漏了會取到不存在的幀,出現黑屏或空框。 - 一鏡 = 一個機位函數 + 幾層畫面:機位用
camPath(t, 起點, 移動表),每層用L(機位, 上一幀機位, z, html)包起來,遠的層 z 小,運動模糊自動算。 - 鏡頭之間要承接時,把上一鏡的函數在它最後一刻的畫面拿來做下一鏡的開場(推過鏡頭、縮小挪走、撐開、橫推出去)。這樣上一鏡的末態和下一鏡的首態天然一致。
- 720p 看效果,1080p 只在定稿後渲一次。