用程式碼拍電影
電影就是一個程式。每一幀畫面都是你撰寫的、時間的純函數,而旁白、音樂與每一個音效也都來自程式碼。過程中不涉及任何圖片或影片產生器。因此,任何一秒都可以被修改並重新渲染;另一個語言版本只需重新執行一次,而不是重新剪輯。
這個流程已成功製作了一部 5 分 16 秒的俄語與英語電影:包含 16 個節拍、57 個提示點、10 個 3D 插入畫面,從腳本到第一種語言版本約需 1.5 至 2 小時,每種語言在筆記型電腦上渲染約需 14 至 16 分鐘。該電影的程式碼位於 assets/examples/court-astronomer/。
核心概念:語音優先
先撰寫帶有標記的腳本。讓語音服務朗讀它,並回報每個單詞的時間點。如此一來,每個標記就變成了一個絕對秒數,而畫面與音效都依附於這些秒數。
Придворные астрономы {plant}поставили её на карту и {cut}записали дату.
CUE.plant = 9.21 手放下星星:咚,火花
CUE.cut = 10.50 切到文書,羽毛筆開始書寫
每種語言根據各自的錄音產生自己的時間軸,因此俄語與英語電影無需額外工作就能有不同的剪輯方式,且改寫一個句子後,其後的所有內容都會自動移動。這就是為什麼下面的順序是:腳本、語音、畫面、音效,而永遠不會先處理畫面。
script/script.json ─ tools/tts.py ─> audio/voice/<lang>/ + web/timing_<lang>.js
│
┌─────────────────────────────────────────┴───────┐
web/film.js + shots + space.js audio/score.py
│ render.py │
renders/film_<lang>/film_<lang>.mp4 audio/mix/<lang>.wav
└───────────────── tools/finish_film.py ──────────┘
final/<stem>.mp4, -phone.mp4, .srt
開始一個專案
python <this-skill>/scripts/check_env.py
python <this-skill>/scripts/new_project.py <folder>
將專案放在有足夠空間的磁碟上,放在一個以電影名稱命名的資料夾中,路徑要短。幀畫面會串流到編碼器,不會儲存,因此一部 5 分鐘的電影大約需要 1 GiB。
新的專案是一個可運作的 25 秒示範,主題是月相,包含兩種語言。執行 new_project.py 所輸出的指令,然後在修改任何東西之前先查看聯絡表:如果示範可以運作,那麼之後的任何失敗都是你的問題,而不是機器的問題。
模板的狀態。 這個流程確實製作出了真正的電影,但這個模板是之後從中提取出來的。在示範中,tts.py、混音與音效檢查都已經執行過。交付工具已在一個黑色片段上執行過,render.py 則在佔位的頁面上執行過,而平面的畫面邏輯則在每一幀上對兩種語言的佔位畫布執行過。這個模板從未繪製過真正的幀畫面,而且它的 3D 鏡頭也從未運作過。所以,第一批靜態畫面同時也是對模板的測試:如果它們失敗了,請與 assets/examples/court-astronomer/ 進行比較,那是真正渲染過的程式碼。
然後替換內容,保留機制:
| 每部電影需更換的部分 | 通常保留不動的部分 |
|---|---|
script/script.json | tools/ |
web/shots.js (平面鏡頭) | render.py, server.py |
web/film.js: SHOT 和 SEQ | web/main.js, web/lib.js, web/labels.js |
web/space.js: 建構器 | web/space.js: 其上方的工具集 |
audio/score.py | audio/mixlib.py, audio/synth.py |
工作流程
將耗時超過兩分鐘的指令在背景執行。如果機器有任務佇列或散熱規則(請查閱專案筆記與記憶體),請透過它們來執行渲染。
1. 確認需求
只詢問你無法預設的項目:主題、語言、發布平台。預設解析度為 1920x1080,24 fps,-15 LUFS,長度由腳本決定。在完善任何部分之前,先建立一部完整的粗剪電影。人們對於整部電影的評價遠比對於完美的十秒鐘要來得更好,而且他們常常會直接說頂級品質可以等。
2. 閱讀參考資料(如果有的話)
測量它而不是猜測:剪輯點、節奏、色調、角色更新頻率、線條粗細、顆粒感。你可以在瀏覽器中逐幀進行,無需下載影片。閱讀 references/reference-analysis.md。將數據簡短地寫成樣式表,放在專案的 README 中。
借鑑技巧,捨棄內容。創造你自己的角色、故事與設計。不要重複使用參考資料中的幀畫面、角色、標誌或可辨識的曲調,也不要重新創作特定的作品,即使換個名稱也不行。
3. 製作 10 秒的試作
一個最終風格的鏡頭,無聲。這裡可以使用硬編碼的時間,因為這只測試外觀。將它發送給使用者。這是整個專案中改變方向成本最低的時刻。
4. 收集事實,撰寫腳本
閱讀 references/script-and-voice.md。將電影分解成 10 到 35 秒的節拍,每個節拍包含一個想法,通常也是一個鏡頭。預算字數:俄語約每分鐘 125 字,英語約 150 字,包含停頓。在需要螢幕上發生某件事的單詞上放置提示點。
在電影中(而不僅僅是在你的筆記中)明確區分確切的事實與詮釋。如果你需要計算某個數據,請將數據保留在電影會讀取的檔案中,這樣螢幕上顯示的就是數據告訴你的內容。
如果主題敏感,或者使用者要求批准,請向他們展示腳本。否則就繼續進行,讓他們對電影做出反應。
5. 語音,然後時間軸
python tools/tts.py
它會列印出每個提示點,格式為 name=word@seconds。閱讀這些行:在錯誤的單詞上發現提示點,在這裡處理起來成本低得多。檢查總時長是否符合目標。如果時間太長,請刪減文字;不要將語音速度調快超過約 +10%。
6. 撰寫鏡頭
閱讀 references/picture.md。螢幕上的一切都是 (g, t) 的函數,而每個時間都源自 CUE 或 BEAT。平面鏡頭使用 Canvas 工具集繪製;3D 鏡頭透過合成器渲染到同一個 2D 畫布上。在每一幀結束時進行一次顆粒感處理,並使用一組標籤,使兩者看起來像同一部電影。
7. 查看靜態畫面,修正,重複
python render.py renders/check "lang=ru×=25,66,241,273"
python tools/contact.py renders/check 4
閱讀 references/review-and-render.md,了解如何選擇時間點以及要注意什麼。打開聯絡表並仔細檢查:大多數缺陷在程式碼中看不見,但在圖片中卻很明顯。將你的問題分批提出。連續進行審查渲染是讓筆電發燙、會議變慢的原因。
8. 撰寫音效
閱讀 references/sound.md。段落從語音節拍開始,音效使用與畫面相同的提示點名稱,音樂在語音下方降低音量,混音達到 -15 LUFS。
python audio/score.py ru
python tools/bands.py ru
python tools/qa_audio.py ru whisper
你無法聽到它,所以要依靠數據。目標是在每個節拍上,語音音量比其餘部分高出約 10 dB;真正的電影落在 6.7 到 14.2 dB 之間,大部分是 7 到 9 dB,所以不要低於這個範圍。明確說明還沒有人聽過它。
9. 每種語言的靜態畫面,然後完整渲染
python render.py renders/check_en "lang=en×=25,66,241,273"
THREADS=6 CRF=17 python render.py renders/film_ru "lang=ru&fps=24&file=film_ru.mp4"
先讓每種語言的靜態畫面都通過測試。一種語言的小數點逗號錯誤,會導致之後需要完全重新渲染。一次只執行一個繁重的工作。僅更改音效不需要重新渲染畫面:重新製作混音並再次執行 finish_film.py 即可。
10. 交付、清理、報告
python tools/finish_film.py ru
python tools/telegram_copy.py ru
python tools/chapters.py ru
閱讀 references/delivery.md,了解平台副本、描述與報告的相關資訊。除非使用者要求該特定貼文,否則切勿代替他們上傳或發布。將草稿移至資源回收筒,而不是刪除它們,並保留最終版本以及重新製作它們所需的一切。
最能減少重工的規則
- 每一幀畫面只依賴
t。 沒有時鐘、沒有未設定種子的隨機數、沒有從前一幀繼承的狀態。否則靜態畫面會與電影不符,而部分重新渲染也會與其前後幀不符。 - 時間來自提示點。 從提示點偏移是可以的。手動輸入的絕對秒數在另一種語言中或任何改寫後都會失效。
- 所有螢幕上的文字都透過
T_,數字也不例外。29,5 дня和29.5 days是不同的字串。這就是真實電影的英語母版中出現的錯誤:一個23,4°。 - 不要假設跨語言的提示點順序。 單詞順序不同,因此
CUE.a < CUE.b可能只在其中一種語言中成立。由兩個提示點構成的區間需要保護。 - 標籤是 2D 的,使用
project()放置。 這樣它們就能與平面鏡頭共享字型、顆粒感處理和語言處理。 - 將攝影機保持在會旋轉的物體之外。 在聯絡表上檢查動作的極端位置,而不僅僅是中間位置。
- 靜態圖層放入
plate()中。 每一幀都重新繪製複雜的背景是造成渲染緩慢的原因。 - 先修改,再查看,然後報告。 在你看到那幀畫面之前,不要說某個問題已修復。
你無法檢查,且必須說明的項目
- 音效。 你能看到音量、平衡、頻譜圖和轉錄稿。但你不知道它聽起來如何。
- 流暢度。 你看到的是幀畫面,而不是觀看者的體驗,因此節奏是你最弱的判斷。請特別向使用者詢問關於節奏的意見。
- 平台。 你無法知道一個檔案在使用者的 Telegram 或 YouTube 帳號中表現如何。
報告哪些已驗證、哪些未驗證,並使用這些詞彙。決策(想法、方向、要刪減的內容)屬於使用者。
包含的檔案
| 路徑 | 這是什麼 | 何時閱讀 |
|---|---|---|
references/reference-analysis.md | 經過測試的瀏覽器程式碼片段,用於測量影片、樣式表模板 | 有參考影片時 |
references/script-and-voice.md | script.json、提示點語法、字詞預算、聲音、事實 | 撰寫腳本之前 |
references/picture.md | 時間軸、平面工具集、根據提示點演出、文字、顆粒感、3D 工具集、範例程式碼地圖 | 撰寫鏡頭之前 |
references/sound.md | 樂器、樂譜結構、語音鏈、混音數值、檢查 | 撰寫樂譜之前 |
references/review-and-render.md | 在聯絡表上要注意什麼、渲染模式與選項、負載 | 第一次審查之前、完整渲染之前 |
references/delivery.md | 母版、手機版、Telegram、YouTube、X、字幕、清理、報告 | 最後 |
references/pitfalls.md | 症狀、原因、解決方案,涵蓋整個流程 | 當某些東西看起來不對勁時 |
scripts/check_env.py | 機器有什麼 | 首先 |
scripts/new_project.py | 從模板建立專案 | 第二步 |
assets/template/ | 專案骨架,一個可運作的示範 | 由 new_project.py 複製 |
assets/examples/court-astronomer/ | 真實電影的程式碼:10 個 3D 建構器、平面鏡頭、一個手的骨架、完整的樂譜 | 搜尋其中某個技巧;它無法獨立執行 |