模組三|AI 生圖與生片產線(Day 10–19)
昨天那篇的最後一行寫著:明天講成本結算,這一整條產線實際花了多少。
今天我要說的是:我拿不到那個數字。
而且拿不到的原因不是我懶得查,是我昨天自己寫下的那行禁令擋住了。這篇就講這件事,以及一個沒有單價也能做的成本估算方式——那才是這一天真正能帶走的東西。
昨天講的 bug 是:三視圖生成腳本的「已存在就跳過」比對的是中文檔名,成品早就改成英文了,所以重跑會把 20 個角色全部重生。實測 20/20 重生、0 skip。
我當時在 開發足跡.md 裡加了一行禁令:
未修前禁止事項:不得直接執行
bash gen_turnarounds.sh,包含為了取得成本數字而試跑。
「包含為了取得成本數字而試跑」——這半句是我自己補上去的,因為我當時就預料到會有今天這一刻。
要拿到「一輪全員三視圖重製實際花多少」,最直接的做法就是跑一輪然後看帳單。而跑一輪的意思,在 skip 失效的現在,就是 20 次 API 呼叫全額重來。
為了量成本而付出的成本,本身就是這篇要講的成本。
沒有。
我剛剛回去看了一次,gen_turnarounds.sh 第 27 行還是這樣:
if [ -f "$out" ]; then echo "skip $name (exists)"; continue; fi
out 仍然從中文的 prompt 檔名推導。昨天說的三個修法——建映射表、prompt 檔改英文、加 --dry-run 旗標——一個都還沒進去。
更難看的是這個:我回去查 git log,這支腳本在那之後確實被改過一次。
2026-08-07 fix(turnarounds): locate prompt fences by heading instead of index
那次改的是另一個 bug——原本用「第 n 個程式碼圍欄」抓 prompt,只要有人在檔案中間插一節就會整批抓錯,改成用 H2 標題定位。是個好修法。
但我查了 skip 那一行最後一次被動是什麼時候:
2026-07-23 feat(novel, docs, assets): ...
我回到了同一支檔案,修了旁邊的東西,然後沒有碰它。
這比「一直沒空回去看」難堪得多。不是沒機會,是有機會而它不在我當下的注意力裡。
我把這件事寫出來,因為連載最容易出現的一種假象,就是文章裡承諾過的修法,讀者以為已經發生了。沒有就是沒有。
單價拿不到,不代表這篇沒東西可寫。因為對個人創作者來說,真正會失控的從來不是單價,是次數。
這條產線的成本可以拆成三層:
| 層 | 內容 | 特性 |
|---|---|---|
| 一次性 | 風格錨定圖、prompt 模板、腳本本身 | 做一次,之後每輪都在用 |
| 每輪固定 | 20 個角色 × 1 次呼叫 | 角色數決定,一輪就是一輪 |
| 每次改動 | 改風格、改構圖、改規格後的重製 | 沒有上限,這層才會爆 |
前兩層是可以事先算的。第三層算不了,因為它取決於你改幾次主意。
而我這個專案的實際情形是:第三層已經發生過至少一次全員重製(中文檔名那批 20 張還留在 assets/turnarounds_old/,跟新的 20 張並存),而那次重製的觸發原因不是圖不好看,是檔名規範改了。
一個純粹的工程決定,觸發了一整輪生成成本。
不能寫的是價格,能寫的是量。這些是實查得到的:
角色 prompt 檔(扣除 index.md) 20
會進入生成迴圈的 20
一輪的 API 呼叫次數 20
模型與端點也是確定的:走 OpenAI 的 /v1/images/edits,模型 gpt-image-1,每次呼叫都帶同一張固定的風格錨定圖 assets/char-tuner.png。
所以一輪的成本結構是:
一輪成本 = 單張成本 × 20 × 重跑倍率
三個因子裡,我確定的是 20,不確定的是單張成本,而最危險的是重跑倍率。
單張成本是你選模型的時候就決定的,選了就固定,而且查得到。
重跑倍率不是。它等於「這批圖你重生了幾次」,取決於:
前兩項是工程問題,可以修。第三項是創作問題,修不了,只能框住。
我自己的實際倍率至少是 2(中文檔名一批、英文檔名一批)。如果那次我不小心直接重跑,就會變成 3。
所以個人創作者的預算控制,重點不是找更便宜的模型,是把倍率壓回 1。
便宜一半的模型省 50%。倍率從 3 壓到 1 省 67%,而且不用換模型、不用犧牲品質。
這是這篇真正可以帶走的部分。在你還沒花第一塊錢之前,就能算出上限:
一、數清楚「單位」有幾個 → 我的是 20 個角色
二、查那個模型的公開單價 → 官方定價頁,不用實跑
三、乘起來得到「一輪理論成本」 → 這是地板,不是天花板
四、乘上你誠實估計的重跑倍率 → 這才是你要準備的預算
五、把倍率寫進計畫,當成 KPI → 目標是讓它趨近 1
第四步大部分人會跳過,然後預算就爆了。
我建議估倍率的時候用這個問法:這批東西,我有多少把握規格不會再改? 不確定的話倍率就從 2 起跳。
第五步是把它變成可管理的東西。倍率不是天災,它是「規格沒定好」和「腳本不冪等」的總和,兩個都是你能動的。
寫到這裡要補一件事:那行禁令其實留了一個出口。原文是「要測成本請先修 skip 邏輯,或單獨抽一個角色跑」。
單獨抽一個角色跑,就是 1 次呼叫,不是 20 次。這是合法的,也是取得單張成本最便宜的路。
我這次沒有跑,理由很簡單:我要的是「一輪全員重製的實際花費」,而抽一個角色只能給我單張價格,剩下的還是乘出來的。既然都是乘出來的,那我用官方定價頁乘也一樣,何必花這一塊錢。
這也是個判斷:測量本身要花錢的時候,先問你想知道的東西是不是非測不可。
如果我要的是「這個模型出圖品質行不行」,那非跑不可。要的是一個乘法的結果,查定價頁就夠了。
這篇的代價很直接——它答應了一個數字,然後沒有給。
我可以有另外兩種寫法:
一種是估一個數字寫上去,加註「約」。讀起來完整多了,而且大概率沒人會查。但這個系列的規矩是量化陳述必須來自實測或實查,估算不算。一旦開了這個口,後面每個數字的可信度都要打折。
另一種是把這天跳過,等有數字了再寫。但那等於承認連載的節奏比誠實重要。
第三種就是這篇:講清楚為什麼沒有,以及沒有數字的情況下還能給出什麼。
代價是這篇讀起來不如「我花了 X 美金」那麼有衝擊力。我接受,因為一個編出來的數字對讀者的傷害,比一個誠實的空白大。你照著一個編的數字做預算,會賠錢;照著這篇的估算法做,至少方向是對的。
還有一個代價是:這件事到現在還沒修。禁令擋住了花錢,但它同時擋住了測量。一個沒修的 bug,會連帶擋掉你其他想做的事,這件事我是今天才體會到的。
一、成本要拆成三層來看:一次性、每輪固定、每次改動。
前兩層算得出來,第三層算不出來。看到有人報「這個專案花了 X 元」,先問那是哪一層。多數人報的是第二層,而爆掉的都是第三層。
二、單價乘數量只是地板,真正的預算是再乘一次重跑倍率。
沒有把倍率放進去的估算,一定會低估。而倍率不是命運,它是規格穩定度和腳本冪等性的總和。
判斷句:這批東西的規格,我有多少把握不會再改? 沒把握就從 2 起跳。
三、省錢的順位是先降倍率,再談換模型。
換便宜模型是拿品質換錢,壓倍率是純賺。而且壓倍率的手段——把規格寫死、把 skip 邏輯修對、加 --dry-run——每一項都是你本來就該做的工程。
四、測量本身有成本的時候,先確認你非測不可。
問一句:這個數字我是要拿來做決定,還是拿來寫進報告?拿來做決定,就去測。只是想填一個欄位,查公開資料乘一乘就好。
五、「有空再修」不會發生,因為你回去的時候不會想起它。
我 08-07 打開了同一支腳本,修了旁邊的圍欄抽取邏輯,然後關掉。skip 那行就在上面幾行,我沒看見。
所以「等我下次動這個檔案就順手修掉」是假的。下次動這個檔案的時候,你腦子裡裝的是那時候要修的東西。
判斷句:這條待修事項,有沒有一個東西會在我下次執行時擋住我? 沒有的話,它就只是一個願望。這也是為什麼 --dry-run 比日誌裡的禁令強——一個會攔住你,一個要你記得。
六、答應過的東西沒做到,要說。
昨天說今天給數字,今天沒有;昨天說要修 skip,到現在沒修。這兩件事我都寫進來了。連載跟專案一樣,最貴的不是進度落後,是讀者以為你做完了。
明天 Day 18,講角色卡管線:為什麼出圖的提示詞裡,反而不准出現角色的名字。