TL;DR:我要幫一款 Splendor 網頁版生 90 張發展卡 + 10 張貴族卡的插圖,預算是 $0、手上沒綁信用卡。最後用 Hugging Face 的FLUX.1-schnell當主力(免費帳號每月 $0.10 額度)、額度用完自動 fallback 到完全免費的 Pollinations,再用sharp後製依寶石色染色,100 張圖一次跑完、整副風格一致、總花費 $0。這篇把 token 怎麼拿、額度怎麼算、bash 怎麼封裝、批次怎麼重現、後製怎麼補色全寫清楚。
📌 目錄
- 為什麼選 FLUX.1-schnell 當免費生圖主力
- 先搞懂 HuggingFace 免費額度到底有多少
- 一個 token 的取得與權限設定
- bash 封裝:HF 主力 + Pollinations fallback
- 批次生 100 張:固定 seed 換風格一致
- schnell 不吃顏色?用 sharp 後製上色
- 踩坑紀錄
- 免費生圖管道比較
- 常見問題 FAQ
- 延伸資源
🎨 為什麼選 FLUX.1-schnell 當免費生圖主力
我在做一款 Splendor(璀璨寶石)的網頁版,引擎、React UI、測試都寫完了,剩一件事:90 張發展卡 + 10 張貴族卡的插圖。商業圖庫授權貴、找美術不現實、自己畫一百張更不可能。生成式 AI 是唯一可行解,但有一條硬限制——這專案的圖預算是 $0,而且我手邊沒有綁信用卡的生圖帳號,不能讓任何一步「不小心被扣款」。
我自己一開始也以為「免費生圖」等於畫質爛、等於 watermark、等於只能玩玩。實際跑下來發現,black-forest-labs/FLUX.1-schnell 這顆模型本身就是 Black Forest Labs 開源、走 Apache-2.0 授權的 distilled 版本,4 步就能出圖、速度快、品質夠用在遊戲卡面。它在 Hugging Face 上可以直接透過 Inference Providers 呼叫,免費帳號就有額度。
schnell 在德文是「快」的意思,這顆就是 FLUX 家族裡為速度優化的版本:步數少、延遲低,特別適合「同一套 prompt 批次出幾十上百張」這種場景。
💰 先搞懂 HuggingFace 免費額度到底有多少
動手前先把錢的事算清楚,免得跑到一半被擋。根據 Hugging Face 官方 Inference Providers 定價頁(2026-06 查證):
| 帳號類型 | 每月免費額度 | 超額 |
|---|---|---|
| 免費註冊用戶 | $0.10(官方註明 subject to change) | 需先購買 credit 才能續用 |
| PRO 用戶($9/月) | $2.00 | 可 pay-as-you-go |
| Team / Enterprise | 每 seat $2.00 | 可 pay-as-you-go,額度組織內共用 |
FLUX.1-dev 請求跑 10 秒、GPU 每秒 $0.00012,這張就billed $0.0012。換算下來,免費的 $0.10 大概只夠 每月數十張 FLUX 圖。
這就是關鍵矛盾:我要 100 張,免費額度只夠數十張。所以策略不是「想辦法塞進 $0.10」,而是 「HF 額度先榨乾、用完自動切到完全免費的 Pollinations」——這樣 HF 出高品質的那幾十張,剩下的由 Pollinations 補滿,整體還是 $0。
重點:免費帳號超額不會自動扣款,它會直接擋下請求(要先 purchase credit 才會續用)。對「絕不能被扣款」的需求來說,這反而是保險——沒綁卡、超額就停,不會有意外帳單。
🔗 一個 token 的取得與權限設定
整套流程只需要一個 Hugging Face token。取得步驟:
~/.cache/huggingface/token,並 chmod 600 鎖權限;或 export HF_TOKEN= 走環境變數# 存 token(注意:token 是機密,別 commit、別貼公開地方)
mkdir -p ~/.cache/huggingface
printf '%s' 'hf_你的token' > ~/.cache/huggingface/token
chmod 600 ~/.cache/huggingface/token
# 驗證:能不能讀到
test -r ~/.cache/huggingface/token && echo "token ok"
呼叫的 endpoint 是 router,不是舊的 Inference API:
https://router.huggingface.co/hf-inference/models/black-forest-labs/FLUX.1-schnell
⚡ bash 封裝:HF 主力 + Pollinations fallback
我把生圖封成一支 free-image.sh,介面就一行:free-image.sh "。它的 provider 優先序是 HF FLUX.1-schnell → Pollinations,前者失敗就掉到後者,兩者都掛才非 0 退出。
核心有三個設計值得抄:
1. 圖檔 round-trip 自驗
生圖 API 失敗時常常回的是 HTML 錯誤頁或 JSON error,但 HTTP 200,檔案也寫進去了——如果不驗,你會得到一堆「看起來存在、其實打不開」的壞檔。所以寫檔後一定要驗它真的是圖:
verify_image() {
local path="$1"
[[ -s "$path" ]] || return 1
local ftype
ftype="$(file -b --mime-type "$path" 2>/dev/null)"
if [[ "$ftype" == image/* ]]; then
return 0
fi
rm -f "$path" # 不是圖 → 刪掉避免殘留誤導
return 1
}
2. 尺寸先 floor 到 8 的倍數
FLUX 要求寬高是 8 的倍數,傳 768 沒事,但若參數化傳了奇怪的值會報錯。封裝層先除整:
WIDTH=$(( (WIDTH / 8) * 8 ))
HEIGHT=$(( (HEIGHT / 8) * 8 ))
3. 用 python3 安全組 JSON body
prompt 裡常有逗號、引號、換行,用字串拼 JSON 一定爆。交給 python3 -c 組:
build_hf_body() {
python3 - "$PROMPT" "$WIDTH" "$HEIGHT" "$SEED" <<'PY'
import sys, json
prompt, w, h, seed = sys.argv[1], int(sys.argv[2]), int(sys.argv[3]), sys.argv[4]
params = {"width": w, "height": h}
if seed != "":
params["seed"] = int(seed)
print(json.dumps({"inputs": prompt, "parameters": params}))
PY
}
HF 失敗時 fallback 到 Pollinations 走的是匿名路徑——免 key、把 prompt URL-encode 進路徑 https://image.pollinations.ai/prompt/,直接 GET 回圖。Pollinations 完全免費、無明確月額度上限,匿名 tier 高併發時可能 rate limit,但對「補滿剩下幾十張」綽綽有餘。
🧠 批次生 100 張:固定 seed 換風格一致
封裝層搞定後,上面再疊一支 gen-art.mjs 做批次。整副 100 張要看起來像同一套牌,靠三件事:
共用 style suffix
所有圖共用同一段風格尾巴,確保畫風統一:
Renaissance fantasy gemstone trade illustration, ornate baroque detail,
rich jewel tones, dramatic chiaroscuro lighting, painterly oil texture,
centered composition, no text, no letters, no watermark, square format
no text, no letters, no watermark 這幾個負面詞很重要——生圖模型很愛在圖上亂塞看不懂的假文字,明確排除能少修很多。
固定 seed(由 id 推導)
同一張卡每次重生都要長一樣,否則補圖時整副風格會飄。我用 FNV-1a hash 把卡片 id 轉成穩定 seed:
function seedFromId(id) {
let h = 2166136261;
for (let i = 0; i < id.length; i++) {
h ^= id.charCodeAt(i);
h = Math.imul(h, 16777619);
}
return Math.abs(h) % 2_000_000_000;
}
同 id → 同 seed → 同 prompt → 結果可重現。這招讓「HF 額度回補後再跑一次補齊高品質版」變得安全:已存在的檔會被跳過,沒生成的才補。
prompt 結構:顏色 motif 放最前面
FLUX 對開頭 token 權重最高。一開始我把場景寫前面、顏色寫後面,結果所有寶石都被畫成透明鑽石。把顏色詞前置並重複(vivid GREEN emerald gemstones glowing bright green)才壓得住:
const prompt = ${theme.motif}, displayed in ${TIER_SCENE[c.tier]}, ${theme.palette} color scheme dominates the image. ${STYLE};
tier 越高場景越豪華(T1 是工匠小作坊、T3 是皇家寶庫),讓三階牌一眼能分辨等級。
🎨 schnell 不吃顏色?用 sharp 後製上色
即使 prompt 把顏色寫到頂,schnell 因為步數少,顏色控制力還是不如 dev——綠寶石卡常常出來偏灰、紅寶石不夠紅。硬要靠 prompt 救,得反覆重生、燒額度。
我的解法是 方案 B:生完用 sharp 依卡片 bonus 色後製染色。$0、100% 正確、可重現,不用跟模型的隨機性纏鬥:
const TINT = {
emerald: { r: 120, g: 180, b: 130 },
sapphire: { r: 110, g: 140, b: 200 },
ruby: { r: 200, g: 110, b: 120 },
diamond: null, // 不染,保留透明白
onyx: { r: 90, g: 85, b: 110 }, // 偏暗紫黑
};
async function recolor(rawPath, finalPath, bonus) {
const tint = TINT[bonus];
let img = sharp(rawPath);
if (tint) {
img = img.tint(tint).modulate({ saturation: 1.3 });
}
await img.jpeg({ quality: 88 }).toFile(finalPath);
}
tint() 套色相、modulate({ saturation: 1.3 }) 補回飽和度避免染完發灰。diamond 維持中性(它本來就該無色)。下面這張是同一張原圖套不同 tint 的效果——最左是原圖,後面依序套 emerald / ruby / sapphire:
最後 100 張全是 768×768、quality 88 的 JPEG,cards 約 9.3 MB、nobles 約 1.3 MB,全副風格統一、顏色正確。
📝 踩坑紀錄
壞檔當成功檔:沒驗就直接跳下一張
第一版沒做 verify_image,跑完看到 100 個檔很開心,結果有幾張是 HF 排隊時回的 JSON、副檔名卻是 .jpg。遊戲一載入就破圖。加上 mime-type 驗證、不是圖就刪掉重生後才乾淨。「檔案存在」不等於「圖生成成功」,一定要 round-trip 驗它打得開。
顏色 token 放後面 → 整副變鑽石
前面提過,FLUX 對開頭 token 權重最高。場景寫前面、顏色寫後面時,模型把「gemstone」當主體、顏色當裝飾,結果五色全畫成透明鑽石。顏色詞前置 + 重複 + 大寫強調才壓得住。
schnell 顏色救不動,別硬燒額度
我一度想靠加強 prompt + 重生把綠寶石救綠,燒掉好幾次額度都沒穩定。停下來改走 sharp 後製,一次解決還可重現。模型不擅長的事,丟給確定性的後製,比跟隨機性纏鬥划算。
token 少勾 inference 權限 → 401
建 token 時沒勾「Make calls to Inference Providers」,router 直接擋。重建 token 勾對權限即可。
⚖️ 免費生圖管道比較
| 維度 | HF FLUX.1-schnell | Pollinations | 商業 API(DALL·E / Midjourney) |
|---|---|---|---|
| 費用 | 免費額度 $0.10/月,超額需購 credit | ✓ 完全免費 | ✗ 按張付費 |
| 需信用卡 | ✗ 不需(超額自動擋) | ✗ 不需 | ✓ 需綁卡 |
| 需 API key | △ 需 token(免費申請) | ✗ 匿名可用 | ✓ 需 key |
| 畫質 | ✓ 高 | △ 中(匿名 tier) | ✓ 高 |
| 月額度上限 | 數十張(免費) | 無明確上限 | 看付費方案 |
| 適合場景 | 主力出高品質圖 | 補量 / fallback | 商業專案有預算 |
❓ 常見問題 FAQ
Q1:FLUX.1-schnell 免費可以商用嗎?
模型本身走 Apache-2.0 授權(Black Forest Labs 開源的 schnell 版本),生成的圖可商用。但每個 Inference Provider 的服務條款不同,正式商用前還是去確認你呼叫的那個 provider 的 ToS。
Q2:免費的 $0.10 額度用完會自動扣款嗎?
不會。免費帳號超額會直接擋下請求,要先在 billing 頁 purchase credit 才能續用。沒綁卡就不會有意外帳單——這對「絕不能被扣款」的需求反而是保險。
Q3:為什麼不直接全用 Pollinations,免 key 又免費?
可以,但 Pollinations 匿名 tier 在高併發時會 rate limit、畫質也略遜 FLUX.1-schnell。我的策略是 HF 出主力品質的那幾十張,Pollinations 補剩下的量,兼顧品質與成本。
Q4:schnell 和 dev 差在哪?該選哪個?schnell 是 distilled 速度版,4 步出圖、快、適合批次;dev 步數多、品質與顏色控制更好但較慢、計費也更高。批次大量出圖選 schnell + 後製,少量精修選 dev。
Q5:seed 固定真的能完全重現嗎?
同一個 provider、同 model、同 prompt、同 seed 下結果穩定,這是「同 id 重生不變」的基礎。但跨 provider(HF vs Pollinations)不保證一致,所以補圖時要用「跳過已存在檔」而不是「整副重生」。
🔗 延伸資源
- Hugging Face Inference Providers 定價文件 — 額度與計費規則官方來源
- black-forest-labs/FLUX.1-schnell on Hugging Face — 模型卡與授權
- Pollinations — 免 key 免費生圖 fallback
- sharp 官方文件 — Node.js 影像後製(tint / modulate)
- HuggingFace token 設定頁 — 記得勾 Inference Providers 權限