動畫 GIF
三個工具,一個組裝核心。根據輸入選擇對應的路徑。
| 輸入 | 工具 | 動作 |
|---|---|---|
| 帶有 ANSI 顏色的文字影格 | bin/ascii_gif.py | 影格序列 |
| 照片或圖片資料夾 | bin/pics_gif.py | 靜止、淡入淡出、Ken Burns |
| SVG 或 HTML 動畫 | bin/svg_gif.py | SMIL、CSS 或預設旋轉/脈衝/淡出 |
所有路徑共享 bin/gifkit.py:整個循環使用一個色板、10 毫秒時間網格、合併連續相同影格以延長延遲、原子寫入、讀回驗證。
依賴
需要 Pillow。SVG 和 HTML 需要 Node 以及 Playwright 和 Chromium headless shell。
python -c "import PIL; print(PIL.__version__)"
node -e "require('playwright')"
npx playwright install chromium --only-shell
當缺少依賴或輸入時,每個工具會在 stderr 輸出一行 FAIL ... 並以狀態碼 1 退出。不要使用相同參數重試。
工作流程
- 從表格中選擇路徑。閱讀下方對應小節。
- 在正在處理的專案內,使用明確的輸出路徑執行工具。不要寫入系統暫存目錄或桌面。
- 記錄輸出的摘要:影格數、時長、像素尺寸。列印出的路徑代表已驗證的 GIF。
- 對於視覺工作,開啟 GIF 或使用
--preview preview.png並先檢查該靜止畫面,再進行回報。 - 回報絕對路徑以及重要的設定:fps、尺寸、時長、模式。
ASCII 路徑
輸入為文字檔。影格由僅包含 --- 的行分隔;可選擇在分隔符後加上延遲時間(毫秒):--- 250。支援 ANSI SGR 顏色:30-37、90-97、38;5;n 和 38;2;r;g;b。一個包含 .txt 檔案的目錄會按檔名排序,每個檔案視為一個影格。
python bin/ascii_gif.py frames.txt -o project/loader.gif --size 28 --delay 120
python bin/ascii_gif.py frames/ -o project/loader.gif --preview project/loader.png
--font必須是等寬 TTF 或 TTC;省略時會自動偵測常見的等寬字型。--width和--height固定畫布並將文字網格置中。兩者同時指定或同時省略。用於在多個樣本間匹配尺寸。--fg和--bg預設為接近黑色的畫布上顯示淺色文字。--delay是預設影格延遲;分隔符延遲會覆蓋每個影格的預設值。- 將影格控制在約 120 列和 40 行內;較大的畫布會產生較長的 GIF。
圖片資料夾路徑
檔案會自然排序(pic-2 在 pic-10 之前),根據 EXIF 旋轉,並適配到同一畫布。
python bin/pics_gif.py photos/ -o project/reel.gif --mode kenburns --fps 12 --hold 1.2 --transition 0.5 --width 800
python bin/pics_gif.py photos/ -o project/reel.gif --mode sequence --fps 10 --hold 0.8 --fit contain --bg "#101010"
sequence保持每個圖片靜止;crossfade在圖片之間混合;kenburns緩慢放大每個圖片,交替方向。--width設定畫布寬度;--height預設為第一張圖片的長寬比。--fit cover裁剪以填滿畫布,contain使用--bg填補空白。--hold是每張圖片的停留秒數,--transition是混合的秒數,--zoom是 Ken Burns 的結束縮放倍率。- 一個 100 張照片的資料夾,在 800 像素和 12 fps 下會產生大型檔案;請優先降低寬度或 fps。
SVG 與 HTML 路徑
該工具會將 .svg 包裝在指定視口大小的頁面中,或直接開啟 .html,然後在每次截圖前暫停並將每個動畫定位到明確的時間點。影格不依賴於真實時鐘時間。
python bin/svg_gif.py logo.svg -o project/logo.gif --duration 3 --fps 15
python bin/svg_gif.py logo.svg -o project/logo.gif --animate rotate --selector "#mark" --duration 2 --background "#0b0d12"
python bin/svg_gif.py page.html -o project/page.gif --width 960 --height 540 --duration 4 --fps 12
- 若無
--animate,SVG 或頁面必須已透過 SMIL 或 CSS 產生動畫。靜態圖畫需要使用預設效果。 - 預設效果:
rotate、pulse、fade,應用於 SVG 根元素或--selector指定的元素。 --width和--height預設為 SVG 的width/height或viewBox。--dpr 2會以兩倍視口解析度擷取,使文字更清晰;GIF 的像素尺寸也隨之加倍。- 此工具不驅動 JS 驅動的 canvas 或 WebGL 頁面。請使用能暴露影格鉤子的頁面,或預先渲染影格並使用 gifkit 組裝。
共用選項
--colors最多 255。僅在色板簡單或檔案需要縮小時才降低此值。--dither none適用於平面藝術和文字;floyd有助於漸層和照片。--loop 0無限循環;其他數值則重複該次數。--preview PATH寫入第一影格的 PNG 靜止畫面。- 對於相同的輸入、設定和工具鏈,輸出是確定性的。
自訂影格
任何影格序列都可以使用相同的核心。影格必須是 RGB 且尺寸相同;延遲時間以毫秒為單位,位於 10 毫秒網格上。
import sys
sys.path.insert(0, "bin")
import gifkit
from PIL import Image
frames = [Image.new("RGB", (320, 180), (n * 20, 40, 90)) for n in range(12)]
gifkit.write_gif(frames, "project/gradient.gif", [100] * 12)
write_gif 建立一個色板,合併連續相同影格,原子寫入並驗證結果。此路徑適用於資料動畫、生成的圖表或這些路徑未涵蓋的任何影格。
合約
- 工具會寫入輸出目錄中的
<name>.tmp.gif,透過讀回檔案驗證影格數、總時長和像素尺寸,然後重新命名。失敗時會刪除暫存檔,不留下不完整的目標檔案。 - GIF 對所有影格使用單一色板,因此顏色不會閃爍。
- 連續相同的影格會合併為一個具有較長延遲的影格;列印的影格數是儲存的影格數。
- 延遲時間位於 10 毫秒 GIF 網格上,且至少為 20 毫秒。
驗證
路徑檢查位於原始碼儲存庫中。從儲存庫根目錄執行:
python tools/check.py
每個檢查會輸出一行 PASS、SKIP 或 FAIL。缺少可選依賴時預設跳過;--strict 要求每個路徑都通過。檢查會在 scratch/checks 下生成測試用固定檔案,並掃描儲存庫中的機密、絕對路徑、非 ASCII 文字和 CRLF 結尾。
限制
- GIF 是 8 位元索引色,最多 256 色;照片未經抖色會出現條帶。
- 檢視器會限制短延遲;請保持影格延遲在 20 毫秒或以上。
- 長時間、高 fps、真彩色的序列更適合使用 APNG 或 WebM。在要求品質時請提出。
- 記憶體用量隨影格數和畫布尺寸增長;工具在建立單一色板時會保留所有影格。
- ASCII 字形涵蓋範圍取決於所選字型;缺少方塊或區塊字形時會回退為空白方塊。
請參閱 references/animated-gif-considerations.md 了解格式限制以及這些預設值背後的原理。
檔案
bin/gifkit.py- 色板、時間、合併、原子寫入、驗證。bin/ascii_gif.py- ANSI 文字影格轉 GIF。bin/pics_gif.py- 圖片資料夾轉 GIF。bin/svg_gif.py- SVG/HTML 動畫轉 GIF。bin/render_frames.cjs- Playwright 影格擷取輔助程式。references/animated-gif-considerations.md- 格式說明。
儲存庫檢查和範例生成位於 tools/ 目錄中,不在已安裝的技能承載中。