第四話不是我畫的:一部社群漫畫怎麼長出「自己出下一話」的能力
2026-07-30 晚上在 LINE 的 C# 社群閒聊生出來的漫畫,兩天後長成一個按一次按鈕就會寫劇本、畫七張圖、開好 PR 等我驗收的東西。這篇講整條線怎麼接的,以及 cron 為什麼到現在還關著。

這篇講的東西
- 線上看(免費、可離線、可裝成 App):https://yazelin.github.io/neko-tensei/
- 原始碼(程式碼 MIT、圖文 CC BY-NC 4.0):https://github.com/yazelin/neko-tensei
- 誕生地:LINE 的 C# 社群
第四話一張封面加六頁,我只動了一個字。中年攻城屍的台詞被畫成「完旦了」,我把那一頁重生一次,改成「完蛋了」,然後按 merge。
其餘的部分:這一話要講什麼、三個轉折怎麼排、六頁十八格誰在說話、每一句用哪種對話框、七張圖,全部是我在 GitHub 的 Actions 頁面按一次「下一話」跑出來的。跑了 28 分鐘,它自己開了一條 PR,標題寫著「第 4 話草稿,待你看過再 merge」。
這篇寫給想拿 AI 畫短篇漫畫的人。整條產線我開源了,程式碼 MIT,fork 一份就能換成你自己的題材。
起點是一群人在 LINE 上亂聊
2026-07-30 晚上,LINE 的 C# 社群裡聊著聊著,群友的暱稱一個個變成了角色:小鳥不啾是大法師、小白++是劍士、中年攻城屍是武士、里歐是盜賊。四個深夜加班的工程師被螢幕裡的魔法陣吸進異世界,醒來全變成貓。
第一話八頁的原畫初稿,是我私下跟我們家的 AI 助理擎添助理聊出來的:我把群裡那些哏講給它聽、叫它畫,畫完貼回群裡給大家看。接著我才把它做成網站。第二話的封面更好玩,社群裡的荒坂小次郎親手畫了一張交上來,畫完大家才發現,那隻紅眼睛的魔王貓就是他自己。
所以這部作品的底是社群的,角色是群友的暱稱,哏是那天晚上真的講過的話。我做的是把它變成一個站、變成一條能繼續長下去的產線。
第一天先把站蓋起來
站本身沒什麼玄機,故意做得很薄:
episodes.json是單一事實來源,話數、頁次、每一頁的 alt 文字、掛名、角色清單全在裡面build.py讀它,產出ep/N.html、首頁的話數列表、上一話下一話、sitemap.xml,還有sw.js的離線快取清單- 加一話等於:圖丟進
images/epN/、episodes.json加一段、跑python3 build.py
這個薄殼是後面那條自動化的前提。如果加一話要手改五個 HTML 檔,機器就沒辦法幫我加。
PWA 的部分踩過一個坑值得講:快取分成 SHELL 和 ASSET 兩層,版號要分開 bump。圖沒換卻順手把 ASSET 一起 bump,回訪的讀者會整包重抓 10.6 MB。這種事在自己的網路上完全感覺不到,在讀者的手機上就是打開很久沒反應。
第二話花掉七八輪重跑,換來一份規範
第二話我是手工做的,重跑了七、八輪才收斂。每一輪失敗幾乎都是同一類原因:以為文字描述夠了。
那幾輪的教訓現在寫死在 story/README.md 裡,我覺得最值錢的是這四條:
一、角色設定圖每次都要當參考圖傳進去。 文字寫「胸前圓形金牌」,模型會畫成一塊肉球牌。它不是不聽話,是「圓形金牌」這五個字對它來說有幾百種長相。設定圖傳進去,那幾百種就收斂成一種。
二、「沒有什麼」跟「有什麼」一樣要寫死。 第三話第 02 頁出過事:小白++被畫上了小鳥不啾的圓框眼鏡。回頭查設定,發現我只寫了小鳥不啾戴眼鏡,沒寫「小白++不戴眼鏡」,也沒寫「眼鏡全劇只有小鳥不啾有」。模型很合理地補了一副上去。現在設定表裡小白++那一格寫的是「光頭沒有頭帶、不戴眼鏡、短毛、身形小一號」。
三、對話框的形狀要跟著情緒走。 讀者在讀到字之前,先讀到的是框的形狀。所以我列了一張七種框型的表:大喊用爆炸尖角框、傻眼用抖動的小扁橢圓、內心 OS 用雲朵框、魔王發話用黑底白字帶尖刺、旁白用直角方框(全頁唯一該用直角的地方)。分鏡表上每一句都要標框型,prompt 裡也一句一句寫出來。整頁圓角矩形是最省事也最沒力的做法。
四、對白跟圖一起生,不要事後用程式疊字。 疊出來的框跟畫面是兩層東西,放大就看得出來。代價是機率性輸出會出錯字,所以規定一頁 3 到 6 句、句子不要長,錯了整頁重生。第四話那個「完旦了」就是這條規則的稅金,我認。
這部作品還有一條我自己很喜歡的設定語法:貓形是現在,人臉是內心。角色在心裡吐槽時,頭上浮一顆小圓框,框裡是他前世的人類身影,一律黑白灰階,貓的世界維持全彩。一頁最多用一次,用多了就不好笑了。
把規範寫成程式,因為手寫兩份一定會歪
規範寫成 Markdown 給人看,同一份設定也要給程式用。我一開始讓 prompt.py 自己抄一份英文描述,結果就出事了。
cast.json 裡把小次郎的紋章寫成「樹在爪上」,prompt.py 跟著寫 tree above a paw。而正典上那個紋章根本沒有樹也沒有肉球,畫的是紅色三球剪影。模型很聽話地照著錯的描述畫,通行證那個道具漂成了一隻掛著繩子的金懷錶。
現在 story/cast.json 是唯一的設定資料,prompt.py 只負責組裝,一個字都不自己寫。這是整個專案裡最無聊也最有效的一次重構。
讓它自己出下一話
自動化那條線只有三段,全部在 scripts/next_episode.py(964 行,測試 1272 行):
第一段,寫劇本。 把 story/README.md 整份創作規範、最近兩話的完整分鏡、社群在首頁許願串留的話,一起丟給 Gemini,要它回一份純 JSON 的企劃:標題、話型、三個轉折、六頁、每頁 2 到 3 格、每一格的畫面描述與每一句對白(誰說的、什麼框型、逐字的中文)。
第二段,守門。 企劃回來先驗,這是花掉出圖額度之前唯一的關卡,所以寧可嚴一點。實際擋的東西長這樣:
- 內頁必須正好六頁,頁碼 01 到 06 各一次不重複
- 框型只能是那七種,同一頁的框型不可以全部一樣
- 對白有簡體字就退(拿 OpenCC 自帶的字表逐字比對,不手 key 一份自己的表)
- 說話者只能是那五隻貓,畫面裡出現通行證或黑塔就必須標上道具 id,沒標等於沒鎖,那一格會重抽一個樣子
- 荒坂小次郎不可以用內心 OS 框,因為他的前世是一個背對鏡頭的黑色剪影,沒有臉可以浮出來
沒過就用同一份 prompt 再擲一次。這是機率性輸出,第一次不過通常不代表 prompt 寫壞了,連兩次都不過才是真的有問題。
第三段,畫。 每一頁 1024×1536、三格橫幅。參考圖的順序是寫死的:image 1 永遠是第一話的第 07 頁(鎖畫風、上墨感和手寫黑體字),後面接這一格要鎖的道具或場景,再接出場角色的設定圖。上限 8 張,塞太多張特徵會開始互相污染。
圖回來還要重壓。生圖服務回的是接近無損的 webp,一頁 3.7 MB,第三話第一次真跑整話 23 MB,比我手工做的第一話重五倍。重壓成 q95 之後一頁 0.88 MB,平均像素差 2.5/255,放大看對白照樣銳利。這個站是 PWA,所有圖都會被 precache,一話 23 MB 跟一話 5 MB 對讀者是完全不同的兩件事。
跑到一半掛掉,不能整話重來
GitHub 的 runner 用完即丟。一話七張圖要跑快半小時,中間任何一次網路抖動都可能讓整話白跑,所以圖一出來就得存進 Actions 的 cache。
第四話正好把這條路走完整。我先在半夜 00:28 按了一次,跑了 15 分 27 秒之後自己按了 Cancel(那時候還在改別的東西)。00:44 再按一次,log 裡是這樣的:
Cache hit for: ep-progress-4
Cache Size: ~2 MB
-> 03 ok 388s 0.86MB
-> 04 ok 310s 0.90MB
-> 05 ok 696s 0.90MB
-> 06 ok 234s 0.84MB
封面、01、02 是上一次燒掉的,直接撿回來用,第二次只補畫四張。單張最快 234 秒、最慢 696 秒。
這裡有兩個坑我踩完寫在 workflow 的註解裡。一個是 if: failure() 在 run 被取消時不會執行,可是人按 Cancel 的那一刻,圖已經燒掉了,一樣該存,所以條件要寫 failure() || cancelled()。另一個是快取不能只存圖,要連那份企劃一起存,不然下次重跑會生出一份新劇本,配上一批舊圖。
PR 內文才是這條線真正的產品
我覺得整條線最關鍵的設計不在生圖,在那封 PR。
它除了把圖 commit 進來,還把每一頁的圖和劇本並排寫進 PR 內文:這一格的畫面描述是什麼、這句話誰說的、用哪種框型,下面就是實際畫出來的那張圖。開頭寫著一句提醒我自己的話:
你要看的不是劇情,是圖有沒有照劇本畫。
因為劇情在文字層通常沒問題,會出事的是「劇本寫的」跟「圖畫出來的」之間那道縫。第二話里歐的隱形術,分鏡寫的是「只隱一半」,圖卻畫出一隻完整的橘貓,整頁的笑點沒了,而光讀分鏡檔案完全看不出來。
所以我的驗收動作被壓縮成:滑七張圖,對照旁邊的劇本,找那道縫。第四話我花了大概五分鐘,抓到一個錯字,重生那一頁,merge,站上就多了一話。
我刻意沒做的事
這部分我覺得比功能清單重要。
cron 到現在還關著。workflow 裡那三行排程被我註解掉,只留手動按鈕。我不希望某個週五晚上十點,一部有社群朋友在裡面的漫畫,在沒人看過的情況下自己更新。
它不會自己 merge。產出的永遠是草稿 PR,最後那一下一定是人按的。
同時只允許一個草稿 PR 開著。上一話還沒處理完就不准產下一話,不然會堆出一疊互相衝突的分支。
失敗會開 issue,取消不會。自己按的取消不需要通知自己。
許願串目前 0 則留言。首頁有一條給社群許願劇情的討論串,pipeline 也真的會去讀、會盡量把許願收進下一話。機制做好了,人還沒來。老實寫出來比假裝熱鬧好。
想自己 fork 一份
這個 repo 歡迎 fork,換掉三個地方就是你自己的連載:
story/cast.json:你的角色、設定圖、識別特徵、道具與場景story/README.md:你這部作品的鐵律(畫風、框型、版面、絕對不能出現什麼)episodes.json:清空,從第一話開始
scripts/next_episode.py 和那條 workflow 幾乎不用動。有兩件事要先知道:
- 寫劇本那半段打的是 Gemini 官方 API 的形狀(
/v1beta/models/<model>:generateContent?key=),我跑的是自架的中繼,把GEMINI_WEB_BASE_URL指到官方端點就是原生用法。這條路我沒實測過,理論上只差一個 base url 和一把自己的金鑰。 - 出圖那半段打的是我自架的服務,
POST /v1/images/jobs加 base64 參考圖。這段要改成你自己的生圖 API,改的是generate_image()這一個函式。整條線只有這裡跟我的機器綁著。
其餘的東西(企劃驗證器、參考圖組裝、重壓落檔、續傳快取、PR 逐頁對照)全部是跟題材無關的,換成你的角色照樣能用。
分工線
角色和哏是 LINE C# 社群的群友的,第二話封面是荒坂小次郎親手畫的。這部作品要往哪走、每一個「要不要做」的取捨、每一條驗收標準是我定的;程式碼含測試是 AI 在這套規格下寫的,圖是 AI 畫的。我做的事情比較像一個編輯:定規範、看稿、退稿、按 merge。
三個出口
想看漫畫:https://yazelin.github.io/neko-tensei/,四話全部免費,手機上可以裝成 App、斷網也讀得完。想許願下一話畫什麼,首頁有一條許願串,你的願望會真的被丟進下一次的 prompt 裡。
想自己蓋一條:https://github.com/yazelin/neko-tensei,上面那三個檔案換掉就開始了。授權分兩份:漫畫本身(圖、角色、站上文字)是 CC BY-NC 4.0,署名給我和社群群友、別拿去商用;產線那些程式碼是 MIT,拿去改成你自己的題材完全沒問題。
想有人帶著走一遍:8 月 19 日(週三)晚上 8 點,我會辦一場線上分享,主題就是這條線,從創作規範怎麼寫、參考圖怎麼鎖,到把它接成一條會自己出下一話的產線。這場的門檻會比我 8/5 的貼圖實作營高一些,需要你電腦上有 Claude Code 或 Codex CLI 這類 AI 編碼工具,也需要你不排斥看 JSON 和 YAML。報名方式我會公告在 LINE 社群,想來的先進來卡位。