※この記事は、Claude Codeで1人開発しているSNS運用SaaS「ThreadPost」の開発日記です。
4コマ漫画生成を「Vercel」で動かしたら、タイムアウトでしんどいことになった。
非同期にしたら、今度はポーリングが途中で止まった。
同期に戻したら、またタイムアウト。
年末の5日間、僕はただひたすらAIとサーバーレス環境の壊れ方を眺めていた。
SNS運用を自動化しませんか?
ThreadPostなら、投稿作成・画像生成・スケジュール管理まで全てAIにお任せ。
3往復して気づいた「壊れ方を覚えるゲーム」の正体
今週の総コミット数は50件。新機能は1件、バグ修正は2件だ。
4コマ漫画生成機能の実装中、非同期処理の設計で迷走し、同期と非同期の間を3往復する泥沼にハマった。
最終的に出来上がったのは華麗なコードではない。AIの壊れ方を理解して敷き詰めた、泥臭いルールの山だった。

構図の欠落と紙芝居の絶望
「AIが全コマ同じ構図で描いてくる」問題に直面した。
4コマ漫画なのに、全コマが「正面・ミドルショット」の紙芝居状態だ。
プロンプトの指示不足だと思った。
「Enhance manga prompt rules: Prevent panel splitting and enforce character positioning」というコミットで、プロンプトをガチガチに固めた。
それでもAIは頑なに正面を向いたキャラを描き続けた。
しんたろー:
10回生成して10回とも正面ミドルショット。プロンプトの文字数を2倍にしても結果は同じ。僕の指示が完全に無視されている。まじかよ。
「improve manga generation prompting and background consistency」でさらにプロンプトをこねくり回した。
結果は全く変わらなかった。PCの画面を睨みつけながら、根本的な原因を探った。
原因はプロンプトではなかった。
「generateMangaStoryCoreでcomposition_descriptionをDBに保存していなかった」というコミットが全てを物語っている。
データベース保存時に構図の指示データが完全に欠落していた。
AIは悪くなかった。僕がAIに渡す直前で、構図のデータをドブに捨てていた。
AIは毎回デフォルトの「正面・ミドルショット」を生成するよう強制されていたのだ。
修正後、全コマ同じ構図の紙芝居状態から、ダイナミックなストーリーテリングへ変化した。

「display Japanese composition/scene/background in manga dialog」で、日本語の構図指示をUIにも表示するようにした。
データが正しく流れていることを可視化するためだ。
「fetch generated_prompts on story completion for Japanese display」を追加し、生成完了時にプロンプトを即座に再取得するようにした。
さらに、「同一キャラの複数セリフをグループ化してプロンプト生成」というコミットで別の問題にも対処した。
同じキャラクターが複数回登場する場合、それぞれ別のキャラクターブロックとして出力されていた。
画像生成AIが2人のキャラクターと誤認していたのだ。
キャラクター名でグループ化してマップで管理するようにした。
複数のアクションは結合し、複数のセリフは1ブロック内に出力するように修正した。
「再生成時に初回生成時のプロンプトを使用するように修正」というコミットも追加した。
データベースに保存されたプロンプトを再生成時に使用することで、再生成しても同じプロンプトが使われるようになった。
ユーザー管理画面の改善も行った。
「ユーザー管理画面に漫画生成数列を追加」というコミットで、管理側の可視性を高めた。
「漫画列をストーリー/パネル形式に変更 (例: 1/4)」で、データの見せ方も工夫した。
「漫画パネル数を画像生成済みのみカウントするよう修正」というコミットで、正確な集計も実現した。
ペイロードの罠とコスト半減の執念
漫画が生成できるようになった後、「セリフだけ変えたい」という要望が出た。
画像全体を再生成するとコストの無駄だ。部分修正で済ませようとした。
「完了画面にセリフのみ再描画機能を追加」する作業に取り掛かった。
「Gemini」に既存画像を渡して、セリフの文字だけ書き換える処理を実装した。
しかし、APIリクエストを投げるとエラーの嵐が返ってきた。
しんたろー:
画像再生成のAPI代はバカにならない。部分修正なら半額で済む。そう思って実装したらAPIに全弾弾かれた。3時間溶けた。
エラーの原因はペイロードの構造だった。
「背景画像のinline_dataからurlフィールドを除去」というコミットで修正した。
APIへのリクエストで、画像データの中に不要なURLフィールドが含まれていた。
マルチモーダルAIへの画像入力において、Base64エンコードされた画像データとURLフィールドが混在すると、APIのバリデーションで弾かれると言われている。
不要なフィールドが一つあるだけで、推論以前にリクエストが拒絶される。
僕はAPIの仕様書を読み込み、ペイロードを極限まで削ぎ落とした。
修正前は画像再生成に6pt必須だったが、修正後はセリフのみ再描画が3ptで可能になった。
ユーザーのクレジット消費を半減させることに成功した。ただし3時間かかった。
「regeneratePanelSpeechOnly Server Actionを追加」し、既存画像を参照画像として渡す仕組みを構築した。
Image-to-Imageの技術を使い、既存画像をプロンプトのコンテキストとして入力した。
セリフの変更という微小な変更のみを指示することで、潜在空間上のキャラの固定を維持している。
完了画面のUIには「セリフのみ再描画」セクションを追加した。
オレンジ色のUIで通常の再生成と視覚的に区別した。
「文字が変な時に」というヒント表示も添えた。
「漫画生成の修正 - post_candidates保存エラー修正、UI改善、デバッグログ追加」というコミットで、完了画面での切り替えボタンも追加した。
パネル一覧と結合画像を簡単に切り替えられるようにした。
「漫画の結合画像を既存の投稿候補の画像候補に追加するように変更」で、シームレスな投稿体験も実現した。
「背景画像を投稿候補に保存しないように変更」というコミットで、ストレージの節約も行った。
「背景画像生成時にactivityログを記録」で、必要なログだけを残すようにした。
「新キャラ8人を漫画生成に追加」というコミットで、キャラクターの選択肢も大幅に増やした。
データベースのテーブルに8人を追加し、マッピングを更新した。
「improve: キャラ選定ガイドをカテゴリ別に整理」で、AIが適切なキャラクターを選べるようにした。
「漫画生成Stage1にキャラ選択理由フィールドを追加」し、AIがキャラを選んだ理由を保存するようにした。
「漫画生成のキャラ選択ロジックを改善」で、僕の固定設定を撤廃し、AIに自由を与えた。
ここまで読んだあなたに
今なら無料で全機能をお試しいただけます。設定後は完全放置でプロ品質の投稿を毎日生成。
非同期処理の泥沼とInngestの罠
非同期処理のタイムアウトを回避するために「Inngest」を導入した。
サーバーレス環境では処理時間が長くなると強制終了されると言われている。
4コマ漫画の生成には時間がかかるため、バックグラウンド処理が必須だった。
導入したことで、今度は「ポーリングが再開されない」という新しいバグが爆誕した。
「キャラ確認後のポーリング再開」というコミットの通り、ステップを挟むと処理が止まる。
しんたろー:
動いたと思ったら止まる。直したと思ったら別の場所がしんどいことになる。非同期処理は僕の精神を確実に削っていった。50件コミットして新機能1件。これが現実。
僕は一部を同期処理に戻した。
シンプルにしようと思って戻したら、今度はまたタイムアウトした。当たり前だ。
3往復して、最終的に非同期に落ち着いた。
「Inngestに新しいmanga workflowを登録」し、ワークフローをStage1とStage2-3に分割した。
着地したのは「Inngestを使いこなした」ではない。壊れ方のパターンを覚えただけだった。
ステップ間でコンテキストが揮発しないよう、「Supabase」を信頼できる唯一の情報源として活用する設計にした。
「ポーリングタイムアウト時のプロンプト表示フォールバック追加」というコミットで、セーフティネットも張った。
画像生成完了時にIDがない場合、データベースから直接取得するようにした。
Reactのフックのルール違反を回避するため、エフェクトを2つに分割した。
フェッチの重複を防止するための参照も追加した。
「パネル画像の個別投稿候補保存を削除(Inngest側)」というコミットで、バックグラウンド処理の責務も整理した。
「漫画生成にキャラ確認ステップを追加」で、ユーザーの介入ポイントも明確にした。
落とし穴:「プロンプトを直せば直る」という幻想
10回生成して10回とも同じ構図が出てきたとき、最初にやったのはプロンプトの修正だった。
文字数を2倍にした。指示を細かくした。それでも変わらなかった。
原因はプロンプトの外にあった。DBへの保存処理で構図データが欠落していた。
AIはそもそも構図の指示を受け取っていなかった。
ペイロードのURLフィールドも同じだ。
APIが弾いていた原因は、推論の問題ではなくリクエストの構造の問題だった。
3時間、推論側を疑い続けた。
「AIがおかしい」と思ったとき、まずデータのパイプラインを疑う。次からはそうする。たぶん。
今日の数字
| 項目 | 数字 | 比較対象 |
|------|------|----------|
| 総コミット | 50件 | 先週は32件 |
| 新機能 | 1件 | バグ修正は2件 |
| 漫画生成コスト | 16pt | 以前は26pt(約38%削減) |
| キャラ選択肢 | 12人 | 以前は僕固定の0% |
4コマ漫画1本あたりの生成コストを16ptに最適化した。
パネル生成4枚で16pt、背景は無料だ。
以前は背景込みで26ptかかっていた。50ptで3回の漫画生成が可能になった。
50件コミットして新機能1件。残り49件はバグ修正とデータパイプラインの穴塞ぎだ。
企業なら複数人で数週間かかる作業量だと思う。1人でやると、壊れ方を全部自分で覚えるしかない。
よくある質問
Q: 構図データの欠落はどうやって気づきましたか?
プロンプトを2倍にしても変わらなかったので、AIではなくデータを疑った。
DBの保存処理をログで追ったら、composition_descriptionが保存されていなかった。
「AIがおかしい」より「データがおかしい」を先に疑う方が早い、という順番を今回で覚えた。
Q: Inngestの導入で同期→非同期→同期→非同期と3往復した理由は?
最初の非同期化でポーリングが止まるバグが出た。
「シンプルにすれば直る」と思って同期に戻したらタイムアウト。当たり前だった。
結局、ステップ間のコンテキスト管理をSupabaseに委ねる設計にして落ち着いた。設計を先に決めずに実装したのが原因だ。
Q: セリフのみ再描画機能のコスト削減はどう実現しましたか?
既存画像をBase64でAPIに渡し、セリフ変更の指示だけを追加するImage-to-Image方式にした。
画像全体を一から生成する6ptから、参照画像ありの3ptに半減した。
ペイロードに不要なURLフィールドが混在していてAPIに弾かれ続けたので、仕様書を読んで削ぎ落とすのに3時間かかった。
年末5日間、50コミット、新機能1件。
ThreadPostの漫画生成は今日も壊れながら前に進んでいる。

この記事が参考になったら、ThreadPostを試してみませんか?
投稿作成・画像生成・スケジュール管理まで、全てAIにお任せできます。
ThreadPostをもっと知る