教學影片
教學影片旨在講解一個機制,讓新手看過一次後就能解釋清楚。每一幀畫面皆由程式繪製,旁白語音是時間軸,音樂則填補語音間的空白。它建立在 code-film 之上:該技能負責外觀、圖庫、品味與缺陷檢查。本技能則負責教學、文字、語音、節奏、結尾以及 YouTube 相關事項。
範例作品位於 examples/parcel42-lesson/,是一個長度 130 秒、關於 Apache Pinot 如何透過 upsert 隱藏舊資料列的教學。技能作者 Kartik 在八個版本後稱其為「完美」,沿途的每一則筆記都記錄在它所屬的參考檔案中。請閱讀其 README 以了解方法,而非外觀。
核心:追蹤觀眾
教學影片是一段對話的一半,觀眾在靜默中提供另一半。在每一秒,觀眾都擁有以下三項:
- 他們已知的內容。 僅限於影片至此已展示與說明的內容,以及日常知識。不包括原始碼,也不包括你為了製作影片而閱讀的內容。
- 他們正在提出的疑問。 每一張圖片與每一個論點都會引發下一個問題:「那麼舊的會怎樣?」、「如果它遲到了呢?」、「那不會浪費空間嗎?」
- 他們相信的內容。 一個僅根據影片建立的機制模型。一個錯誤的詞彙就會植入錯誤的模型。「Pinot 從不拆掉舊房子」暗示了沒有任何東西會被移除,接著影片展示了壓縮正在移除它。
製作影片就是逐秒運行這個模型,並同步考慮語音與畫面:
- 在觀眾產生疑問的地方回答。 遲到的信件緊接在規則之後,「那深色房子呢?」則緊接在查詢之後。
- 在你宣布之前,讓觀眾自己先抵達。 畫面在語音說出名稱之前一個節拍展示證據。標題、標籤或章節名稱絕不會在問題被提出之前給出答案。
- 絕不中斷線索。 承諾某事的一行文字,就擁有下一張畫面的所有權。在「兩個開關翻轉」之後,螢幕上出現的下一個東西就是開關。
- 在花費每個詞彙之前,先將它交給觀眾。 螢幕上的每個術語都會在畫面展示它時被朗讀一次,且沒有任何術語出現在第一行。世界中的事物先出現,術語隨後命名。在那個命名行之外,句子應保持在同一世界:一朵花已停止生長,它絕不是「關閉」。整部影片在路牌上顯示了「第 7 區段」,卻從未說出「區段」這個詞。
- 教導機制,而非程式碼。 只有當觀眾會搜尋它時才顯示真實名稱(如
validDocIds),永遠不要使用僅標示機制的函數名稱。
參考資料中的每一條規則都是這五項原則的應用。當一條規則似乎與另一條衝突,或沒有任何規則涵蓋某個情況時,運行觀眾模型來決定。
一則筆記從不針對單一實例。 當你為之製作影片的人指出某一時刻時,他們是在指出模型出錯的一個地方。找出所有以同樣方式出錯的其他地方,全部修正,並回報數量。Kartik 的「痛苦節拍」既是指填充音,也是指叮噹聲和點擊聲。他「遺漏的字母」是指任何從固定影格計時的事件,這就是 shiftcheck.py 存在的原因。他的「錯誤片語」是指每個絕對詞彙,這就是 scriptcheck.py 列出它們的原因。
設定
此技能需要將 code-film 安裝在與其相同的技能資料夾中。它的建置、閘道、捕捉、接縫和聲音檢查以及手寫功能皆來自該技能,每個腳本都會在該處或 $CODE_FILM 路徑下尋找它。
執行 bash assets/setup.sh 一次。它會檢查 code-film 的 doctor,然後在 ~/.cache/lesson-film/venv 建立一個 Python 3.12 虛擬環境,包含 Kokoro、soundfile、faster-whisper 和 spaCy 英文模型,並檢查 ffmpeg 是否具備 loudnorm 功能。
好的樣貌
- 新手能夠複述。 他們的兩句話與意圖卡上的重點一致,並在正確的位置使用了真實的術語。
- 聽起來像一個人在向你解釋。 每個句子引導到下一個,每個場景切換都承載著觀眾當前的疑問。在不看畫面的情況下朗讀腳本。如果聽起來像是一系列標籤清單,那就還未完成(參閱
reference/words.md)。 - 有呼吸空間。 觀眾在下一項變化發生前,有時間看到每一項變化。Kartik 發現一個 64 秒的剪輯,每秒 0.36 次切換「節奏太快」。獲准的剪輯長度為 130 秒,每秒 0.16 次切換,語音速度正常,並包含真實的呼吸聲(參閱
reference/pace-and-ending.md)。 - 每個陳述都是真實的,並經過檢查。 在任何繪製之前,將陳述寫入
facts.md並對照來源。畫面應精確顯示該狀態。 - 畫面隨詞彙變化。 每個事物應在語音說出它的那一刻出現。動態與色彩僅作用於正在被解釋的部分(參閱
reference/teaching.md)。 - 開頭輕柔,結尾緩慢。 第一行要讓每個人都能理解,且畫面和音樂已經在播放;一個冷開場,以問題結束,然後是大約五秒的標題畫面,就像 Kurzgesagt 的做法。「開頭感覺突兀」是 Kartik 在一部於觀眾尚未認識的角色上開場的影片中所做的筆記(參閱
reference/pace-and-ending.md)。 - 結束,而非停止。 一個回顧、一個收穫、一個呼應開頭的結尾句、一個主和絃,然後畫面和聲音在數秒內一起淡出。「結尾太突然」是永遠不該再收到的筆記。
- 缺陷為零。 沒有閃爍、沒有爆音、沒有削波,響度為 -14 LUFS,每個字都聽得清楚。
這些是判斷,而非規則。當意圖卡說明原因時,可以打破它們。
工作流程
將此複製到你的筆記中,並在完成每一項時回報。一項未說明如何完成就不能勾選。
[ ] 0 參考 僅在他們分享了參考資料時。一個片段、一張定格照或一個 HTML 頁面。回報其形式、作用、哪些差距可以彌補,以及你取用了什麼、留下了什麼。
[ ] 1 事實 根據來源撰寫 facts.md。回報陳述及其檢查位置。
[ ] 2 意圖 將 assets/intent.md 複製為 <piece>.intent.md,包含要點、感受、問題、猜測。回報它們。
[ ] 3 圖庫 code-film 的 reference/gallery.md,找出兩三部最接近的影片。回報你取用了什麼,以及不會複製什麼。
[ ] 4 草稿 三個新故事,每個都是用工具(sketch.py)繪製的、看起來已完成的作品定格照,其中一個是你能夠沉浸其中的世界,且不得取自範例或共享的參考資料。sketchcheck.py 不得有 BLOCK 項目,然後根據評分表進行評判。展示它們。回報每個故事的台詞、三個評判答案以及選擇。
[ ] 5 文字 將整個腳本作為一個段落寫入 <piece>.chain.txt,然後將其剪裁成行,並標明「術語」、「事物」和「技術」。在段落之前,寫下每個術語對應的事物,以及世界對於每個真實狀態的動詞。scriptcheck.py 不得有 BLOCK 項目。回報該對應表、朗讀一遍腳本、每個關鍵轉折點,以及對每個 REVIEW 項目的決定。
[ ] 6 語音 <piece>.lines.json -> voice.py -> heard.py --write。回報長度,以及每個被聽到的詞或未聽到的原因。
[ ] 7 計劃 場景,每個場景都與改變它的詞彙以及它們共享的世界狀態相關聯。回報計劃,包含世界中展示每個術語的事物,以及世界對於每個真實狀態的動詞。
[ ] 8 建置 從 assets/template/ 建立頁面。先單獨在草稿中檢查場景。回報你在查看後重新繪製了什麼。
[ ] 9 聲音 從 assets/score_template.py 建立 <piece>.score.py。回報和絃、間隙中的旋律,以及世界內的聲音。
[ ] 10 渲染 assets/build.sh。先使用 DRAFT=1。回報數字。
[ ] 11 驗證 以下所有三個層級。分別回報每個層級。
[ ] 12 交付 每次建置都產生新檔案,切勿覆寫。為 YouTube 準備的主檔案,以及一個用於發送、小於 30 MB 的預覽檔案。
步驟 1 到 5 是決定教學成敗的關鍵。特別是步驟 5:先將腳本寫成散文,然後再剪裁成行。先剪裁是讓腳本變成一系列字幕的方式。
驗證
在交付說明中分別回報所有三個層級。
- 缺陷區塊。
build.sh會執行scriptcheck.py(每個術語都說過、不在第一行、存在連結)、code-film 的check.py和seamcheck.py,將母帶處理至 -14 LUFS 整合響度,真實峰值為 -1.5 dBTP,並根據 YouTube 規範進行編碼(參閱reference/youtube.md)。 - 教學效果被量化。
verify.py檢查意圖卡的長度、節奏和聲音。heard.py轉錄語音,並指出哪些詞未被聽到,以及聲音落後提示時間多遠。wordsync.py檢查畫面綁定的每個詞是否引發了動態。shiftcheck.py將語音延遲兩秒後重新渲染影片,並找出任何因此變化的場景,由此可以發現從固定影格計時的事件。captions.py根據相同的提示時間撰寫精確的 SRT 字幕。 - 觀看測試是你的,然後是對方的。 像新手一樣複述。說出聯絡表上每個畫格的內容。關掉聲音觀看。在不看畫面的情況下朗讀腳本。單獨評判最後十秒。然後坦白說出你沒有檢查的事項,例如用耳朵聽語音。
何時閱讀什麼
每個檔案應一次性完整閱讀,若閱讀時發現 Token 被截斷,則應單獨再讀一次。code-film 的「何時閱讀什麼」說明了批次閱讀的代價。
- 當他們分享參考資料時,閱讀 code-film 的
reference/references.md。它涵蓋了所有三種形式。片段和定格照需要使用 ffmpeg 進行拆解。一個 HTML 頁面(無論是我們的還是他們的)則透過 code-film 的assets/refpage.mjs處理,該工具會觀察頁面繪製過程,並回報其調色盤、標記、圖層和音訊工具,同時寫出一個 MP4 檔案,以便片段檢查也能在其上執行。 - 在事實與意圖卡之前,閱讀
reference/teaching.md。 - 在草稿之前,閱讀本技能的
reference/sketches.md及其reference/traps.md中的「故事」章節。然後閱讀 code-film 的reference/story.md瞭解「先選形狀」和「什麼會持續存在」,以及 code-film 的reference/traps-story.md。 - 在你撰寫腳本的任何一行之前,閱讀
reference/words.md。 - 當你規劃開頭或結尾,以及設定語音的速度、呼吸和停頓時,閱讀
reference/pace-and-ending.md。 - 當你製作或修正語音時,閱讀
reference/voice.md。 - 當你規劃場景、將場景拆分給輔助功能,或建置頁面時,閱讀
reference/film.md,以及 code-film 的reference/moves.md,後者負責兩張畫面之間的動態。 - 當你製作聲音時,閱讀
reference/sound.md,以及 code-film 的reference/sound.md以了解樂器,和 code-film 的reference/traps-sound.md。 - 在首次渲染之前,以及收到任何關於渲染的筆記之後,閱讀
reference/traps.md。 - 在發布之前,閱讀
reference/youtube.md。 - 當一條規則需要其來源,或有人詢問技能為何如此運作時,閱讀
reference/research.md:包含證據、效應大小和連結。 - 關於外觀、品味和最終印刷效果,閱讀 code-film 的
gallery.md、taste.md和press.md,並在調整最終效果之前閱讀 code-film 的traps-print.md。
檔案列表
| 檔案 | 說明 |
|---|---|
assets/setup.sh | 一次性設定:語音和聽力虛擬環境,以及檢查項目 |
assets/intent.md | 教學意圖卡,基於 code-film 的卡片並加入教學相關的行 |
assets/voice.py | 使用 Kokoro 朗讀 <piece>.lines.json,將語句排在節拍網格上,寫出語音和提示時間 |
assets/heard.py | 使用 Whisper 轉錄語音,回報遺漏的詞彙和延遲,--write 將延遲寫入提示時間 |
assets/saytest.py | 嘗試 Kokoro 說錯的詞的不同拼寫,並找出 Whisper 能正確聽到的拼寫 |
assets/captions.py, assets/wordsync.py | 從提示時間產生 SRT 字幕,以及檢查每個綁定詞是否觸發動態 |
assets/shiftcheck.py | 檢查每個場景是否從語音計時,而非從固定影格 |
assets/scriptcheck.py | 腳本檢查:術語都說過、不在第一行、每個術語的事物在術語之前說過、存在連結,以及絕對詞彙、未說出的螢幕詞彙和混合世界與真實系統的句子列表(供閱讀) |
assets/sketchcheck.py, assets/barsheet.py | code-film 的草稿檢查,使用此技能已獲准的影格、範例的城鎮和模板的存根。以及重建評分表的腳本 |
assets/score_template.py | 每行一個背景音、間隙中的旋律、狀態變化時的世界內音效、語音下方 16 dB 的壓低、淡出結尾 |
assets/build.sh | 頁面、閘道、並行捕捉、接縫、配樂、-14 LUFS 母帶、編碼、字幕、聯絡表、所有檢查 |
assets/template/ | 要複製的頁面:assemble.py、film/kit.js(不含世界內容的工藝:墨水、點、邊緣、光線、手寫、印刷效果)、film/core.js(語音時鐘、圖層、攝影機、潛入和虹膜動態)、film/main.js、film/SCENES.md、一個示範如何建立一個臨時物件的場景,以及包含 sketches/sketch.js 的 sketch.py(用於三張故事定格照) |
reference/stills/ | 來自已獲准教學影片的影格,附有說明文字,用於說明散文無法清楚傳達的兩條規則:開頭和結尾的節拍,以及隨詞彙變化的畫面。此外還有草稿評分表 sketch-bar.jpg(僅在你完成自己的三張草稿後才打開)以及 sent-back.jpg |
examples/parcel42-lesson/ | 已獲准教學影片的完整原始碼、語音軌道、可供觀看的預覽連結、其 README、聯絡表和縮圖 |
並行捕捉功能位於 code-film(assets/capture-range.mjs、assets/capture-par.sh),因為任何較長的影片都需要它。
修改此技能
說明意圖與判斷,並根據意圖檢查結果。一個獲得批准的新教學影片將成為第二個範例,並在此檔案中添加一行說明其運作原因。一個學到的教訓將記錄在其所屬的單一參考檔案中,所有其他檔案都會在其中一行指向該檔案。