4コママンガ『ハコブくん』を Gemini API のバッチで描く ― 5話の下書きが3分で届いた

この記事の素材(コード・ログ・データ 7ファイル・まとめてダウンロードあり)
AIで読む ChatGPT・Claude などで、この記事に質問できます

4コママンガ『ハコブくん』の絵を Google の Gemini API のバッチ(何枚もの頼みを1つにまとめて送る、半額の頼み方)で頼むと、5話・40枚の下書きが約3分で全部返り、そのうち36枚をそのまま使えた。 描き直しが要ったのは4コマだけで、それは今までどおり1枚ずつ頼んで直しました。

この形に変えて、変わったことは3つです。

  • 費用:今回の5話で Gemini に描かせた絵は67枚、見積もりで約460円(1話あたり約90円)。前の第134〜137話は4話で156枚・約1,500円(1話あたり約390円)だった。下書きを半額のバッチに回したことと、1コマの候補を3〜5枚から2枚に減らしたことの両方が効いている
  • 待ち時間:バッチは「最大24時間で返す」と案内されているが、40枚が約3分で返った。夜に頼んで朝に見る前提だったのが、その場で選べる
  • 手間:描き直しの指示は、5話をまとめて見てから出せる。何話ぶんの下書きでも、頼むのは1つのコマンドで済む

『ハコブくん』は、病院で薬や物を運ぶロボット・ハコブくんと、看護師さんたちの4コママンガです。実際の病院でロボットを使ったときに起きたことを、調べた報告をもとに毎話1つ描いています(pixelstomotors.com/manga )。絵は1コマずつ、縦長(縦横比 4:5)で Gemini の画像生成 API(文章と参考の絵を渡すと絵を返す仕組み)に描かせています。

困っていたのは費用でした。正確な絵は、だいたい一発では上がってきません。腕が3本になる、ロボットの大きさが変わる、セリフの字が崩れる。そのたびに描き直すので、前の4話では1話あたり30〜70枚描かせていました。描き直しは避けられない。それなら、最初の下書きを安く大量に作り、だめなコマだけを直す。そのために使ったのが、Gemini API のバッチモードです。

第141話の下書き。上下の段が同じコマの2枚の候補で、バッチで一度に返ってきたもの

やったことの全体は次のとおりです。

やったことなぜ結果
バッチで頼む道具 vbatch.py を作った
下書きを半額で、何話もまとめて頼むため
1コマ1枚の試しで、ふつうの頼み方と同じ絵柄になった
第138〜142話の指示(spec)を、プロットからカメラワーク付きで書いた
5話を一度に頼むため5話・20コマ
1コマ2枚・40枚をバッチで頼んだ
候補を2枚に減らして費用を下げる
約3分で40枚返り、36枚を使えた
描き直しは1枚ずつ(ふつうの頼み方)
直しはすぐ見たい
第140話3コマ目・第141話3・4コマ目を直した
サイト(日本語・英語)・表紙・ショート5本・SNS の予約
いつもの公開の流れ
5話とも公開。ショートは YouTube にアップロード待ち

効果の数字について断っておきます。枚数・トークン数・返ってくるまでの時間は、API の返事と記録に残った実際の値です。円の額は、1枚約11円(ふつうの頼み方の実績・LOG410)と、バッチはその半額という Google の案内から出した見積もりで、次の請求で確かめます。

作業ログ ― Gemini API のバッチで下書きを頼む道具を作った

この記事のコード・ログ・データは、1ファイルずつ下に置いています。全文はリンク先にあります。

ファイルの一覧(7本)

01_vbatch.py.txt ― vbatch.py(バッチで頼む・状態を見る・回収する道具)・9,319字

02_sec02.py.txt ― プロットとカメラワーク / 第138話の spec.py(柱のわきで待つ)・6,294字

03_sec02.py.txt ― プロットとカメラワーク / 第139話の spec.py(扉の向こう)・6,308字

04_sec02.py.txt ― プロットとカメラワーク / 第140話の spec.py(紙くず2つ)・6,628字

05_sec02.py.txt ― プロットとカメラワーク / 第141話の spec.py(隅っこ)・6,989字

06_sec02.py.txt ― プロットとカメラワーク / 第142話の spec.py(ガラスの壁)・5,795字

07_sec04.py.txt ― YouTube ショート5本:冒頭の動き / motion138x.py(第138〜142話の冒頭の動き)・5,403字

Gemini API のバッチモードは何か

バッチモードは、たくさんの頼みを1つのファイルにまとめて送り、あとでまとめて結果を受け取る頼み方です。すぐに返事が要らない代わりに、料金がふつうの頼み方の半分になります。

この記事で使う言葉意味
ふつうの頼み方
1枚ずつ頼んで、その場で絵が返る(generateContent)。今までのやり方
バッチ
頼みを JSONL(1行に1つの頼みを書いたファイル)にまとめて送る。返りは最大24時間、48時間たつと取り消される
Files API
絵やファイルを先に Google に上げておき、頼みの中では住所(fileUri)だけで指す仕組み。上げたファイルは48時間で消える
下書き
バッチで頼んだ1コマ2枚の候補。ここから選び、だめなコマだけ描き直す

マンガの1コマを頼むときは、プロンプトの文と一緒に、キャラの設定画(三面図)や大きさの並び図など、参考の絵を何枚も付けます。ふつうの頼み方では絵を毎回中に埋め込んで送っていましたが、バッチで40枚分を埋め込むとファイルが重くなります。そこで、参考の絵は Files API に一度だけ上げて、44時間のうちは同じ絵を使い回すようにしました。

1コマの試しで、ふつうの頼み方と同じ絵になるかを確かめた

最初に、第137話の1コマ目だけをバッチで頼みました。左がふつうの頼み方で前に描いた絵、右がバッチの絵です。参考の絵が効いているか(キャラの髪型・服・ロボットの形がそろうか)を見ました。入力のトークンのうち絵の分は、ふつうの頼み方と同じ1,290でした。参考の絵が同じように読まれています。

$ python3 vbatch.py submit 137 -n 1 -p 1 && sleep 20 && python3 vbatch.py status
第137話 プロンプトを作った
頼んだ: batches/6pew97xg467pd0ru7671caw3oj2m1218r4qz 枚数 1 (第137話・1コマ1枚)
20261105_090929 batches/6pew97xg467pd0ru7671caw3oj2m1218r4qz 第137話 1 枚 BATCH_STATE_RUNNING {"requestCount": "1", "pendingRequestCount": "1"}

(約1分後)
20261105_090929 batches/6pew97xg467pd0ru7671caw3oj2m1218r4qz 第137話 1 枚 BATCH_STATE_SUCCEEDED {"requestCount": "1", "successfulRequestCount": "1"}

$ python3 vbatch.py fetch
batches/6pew97xg467pd0ru7671caw3oj2m1218r4qz 回収 1 枚・画像なし 0 ・入力トークン 3465 ・出力トークン 1860
ふつうの頼み方 第137話_P1_20261105_064605.json {"promptTokenCount": 3342, "candidatesTokenCount": 1615, "totalTokenCount": 4957, "promptTokensDetails": [{"modality": "TEXT", "tokenCount": 2052}, {"modality": "IMAGE", "tokenCount": 1290}], "candidatesTokensDetails": [{"modality": "IMAGE", "tokenCount": 1120}], "serviceTier": "standard"}
バッチ         第137話_P1_20261105_091231b1.json {"promptTokenCount": 3465, "candidatesTokenCount": 1860, "totalTokenCount": 5325, "promptTokensDetails": [{"modality": "TEXT", "tokenCount": 2175}, {"modality": "IMAGE", "tokenCount": 1290}], "candidatesTokensDetails": [{"modality": "IMAGE", "tokenCount": 1120}], "serviceTier": "SERVICE_TIER_STANDARD"}

(時刻は Mac の中の作業環境の時計で、日本時間より9時間遅れています。以下の記録も同じです。)

vbatch.py(バッチで頼む・状態を見る・回収する道具)

置き場所は iCloud の ハコブくん/4コママンガ作成データ/道具/vbatch.py。プロンプトの組み立ては、今までの vbuild.py をそのまま使います。回収した絵は、ふつうの頼み方と同じ名前の形(第138話_P1_{時刻}b1.jpg)で各話の 生成/ に置くので、大きさを測る・選ぶ・仕上げる道具はそのまま動きます。

01_vbatch.py.txt9,319字・170行・python
#!/usr/bin/env python3
"""縦長4コマを Gemini API のバッチで頼む(2026-11-05 エイイチ「Gemini 代を節約。バッチで多めの下書きを何話も一気に頼んでから修正」)

使い方(道具/ で動かす):
  python3 vbatch.py submit 138 139 140 [-n 2] [-p 1 3]   … 話ごとに prompts を作り、1コマ n 枚をまとめて頼む(-p でコマを絞る)
  python3 vbatch.py status                                 … 頼んだバッチの状態
  python3 vbatch.py fetch                                  … 終わったバッチを回収し、各話の 生成/ に置く(ふつうの gen と同じ名前の形)
直しは今までどおり vbuild.py の gen(-n 1)でその場で頼む。
別のタブで開く保存
  • ねらい:描き直しが避けられない前提で、最初の下書きを半額で何話もまとめて作る
  • 変わったこと:1コマの候補を3〜5枚から2枚に減らし、下書きはバッチ、直しはふつうの頼み方、と分けた。vbuild.py の gen も、1コマ2枚が既定になった(描き直しは -n 1)
  • 見込める効果:1話あたりの Gemini 代が、前の4話の約390円から約90円になった(見積もり)。次の請求で、バッチの分が本当に半額だったかを確かめる

第138〜142話の5話を、1つのバッチで40枚頼んだ

プロットとカメラワーク

5話のプロットは、スプレッドシートの「4コママンガプロット」にある第138〜142話です。どれも、実際の病院でロボットを使ったときの報告をもとにしています。spec(各コマの人物・カメラ・吹き出し・場面を書いた指示)は、前の LOG447 で決めたカメラワークの決まりどおり、コマごとにショットの大きさ・カメラの位置・高さ(cm)を書きました。

話題もとにした報告1話のカメラ
138柱のわきで待つ
神奈川県の病院での案内ロボットの実証(受付前の混雑で動けず、出発位置を変えた)
ハコブくん目線の背中なめ → 肩なめと横切る人の影 → 槙原さんの顔に寄る → 低い位置から柱のわき
139扉の向こう
トヨタの病院の搬送ロボットの開発(扉の向こうから来る物を前もって知れない)
背中なめの扉 → 低い位置の横から鼻先 → 岩田さんの顔を手前に → 引きで扉の上のカメラ
140紙くず2つ
米NBCニュースの報道(紙くず2枚を壁ぎわまで寄ってよけた)
床すれすれの紙くず → 寺島さんの背中なめ → ハコブくんの画面を手前に → ハコブくん目線
141隅っこ
Proof News の報道(エレベーターで職員を隅に押し込めた)
背中なめのかご → 低い斜めから回る → 外の廊下から戸口 → 扉の脇
142ガラスの壁
KQED の報道と神奈川県の実証(ガラス扉にぶつかる・ガラス壁の近くを走らない設定)
引きのガラスの部屋 → 部屋の中から肩なめ → タブレットに寄る → 角の引き

第138話の spec.py(柱のわきで待つ)

02_sec02.py.txt6,294字・51行・python
EP, TITLE = 138, "柱のわきで待つ"
# 2026-11-05 カメラワーク:P1 ハコブくん目線で見上げる森田さん(ハコブくんの頭なめ)/P2 森田さんの肩なめ、間を横切る人の影/P3 槙原さんの顔に寄る(頭をかく)/P4 低い位置から、柱のわきから出てくるハコブくんと森田さん
NOFRONT = "NOT a front-facing lineup. NOBODY faces the viewer directly."
PILLAR = ("LOBBY PILLAR", ["one plain thick round lobby column standing on the floor, plain white with light screentone. NO text, NO signs, NO posters on it"])
NOBADGE = ["Mr. Morita is a patient: he wears NO lanyard, NO name badge, NO ID card"]
PANELS = [
 dict(chars=["森田茂", "ハコブ"], mouth="NORMAL", no_yline=True, back=True, costume=NOBADGE,
      hscale_text=["Hakobukun is in the near foreground at the bottom-left, seen from BEHIND, cut by the left and bottom edges: x 0–42%, its top at about 60% of the image height",
別のタブで開く保存

第139話の spec.py(扉の向こう)

03_sec02.py.txt6,308字・55行・python
EP, TITLE = 139, "扉の向こう"
# 2026-11-05 カメラワーク:P1 ハコブくんの背中なめ、開き始める扉/P2 低い位置の横から、鼻先で向かい合うハコブくんとベッド/P3 岩田さんの顔を手前に、奥に高杉さんと止まったハコブくん/P4 引き:扉の上のカメラと、脇で待つハコブくん、通るベッド
NOFRONT = "NOT a front-facing lineup. NOBODY faces the viewer directly."
DOORS = ("DOUBLE DOORS", ["a pair of large plain hospital swinging double doors, each with a small round window (empty, no faces seen through it). NO text, NO signs"])
BED = "a plain hospital bed on casters with a white sheet and a pillow, Mr. Iwata lying on it under a blanket, his upper body slightly raised. NO text on the bed"
PANELS = [
 dict(chars=["ハコブ"], mouth="NORMAL", no_yline=True, back=True, prop=DOORS,
      hscale_text=["Hakobukun is in the near foreground at the bottom-left, seen from BEHIND, cut by the left and bottom edges: x 0–48%, its top at about 46% of the image height",
別のタブで開く保存

第140話の spec.py(紙くず2つ)

04_sec02.py.txt6,628字・54行・python
EP, TITLE = 140, "紙くず2つ"
# 2026-11-05 カメラワーク:P1 床すれすれ、手前に大きな紙くず2つ・奥で止まるハコブくん/P2 寺島さんの背中なめ、壁ぎわを大回りするハコブくん/P3 ハコブくんの画面を手前に大きく、紙くずを拾ってゴミ箱へ投げる寺島さん/P4 ハコブくん目線、腰に手の寺島さん
NOFRONT = "NOT a front-facing lineup. NOBODY faces the viewer directly."
PAPER = "two small crumpled balls of white paper, each about the size of a fist, plain, NO writing"
PANELS = [
 dict(chars=["ハコブ"], mouth="STOPPED", no_yline=True,
      prop=("PAPER BALLS", [PAPER + ", LARGE in the foreground at the bottom, x 20–70%, y 72–96%"]),
      hscale_text=["Hakobukun is about 1.5 m beyond the paper balls, three-quarter front view: its top at about 22% and wheels at about 70% of the image height, x 30–74%"],
別のタブで開く保存

第141話の spec.py(隅っこ)

05_sec02.py.txt6,989字・56行・python
EP, TITLE = 141, "隅っこ"
# 2026-11-05 カメラワーク:P1 ハコブくんの背中なめ、かごの奥に立つ高杉さん/P2 低い位置の斜めから、その場で回るハコブくんと隅に押し込まれる高杉さん/P3 外の廊下から、開いた扉をふさぐハコブくん(高杉さんは肩ごしにのぞく)/P4 扉の外で待つハコブくんを手前に、閉まりかける扉の中の高杉さん
NOFRONT = "NOT a front-facing lineup. NOBODY faces the viewer directly."
CAR = "a small plain hospital elevator car: plain back wall and side walls with light screentone, a handrail on the back wall, a simple button panel with blank round buttons. NO numbers, NO text, NO floor display"
PANELS = [
 dict(chars=["高杉", "ハコブ"], mouth="NORMAL", no_yline=True, back=True, prop=("ELEVATOR", [CAR, "the elevator doors are open, their edges at the left and right edges of the picture"]),
      hscale_text=["Hakobukun is in the near foreground at the bottom-left, seen from BEHIND as it rolls in, cut by the left and bottom edges: x 0–46%, its top at about 50% of the image height",
                   "Takasugi stands at the back wall of the car, about 1.5 m beyond it, at the right, full body: her head at about 22% and shoes at about 78% of the image height, x 56–80%"],
別のタブで開く保存

第142話の spec.py(ガラスの壁)

06_sec02.py.txt5,795字・48行・python
EP, TITLE = 142, "ガラスの壁"
# 2026-11-05 カメラワーク:P1 引き:ガラス張りの面談室と、廊下を来るハコブくん/P2 部屋の中から、大城さんの肩なめ、ガラスにコツンのハコブくん/P3 槙原さんのタブレットの画面と顔に寄る(下から)/P4 高い引き:ガラスから離れて角を曲がるハコブくん
NOFRONT = "NOT a front-facing lineup. NOBODY faces the viewer directly."
GLASS = "a floor-to-ceiling clear glass partition, shown ONLY by thin vertical frame lines and a few diagonal white shine streaks. NO text, NO stickers, NO signs on the glass"
PANELS = [
 dict(chars=["大城", "ハコブ"], mouth="NORMAL", no_yline=True, prop=("GLASS ROOM", [GLASS + "; behind it, a small meeting room with one plain table", "Oshiro stands BESIDE the table (never behind it), full body, arranging plain blank papers. NO writing"]),
      hscale_text=["the glass partition runs diagonally from the upper left to the right, x 20–100%",
                   "Oshiro is inside the room beyond the glass at the right, full body: her head at about 22% and shoes at about 66% of the image height, x 62–80%",
別のタブで開く保存

第138話と第140話の spec の、ハコブくんの大きさ・頭の形・吹き出しの位置を足した行は、あとで描き直そうとして足し、描き直しをやめたあとも残ったものです(下の「描き直しをやめたバッチ」)。選んだ絵(PICK)は、足す前の spec で描いたバッチの下書きです。

40枚のバッチは約3分で全部返った

$ python3 vbatch.py submit 138 139 140 141 142 -n 2 && sleep 5 && python3 vbatch.py status
第138話 プロンプトを作った
第139話 プロンプトを作った
第140話 プロンプトを作った
第141話 プロンプトを作った
第142話 プロンプトを作った
頼んだ: batches/265eg1lnyjrmekthe44y8lbypu6uxxotz4zz 枚数 40 (第138・139・140・141・142話・1コマ2枚)
20261105_091459 batches/265eg1lnyjrmekthe44y8lbypu6uxxotz4zz 第138・139・140・141・142話 40 枚 BATCH_STATE_RUNNING {"requestCount": "40", "pendingRequestCount": "40"}

(約3分後)
20261105_091459 batches/265eg1lnyjrmekthe44y8lbypu6uxxotz4zz 第138・139・140・141・142話 40 枚 BATCH_STATE_SUCCEEDED {"requestCount": "40", "successfulRequestCount": "40"}

$ python3 vbatch.py fetch
batches/265eg1lnyjrmekthe44y8lbypu6uxxotz4zz 回収 40 枚・画像なし 0 ・入力トークン 133576 ・出力トークン 67213

バッチは最大24時間と案内されているのに、40枚が約3分で返りました。 夜に頼んで朝に選ぶつもりでしたが、その場で選べます。混み具合で変わるはずなので、いつも3分で返るとは限りません。

2枚の候補から選んだ結果(20コマ中、描き直しは4コマ)

2枚を並べて、チェック項目(体の数・大きさ・ロボットの形・字の1字ずつ・台本にない『』)で選びました。2枚とも使えなかったのは次の2コマです。

コマ2枚の候補で起きていたこと直し方
第140話 3コマ目
1枚は両方の吹き出しに台本にない『』、もう1枚は寺島さんの吹き出しに意味のない字(拾着に構後ら)
ふつうの頼み方で2枚描き直した
第141話 4コマ目
2枚とも「乗リマス」が「乗りマス」(カタカナがひらがなに)
ふつうの頼み方で2枚描き直した(あとで場面ごと変えた)
$ python3 vbuild.py 140 gen 3 -n 2 && python3 vbuild.py 141 gen 4 -n 2
頼む枚数 2 (1コマ 2 枚)
第140話_P3_20261105_092016.jpg 19秒
第140話_P3_20261105_092019.jpg 22秒
頼む枚数 2 (1コマ 2 枚)
第141話_P4_20261105_092041.jpg 22秒
第141話_P4_20261105_092040.jpg 20秒

ほかに、縦書きになった吹き出しが何コマかあります。チェック項目では軽い問題として通す決まりなので、そのまま使いました。

仕上げた第138〜142話の4コマ。上から第138話(柱のわきで待つ)、第139話(扉の向こう)、第140話(紙くず2つ)、第141話(隅っこ)、第142話(ガラスの壁)

第141話の3・4コマ目を、見て直した

3コマ目:ハコブくんが大きすぎ、直すと今度は邪魔に見えなかった

並べた絵を見て、次の指摘がありました。

ハコブくんが大きすぎる?

高杉さんは155cm、ハコブくんは115cmなので、ハコブくんは高杉さんの約74%(上の端がみぞおち)が正しい大きさです。下書きの絵では約87%あり、肩の近くまで届いていました。原因は spec の書き方で、2人が同じ床に並んで立つコマなのに、並び図どおりに大きさを決める仕組み(vbuild.py の yline)を切って、文章で位置を書くだけにしていました。yline に戻して描き直すと、比は約81%になりました。ところが、その絵を見て次の指摘がありました。

これだとハコブくんは高杉さんの邪魔には見えないね

大きさを比べやすくしようとして2人を横に並べたので、高杉さんがハコブくんの横をすっと通れそうに見えていたのです。最後は、ハコブくんを戸口の幅いっぱいに置き、高杉さんをその真後ろ(半歩奥)に立たせました。大きさは「ハコブくんの上の端が高杉さんのみぞおち」と文で書いて合わせています。

第141話3コマ目の3つの版。左がバッチの下書き(ハコブくんが大きすぎる)、中が1回目の直し(大きさは合ったが横を通れそう)、右が採用した版(戸口をふさぎ、高杉さんは後ろで出られない)
  • ねらい:めくる前のコマで、ハコブくんが邪魔をしていることが一目で分かるようにする
  • 変わったこと:大きさを合わせる構図(横に並べる)から、話を見せる構図(戸口をふさぐ)に変え、大きさは体の部位で書いた
  • 見込める効果:ふさぐ・はさまる話のコマで、同じ直しを繰り返さない(チェック項目の台帳に、ふさぐ話の置き方として1行足した)

4コマ目:セリフと構図が合っていなかった

4コマ目このセリフだとこの構成おかしくない?

もとの4コマ目は、高杉さんが開いたかごの中に立っていて、ハコブくんが外で「次ニ、乗リマス」と言う絵でした。これでは、次のかごを待つことも、「それでいいの」が何に向けた言葉かも伝わりません。セリフを変えて、3コマ目と同じ廊下側から撮る構図にしました。ハコブくんはかごの左の壁にぴったり寄って扉の前の右半分を空け、高杉さんはそこを通って降ります。セリフは「扉ノ前ハ、空ケテオキマス」と「それでいいの」です。スプレッドシートの第141話の4コマ目も同じ中身に書き換えました。

第141話4コマ目の前と後。左は高杉さんがかごの中に立つだけの絵、右はハコブくんが壁に寄って扉の前を空け、高杉さんが降りていく絵

描き直しをやめたバッチ(10枚)

ほかの4話についても、自分のチェックで気になった所(ハコブくんが手前で大きく見える・画面が胴から飛び出す・吹き出しが端で切れる・患者さんが名札を下げている)を挙げて、直すかを聞きました。返事は「他はOK」で、これは直さなくてよいという意味でした。直すという意味に読み違えて、第138話の2コマと第140話の3コマをバッチで頼んでしまい、取り消そうとした時点で10枚とも描き終わっていました。この10枚(約55円)は取り込まず、使っていません。

batches/cv6yfgklt9812g24xkzaexy0v7xkmi985mbx BATCH_STATE_SUCCEEDED
batches/8r6ale5emqpg4yq83rpao86wuhslyaijccyr BATCH_STATE_SUCCEEDED
138 PICK を戻した
140 PICK を戻した

Gemini に描かせた枚数と費用の見積もり

頼んだもの頼み方枚数見積もり
1コマの試し(第137話)バッチ1約6円
5話の下書きバッチ40約220円
描き直し(第140話3、第141話3・4)
ふつう10約110円
表紙の吹き出し消しふつう6約66円
描き直しをやめた分バッチ10約55円
計67約460円

1話あたり約90円です。前の第134〜137話は4話で156枚・約1,500円(1話あたり約390円)でした。

サイト・英語版・表紙・ショートに出した

表紙

表紙は、見せ場のコマから吹き出しを消し、題名を重ねて作ります(LOG413)。吹き出しは Gemini の編集で消しています。第138話は、消すときの指示に「小窓の中の吹き出しも消す」という一文があったため、小窓のないコマに Gemini が小窓を描き足しました。その一文を抜いた指示で描き直しています。

第138〜142話の表紙。吹き出しを消したコマの上に、第N話と題名を重ねている

cover_edit_latest.py(表紙用に吹き出しを消す道具。PICK を第138〜142話にした)

"""縦長4コマの表紙用:選んだコマから吹き出しと字を消す(Gemini の API・2026-10-31)"""
import sys, os, concurrent.futures
sys.path.insert(0, os.path.expanduser('~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/道具'))
import vbuild as V
PICK = {138:2,139:2,140:1,141:2,142:2}
NOEDIT = {133,128,116,111,101,99,76}
PROMPT = """Edit this manga panel. Remove EVERY speech bubble and thought bubble completely, including their tails and all the text inside them (ALSO the speech bubble inside the small square inset window in the corner: erase that bubble entirely so the inset shows only the person in the room). Where a bubble was, redraw what would be behind it: plain white background, or the continuation of the wall, hair, body or object that the bubble covered. Keep sound-effect lettering drawn directly on the art (like バチン, カラン, ジリリリ) as it is. Keep EVERYTHING else exactly the same: same characters, faces, eyes, poses, sizes, positions, clothes, robots, screentone, line style, black-and-white manga look, white background, 4:5 framing. Do not add any new text, bubble, border, inset window, portrait or object. Where the bubble was, leave plain white background (and continue the thin vertical line if it passed behind the bubble)."""
here = os.path.dirname(os.path.abspath(__file__))
open(here + '/cover_edit/_prompt.txt', 'w', encoding='utf-8').write(PROMPT)
eps = [int(a) for a in sys.argv[1:]] or [e for e in PICK if e not in NOEDIT]
def job(e):
    src = os.path.expanduser(f'~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/第{e}話/仕上げ/第{e}話_P{PICK[e]}_1080x1350.png')
    return V.gen_one(here + '/cover_edit/_prompt.txt', here + f'/cover_edit/ep{e}_P{PICK[e]}', [("the manga panel to edit", src)], "4:5")
with concurrent.futures.ThreadPoolExecutor(6) as ex:
    for r in ex.map(job, eps): print(r)

第138話だけ使った、吹き出しを消す指示(_prompt138.txt)

Edit this manga panel. Remove BOTH speech bubbles completely, including their tails and all the text inside them. Where a bubble was, leave plain white background. Keep EVERYTHING else exactly the same: same characters, faces, poses, sizes, positions, clothes, robot, the grey passer-by silhouettes, the small stuck mark lines above the robot, screentone, line style, black-and-white manga look, white background, 4:5 framing. Do NOT add anything: no inset window, no picture-in-picture, no frame, no new person, no text.

英語版

英語版は描き直さず、吹き出しの中の日本語を消して英語を組みます(LOG416 の en_manga.py)。seed は各吹き出しの中の1点で、今回は白い閉じた領域を探すプログラムで座標を出してから、どの吹き出しかを見て当てました。第140話3コマ目の寺島さんの吹き出しは、コマの右の端で切れていて吹き出しとして見つけられないので、四角を指定して手書き風の字(signs の hand)で入れています。

第138〜142話の英語版。各段の左4つが英語にしたコマ、右端が英語版の表紙

英語版の指定 ep138.json

{"ep": 138, "cover_line": "I'VE BEEN WAITING FOREVER.", "panels": [{"bubbles": [{"seed": [293, 201], "text": "Could you take me\nto the exam room?"}], "signs": []}, {"bubbles": [{"seed": [270, 190], "text": "Unable to\ndepart."}, {"seed": [820, 171], "text": "I've been waiting\nhere forever."}], "signs": []}, {"bubbles": [{"seed": [228, 336], "text": "I parked it\nwhere the most\npeople walk…"}], "signs": []}, {"bubbles": [{"seed": [573, 233], "text": "Mr. Morita,\nthis way."}], "signs": []}]}

英語版の指定 ep139.json

{"ep": 139, "cover_line": "WHO'S BACKING UP?", "panels": [{"bubbles": [], "signs": []}, {"bubbles": [{"seed": [753, 202], "text": "Whoa!"}], "signs": []}, {"bubbles": [{"seed": [915, 188], "text": "…So who's\nbacking up?"}, {"seed": [457, 251], "text": "I could not see\nbehind\nthe door."}], "signs": []}, {"bubbles": [{"seed": [835, 272], "text": "A bed is coming\nthrough.\nI will wait."}], "signs": []}]}

英語版の指定 ep140.json

{"ep": 140, "cover_line": "IT'S PAPER.", "panels": [{"bubbles": [{"seed": [818, 195], "text": "Obstacle\ndetected."}], "signs": []}, {"bubbles": [{"seed": [572, 239], "text": "…It's paper."}], "signs": []}, {"bubbles": [{"seed": [324, 245], "text": "I could not tell\nwhat it was."}], "signs": [{"box": [880, 30, 1075, 330], "text": "Faster to just pick it up.", "style": "hand"}]}, {"bubbles": [{"seed": [313, 159], "text": "It may be paper.\nPlease check."}, {"seed": [878, 147], "text": "Just say so,\nand I'll\npick it up."}], "signs": []}]}

英語版の指定 ep141.json

{"ep": 141, "cover_line": "I WANT TO GET OFF!", "panels": [{"bubbles": [], "signs": []}, {"bubbles": [{"seed": [771, 185], "text": "Hey, hey,\nhey!"}], "signs": []}, {"bubbles": [{"seed": [262, 322], "text": "My floor is\nthe next one."}, {"seed": [819, 150], "text": "I want to get off!"}], "signs": []}, {"bubbles": [{"seed": [279, 165], "text": "I will keep\nthe door clear."}, {"seed": [839, 143], "text": "That's\nthe way."}], "signs": []}]}

英語版の指定 ep142.json

{"ep": 142, "cover_line": "…THERE WAS NOTHING THERE.", "panels": [{"bubbles": [], "signs": []}, {"bubbles": [{"seed": [278, 154], "text": "…There was\nnothing there."}], "signs": []}, {"bubbles": [{"seed": [541, 210], "text": "The sensor doesn't see glass.\nTo Hakobukun, there was\nno wall here at all."}], "signs": []}, {"bubbles": [{"seed": [848, 160], "text": "Walls I can't see,\nI keep on the map."}], "signs": []}]}
話日本語のページの題英語のページの題
138
人が集まる場所は、ロボットの待ち場所に向かない
Busy Spots Make Bad Robot Stops
139
ロボットに見えない所は、建物の目を借りる
Borrowing the Building’s Eyes
140
分からない物の前では、粘らずに人に聞く
When in Doubt, Ask a Human
141
狭い箱の中では、人の逃げ道を残す
Leave People a Way Out
142
センサーが見落とす物は、地図で守る
Mapping the Walls Robots Can’t See

ページは pixelstomotors.com/manga/ep138 〜 ep142 と pixelstomotors.com/english-4-koma/ep138 〜 ep142 です。p2m-site への commit は 4a0ae71 です。

$ timeout 170 python3 upload_media.py media_ep138_142
入れる 25・入っている 0・名前の重なり 0・合計 4.5MB
  25/25
おわり
$ for e in 138 139 140 141 142; do curl ... /manga/ep$e ... /english-4-koma/ep$e; done
138 200 200
139 200 200
140 200 200
141 200 200
142 200 200

YouTube ショート5本:冒頭の動き

マンガは、縦長のコマを順に見せ、声と効果音を付けた YouTube ショートにもしています。声は ElevenLabs(文章を人の声で読み上げるサービス)で作ります。冒頭の約3.6〜3.8秒は話ごとに違う動きをするハコブくんのアニメで、5つとも新しく作りました。

話冒頭の動き声(借りた声)
138
出ようとしてガクッと2回止まり、しょんぼり → 左の脇へスッと寄る
森田さん(田中先生の声)
139
走ってきて、のけぞって「!?」→ じりじり下がる
岩田さん(小芝先生の声)
140
「障害物?」→ 小刻みにじりじり大回り →「?」
寺島さん
141
その場でくるくる回り(横に縮んで裏返る)→ 目が回る →「次ノ階デス」
高杉さん
142
勢いよく走ってきて見えない壁にゴツン → 跳ね返る →「…何モ?」
槙原さん

motion138x.py(第138〜142話の冒頭の動き)

07_sec04.py.txt5,403字・121行・python
"""第138〜142話の冒頭の動き(2026-11-05)。話ごとに違う動き。
138 出ようとして、ガクッと止まる(2回)→ しょんぼり → 左の脇へスッと寄る(柱のわき)
139 走ってきて、見えない物に鼻先でぶつかりそうになり、のけぞって止まる →「!?」→ じりじり下がる
140 止まって「障害物?」→ じりじり横へ大回り(小刻みに)→「?」
141 その場でくるくる回る(横に縮んで裏返る)→ 目が回る →「次ノ階デス」
142 勢いよく走ってきて、見えない壁にゴツン → 跳ね返って揺れる →「…何モ?」"""
import sys
import numpy as np
別のタブで開く保存

spec_ep138.py(第138話_柱のわきで待つ)

import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[138] = "第82話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第138話_柱のわきで待つ", 138
HEAD = ['受付の前で', '出発できない']
COMIC = C + "ep138.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.8
MOTION = mot("ep138", EP)                  # motion138x.py
SCENES = [
  dict(kind="op", video=anim(EP, "ep138"), dur=DUR, lines=[], se=[dict(at=0.5, f="se/se_pikon.mp3", db=-12), dict(at=1.4, f="se/se_pikon.mp3", db=-12), dict(at=2.6, f="se/se_dash.mp3", db=-12)]),
  dict(kind="panel", crop=P1, fit=False, lines=[ns("森田茂", 1, "検査室まで|【頼める】かね")]),
  dict(kind="panel", crop=P2, fit=False, lines=[hk(1, "【出発デキマセン】"), ns("森田茂", 2, "わしはもう、|【ずっと待っとる】が")], se=[dict(at=0.2, f="se/se_dash.mp3", db=-14)]),
  dict(kind="panel", crop=P3, fit=False, lines=[ns("槙原", 1, "一番人が通る所に、|【待たせてた】んだ…")]),
  dict(kind="panel", crop=P4, fit=False, lines=[hk(2, "森田サン、|【コチラデス】")]),
  end(("人が一番集まる場所は", 74, "ink", 0.0), ("ロボットの", 74, "ink", 0.25), ("待ち場所", 120, "orange", 0.9), ("に向かない", 120, "orange", 0.9), ("(呼ぶ場所と待つ場所を分ける)", 34, "gray", 1.8)),
]

spec_ep139.py(第139話_扉の向こう)

import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[139] = "第63話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第139話_扉の向こう", 139
HEAD = ['扉を開けたら', '目の前にベッド']
COMIC = C + "ep139.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep139", EP)                  # motion138x.py
SCENES = [
  dict(kind="op", video=anim(EP, "ep139"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=0.8, f="se/se_pikon.mp3", db=-10)]),
  dict(kind="panel", crop=P1, fit=False, min=1.8, words=[W_("手術棟の扉", 0.1, 540, 1500, 100, "orange", 0)]),
  dict(kind="panel", crop=P2, fit=False, min=1.6, lines=[ns("高杉", 1, "【わっ!】")]),
  dict(kind="panel", crop=P3, fit=False, lines=[ns("岩田", 1, "…【どっちが下がる】の?"), hk(1, "扉ノ向コウハ、|【見エマセンデシタ】")]),
  dict(kind="panel", crop=P4, fit=False, lines=[hk(2, "向コウカラ、ベッドガ来マス。|【待チマス】")]),
  end(("見えない所は", 74, "ink", 0.0), ("建物の", 120, "orange", 0.9), ("目を借りる", 120, "orange", 0.9), ("(扉の向こうをカメラで見る)", 34, "gray", 1.8)),
]

spec_ep140.py(第140話_紙くず2つ)

import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[140] = "第48話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第140話_紙くず2つ", 140
HEAD = ['紙くず2つに', '大回りする']
COMIC = C + "ep140.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.8
MOTION = mot("ep140", EP)                  # motion138x.py
SCENES = [
  dict(kind="op", video=anim(EP, "ep140"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=0.8, f="se/se_pikon.mp3", db=-10)]),
  dict(kind="panel", crop=P1, fit=False, lines=[hk(1, "障害物ヲ、|【検知シマシタ】")]),
  dict(kind="panel", crop=P2, fit=False, lines=[ns("寺島", 1, "…【紙よ】、それ")]),
  dict(kind="panel", crop=P3, fit=False, lines=[ns("寺島", 2, "【拾ったほうが早い】わ"), hk(2, "何デアルカ、|【分カリマセンデシタ】")]),
  dict(kind="panel", crop=P4, fit=False, lines=[hk(3, "紙カモシレマセン。|【確カメテクダサイ】"), ns("寺島", 3, "最初からそう言えば、|【拾う】わよ")]),
  end(("分からない物の前では", 74, "ink", 0.0), ("粘らずに", 74, "ink", 0.25), ("人に聞く", 120, "orange", 0.9), ("(用心しすぎも遅れになる)", 34, "gray", 1.8)),
]

spec_ep141.py(第141話_隅っこ)

import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[141] = "第83話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第141話_隅っこ", 141
HEAD = ['エレベーターで', '隅に押し込む']
COMIC = C + "ep141.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.8
MOTION = mot("ep141", EP)                  # motion138x.py
SCENES = [
  dict(kind="op", video=anim(EP, "ep141"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=0.9, f="se/se_dash.mp3", db=-14), dict(at=3.0, f="se/se_pikon.mp3", db=-10)]),
  dict(kind="panel", crop=P1, fit=False, min=1.8, words=[W_("エレベーター", 0.1, 540, 1500, 100, "orange", 0)]),
  dict(kind="panel", crop=P2, fit=False, lines=[ns("高杉", 1, "【ちょっと、ちょっと!】")]),
  dict(kind="panel", crop=P3, fit=False, lines=[ns("高杉", 2, "【降りたいの!】"), hk(1, "ワタシハ、|【次ノ階】デス")]),
  dict(kind="panel", crop=P4, fit=False, lines=[hk(2, "扉ノ前ハ、|【空ケテオキマス】"), ns("高杉_納得", 1, "そうそう、|【それでいいの】")]),
  end(("狭い箱の中では", 74, "ink", 0.0), ("人の", 74, "ink", 0.25), ("逃げ道", 120, "orange", 0.9), ("を残す", 120, "orange", 0.9), ("(扉の前を空けて止まる)", 34, "gray", 1.8)),
]

spec_ep142.py(第142話_ガラスの壁)

import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[142] = "第72話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第142話_ガラスの壁", 142
HEAD = ['何もないのに', 'ぶつかった']
COMIC = C + "ep142.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep142", EP)                  # motion138x.py
SCENES = [
  dict(kind="op", video=anim(EP, "ep142"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=0.6, f="se/se_don.mp3", db=-8)]),
  dict(kind="panel", crop=P1, fit=False, min=1.8, words=[W_("ガラスの面談室", 0.1, 540, 1500, 96, "orange", 0)]),
  dict(kind="panel", crop=P2, fit=False, lines=[hk(1, "…【何モ、アリマセンデシタ】")]),
  dict(kind="panel", crop=P3, fit=False, lines=[ns("槙原", 1, "センサーには|【ガラスが映ってない】||ハコブくんには、ここに|【壁がない】ように見えてたんだ")]),
  dict(kind="panel", crop=P4, fit=False, lines=[hk(2, "見エナイ壁ハ、|【地図デ覚エマス】")]),
  end(("センサーが", 74, "ink", 0.0), ("見落とす物は", 74, "ink", 0.25), ("地図", 120, "orange", 0.9), ("で守る", 120, "orange", 0.9), ("(ガラスの壁ぎわを走らない)", 34, "gray", 1.8)),
]
$ for d in ep/第1[34]*; do python3 mkshort.py $d/spec_ep*.py; done
== 第138話_柱のわきで待つ
できあがり: out_第138話_柱のわきで待つ.mp4 21.4 秒
== 第139話_扉の向こう
できあがり: out_第139話_扉の向こう.mp4 19.6 秒
== 第140話_紙くず2つ
できあがり: out_第140話_紙くず2つ.mp4 23.4 秒
== 第141話_隅っこ
できあがり: out_第141話_隅っこ.mp4 19.8 秒
== 第142話_ガラスの壁
できあがり: out_第142話_ガラスの壁.mp4 22.2 秒

冒頭1秒の音量(効果音が鳴っているか)
第138話_柱のわきで待つ 21.4 mean_volume: -21.8 dB
第139話_扉の向こう 19.6 mean_volume: -16.1 dB
第140話_紙くず2つ 23.4 mean_volume: -16.1 dB
第141話_隅っこ 19.8 mean_volume: -16.4 dB
第142話_ガラスの壁 22.2 mean_volume: -12.8 dB

書き出したあと、各ショートのコマを15枚ずつ並べて見ました。第142話は、絵に描かれたコツンの上に字幕のコツンも出して二重になっていたので、字幕のほうを消して書き出し直しています。

第138話のショートのコマ。冒頭で出ようとしては止まるハコブくん、4コマ、最後のまとめの字

第141話の「それでいいの」が疑問形に聞こえた

エレベーターの動画の最後のセリフ「それでいいの」のイントネーションが変 これだと疑問系の発音だね。あの場面は納得する感じのそれでいいの」にしないと 言葉尻を下げる感じかな

1回目は、区切り・うなずき・言い切りの3通り(「それで、いいの。」「うん、それでいいの。」「それでいいの!」)を作りましたが、どれも疑問形に聞こえました。2回目に、言葉尻を下げる読みとして次の4通りを作り、1つ目を使うことにしました。

$ python3 ../../_制作ベース/tts_eleven.py --voice 2zABg81whjrIKypr7XTd --name 高杉_納得 --try "そうそう、それでいいの。|うん、それでいいのよ。|それでいいのよ。|[satisfied] それでいいの。"
試し_01 そうそう、それでいいの。
試し_02 うん、それでいいのよ。
試し_03 それでいいのよ。
試し_04 [satisfied] それでいいの。
できあがり: voice_eleven/高杉_納得  使った文字数 約50字

納得・言い切りのセリフは、「。」で止めて、前に「そうそう、」のようなうなずきを足すと、語尾が下がって聞こえました。 字幕も声に合わせて「そうそう、それでいいの」にしています(マンガの吹き出しは「それでいいの」のまま)。チェック項目の台帳にも、この直し方を1行足しました。

書き出した mp4 と題名・説明の txt は、KIOXIA の videos/_ショート専用/_未アップ/第138〜142話_*/ に置きました。

SNS の予約と、本編3本の投稿文

マンガ5話の予約

話
日本語の X・LinkedIn(日本時間)
英語の X(米国東部時間)
13812/2 20:002/1 11:00
13912/3 20:002/2 11:00
14012/4 20:002/3 11:00
14112/5 19:302/4 11:00
14212/6 19:302/5 11:00

マンガの投稿文は r2r2r-content の sns/MANGA_ep138〜142_sns_posts.json、ショートの X の型は sns/SHORT_ep138〜142_sns_posts.json です(commit ea80544)。

予約が抜けていた本編3本

YouTube で公開予約したショートを確かめたとき、本編3本の X と LinkedIn の予約がないことに気づきました。投稿文の json がなかったためです。3本とも作って、YouTube の公開時刻に合わせて予約しました(commit b6e1c09)。

本編XLinkedIn
ハコブくんの声と絵は、どう作っているのか
11/13 20:3011/13 20:30
ロボットの頭脳は、脳のように分かれるのか
11/18 20:0011/18 19:30
配膳ロボットが店に広がった理由は「賢さ」じゃなかった
11/20 20:0011/20 19:30
$ python3 tools/sync_youtube_shorts.py --videos youtube_videos.json
足した VIDEO_hakobu-voice-art-x 2026-11-13T20:30:00+09:00 ハコブくんの声と絵は、どう作っているのか ― キャラクターの
足した VIDEO_hakobu-voice-art-linkedin 2026-11-13T20:30:00+09:00 ハコブくんの声と絵は、どう作っているのか ― キャラクターの
足した VIDEO_robot-brain-divides-x 2026-11-18T20:00:00+09:00 ロボットの頭脳は、脳のように分かれるのか|大きなAIは大脳、
足した VIDEO_robot-brain-divides-linkedin 2026-11-18T19:30:00+09:00 ロボットの頭脳は、脳のように分かれるのか|大きなAIは大脳、
足した VIDEO_serving-robot-last-mile-x 2026-11-20T20:00:00+09:00 配膳ロボットが店に広がった理由は「賢さ」じゃなかった
足した VIDEO_serving-robot-last-mile-linkedin 2026-11-20T19:30:00+09:00 配膳ロボットが店に広がった理由は「賢さ」じゃなかった

VIDEO_hakobu-voice-art_sns_posts.json

{
  "meta": {
    "kind": "youtube_video",
    "title": "ハコブくんの声と絵",
    "youtube_title": "ハコブくんの声と絵は、どう作っているのか ― キャラクターの声と絵を、AIで作って分かったこと",
    "title_match": [
      "ハコブくん",
      "声と絵"
    ],
    "seconds": 671,
    "url": "https://youtu.be/ZT3AJ6aL-_k",
    "youtube_id": "ZT3AJ6aL-_k",
    "publish_at": "2026-11-13T20:30:00+09:00"
  },
  "posts": {
    "x_template": "AIが描いたマンガのコマ、看護師さんの腕が3本あった。見つけたのは人の目なんだよね。\nハコブくんの声も絵もAIの候補から選んでるけど、気を抜くとデザインが変わってる(笑)\n#生成AI #ロボット\n{url}",
    "linkedin_template": "このマンガのコマ、腕を数えてみてください。1、2、3。\n\n描いたのは画像を作るAI。3本目に気づいたのは、私でした。\n\nこのチャンネルの案内役ハコブくん(病院で物を運ぶ小さなロボット)は、絵も声もAIで作っています。ただ、ボタン1つではありません。\n・絵:Claude が1コマずつ指示の文を書き、Gemini が1コマずつ描き、AIがチェックのリストと見比べ、最後に私が全部のコマを見て通す。過去の間違いのリストは、2日で22行になりました。ハコブくんの横の輪に穴、ハコブくんに腕が生える、扉が頭の上に浮く……\n・声:ElevenLabs のボイスデザインで説明の文章を6通り書き、1つから3つずつ出た声を聞き比べて決めた。いちばん落ち着いて正確な声は、ハコブくんの見た目に合いませんでした\n・読み:読み間違いを見つけるたびに、直しのリストに足す。37本の台本で207組になりました\n\n減ったのは、声を録る・一から描く手間。減っていないのは、選ぶことと確かめること。むしろ確かめる所は、リストになって増えています。\n\n選ぶ仕事は、人に残るのか。正直、分かりません。ただ今は、腕の数を数えているのは人です。\n\n動画:{url}\n\nYouTube のほかの動画: https://www.youtube.com/@PixelstoMotors\n\n#生成AI #ロボット",
    "linkedin_comment_template": "補足:22行・207組は、2026年11月1日に数えた数です。マンガの絵は生成AI(Gemini)、声は AI 音声(ElevenLabs)で作っています。目次と、扱う範囲の断りは YouTube の概要欄にあります。",
    "x": "AIが描いたマンガのコマ、看護師さんの腕が3本あった。見つけたのは人の目なんだよね。\nハコブくんの声も絵もAIの候補から選んでるけど、気を抜くとデザインが変わってる(笑)\n#生成AI #ロボット\nhttps://youtu.be/ZT3AJ6aL-_k",
    "linkedin": "このマンガのコマ、腕を数えてみてください。1、2、3。\n\n描いたのは画像を作るAI。3本目に気づいたのは、私でした。\n\nこのチャンネルの案内役ハコブくん(病院で物を運ぶ小さなロボット)は、絵も声もAIで作っています。ただ、ボタン1つではありません。\n・絵:Claude が1コマずつ指示の文を書き、Gemini が1コマずつ描き、AIがチェックのリストと見比べ、最後に私が全部のコマを見て通す。過去の間違いのリストは、2日で22行になりました。ハコブくんの横の輪に穴、ハコブくんに腕が生える、扉が頭の上に浮く……\n・声:ElevenLabs のボイスデザインで説明の文章を6通り書き、1つから3つずつ出た声を聞き比べて決めた。いちばん落ち着いて正確な声は、ハコブくんの見た目に合いませんでした\n・読み:読み間違いを見つけるたびに、直しのリストに足す。37本の台本で207組になりました\n\n減ったのは、声を録る・一から描く手間。減っていないのは、選ぶことと確かめること。むしろ確かめる所は、リストになって増えています。\n\n選ぶ仕事は、人に残るのか。正直、分かりません。ただ今は、腕の数を数えているのは人です。\n\n動画:https://youtu.be/ZT3AJ6aL-_k\n\nYouTube のほかの動画: https://www.youtube.com/@PixelstoMotors\n\n#生成AI #ロボット",
    "linkedin_comment": "補足:22行・207組は、2026年11月1日に数えた数です。マンガの絵は生成AI(Gemini)、声は AI 音声(ElevenLabs)で作っています。目次と、扱う範囲の断りは YouTube の概要欄にあります。"
  },
  "note": "YouTube の本編の X と LinkedIn。url と posts.x・posts.linkedin は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。ひとりとAIのチーム 4回目。文は iCloud の 動画/ハコブくんの声と絵/投稿文_X_LinkedIn.txt(LinkedIn は日本語の部分)"
}

VIDEO_robot-brain-divides_sns_posts.json

{
  "meta": {
    "kind": "youtube_video",
    "title": "頭脳は脳のように分かれる",
    "youtube_title": "ロボットの頭脳は、脳のように分かれるのか|大きなAIは大脳、専用AIは小脳",
    "title_match": [
      "頭脳",
      "脳"
    ],
    "seconds": 426,
    "url": "https://youtu.be/TOUyy-o-f0s",
    "youtube_id": "TOUyy-o-f0s",
    "publish_at": "2026-11-18T19:30:00+09:00"
  },
  "posts": {
    "x_template": "ロボットを動かすAIが1回考えるのに、専用のAIは0.05秒、大きなAIは18.6秒。\n人の脳みたいに、大脳と小脳に分かれていくのかも。ハコブくんと壁打ちした考察回だよ。\n#フィジカルAI #ロボット\n{url}",
    "linkedin_template": "ロボットを動かすAIが1回考えるのに、専用のAIは0.05秒。何にでも使える大きなAIは18.6秒でした。\n\n速さで比べると、370倍ほどの差です。大きなAIが賢くなれば、ロボット専用の頭脳はいらなくなる、という声もあります。でも、コップを落としかけた手を0.05秒で戻すのは、考える頭とは別の仕事です。\n\n動画では、案内役のハコブくんと一緒に、\n・人の脳が大脳・小脳・反射に分かれているように、ロボットのAIも分かれていくのか\n・小脳を育てるのは何か(失敗した所の手直し)\n・手直しの記憶を、どう整理して学ばせるか\nを考えました。答えを伝える回ではなく、考えている途中をそのまま見せる考察回です。数字と考えた道すじの全文はサイトの記事にあります。\n\n動画:{url}\n\nYouTube のほかの動画: https://www.youtube.com/@PixelstoMotors\n\n#フィジカルAI #ロボット #AI",
    "linkedin_comment_template": "補足:0.05秒・18.6秒は NVIDIA の Astranomy(2026年10月14日)の値です。数字の出どころは概要欄に、考えた道すじは記事にあります https://pixelstomotors.com/record/robot-ai-divides-like-brain",
    "x": "ロボットを動かすAIが1回考えるのに、専用のAIは0.05秒、大きなAIは18.6秒。\n人の脳みたいに、大脳と小脳に分かれていくのかも。ハコブくんと壁打ちした考察回だよ。\n#フィジカルAI #ロボット\nhttps://youtu.be/TOUyy-o-f0s",
    "linkedin": "ロボットを動かすAIが1回考えるのに、専用のAIは0.05秒。何にでも使える大きなAIは18.6秒でした。\n\n速さで比べると、370倍ほどの差です。大きなAIが賢くなれば、ロボット専用の頭脳はいらなくなる、という声もあります。でも、コップを落としかけた手を0.05秒で戻すのは、考える頭とは別の仕事です。\n\n動画では、案内役のハコブくんと一緒に、\n・人の脳が大脳・小脳・反射に分かれているように、ロボットのAIも分かれていくのか\n・小脳を育てるのは何か(失敗した所の手直し)\n・手直しの記憶を、どう整理して学ばせるか\nを考えました。答えを伝える回ではなく、考えている途中をそのまま見せる考察回です。数字と考えた道すじの全文はサイトの記事にあります。\n\n動画:https://youtu.be/TOUyy-o-f0s\n\nYouTube のほかの動画: https://www.youtube.com/@PixelstoMotors\n\n#フィジカルAI #ロボット #AI",
    "linkedin_comment": "補足:0.05秒・18.6秒は NVIDIA の Astranomy(2026年10月14日)の値です。数字の出どころは概要欄に、考えた道すじは記事にあります https://pixelstomotors.com/record/robot-ai-divides-like-brain"
  },
  "note": "YouTube の本編の X と LinkedIn。url と posts.x・posts.linkedin は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。考察回「壁打ちの型」の1本目(もとは LOG424)。投稿文の txt がないため、概要欄_下書き.md から作った(2026-11-05)"
}

VIDEO_serving-robot-last-mile_sns_posts.json

{
  "meta": {
    "kind": "youtube_video",
    "title": "現場で扱えるか",
    "youtube_title": "配膳ロボットが店に広がった理由は「賢さ」じゃなかった",
    "title_match": [
      "配膳ロボット",
      "賢さ"
    ],
    "seconds": 516,
    "url": "https://youtu.be/yn7tePEfPec",
    "youtube_id": "yn7tePEfPec",
    "publish_at": "2026-11-20T19:30:00+09:00"
  },
  "posts": {
    "x_template": "成功率99%でも、1時間に600回働けば6回呼ばれる。\n配膳ロボットが店に広がったのは、賢さより「止まったとき店の人が戻せるか」だったんだよね。ハコブくんと壁打ちした考察回だよ。\n#配膳ロボット #ロボット\n{url}",
    "linkedin_template": "成功率99%のロボットでも、1時間に600回働けば、10分に1回は人が呼ばれます。\n\n配膳ロボットが店に広がったのは、賢さではありませんでした。いちばん難しい「料理をテーブルに置く」はお客さんに任せ、止まってもボタン1つで店のスタッフさんが戻せる。\n\n動画では、ハコブくんと一緒に、\n・配膳ロボットが先に広がった条件\n・止まった理由が分かるか、その場の人が戻せるか、次の動きが読めるか\n・足りなくなるのは、作る人より、店に入れて回す人\n・最後の壁、下げ膳と調理場の扉\nを考えました。考えた道すじの全文はサイトの記事にあります。\n\n動画:{url}\n\nYouTube のほかの動画: https://www.youtube.com/@PixelstoMotors\n\n#配膳ロボット #フィジカルAI #ロボット",
    "linkedin_comment_template": "補足:考えた道すじの全文は記事にあります https://pixelstomotors.com/record/service-robot-last-mile",
    "x": "成功率99%でも、1時間に600回働けば6回呼ばれる。\n配膳ロボットが店に広がったのは、賢さより「止まったとき店の人が戻せるか」だったんだよね。ハコブくんと壁打ちした考察回だよ。\n#配膳ロボット #ロボット\nhttps://youtu.be/yn7tePEfPec",
    "linkedin": "成功率99%のロボットでも、1時間に600回働けば、10分に1回は人が呼ばれます。\n\n配膳ロボットが店に広がったのは、賢さではありませんでした。いちばん難しい「料理をテーブルに置く」はお客さんに任せ、止まってもボタン1つで店のスタッフさんが戻せる。\n\n動画では、ハコブくんと一緒に、\n・配膳ロボットが先に広がった条件\n・止まった理由が分かるか、その場の人が戻せるか、次の動きが読めるか\n・足りなくなるのは、作る人より、店に入れて回す人\n・最後の壁、下げ膳と調理場の扉\nを考えました。考えた道すじの全文はサイトの記事にあります。\n\n動画:https://youtu.be/yn7tePEfPec\n\nYouTube のほかの動画: https://www.youtube.com/@PixelstoMotors\n\n#配膳ロボット #フィジカルAI #ロボット",
    "linkedin_comment": "補足:考えた道すじの全文は記事にあります https://pixelstomotors.com/record/service-robot-last-mile"
  },
  "note": "YouTube の本編の X と LinkedIn。url と posts.x・posts.linkedin は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。考察回。文は KIOXIA の videos/現場で扱えるか/アップロード用/投稿文_X_LinkedIn.txt(LinkedIn は日本語の部分)"
}

次の話も、下書きはバッチで何話もまとめて頼む

5話の下書きが3分で返ったので、次は10話ぶんを1回のバッチで頼むこともできます。ただし、バッチの下書きが36枚使えたのは、spec にカメラワークと大きさを先に書いていたからです。並んで立つコマで大きさの仕組みを切らないこと、ふさぐ・はさまる話のコマは、大きさではなく話を見せる構図にすること。この2つを spec を書く段階で守れば、描き直しはさらに減る見込みです。

出典