Communitygithub.com

li-code-animation

用代码製作初中數學知識短影音(函數圖像、幾何作圖、公式推導、概念辨析),16:9 MP4,畫面由 HTML/CSS/SVG 寫死座標、GSAP 編排動作、無頭 Chromium 逐幀截圖、FFmpeg 編碼,預設無旁白只畫面加字幕、預設深夜光軌深色風、六鏡結構、交付前必過六道自檢。

li-code-animation 是什麼?

這個技能(li-code-animation)專門用於將初中數學中難以口頭說明的概念(如函數圖像、幾何作圖、公式推導與概念辨析)轉化為 90 秒左右的程式碼動畫短片。其核心技術鏈固定為四步:HTML/CSS/SVG 精確定義畫面、GSAP 控制時間線與補間動畫、無頭 Chromium 逐幀截圖、最後由 FFmpeg 編碼成 16:9 的 H.264 MP4 影片。它預設使用深夜光軌深色視覺風格,無旁白,僅以畫面與字幕呈現,結構採用固定的六鏡骨架(鉤子、問題、驗證、推論、糾錯、收尾),確保教學邏輯連貫。用戶交付前必須通過六道自檢(lint 合規、六鏡皆有畫面且無 JS 錯誤、元素不越界、時序正確、口徑符合數學規則、成片參數達標),以保證品質。此技能主要支援 Claude Code 等 AI 代理,但強調 AI 僅負責工程協調與排程,畫面與動畫邏輯由開發者手寫,確保精準度。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MathLiLiLi/li-code-animation/tree/main

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Li 的程式碼動畫技能

一句話定位:把數學課上一個「說不清」的地方,做成一支 90 秒、能反覆暫停看、公式永遠排得正的程式碼動畫片。

核心技術鏈固定為四步,不用 AI 生成畫面:HTML/CSS/SVG 定畫面 → GSAP 排時間線 → 無頭 Chromium 逐幀截圖 → FFmpeg 編成 H.264 MP4。HyperFrames 只做工程契約與排程,它不生產任何一幀——它是台印刷機,稿子得你自己寫。

前置條件(開工前先查,缺項不要往下走)

在專案根目錄執行 npx -y [email protected] doctor,下列四項全綠才繼續。

軟體版本用途缺了會怎樣怎麼補(Linux/雲電腦)
Node.js≥22跑 CLI 與腳本全流程起不來nvm install 22
FFmpeg 和 ffprobe4.x編碼、抽幀、參數核對只有 ffmpeg 沒有 ffprobe,匯出與核對都會失敗apt install ffmpeg(自帶 ffprobe),不要用第三方套件管理器裝,容易只裝半套
Chromium / Chrome 無頭近兩年版本逐幀取景出不了圖apt install chromium,雲電腦一般在 /usr/local/bin/chromium
GSAP3.x 本地檔案時間線與補間引用 CDN 會靜默黑屏,無報錯從本技能 assets/gsap.min.js 拷進工程 assets/

自檢另需三樣(缺了只是自檢打折,不影響出片):

工具用途缺了怎麼辦
playwright-core六鏡自動截圖npm i playwright-core
ffmpeg 的 scale 濾鏡截圖亮度診斷自動降級為只做 DOM 診斷
zip打原始碼包改用 tar.gz,並在交付說明裡寫明

五個必踩的坑

  1. ffmpeg 與 ffprobe 必須同時存在,很多系統只裝了前者。
  2. 不要用 winget / 可攜包混裝,PATH 裡指向的版本會對不上。
  3. GSAP 一律本地檔案,禁止 CDN;CDN 斷連的表現是全片黑屏而不是報錯。
  4. 瀏覽器在軟體渲染下跑(日誌出現 BeginFrame did not run 是正常的),不用折騰顯卡。
  5. 渲染預設碼率只有約 500 kbps,1080p 正常應 3–8 Mbps。不顯式指定碼率,深色細線必糊。見第六節。

路線選擇:預設走 A,需要旁白或複雜畫面才走 B

A 軌 · 純圖形(預設)B 軌 · 旁白/複雜畫面
適合函數圖像、幾何、公式推導、概念辨析要旁白講解、要手/角色/地圖/3D、要配樂成片
畫面本技能六鏡 HTML+SVG,座標寫死調用 code2video 技能:film.json 劇本 + 積木庫
聲音預設無旁白,字幕即畫面文字;BGM 使用者後期自配TTS 旁白 + 配樂 + 響度對齊
命令npx [email protected] rendernode $C/tools/make.mjs <片目錄> film
何時改道使用者明確要「有講解聲/要配音/要有旁白」,或畫面需要真人動作、地圖、角色使用者只要畫面和字

B 軌的能力繼承但不複製:不把 code2video 的 engine/kits/presets 搬進本技能(約 20MB,且會造成兩個技能各自升級後版本漂移),改為呼叫它已安裝的那份。橋接細節見 references/two-tracks.md。分鏡腳本兩軌通用,A 軌分鏡可轉成 B 軌的 film.json(scripts/story-to-filmjson.mjs)。

收到任務後執行流程

0 · 環境自檢

npx -y [email protected] doctor
ls assets/gsap.min.js

缺項時給出安裝命令並暫停等使用者裝好,不要假裝能跑。

1 · 追問補全(使用者通常只給一句話)

老師開口多是二十個字:「用程式碼做個影片,講虛數,x²=-4 到底有沒有這樣的 x。」剩下的規格由你補齊,只問四問,每問給現成選項:

問為什麼必須問建議預設
口徑停在哪決定數學結論對不對,是全片唯一會「講錯」的地方停在不需要新概念的那一步
時長與段落決定切幾鏡90 秒六鏡
分鏡誰來定使用者可能已有板書順序你寫,先給他看
受眾年級決定深度與用詞按主題所處學段

畫風不問:預設深夜光軌深色風(使用者已鎖定)。除非使用者指定白底。

使用者說「你看著辦」時,把預設值寫成一句話回給他(「按深色、90 秒、六鏡、只到這一步做,不對就喊停」),他只需點頭。

2 · 出六鏡分鏡,等使用者點頭

按第三節骨架寫一張分鏡表:鏡號、時長、畫面要素、字幕原文、該鏡要解決的一個問題。只給分鏡,不寫程式碼。使用者說「可以」再進第 3 步。此步返工成本最低,務必等確認。

3 · 建工程

node <技能目錄>/scripts/init-project.mjs --name <工程目錄> --title "<片名>" --scenes 6

腳本會:拷 assets/project-template/ 的六鏡骨架與 index.html、拷 GSAP、生成 verify-seeks.json 骨架。不用手工 npx hyperframes init,模板已符合契約。

模板內容就是「反比例 k 的幾何意義」那支的完整六鏡(深色版),可直接複渲出同款;換主題時保留它的座標體系、時間軸與樣式,只改文案和 K 值,比從零寫快得多。

4 · 逐鏡寫畫面

  • 六鏡各一個檔案:compositions/scene-1-hook.html … scene-6-outro.html;index.html 只做掛載,不要把內容寫成一個巨型 HTML。
  • 座標全部寫死,不靠流式佈局:先定原點與比例尺(例:OX=460, OY=620, S=96,1 單位 = 96 像素),所有點由它算。
  • 曲線按函數取樣生成 path,不許手畫近似。
  • 公式與配色按 references/visuals.md;口徑按 references/math-rules.md。

5 · lint

npx -y [email protected] lint

必須 0 錯誤 0 警告。有報錯就按報錯改,改完重跑。

6 · 六鏡截圖(自檢 1–3)

node <技能目錄>/scripts/verify.mjs --browser=/usr/local/bin/chromium

每鏡 seek 到資訊最全的那一秒截圖到 verify-shots/,同時診斷 GSAP 是否載入、時間線是否註冊、元素是否溢出、有無 JS 錯誤。逐張自己看,不是跑完就沒事。

7 · 抽幀核對(自檢 4)

對上一版成片抽 16 幀拼板,確認每段關鍵元素真的在自己聲稱的時刻出現。做法見 references/qa.md。

8 · 渲全片(必須顯式給碼率)

npx -y [email protected] render --output <name>.mp4 --quality delivery --video-bitrate 3M

--video-bitrate 與 --crf 互斥,二選一。90 秒 1080p 成品正常 15–25MB;低於 10MB 說明壓過頭了。

9 · 成片參數核對(自檢 6)

node <技能目錄>/scripts/inspect-video.mjs <name>.mp4 --expect-duration 90

核對解析度、幀率、總幀數、時長、碼率、體積;任一項不合格就回第 8 步重渲。

10 · 交付

zip -qr <name>-project.zip <工程目錄> \
  -x "<工程目錄>/node_modules/*" -x "<工程目錄>/verify-shots/*" \
  -x "<工程目錄>/.verify-tmp/*" -x "<工程目錄>/*.mp4"

交付三件:成片 mp4、純原始碼工程包(排除 mp4)、三條說明(講了什麼、替使用者定了什麼、哪幾處請老師複核)。只發檔案不算交付。

三、六鏡骨架(90 秒基準)

時長可按要求縮放,但結構順序不要變:先勾住,再推一步,再推廣,再落推論,再糾錯,最後收。

#鏡 id起點/時長這一鏡的任務必含
1s1-hook0 / 10拋一個真問題,讓人想往下看主圖形定格 + 右側三行提問 + 底部圖註
2s2-q110 / 20在最簡單的情形裡把關鍵量算出來座標軸、曲線、動點、矩形/三角形、逐行字幕
3s3-other30 / 18換象限驗證同一結論四支曲線依次點亮 + 結論卡
4s4-triangle48 / 15把結論拆成一半,給出大前提幾何塊 + 直角標記 + 三行推論
5s5-table63 / 12糾最常見的錯細線表 + 錯誤卡(帶刪除線)+ 正確卡 + 金句
6s6-outro75 / 15換座標尺度複述結論,收住同構圖縮小版 + 居中三行 + 脈動強調

index.html 掛載要點:body 背景寫死底色(深色 #050a14),六鏡 track-index 0–5 連續,start/duration 與上表對齊,全片 title 寫「主題|角標名」。

四、數學口徑速查(寫錯就是教學事故)

硬約束,逐條都要落到畫面。完整清單與反例見 references/math-rules.md。

  1. 只推符號,不代數字。講反比例只到 |k| 與 ½|k|,全片不出現「4」這類具體值;講一般結論時同理。
  2. 分數一律水平分數線,不用斜槓、不用 a/b 寫法。
  3. 三角形符號作 S 的右下角標,不是與字母平排。
  4. 用「公共點」,不用「交點」。
  5. 負數情形表述固定:「k<0 時,二四象限亦是如此」。
  6. 同一概念全片一個詞,不換說法;字幕用語與教材一致。
  7. 結論出現前,畫面必須已經把依據畫出來;不許「結論先出、依據後補」。

五、視覺速查(預設深夜光軌)

完整色值與實現見 references/visuals.md。記住三條深底鐵律,其它都可調:

  1. 面積類填充降到 18% 並加描邊——深底上 40% 的填充會糊成霧。
  2. 三角形/幾何塊用「琥珀輪廓 + 極淡青填充」——金色實心疊在深藍上會變成髒橄欖色。
  3. 表格不用底色,用細線分隔——白底表格直接搬過來會三行連成一片。

字號整體比白底版大 4 號;左上角角標固定 Vibe 知識大賞 | 本鏡小標題,26px、字距 5px、left 84 / top 70。

**字體鐵律:分三類角色——中文 Noto Sans CJK SC(思源黑體)、拉丁標籤與數字 Inter、數學符號 TeX Gyre Termes 襯線斜體(與 Times 同族,和教材字母形態一致)。@font-face 必須寫在 <template> 的 <style> 裡(放 head 會被取景 harness 丟掉,字體靜默不載入)。細節與四個坑見 references/visuals.md 第零節。

六、渲染與碼率

參數取值說明
--qualitydelivery高畫質檔,預設檔會掉碼率
--video-bitrate3M必須顯式給;與 --crf 互斥
--resolution預設 landscape(1920×1080)4K 只在明確要求時用
--resume中斷後續渲已渲幀不重來

判據:90 秒 → 體積 15–25MB、碼率 1.5Mbps 以上、2700 幀、時長 90.000000s。數字不對就重渲,不要交付。

清晰度不夠時(實測:--video-bitrate 不生效)

2026-11 實測:--video-bitrate 30M 渲出來仍是 1.8Mbps,--quality delivery 也一樣。 也就是內置編碼的碼率參數基本被忽略,交付級清晰度只能自己接管編碼。使用者說「看不清」時按這條路走,別再反覆調 --video-bitrate:

# 1) 只渲幀,不編碼(2700 幀 / 約 2.4GB / 16 分鐘)
npx -y [email protected] render --format png-sequence --output pngseq

# 2) 自己編碼。靜止內容多、文字細,必須用 CBR 而不是 CRF(CRF 只給 0.5Mbps,平台二次轉碼必糊)
ffmpeg -v error -framerate 30 -i pngseq/frame_%06d.png \
  -c:v libx264 -b:v 4M -minrate 4M -maxrate 4M -bufsize 8M \
  -preset slow -tune animation \
  -x264-params "nal-hrd=cbr:aq-mode=3:chroma-qp-offset=-2" \
  -pix_fmt yuv420p -movflags +faststart -y out.mp4

chroma-qp-offset=-2 是給彩色細筆畫用的:青字、琥珀字在 4:2:0 色度取樣下邊緣會掉色,這一項讓色度比亮度多給一點碼率。

約 2 分鐘編碼,得 90s / 43MB / 4Mbps。40MB 這條線是「課堂能放、平台轉碼後還清楚」的平衡點;低於 10MB 的檔案在手機端一看就軟。要投平台(影片號/抖音)再加一檔 -b:v 8M 的母版(約 85MB),平台轉碼後仍能保住文字。

不要指望 4K 超取樣:軟體 GPU 下 2700 幀要跑一小時以上(實測 20 分鐘才到 8%),單條片子的工期撐不住。

編碼後必須抽一幀 1:1 看(crop=760:300 看文字邊緣有沒有塊狀/振鈴),不能只看整體縮圖——縮圖看不出糊。

音效(點狀音效,不是 BGM)

使用者說「加點聲音」「太靜了」但沒要 BGM 時,只鋪點狀音效:畫面每發生一個動作才響一次,響完就歸零。數學講解片上了背景音樂會削弱思考感,也會蓋住老師自己的旁白。

# 1) 按分鏡動作點寫時間線(絕對秒),範例見 assets/sfx-events.example.json
python3 <技能目錄>/scripts/make-sfx.py events.json -o sfx.wav --duration 90

# 2) 拷影片流、只混音軌(畫面一個像素都不動)
ffmpeg -v error -i in.mp4 -i sfx.wav -c:v copy -c:a aac -b:a 128k -shortest \
  -movflags +faststart -y out.mp4

六種音效各管一件事:brush 曲線/線段生長、slide 動點勻速滑動、tick 一行文字出現、ding 卡片/標題/問句、thump 最關鍵的那個量、chime ✓/金句/片尾。

三條規矩:

  1. 不給每行字都響——只挑「畫面動作」,90 秒片 30 個點左右就夠,密了就吵。
  2. 峰值壓在 -16dBFS 以內,tick 落在 -29dB 上下、thump/ding 落在 -24dB 上下,這個量級「聽得見但不搶戲」。
  3. 混完用 ffmpeg -ss <t> -t 0.6 -af volumedetect 抽查:有音效處應 -24~-30dB,空白處應 -91dB(真靜音)。有音效處高於 -18dB 就調小。

七、六道自檢(交付前必須全過)

#查什麼命令通過判據
1結構合規npx -y [email protected] lint0/0
2六鏡有畫面scripts/verify.mjs六鏡全部出圖,無黑屏、無 JS 錯誤
3元素不越界同上,看診斷報告無溢出條目;字幕距底 ≥80px
4時序真出現抽幀拼板(見 qa.md)每段元素在自稱時刻已出現,無空段
5口徑正確對照 math-rules.md 逐鏡讀字幕七條全過
6成片參數scripts/inspect-video.mjs解析度/幀數/時長/碼率/體積全達標

第 1、2、3、4、6 查由機器判,人複核;第 5 查只能人做——它是唯一能擋住教學事故的一道。

八、修改迭代的規矩

使用者提意見要按「三件套」接:哪一鏡 / 哪一秒 / 改成什麼。含混的「這裡不太對」要反問定位,不要整段重做。

改完必須重跑:改動涉及座標或字號 → 1+2+3;涉及文案 → 5;涉及多個鏡頭 → 全部六查。

一次攢幾條一起改比反覆小修更快,但跨鏡的大改要重出分鏡確認。

真實修訂過程(十條實錄)見 references/revisions.md。

九、禁止事項

  • assets/gsap.min.js 缺失或改用 CDN
  • 用 scaleX/scaleY + transformOrigin 做 SVG 線段生長(只從一端長)
  • 用 onUpdate 驅動 SVG 屬性(seek 時不觸發,截圖會錯)
  • 補間 letterSpacing、width 等會觸發回流的屬性
  • d="" 時先調 getTotalLength()(必須先給哨兵 d)
  • 渲染不提碼率
  • 把全部內容寫進一個 HTML
  • 公式用斜槓表示分數
  • 交付時只發 mp4 不說改了什麼
  • SVG <text> 裡塞 <sup>(HTML 標籤進 SVG 會讓整段文字跑位;上標一律用 ² 字元)
  • 在滿寬(1920)的容器上做 scale 脈動(放大 4% 就撞邊界,第 3 查直接判溢出;scale 掛在容器內的 inline-block 上)
  • 把絕對定位的刪除線放在目標文字的兄弟位置(會橫跨整列;要放進那個文字自己的相對定位容器裡)
  • 用 repeat: -1 做循環脈動(子組合沒有 data-duration 時 lint 必報錯;改成有限的重複次數)
  • 在工程根留任何暫存 .html(會被當成第二個 root,lint 報「只能有一個 index.html」)
  • 曲線畫兩條 path(亮線 + 光暈)時只給亮線設 dasharray/dashoffset(光暈會整條提前顯影,看起來像「還沒畫完就有一段暗影」;兩條都要設、同一時刻補間)
  • 用 --video-bitrate 追清晰度(實測不生效,見第六節)
  • 編碼只給 CRF 不看體積(靜止內容 CRF 只出 0.5Mbps,平台轉碼後必糊)
  • 用系統預設字體渲染字母數字(system-ui 在無頭 Chromium 裡是 DejaVu Sans,字母數字呆板;一律 "Inter", sans-serif)
  • 在 font-family 裡寫中文名(如 "Noto Sans SC",沒裝會被 lint 判 font_family_without_font_face)
  • 座標軸只畫兩條直線、不在端點畫正方向箭頭(教材規範:x 朝右、y 朝上,各一個實心箭頭,寫法見 references/visuals.md 的「座標軸」一節)

九·五、給舊工程補字體

老工程(字體還是 system-ui)不用重建,跑一條命令就能升級到三分角色字體:

node scripts/apply-fonts.mjs --project <工程目錄>

它做五件事:拷字體到 assets/fonts/、把 @font-face 併進 <template> 的 <style>(head 裡的會被取景 harness 丟掉)、給 .row/.cap/.tag 容器鎖 Inter、把正文裡的裸變數 x/y/k/S 逐個包成 <i>(純 CSS 選擇器管不到裸文字,這是最常見的「改了字體卻沒變」的原因)、把 SVG 的 font-family 換成 'Termes', serif 並給 x/y/k 加斜體。數學符號統一 calc(1em + 2px),補襯線相對無襯線的視覺收縮。冪等,重複跑不會重複插入。

改完照常跑:lint → verify → render,必須重渲,字體不會在舊成片上生效。

十、參考檔案

檔案什麼時候讀
references/pipeline.md第一次做,或要給人講清四步怎麼串起來
references/math-rules.md寫任何公式與結論之前
references/visuals.md定配色、字號、卡片、公式排版時
references/prompts.md追問補全、寫分鏡、教別人怎麼說第一句
references/revisions.md使用者提意見、或要給教研組講「改十遍是怎麼回事」
references/qa.md每輪自檢、判斷一片能不能交
references/two-tracks.md需要旁白/配樂/手/地圖/角色,改道 B 軌時
assets/project-template/建工程時由 init-project.mjs 拷貝,不要手改
assets/gsap.min.js建工程時拷進專案 assets/

相關技能