4コママンガ『ハコブくん』を画像生成AIで描く費用 ― 5話で約590円、1話約120円
この記事の素材(コード・ログ・データ 6ファイル・まとめてダウンロードあり)arrow_downwardAIで読む ChatGPT・Claude などで、この記事に質問できます expand_more
4コママンガ『ハコブくん』の第148〜152話の5話を、Google の Gemini で絵を描き、ElevenLabs の声でショート動画にし、英語版とサイトへの公開、SNS の予約まで出した費用は、使った量から計算して約590円、1話あたり約120円でした。 そのうち約550円が Gemini の絵の代金で、残りは声が約13円、X の投稿の API が約24円です。5話のマンガは pixelstomotors.com/manga/ep148 から読めます。
費用を1回の頼みごとに出したので、次のことが分かりました。
- 何にお金がかかっているか:絵の代金の4割(224円)は最初の下書き40枚で、残りの6割(326円)は描き直しの24回。描き直しが減れば、そのまま安くなる
- 頼み方の差:バッチ(まとめて頼む半額の頼み方)は1枚約5.6円、その場で頼むふつうの頼み方は約11円。下書きをバッチにまとめた分、40枚で約220円浮いた
- 前の5話との差:第143〜147話(LOG468)は、Gemini に描かせた絵が120枚・見積もりで約1,100円、エイイチの指摘が5回だった。今回は描かせた絵が69枚・約550円、指摘は1回。依頼から SNS の予約を入れ終えるまで約1時間15分だった
計算で1つ気づいたのは、1回の頼みで絵が6枚返ってきて、その1回だけで約65円かかっていたことです。 ふつうは1回で1枚(約11円)なので、この1回で5回分を払っています。描く道具は最後の1枚だけを保存するので、ファイルを見ても気づけませんでした。返事の使用量(出力の画像のトークン数)を1回ずつ足したので見つかりました。
もう1つは、Google AI Studio の月の支払い上限です。11月は自動の足し込みで800円ずつ6回、4,800円が入っていて、上限の5,000円に届いていました。そのため、表紙を作るための Gemini の編集(吹き出しを消す)は5回とも断られ、表紙の吹き出しはプログラムで消しました。断られた頼みには費用がかかっていません。
やったことの全体は次のとおりです。
| やったこと | 結果 | Gemini の費用 |
|---|---|---|
第148〜152話のプロットから、5話の構図とセリフの指示(spec)を書いた | 20コマの指示 | ― |
| 下書きをバッチで40枚頼んだ | 4分半で全部返った | 224円 |
| 1コマずつの確認で描き直した | 第150話 P1(字の間違い)・第151話 P4(隣のコマと同じ構図) | 99円 |
別のエージェントに全コマを見てもらい、描き直した | 誰の手か分からない手・ハコブくんが話し相手でなく読者を向く、の6コマ | 135円 |
エイイチの指摘(ハコブくんが細すぎる)で描き直した | 4コマ | 91円 |
ショート5本(冒頭の動き・声・書き出し) | 21〜29秒 | 声 約13円 |
表紙・英語版を作り、サイトに10ページを公開した | 日本語と英語の5話ずつ | 0円 |
| SNS を予約した | 日本語の X 5本・英語の X 5本 | X 約24円(投稿のときに引かれる) |

数字について断っておきます。Gemini の費用は、返事に入っている使用量(トークン数)と Google の料金のページの単価から出した計算です(請求書の明細ではありません)。声の費用は、ElevenLabs の月額の料金を1か月に使える文字数で割った単価から出しています。X の費用は、まだ投稿されていない予約の分です。
作業ログ ― 第148〜152話のプロットから、構図とセリフの指示を書いた
この記事のコード・ログ・データは、1ファイルずつ下に置いています。全文はリンク先にあります。
ファイルの一覧(6本)
01_spec.py.txt ― 第148話 spec.py・7,130字
02_spec.py.txt ― 第149話 spec.py・6,694字
03_spec.py.txt ― 第150話 spec.py・9,639字
04_spec.py.txt ― 第151話 spec.py・8,271字
05_spec.py.txt ― 第152話 spec.py・7,575字
06_sec05.py.txt ― 冒頭の動き(motion148x.py)・5,647字
使ったプロット(plots_134_158_直した版.tsv)
進捗管理表(Google スプレッドシート「4コママンガプロット」)の未着手の先頭5話を使いました。プロットは、病院のロボットの報道と研究を調べて作り、codex(別の AI)に疑ってもらって直した表です(作業フォルダ 記事/ハコブくん_新プロット_20261031/)。
| 話 | 題 | 登場人物 | もとにした調べ |
|---|---|---|---|
| 148 | 積む人がいない | 大城、寺島、白石、ハコブくん | ロボットは人が積まないと仕事が始まらず、急な対応の多い病棟では動けない働き手と見られた(米国の病院の研究の紹介・hinnovic) |
| 149 | 呼ばれなくなった | 寺島、白石、ハコブくん | 厨房スタッフ16人のうち8人が、ロボットを当てにできないとして自分でやっていた(デンマークの病院の研究) |
| 150 | 7つのはずが28 | 大城、白石、ハコブくん | 管理側は7段階と説明したが、実際の運用は28段階だった(ACM Interactions) |
| 151 | 着いたのに | 大城、田中先生、ハコブくん | 救急外来の薬の搬送ロボットで、到着を看護師と薬剤師に知らせる仕組みを試作と試験で作り直した(チャンギ総合病院) |
| 152 | 間に合うかどうか | 寺島、白石、ハコブくん | ロボットが階をまたぐと迷うため、看護師が採血の検体を任せなくなった(Proof News) |
登場人物はプロットより少なく絞りました。第151話は白石さんを出さず、第152話は検査室の人を電話の声だけにしています。ハコブくんの画面には字を出さない決まりなので、プロットで「画面に『積ミ込ミ待チ』」「画面に『到着シマシタ』」と書かれていた所は、吹き出しのセリフにしました。
5話で使う共通の文(_common_148_152.py)
ハコブくんの大きさを体の部位で書く文、ドロワーを閉じる文、向きを書く文をまとめました。TURN は別のエージェントの確認のあと、WIDE はエイイチの指摘のあとに足したものです(下の節)。
# 第148〜152話で使う共通の文(2026-11-14)
import os
from importlib.machinery import SourceFileLoader as _L
F = _L("_face", os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/_face.py")).load_module().face
def SIZE(name, part):
return "SIZE: Hakobukun's top edge reaches only %s. %s's chest, shoulders and head are clearly ABOVE the robot. Hakobukun is NOT as tall as %s chest" % (part, name, "her" if name in ("Oshiro", "Terashima", "Shiraishi") else "his")
PIT = "the pit of {n}'s stomach"
LOWCHEST = "the lower edge of {n}'s chest — still clearly below her shoulders"
CLOSED = ("HAKOBUKUN DRAWER — CLOSED:", ["Hakobukun's drawer is fully CLOSED, exactly as on the reference sheet. Its body has NO window, NO transparent panel, NO opening — nothing inside the robot is visible"])
# 2026-11-14 チェック①(別のエージェント):ハコブくんが話し相手でなく読者を向くコマが5つ → 向きを見える形でさらに書く
def TURN(side, who):
away = "LEFT" if side == "right" else "RIGHT"
return ("HAKOBUKUN IS TURNED TOWARD %s — SEEN FROM ITS %s SIDE:" % (who.upper(), away), [
"we see Hakobukun mostly from its %s side: the flat side panel with the round ring is LARGE and faces the viewer" % away.lower(),
"its screen face is turned toward %s and is seen at a STEEP angle, as a narrow slanted shape at the %s edge of its silhouette" % (who, side.upper()),
"the white oval eyes on the screen look toward %s, NOT at the viewer" % who])
# 2026-11-14 エイイチ「ハコブくん細すぎ。無理に入れ込まないで、人は多少脇にはみだしてもいい」→ ハコブくんの幅を画像の幅で決め、人は左右の端で切れてよいと書く
def WIDE(x0, x1):
return ("HAKOBUKUN WIDTH — WIDE AND STOUT, NEVER SQUEEZED:", [
"Hakobukun's body spans x %d–%d%% of the image width — about one third of the picture. Its width is its height divided by 1.7, exactly as on the reference sheet" % (x0, x1),
"do NOT slim or narrow Hakobukun to make room for the people. Give the robot its full width FIRST, then place the people",
"the people may be cut by the left or right edge of the picture (part of the shoulder or arm outside the frame) — that is fine. Squeezing the robot is NOT"])
第148話 spec.py
spec.py は、1話の4コマの構図・カメラ・セリフ・大きさを書くファイルです。vbuild.py(LOG448 までに作った道具)がこれを読み、キャラクターの参考の絵と決まりの文を足して Gemini への頼み文を組みます。下は、描き直しを全部終えた時点の spec.py で、直したときの上書きを日付と理由を添えて足しています。
EP, TITLE = 148, "積む人がいない"
# 2026-11-14 カメラワーク:P1 ハコブくん目線100cm・全身、リネン庫の前でドロワーを開けて待つ(横に袋を積んだカート)
# P2 人の目線・横から、手前を走り抜ける大城さんと寺島さん(ハコブくんは奥に小さく)/P3 低い90cm・斜め前、同じ床の寺島さんとハコブくん(時計)
# P4 白石さんの肩なめ150cm、表を持つ白石さんと、奥で別の仕事へ向かうハコブくん
import os
from importlib.machinery import SourceFileLoader as _L
C = _L("_c", os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/_common_148_152.py")).load_module()
CART = "a plain wheeled linen cart piled high with four or five tied white laundry bags of used linen. NO text, NO labels"第149話 spec.py
EP, TITLE = 149, "呼ばれなくなった"
# 2026-11-14 カメラワーク:P1 白石さんの肩越しにタブレットの画面(棒が右へ下がる)150cm/P2 廊下を歩く寺島さんの膝上・斜め前140cm、薬の袋を自分で持つ
# P3 低い90cm・斜め前、部屋の隅の充電台のハコブくんと、横に立つ白石さん(同じ床)/P4 斜め前150cm・3人の全身、2本の棒を見せる白石さんと寺島さん
import os
from importlib.machinery import SourceFileLoader as _L
C = _L("_c", os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/_common_148_152.py")).load_module()
TAB = "a plain tablet"
PANELS = [第150話 spec.py
EP, TITLE = 150, "7つのはずが28"
# 2026-11-14 カメラワーク:P1 白石さんの腰上・下から120cm、7つの箱を矢印でつないだホワイトボードを指す(自信)
# P2 白石さんの肩なめ140cm、奥でドロワーを拭く大城さんと、ドロワーを開けたハコブくん/P3 メモ帳の大写し(字にならない書き込みでびっしり)と、奥で青ざめる白石さん
# P4 斜め前150cm・3人の全身、長くなったメモ
import os
from importlib.machinery import SourceFileLoader as _L
C = _L("_c", os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/_common_148_152.py")).load_module()
MEMO = "a plain small spiral memo pad"第151話 spec.py
EP, TITLE = 151, "着いたのに"
# 2026-11-14 カメラワーク:P1 斜め後ろ寄り・150cm、閉まった処置室の扉の前で止まるハコブくん(全身・ぽつん)
# P2 部屋の中、田中先生と大城さんの腰上・斜め前140cm(ハコブくんは出ない)/P3 真横・ハコブくん目線100cm、扉を開けて飛び出す大城さんとハコブくん(同じ床・全身)
# P4 斜め前・150cm、震える端末を手に早足で出てくる大城さんの膝上と、横で待つハコブくん
import os
from importlib.machinery import SourceFileLoader as _L
C = _L("_c", os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/_common_148_152.py")).load_module()
DOOR = "a plain closed sliding door of a treatment room standing on the floor, with a plain vertical handle and NO window, NO sign, NO text"第152話 spec.py
EP, TITLE = 152, "間に合うかどうか"
# 2026-11-14 カメラワーク:P1 斜め前120cm・全身、ドロワーに採血管の立てを入れる寺島さんとハコブくん(同じ床)
# P2 寺島さんの顔に寄る(受話器)・斜め右155cm/P3 低い60cm・引き、別の階のエレベーターの前で迷うハコブくん(ぽつん)
# P4 斜め前150cm・3人の全身、ストップウォッチの白石さん、ほっとしつつ首を振る寺島さん
import os
from importlib.machinery import SourceFileLoader as _L
C = _L("_c", os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長/_common_148_152.py")).load_module()
RACK = "a small plain rack holding four plain blood sample tubes with plain caps. NO labels, NO text"Gemini のバッチで、5話の下書き40枚が4分半で返った
5話の頼み文を作って、1コマ2枚ずつ、40枚をバッチで頼みました。バッチは Google の Batch API(たくさんの頼みをまとめて送り、返りを待つ頼み方)で、料金はふつうの半分です。返りは最大24時間と案内されていますが、今回は4分半で全部返りました。
$ for e in 148 149 150 151 152; do python3 vbuild.py $e prompts; done
P1 8677 字 3 枚
P2 10161 字 6 枚
P3 11717 字 5 枚
P4 9617 字 4 枚
P1 5531 字 2 枚
P2 5641 字 2 枚
P3 11855 字 4 枚
P4 12289 字 5 枚
P1 5584 字 2 枚
P2 10760 字 6 枚
P3 5973 字 2 枚
P4 12739 字 5 枚
P1 8828 字 2 枚
P2 5843 字 4 枚
P3 11878 字 4 枚
P4 10103 字 4 枚
P1 11296 字 5 枚
P2 5627 字 2 枚
P3 8459 字 2 枚
P4 12457 字 5 枚
$ python3 vbatch.py submit 148 149 150 151 152 -n 2
第148話 プロンプトを作った
第149話 プロンプトを作った
第150話 プロンプトを作った
第151話 プロンプトを作った
第152話 プロンプトを作った
頼んだ: batches/vqk06wcirg83wslr842zvdkmynxuy4zqmefb 枚数 40 (第148・149・150・151・152話・1コマ2枚)
$ python3 vbatch.py status
20261114_004330 batches/vqk06wcirg83wslr842zvdkmynxuy4zqmefb 第148・149・150・151・152話 40 枚 BATCH_STATE_SUCCEEDED {"requestCount": "40", "successfulRequestCount": "40"}
$ python3 vbatch.py fetch
batches/vqk06wcirg83wslr842zvdkmynxuy4zqmefb 回収 40 枚・画像なし 0 ・入力トークン 135824 ・出力トークン 66493

下書きから1コマずつ選びました。選ぶときに見たのは、チェック項目(腕と脚の数・字・ハコブくんの形・大きさ・向き)と、隣のコマとの違いです。たとえば第148話の1コマ目は、上の段の絵に台本にない「」が付いていたので下の段を選び、4コマ目は下の段のハコブくんの体に「ハコブくん 115cm」と字が出ていたので上の段を選びました。
1コマずつの確認と、別のエージェントの確認で10コマを描き直した
自分の確認で描き直した2コマ
| コマ | 2枚ともだめだった理由 | 直し方 |
|---|---|---|
| 第150話 P1 | 1枚目は台本にない『』、2枚目は「検体を運ぶを手順は」と字が違い、縦書き | 1字ずつ並べた TEXT CHECK と「運ぶと手順の間に を はない」を足した |
| 第151話 P4 | 「膝上」の指定を無視して全身で描かれ、隣の P3 と同じ並び(左にハコブくん・右に全身の大城さん)になった | 大城さんを手前の胸上、ハコブくんを奥の全身にする重ねの構図に変えた |
第150話 P1 の描き直しは、2回のうち1回で絵が6枚返ってきました。その1回だけで約65円です(下の「費用」の節)。
別のエージェントに20コマを見てもらった
何話もまとめて描いたときは、描いた本人とは別のエージェントに1コマずつ見てもらう決まりです(チェック項目と過去の間違いの台帳)。20コマと5話の並びを渡すと、次の報告が返りました。
| 判定 | コマ | 理由 |
|---|---|---|
| 要修正 | 第150話 P3 | 左下から手帳を持つ大きな手が、誰の手か分からない。手帳に英語もどきの字と1〜20の番号 |
| 軽微 | 第148話 P3 | ハコブくんが寺島さんでなく読者を向く。カートが消え、「1時間後」が絵から分からない |
| 軽微 | 第149話 P3 | ハコブくんが白石さんでなく読者を向く。白石さんの胸で肩ひもが2本交差 |
| 軽微 | 第150話 P4・第151話 P3・第152話 P4 | ハコブくんが話し相手でなく読者を向く |
| 軽微 | 第152話 P4 | ハコブくんの吹き出しのしっぽが、ハコブくんと白石さんの間で止まる |
| 軽微 | 縦書きの吹き出し | 第148話 P3・第149話 P1・第151話 P2〜P4 など |
| OK | ほか | 字は全コマで台本と1字ずつ同じ。名札は白紙。背景の写り込みなし |
ハコブくんが読者を向く件は、LOG468 でエイイチに指摘されたことと同じでした。前回作った face(画面を相手のほうへ約60°)を入れていても起きたので、TURN を足しました。「輪のある側面が大きく手前を向き、画面は相手のほうへ急な角度で細く見える」と、見える面の形で書いています。6コマを1コマ2枚ずつ描き直し、第149話 P3 は2枚とも形と大きさが崩れたので前の絵のままにしました。
4コマ通しの確認で見たこと
1コマずつのあと、4コマを並べて話として読みました(LOG468 で足した手順)。第151話は、3コマ目と4コマ目が同じ並びになっていたので、4コマ目を描き直しています。第152話は、迷子のハコブくんを3コマ目に置き、「間に合ったのは、運がよかっただけ」と「測ってから運ぶ」を4コマ目にまとめました。
エイイチの指摘で、細すぎたハコブくんを4コマ描き直した
確認用の絵を見せると、エイイチから次の指摘がありました。
ハコブくん細すぎ。無理に入れ込まないで、人は多少脇にはみだしたりしてもいいよ
3人が並ぶコマで、人と人の間にハコブくんを押し込んだため、ハコブくんの幅が縮んで縦長になっていました。高さの比は合っていても、幅が足りません。ハコブくんの高さと幅の比は 1.7 : 1 と決まっています。

- ねらい:ハコブくんの幅を、人より先に絵の中で取る
- 変わったこと:
WIDEで「ハコブくんの体は画像の幅の x 32〜66%(約3分の1)」と書き、「人は左右の端で切れてよい・ロボットを細くするのはだめ」と書いた。人の位置は端へ寄せた - 見込める効果:3人並びのコマで、ハコブくんが細くならない。次の話で、細さの指摘が出るかで確かめる
「端で切れてよい」と書くと、第152話 P4 では左右の端に知らない人の肩が写りました。仕上げのときに、その部分を白で塗っています(spec の PATCH)。チェック項目には「ハコブくんの幅が細くなっていない」を足しました。

描き直したあとの高さの比は、vbuild.py の measure と目で測りました。
148 3 [(37, 41, 93, 52), (78, 18, 93, 75)] 比 0.69
149 3 [(30, 34, 93, 59), (74, 4, 95, 91)] 比 0.65
149 4 [(21, 40, 92, 52), (54, 18, 92, 74), (82, 18, 92, 73)] 比 0.70
150 2 [(23, 31, 100, 69), (70, 13, 75, 61)] 比 0.88
150 4 [(31, 20, 96, 77), (68, 20, 97, 77)] 比 1.00
151 3 [(28, 41, 92, 51), (76, 3, 93, 90)] 比 0.57
152 1 [(31, 12, 91, 79), (63, 34, 91, 57)] 比 0.72
152 4 [(18, 23, 96, 74), (52, 40, 95, 55), (82, 23, 97, 74)] 比 0.74
measure は、緑の背景の上の塊を床に立つものとして数えます。吹き出しや扉が人とつながると塊が大きくなり、比がずれます(149 P3・150 P2・150 P4・151 P3)。そのコマは目で測り、第148話 P3 は 0.76、第149話 P3 は 0.74、第150話 P4 は 0.65、第151話 P3 は 0.75 でした。並び図の比は、ハコブくん 115cm と寺島さん・白石さん 160cm で 0.72、大城さん 165cm で 0.70 です。
ショート5本を作った(冒頭の動き・声・書き出し)
作業環境を前回の控えから戻した
ショートを作る道具は、第143〜147話のときに KIOXIA に残した控え(_ショート専用/_取り込み_20261108/w143.tgz)から戻しました。表紙と動きの字に使う Noto Sans CJK の Black の太さが作業環境になかったので、noto-cjk の NotoSansCJKjp-Black.otf を入れて、道具の中のフォントの場所を差し替えています。
冒頭の動き(motion148x.py)
ショートの冒頭の約3.6秒は、話ごとに違う動きをするハコブくんのアニメです。前の話の動きと重ねない決まりなので、5つとも新しく作りました。
| 話 | 冒頭の動き | 背景 |
|---|---|---|
| 148 | 来て止まり「積ミ込ミ/待チ」→ きょろきょろ → 画面の「…」が増えてゆっくり沈む | 夕方の廊下 |
| 149 | 隅でじっと待つ → ピコン!と跳ねて「呼バレタ?」→ しぼんで「…呼バレテ/ナイ」 | 物品の棚の前 |
| 150 | 画面の数字が 1〜7 と数え、止まらず 8〜28 と速くなる → 「28!」で×目、くらっと傾く | 休憩室 |
| 151 | 扉の前に止まって「到着/シマシタ」→ 前のめりに3回コツコツ → 「到着…」 | 夜の廊下 |
| 152 | 右へ左へ行ったり来たり(だんだん速く)→ 真ん中で「ココ/ドコ?」 | エレベーターの前 |
"""第148〜152話の冒頭の動き(2026-11-14)。話ごとに違う動き(143〜147・138〜142 とも重ねない)
148 来て止まり「積ミ込ミ/待チ」→ 左右をきょろきょろ(誰も来ない)→ 時計の針のように画面に「…」が増え、ゆっくり沈む
149 隅でじっと待つ → ピコン!と跳ね上がって「呼バレタ?」→ 何も来ない → しぼんで「…呼バレテ/ナイ」
150 画面の数字が 1,2,3…7 と数える → 止まらず 8…28 と速くなり、体がふるえる → 「28!」で×目、くらっと傾く
151 扉の前(左)に止まって「到着/シマシタ」→ 前のめりに3回コツコツ → 返事がなく、画面が小さく「到着…」
152 右へ進んで止まり、くるっと左へ → 左へ進んで止まり、くるっと右へ(速くなる)→ 真ん中で「ココ/ドコ?」"""
import sys
import numpy as np書き出し: ハコブくん_ep149.mp4
!体が映像の窓からはみ出す(頭・足が切れる): 7コマ 例 [(1.2, 171, 845), (1.23, 164, 840), (1.27, 159, 836)](秒, 上端, 下端)
書き出し: ハコブくん_ep151.mp4
!体が映像の窓からはみ出す(頭・足が切れる): 10コマ 例 [(0.0, 278, 907), (0.03, 275, 904), (0.07, 274, 901)](秒, 上端, 下端)
書き出し: ハコブくん_ep152.mp4
書き出し: ハコブくん_ep148.mp4
!体が映像の窓からはみ出す(頭・足が切れる): 8コマ 例 [(0.0, 278, 907), (0.03, 275, 904), (0.07, 274, 901)](秒, 上端, 下端)
書き出し: ハコブくん_ep150.mp4
148話と151話の知らせは、右の端から走ってくる最初の数コマで、体が画面の端にかかっているものです(前の話の「右から来て止まる」と同じ)。149話はピョンと跳ねる高さが窓の上に出ていたので、70 から 50 に下げて書き出し直しました(1コマだけ残った知らせは窓の左右の端で、体は切れていません)。

声(声.sh)
声は ElevenLabs(文章を人の声で読み上げるサービス)で作りました。鍵は KIOXIA に置いたファイルを tts_eleven.py が読みます。寺島さんの声はロボのアバターさんと同じ声、第152話の検査室の電話の声は槙原さんの声を借りています(作れる声の数の上限のため)。数字は読み間違えないように、「302号室」を「さんまるに号室」、「28個」を「にじゅうはっこ」と書いて読ませました。
5話をいっせいに頼むと、ElevenLabs から「同時に頼めるのは3つまで」と断られたので、1話ずつ順に頼み直しました。
試し_01 で止まりました: 429 {"detail":{"type":"rate_limit_error","code":"concurrent_limit_exceeded","message":"Too many concurrent requests. Your current subscription is associated with a maximum of 3 concurrent requests (running in parallel). This is done such that a single user does not overwhelm our systems and affect other
!白石 で止まりました
第148話の声.sh
#!/bin/bash
# 第148話_積む人がいない のショートの声(2026-11-14)。鍵は KIOXIA の elevenlabs_api_key.txt を tts_eleven.py が読む
cd "$(dirname "$0")"
B=../../_制作ベース
[ -f "voice_eleven/ハコブ/試し_03.mp3" ] || python3 $B/tts_eleven.py --voice gWJpc8whMBqnF7Y0kc9f --name ハコブ --try "積み込みを、お待ちしています|誰も、積みませんでした|積む人がいない時は、後で来ます" || echo " !ハコブ で止まりました"
[ -f "voice_eleven/寺島/試し_02.mp3" ] || python3 $B/tts_eleven.py --voice yWM6Fym2UxDGZqWRoGLB --name 寺島 --try "さんまるに号室、急変です!|ごめん、今日はそれどころじゃなくて…" || echo " !寺島 で止まりました"
[ -f "voice_eleven/大城/試し_01.mp3" ] || python3 $B/tts_eleven.py --voice PrFsT9a2iZebpuiWVeug --name 大城 --try "すぐ行く!" || echo " !大城 で止まりました"
[ -f "voice_eleven/白石/試し_01.mp3" ] || python3 $B/tts_eleven.py --voice orQ2eWONBvtrTIvdS8RS --name 白石 --try "積む人も、予定に入れなきゃね。" || echo " !白石 で止まりました"
第149話の声.sh
#!/bin/bash
# 第149話_呼ばれなくなった のショートの声(2026-11-14)。鍵は KIOXIA の elevenlabs_api_key.txt を tts_eleven.py が読む
cd "$(dirname "$0")"
B=../../_制作ベース
[ -f "voice_eleven/白石/試し_02.mp3" ] || python3 $B/tts_eleven.py --voice orQ2eWONBvtrTIvdS8RS --name 白石 --try "あれ、ここ数日、配送の依頼がほとんどない|故障の報告はない。ただ、使われなくなってた。" || echo " !白石 で止まりました"
[ -f "voice_eleven/寺島/試し_02.mp3" ] || python3 $B/tts_eleven.py --voice yWM6Fym2UxDGZqWRoGLB --name 寺島 --try "ハコブくん?この前、二回遅れたから、自分で行ったほうが確実なの。|直ったなら、もう一回、頼んでみる。" || echo " !寺島 で止まりました"
[ -f "voice_eleven/ハコブ/試し_01.mp3" ] || python3 $B/tts_eleven.py --voice gWJpc8whMBqnF7Y0kc9f --name ハコブ --try "私は、呼ばれていません" || echo " !ハコブ で止まりました"
第150話の声.sh
#!/bin/bash
# 第150話_7つのはずが28 のショートの声(2026-11-14)。鍵は KIOXIA の elevenlabs_api_key.txt を tts_eleven.py が読む
cd "$(dirname "$0")"
B=../../_制作ベース
[ -f "voice_eleven/白石/試し_03.mp3" ] || python3 $B/tts_eleven.py --voice orQ2eWONBvtrTIvdS8RS --name 白石 --try "検体を運ぶ手順は、七つです。|拭いて、貼って、押し直して…|にじゅうはっこ、あった…" || echo " !白石 で止まりました"
[ -f "voice_eleven/大城/試し_02.mp3" ] || python3 $B/tts_eleven.py --voice PrFsT9a2iZebpuiWVeug --name 大城 --try "そう?いつもやってるから、手順だと思ってなかった。|やっと、数えてくれた。" || echo " !大城 で止まりました"
[ -f "voice_eleven/ハコブ/試し_01.mp3" ] || python3 $B/tts_eleven.py --voice gWJpc8whMBqnF7Y0kc9f --name ハコブ --try "私の仕事は、にじゅうはっこ、でした" || echo " !ハコブ で止まりました"
第151話の声.sh
#!/bin/bash
# 第151話_着いたのに のショートの声(2026-11-14)。鍵は KIOXIA の elevenlabs_api_key.txt を tts_eleven.py が読む
cd "$(dirname "$0")"
B=../../_制作ベース
[ -f "voice_eleven/ハコブ/試し_03.mp3" ] || python3 $B/tts_eleven.py --voice gWJpc8whMBqnF7Y0kc9f --name ハコブ --try "到着しました|少し前から、到着していました|届いたことを、届けました" || echo " !ハコブ で止まりました"
[ -f "voice_eleven/田中/試し_01.mp3" ] || python3 $B/tts_eleven.py --voice ydyMD3g4SbEeNpF0wahP --name 田中 --try "薬は、まだか?" || echo " !田中 で止まりました"
[ -f "voice_eleven/大城/試し_03.mp3" ] || python3 $B/tts_eleven.py --voice PrFsT9a2iZebpuiWVeug --name 大城 --try "まだです…|いつからいたの!|ちゃんと来たよ。" || echo " !大城 で止まりました"
第152話の声.sh
#!/bin/bash
# 第152話_間に合うかどうか のショートの声(2026-11-14)。鍵は KIOXIA の elevenlabs_api_key.txt を tts_eleven.py が読む
cd "$(dirname "$0")"
B=../../_制作ベース
[ -f "voice_eleven/寺島/試し_03.mp3" ] || python3 $B/tts_eleven.py --voice yWM6Fym2UxDGZqWRoGLB --name 寺島 --try "検査室へ、お願いね。|えっ|間に合ったのは、運がよかっただけよね。" || echo " !寺島 で止まりました"
[ -f "voice_eleven/槙原/試し_01.mp3" ] || python3 $B/tts_eleven.py --voice Sryf5xKmMsQChU3HsLhZ --name 槙原 --try "午前の検体が、まだ届いてないんですけど" || echo " !槙原 で止まりました"
[ -f "voice_eleven/ハコブ/試し_02.mp3" ] || python3 $B/tts_eleven.py --voice gWJpc8whMBqnF7Y0kc9f --name ハコブ --try "現在地を、確かめています|間に合うと、測れてから運びます" || echo " !ハコブ で止まりました"
ショートの台本(spec_ep148〜152.py)
字幕は1行14字・2行までの決まりなので、長いセリフは「||」で字幕の画面を分けています(第149話の「ハコブくん?||この前2回遅れたから、…」など)。
spec_ep148.py
import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[148] = "第48話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第148話_積む人がいない", 148
HEAD = ["待っていても", "誰も来ない?"]
COMIC = C + "ep148.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep148", EP)
SCENES = [
dict(kind="op", video=anim(EP, "ep148"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=0.7, f="se/se_pikon.mp3", db=-10)]),
dict(kind="panel", crop=P1, fit=False, lines=[hk(1, "積ミ込ミヲ、|【オ待チシテイマス】")]),
dict(kind="panel", crop=P2, fit=False, se=[dict(at=0.0, f="se/se_dash.mp3", db=-10)], lines=[ns("寺島", 1, "【302号室】、急変です!"), ns("大城", 1, "【すぐ行く】!")]),
dict(kind="panel", crop=P3, fit=False, lines=[hk(2, "誰モ、|【積ミマセンデシタ】"), ns("寺島", 2, "ごめん、今日は|【それどころじゃなくて】…")]),
dict(kind="panel", crop=P4, fit=False, lines=[hk(3, "積ム人ガイナイ時ハ、|【後デ来マス】"), ns("白石", 1, "【積む人も】、|予定に入れなきゃね")]),
end(("ロボットの仕事に", 74, "ink", 0.0), ("積む人の手間も", 74, "ink", 0.25), ("積む人", 120, "orange", 0.9), ("も数に入れる", 120, "orange", 0.9), ("(手がふさがったら、待たずに後で来る)", 34, "gray", 1.8)),
]
spec_ep149.py
import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[149] = "第43話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第149話_呼ばれなくなった", 149
HEAD = ["故障はないのに", "なぜ呼ばれない?"]
COMIC = C + "ep149.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep149", EP)
SCENES = [
dict(kind="op", video=anim(EP, "ep149"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_yusa.wav", db=-16), dict(at=1.0, f="se/se_pikon.mp3", db=-8)]),
dict(kind="panel", crop=P1, fit=False, lines=[ns("白石", 1, "あれ、ここ数日、|【配送の依頼】がほとんどない")]),
dict(kind="panel", crop=P2, fit=False, lines=[ns("寺島", 1, "ハコブくん?||この前2回遅れたから、|【自分で行ったほうが確実】なの")]),
dict(kind="panel", crop=P3, fit=False, lines=[hk(1, "ワタシハ、|【呼バレテイマセン】"), ns("白石", 2, "故障の報告はない。|ただ、【使われなくなってた】")]),
dict(kind="panel", crop=P4, fit=False, lines=[ns("寺島", 2, "直ったなら、|【もう一回頼んでみる】")]),
end(("頼れないと", 74, "ink", 0.0), ("人は黙って自分でやる", 74, "ink", 0.25), ("使われた数", 120, "orange", 0.9), ("も見る", 120, "orange", 0.9), ("(苦情や故障の数だけでは分からない)", 34, "gray", 1.8)),
]
spec_ep150.py
import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[150] = "第7話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第150話_7つのはずが28", 150
HEAD = ["手順は7つ", "のはずが…"]
COMIC = C + "ep150.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep150", EP)
SCENES = [
dict(kind="op", video=anim(EP, "ep150"), dur=DUR, lines=[], se=[dict(at=1.4, f="se/se_spin.wav", db=-14), dict(at=2.6, f="se/se_don.mp3", db=-8)]),
dict(kind="panel", crop=P1, fit=False, lines=[ns("白石", 1, "検体を運ぶ手順は、|【7つです】")]),
dict(kind="panel", crop=P2, fit=False, lines=[ns("白石", 2, "拭いて、貼って、|【押し直して】…")]),
dict(kind="panel", crop=P3, fit=False, se=[dict(at=0.0, f="se/se_don.mp3", db=-10)], lines=[ns("白石", 3, "【28個】あった…"), ns("大城", 1, "そう?||いつもやってるから、|【手順だと思ってなかった】")]),
dict(kind="panel", crop=P4, fit=False, lines=[hk(1, "ワタシノ仕事ハ、|【28個デシタ】"), ns("大城", 2, "【やっと数えてくれた】")]),
end(("効果を測る前に", 74, "ink", 0.0), ("手順を数える", 74, "ink", 0.25), ("現場を見て", 120, "orange", 0.9), ("数える", 120, "orange", 0.9), ("(手順書ではなく、一日横で見る)", 34, "gray", 1.8)),
]
spec_ep151.py
import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[151] = "第21話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第151話_着いたのに", 151
HEAD = ["着いたのに", "なぜ届かない?"]
COMIC = C + "ep151.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep151", EP)
SCENES = [
dict(kind="op", video=anim(EP, "ep151"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=1.2, f="se/se_pechin.wav", db=-14), dict(at=1.55, f="se/se_pechin.wav", db=-14), dict(at=1.9, f="se/se_pechin.wav", db=-14)]),
dict(kind="panel", crop=P1, fit=False, lines=[hk(1, "【到着シマシタ】")]),
dict(kind="panel", crop=P2, fit=False, lines=[ns("田中", 1, "薬は、【まだか】?"), ns("大城", 1, "まだです…")]),
dict(kind="panel", crop=P3, fit=False, se=[dict(at=0.0, f="se/se_don.mp3", db=-10)], lines=[ns("大城", 2, "【いつからいたの】!"), hk(2, "少シ前カラ、|【到着シテイマシタ】")]),
dict(kind="panel", crop=P4, fit=False, se=[dict(at=0.0, f="se/se_buzz.wav", db=-14)], lines=[hk(3, "【届イタコトヲ】、|届ケマシタ"), ns("大城", 3, "【ちゃんと来たよ】")]),
end(("着いただけでは", 74, "ink", 0.0), ("届いていない", 74, "ink", 0.25), ("受け取る人", 120, "orange", 0.9), ("に知らせる", 120, "orange", 0.9), ("(誰の、どの端末に知らせるかを現場で試す)", 34, "gray", 1.8)),
]
spec_ep152.py
import os, sys
sys.path.insert(0, os.environ.get("W24", os.path.expanduser("~/w")) + "/specs"); from common24 import *
import common24
common24.BGMAP[152] = "第83話.png"
HERE = os.path.dirname(os.path.abspath(__file__))
NAME, EP = "第152話_間に合うかどうか", 152
HEAD = ["その検体", "間に合う?"]
COMIC = C + "ep152.jpg"
P1, P2, P3, P4 = [(0, 1350 * i, 1080, 1350 * (i + 1)) for i in range(4)]
DUR = 3.6
MOTION = mot("ep152", EP)
SCENES = [
dict(kind="op", video=anim(EP, "ep152"), dur=DUR, lines=[], se=[dict(at=0.0, f="se/se_dash.mp3", db=-12), dict(at=2.75, f="se/se_pikon.mp3", db=-10)]),
dict(kind="panel", crop=P1, fit=False, lines=[ns("寺島", 1, "【検査室へ】、お願いね")]),
dict(kind="panel", crop=P2, fit=False, lines=[ns("槙原", 1, "午前の検体が、|【まだ届いてない】んですけど", phone=True), ns("寺島", 2, "【えっ】")]),
dict(kind="panel", crop=P3, fit=False, lines=[hk(1, "現在地ヲ、|【確カメテイマス】")]),
dict(kind="panel", crop=P4, fit=False, lines=[ns("寺島", 3, "間に合ったのは、|【運がよかっただけ】よね"), hk(2, "間ニ合ウト、|【測レテカラ運ビマス】")]),
end(("遅れが痛い物は", 74, "ink", 0.0), ("任せる前に", 74, "ink", 0.25), ("間に合うか", 120, "orange", 0.9), ("を測る", 120, "orange", 0.9), ("(確かめ終わるまで、人が運ぶ)", 34, "gray", 1.8)),
]
書き出したショートの長さと、冒頭3秒の音量
できあがり: out_第148話_積む人がいない.mp4 26.2 秒
できあがり: out_第150話_7つのはずが28.mp4 28.1 秒
できあがり: out_第149話_呼ばれなくなった.mp4 28.5 秒
できあがり: out_第151話_着いたのに.mp4 21.4 秒
できあがり: out_第152話_間に合うかどうか.mp4 23.7 秒
$ for e in 148 149 150 151 152; do ... ffmpeg -t 3 -i ... -af volumedetect ...; done
148 mean_volume: -20.9 dB max_volume: -1.5 dB
149 mean_volume: -20.9 dB max_volume: -1.5 dB
150 mean_volume: -18.8 dB max_volume: -1.5 dB
151 mean_volume: -21.7 dB max_volume: -1.5 dB
152 mean_volume: -21.1 dB max_volume: -1.5 dB
5本とも30秒以内で、冒頭の3秒に音が出ています。書き出した動画は1.4秒おきのコマを並べて、字幕のはみ出しと吹き出しの切れがないかを見ました。

できあがった動画とタイトル・説明文は、KIOXIA の videos/_ショート専用/_未アップ/第NNN話_…/ に置きました。YouTube の公開予約はまだです。
表紙・英語版を作り、サイトに10ページを公開した
Gemini の月の上限で、表紙の編集が断られた
表紙は、見せ場のコマから吹き出しを消し、上に「第N話 題」を重ねて作ります。前回までは吹き出しを消すのに Gemini の編集を使っていましたが、今回は5回とも次のように断られました。
失敗 ep152_P3 429 {
"error": {
"code": 429,
"message": "Your project has exceeded its monthly spending cap. Please go to AI Studio at https://ai.studio/spend to manage your project spend cap. Learn more at https://ai.google.dev/gemini-api/docs/billing#project-spend-caps. ",
"status": "RESOURCE_EXHAUSTED
代わりに、吹き出しをプログラムで消しました。吹き出しは、黒い線で囲まれた白い領域です。上半分にある広い白い領域を見つけて、少しふくらませて白で塗り、まわりに残ったしっぽの先を消します。最初は、消し残しの小さな点を絵全体から消したので、リネンの袋の線や手帳の書き込み、「?」まで消えてしまいました。消すのは吹き出しのまわりだけにして、作り直しています。第148話は1コマ目だと袋の線まで消えたので、2コマ目(走る2人)を表紙にしました。
"""第148〜152話の表紙用:選んだコマから吹き出しをプログラムで消す(2026-11-14)
Gemini の編集(cover_edit_143.py)が月の支払い上限で断られたため、代わりに作った。
白い閉じた領域のうち、上半分にあって広い(8,000画素以上・外枠の箱の55%以上が白)ものを吹き出しとみなし、
穴を埋めて9画素ふくらませた所を白で塗る。そのまわり45画素の中に残った小さな点(400画素未満の線の切れ端・しっぽの先)も消す。
第148話は P1 だとリネンの袋の線まで消えたので P2 にし、端に触れていて見つからなかった左の吹き出しは、上から290画素を白で塗って消した。"""
import numpy as np, os
from PIL import Image
from scipy import ndimage
B = os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長")
PICK = {148: 2, 149: 3, 150: 3, 151: 1, 152: 3}
os.makedirs("cover_edit", exist_ok=True)
for e, k in PICK.items():
im = Image.open(f"{B}/第{e}話/仕上げ/第{e}話_P{k}_1080x1350.png").convert("L"); a = np.asarray(im)
white = a > 200; lab, n = ndimage.label(white)
out = np.asarray(im.convert("RGB")).copy(); H, W = a.shape; er = np.zeros((H, W), bool)
for i, sl in enumerate(ndimage.find_objects(lab), 1):
ys, xs = sl; comp = lab[sl] == i; area = comp.sum(); h = ys.stop - ys.start; w = xs.stop - xs.start
if ys.start == 0 or xs.start == 0 or ys.stop == H or xs.stop == W: continue
if area < 8000 or ys.start > H * 0.45 or area / (h * w) < 0.55: continue
m = np.zeros((H, W), bool); m[sl] = comp; m = ndimage.binary_dilation(ndimage.binary_fill_holes(m), iterations=9); er |= m
out[er] = 255
near = ndimage.binary_dilation(er, iterations=45)
g = out.min(2) < 200; lab2, n2 = ndimage.label(g)
for i, sl in enumerate(ndimage.find_objects(lab2), 1):
c = lab2[sl] == i
if c.sum() < 400 and (near[sl] & c).sum() == c.sum(): out[sl][c] = 255
if e == 148:
out[:290] = 255 # 左の吹き出し(画像の端とつながっていて上の方法で見つからなかった)
out[280:315, 455:505] = 255 # 残ったしっぽの先
Image.fromarray(out).save(f"cover_edit/ep{e}_P{k}_nobubble.png")
"""第148〜152話の表紙(2026-11-14):上に「第N話 タイトル」、下に吹き出しを消したコマ(LOG468 の make_covers.py と同じ組み方)
Noto Sans CJK Black が作業環境になかったので、noto-cjk の NotoSansCJKjp-Black.otf を ~/fonts に入れて使った"""
import numpy as np, os
from PIL import Image, ImageDraw, ImageFont
FB = os.path.expanduser('~/fonts/NotoSansCJKjp-Black.otf')
B = os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長")
T = {148: '積む人がいない', 149: '呼ばれなくなった', 150: '7つのはずが28', 151: '着いたのに', 152: '間に合うかどうか'}
PICK = {148: 2, 149: 3, 150: 3, 151: 1, 152: 3}
W, H = 1080, 1350; X0 = 56; MAXW = W - 2 * X0
font = ImageFont.truetype(FB, 96, index=0)
os.makedirs('media', exist_ok=True)
for e, k in PICK.items():
p = Image.open(f'cover_edit/ep{e}_P{k}_nobubble.png').convert('RGB').resize((W, H), Image.LANCZOS)
a = np.asarray(p).astype(np.int16); a[a.min(2) > 232] = 255; p = Image.fromarray(a.astype(np.uint8))
head = f'第{e}話'; t = T[e]; one = f'{head} {t}'
lines = [one] if font.getlength(one) <= MAXW else [head, t]
c = Image.new('RGB', (W, H), 'white'); d = ImageDraw.Draw(c); y = 62
for ln in lines:
f = font
while f.getlength(ln) > MAXW: f = ImageFont.truetype(FB, f.size - 4, index=0)
d.text((X0, y), ln, font=f, fill=(36, 36, 36)); y += f.size + 18
top = y + 40; A = H - top
g = np.asarray(p.convert('L')) < 235; ys = np.where(g.any(1))[0]; xs = np.where(g.any(0))[0]
cy0, cy1, cx0, cx1 = ys.min(), ys.max(), xs.min(), xs.max(); ch = cy1 - cy0
s = min(A * 0.94 / ch, 1.45) if ch < A else A / ch
q = p.resize((round(W * s), round(H * s)), Image.LANCZOS)
mx = (cx0 + cx1) / 2 * s; my = (cy0 + cy1) / 2 * s
if s >= 1:
L = int(min(max(mx - W / 2, 0), q.width - W)); Tp = int(min(max(my - A / 2, 0), q.height - A))
b = Image.new('RGB', (W, A), 'white'); b.paste(q.crop((L, Tp, min(q.width, L + W), min(q.height, Tp + A))), (0, 0)); c.paste(b, (0, top))
else:
t0 = int(cy0 * s); b = Image.new('RGB', (q.width, A), 'white'); b.paste(q.crop((0, t0, q.width, min(q.height, t0 + A))), (0, 0)); c.paste(b, ((W - q.width) // 2, top))
c.save(f'media/manga_ep{e}_cover.webp', 'WEBP', quality=88, method=6)
c.save(f'cover_edit/ep{e}_cover_ja.png')
for i in range(1, 5):
Image.open(f'{B}/第{e}話/仕上げ/第{e}話_P{i}_1080x1350.png').convert('RGB').save(f'media/manga_ep{e}_p{i}.webp', 'WEBP', quality=88, method=6)

英語版(en_manga.py の指定)
英語版は描き直さず、吹き出しの中の日本語を消して英語を組みます(LOG416 の en_manga.py)。seed は各吹き出しの白い内側の1点です。白い閉じた領域を探すプログラムで座標を出し、どの吹き出しかを見て当てました。外枠が絵の端とつながって見つからなかった2つの吹き出し(第150話 P4・第152話 P4 のハコブくんの吹き出し)は、絵を見て座標を書いています。
英語版の指定 ep148.json
{"ep": 148, "cover_line": "NOBODY CAME TO LOAD ME.", "panels": [{"bubbles": [{"seed": [726, 249], "text": "Waiting\nto be loaded."}], "signs": []}, {"bubbles": [{"seed": [331, 90], "text": "Room 302,\nemergency!"}, {"seed": [807, 187], "text": "On my way!"}], "signs": []}, {"bubbles": [{"seed": [310, 255], "text": "Nobody\nloaded me."}, {"seed": [652, 358], "text": "Sorry, today\nwas just\ntoo much…"}], "signs": []}, {"bubbles": [{"seed": [344, 191], "text": "When no one can load,\nI'll come back later."}, {"seed": [890, 92], "text": "We have to schedule\nthe loaders too."}], "signs": []}]}
英語版の指定 ep149.json
{"ep": 149, "cover_line": "NO ONE CALLS ME ANYMORE.", "panels": [{"bubbles": [{"seed": [903, 405], "text": "Huh, almost\nno delivery\nrequests\nlately."}], "signs": []}, {"bubbles": [{"seed": [449, 312], "text": "Hakobukun? It was\nlate twice, so going\nmyself is more reliable."}], "signs": []}, {"bubbles": [{"seed": [353, 202], "text": "No one\nis calling me."}, {"seed": [958, 128], "text": "No fault reports.\nIt just stopped\nbeing used."}], "signs": []}, {"bubbles": [{"seed": [869, 103], "text": "If it's fixed,\nI'll try asking again."}], "signs": []}]}
英語版の指定 ep150.json
{"ep": 150, "cover_line": "SEVEN STEPS? IT WAS 28.", "panels": [{"bubbles": [{"seed": [375, 189], "text": "Carrying a specimen\ntakes 7 steps."}], "signs": []}, {"bubbles": [{"seed": [468, 210], "text": "Wipe, tape,\npress again…"}], "signs": []}, {"bubbles": [{"seed": [258, 46], "text": "There were\n28…"}, {"seed": [824, 47], "text": "Really? I do it every day,\nso I never thought\nof them as steps."}], "signs": []}, {"bubbles": [{"seed": [330, 110], "text": "My job was\n28 steps."}, {"seed": [838, 49], "text": "Finally,\nsomeone counted."}], "signs": []}]}
英語版の指定 ep151.json
{"ep": 151, "cover_line": "WHEN DID YOU GET HERE?!", "panels": [{"bubbles": [{"seed": [294, 132], "text": "I have\narrived."}], "signs": []}, {"bubbles": [{"seed": [210, 279], "text": "Is the\nmedicine\nhere yet?"}, {"seed": [927, 197], "text": "Not\nyet…"}], "signs": []}, {"bubbles": [{"seed": [464, 150], "text": "When did you\nget here?!"}, {"seed": [411, 328], "text": "A little while ago.\nI've been here."}], "signs": []}, {"bubbles": [{"seed": [365, 240], "text": "I delivered\nthe news\nthat I arrived."}, {"seed": [571, 256], "text": "I came\nright\naway."}], "signs": []}]}
英語版の指定 ep152.json
{"ep": 152, "cover_line": "WILL IT MAKE IT IN TIME?", "panels": [{"bubbles": [{"seed": [925, 322], "text": "To the lab,\nplease."}], "signs": []}, {"bubbles": [{"seed": [489, 186], "text": "The morning samples\nhaven't arrived yet…"}, {"seed": [885, 184], "text": "What?"}], "signs": []}, {"bubbles": [{"seed": [648, 179], "text": "Checking my\ncurrent location."}], "signs": []}, {"bubbles": [{"seed": [369, 143], "text": "We only made it\nby luck."}, {"seed": [760, 160], "text": "I'll carry them once\nI've measured that\nI'm on time."}], "signs": []}]}

R2 に画像を入れ、ページを公開した
$ python3 upload_media.py media media_en
入れる 50・入っている 0・名前の重なり 0・合計 8.3MB
50/50
おわり
$ npx astro build
10:46:59 [build] 881 page(s) built in 31.05s
10:46:59 [build] Complete!
$ for e in 148 149 150 151 152; do echo "$e $(curl ... /manga/ep$e) $(curl ... /english-4-koma/ep$e)"; done
148 200 200
149 200 200
150 200 200
151 200 200
152 200 200
| 話 | 日本語のページの題 | 英語のページの題 |
|---|---|---|
| 148 | ロボットの仕事には、積む人の手間が含まれる | Robot Work Includes the People Who Load It |
| 149 | 頼れないと感じると、人は黙って自分でやり始める | When People Can’t Rely on a Robot, They Quietly Do It Themselves |
| 150 | 手順書ではなく、現場を見て数える | Count the Steps on the Floor, Not in the Manual |
| 151 | 着いたことは、受け取る人に届いて初めて意味がある | Arriving Means Nothing Until Someone Knows |
| 152 | 遅れの代償が大きい物は、間に合うと確かめてから任せる | Before Trusting a Robot With Time-Critical Items, Measure It |
ページは pixelstomotors.com/manga/ep148 〜 ep152 と pixelstomotors.com/english-4-koma/ep148 〜 ep152 です。p2m-site への commit は 944f97b です。
commit 944f97b4ddf64700cfbdda9075fc6ffcf0e21dd2
Author: PixelstoMotors <studio@adaptdesign.jp>
Date: Sat Nov 14 10:47:08 2026 +0900
4コマ第148〜152話(日本語・英語)を追加
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXTjc44BADYdkHD3BY8
src/data/english/ep148.json | 1 +
src/data/english/ep149.json | 1 +
src/data/english/ep150.json | 1 +
src/data/english/ep151.json | 1 +
src/data/english/ep152.json | 1 +
src/data/englishCards.json | 60 +++++++++++++++++++++++++++++++++++++++++++++
src/data/manga/ep148.json | 1 +
src/data/manga/ep149.json | 1 +
src/data/manga/ep150.json | 1 +
src/data/manga/ep151.json | 1 +
src/data/manga/ep152.json | 1 +
src/data/mangaCards.json | 60 +++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 130 insertions(+)
ページのデータ(日本語)ep148.json
{"slug": "ep148", "title": "ロボットの仕事には、積む人の手間が含まれる", "label": "MANGA EP148", "character": "ハコブくん", "description": "夕方の病棟、リネン庫の前でドロワーを開けて待つハコブくん。急変の対応で誰も来ず、1時間たってもドロワーは空のまま。「誰モ、積ミマセンデシタ」。積む人の手間まで数に入れて予定を組む意味を描く4コマ漫画、第148話。", "published": "2026-11-14T01:50:00.000Z", "cover": "/media/manga_ep148_cover.webp", "comic": "", "cover_alt": "第148話 積む人がいないの表紙。急変で走る大城さんと寺島さんの奥で、ハコブくんがドロワーを開けて待っている", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep148_p1.webp", "/media/manga_ep148_p2.webp", "/media/manga_ep148_p3.webp", "/media/manga_ep148_p4.webp"], "panel_alts": ["リネン庫の前で、ハコブくんがドロワーを開けて待っている。横に使い終わったリネンの袋を積んだカート", "急変で、寺島さんと大城さんが廊下を走っていく。奥でハコブくんは待ったまま", "1時間後もハコブくんは同じ所にいて、戻ってきた寺島さんが手を上げて謝る", "白石さんが積み込みの時間と担当の表を持ち、ハコブくんは次の仕事へ向かう"], "body": "<p>■ 腕のないロボットは、積まれるのを待つしかない<br>夕方の病棟。ハコブくんはリネン庫の前でドロワーを開け、積ミ込ミヲ、オ待チシテイマス。ところが廊下の奥で急変があり、大城さんと寺島さんは走っていった。1時間たっても、ドロワーは空のまま。誰モ、積ミマセンデシタ。</p><p></p><p>■ 誰もいなければ、仕事が進まない<br><a href=\"https://www.hinnovic.org/post/a-robot-as-a-co-worker\">米国の病院で搬送ロボットを調べた研究の紹介(hinnovic)</a>では、ロボットは人が積まないと仕事が始まらず、急な対応が多い病棟では、急な事態に動けない非効率な働き手と見られていた。ロボットの仕事には、積む人の手間が入っている。</p><p></p><p>■ 結論:積む人も、予定の数に入れる<br>白石さんは積み込みの時間と担当を表にした。担当の手がふさがったら、ハコブくんは待ち続けず、先に別の仕事へ回る。積ム人ガイナイ時ハ、後デ来マス。<br>ロボットの予定を組むときは、そばで手を貸す人の予定も一緒に組む。</p>"}
ページのデータ(日本語)ep149.json
{"slug": "ep149", "title": "頼れないと感じると、人は黙って自分でやり始める", "label": "MANGA EP149", "character": "ハコブくん", "description": "ここ数日、ハコブくんへの配送の依頼がほとんどない。寺島さんは「この前2回遅れたから、自分で行ったほうが確実なの」。故障の報告はないのに、使われなくなっていた。使われている数を見る意味を描く4コマ漫画、第149話。", "published": "2026-11-14T01:52:00.000Z", "cover": "/media/manga_ep149_cover.webp", "comic": "", "cover_alt": "第149話 呼ばれなくなったの表紙。隅の充電台で困り顔のハコブくんと、考え込む白石さん", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep149_p1.webp", "/media/manga_ep149_p2.webp", "/media/manga_ep149_p3.webp", "/media/manga_ep149_p4.webp"], "panel_alts": ["白石さんがタブレットで記録を見る。依頼の数の棒グラフが右へ下がっていく", "寺島さんが薬の袋を持って、自分で薬剤部へ歩いていく", "隅の充電台で待つハコブくんと、あごに手を当てて考える白石さん", "白石さんがタブレットを見せ、寺島さんが腕を組んでうなずく。横でハコブくんがうれしそう"], "body": "<p>■ 故障はない。ただ、呼ばれない<br>白石さんが記録を見ると、ここ数日、ハコブくんへの配送の依頼がほとんどない。病棟へ行くと、寺島さんが自分で薬剤部へ向かうところだった。この前2回遅れたから、自分で行ったほうが確実なの。ハコブくんは隅の充電台で待っていた。ワタシハ、呼バレテイマセン。</p><p></p><p>■ 頼れないと、人は元のやり方に戻る<br><a href=\"https://vbn.aau.dk/ws/files/461098840/SHTI_286_SHTI210639.pdf\">デンマークの病院の搬送ロボットの研究(Tornbjerg ほか)</a>では、厨房スタッフ16人のうち8人が、ロボットを当てにできないと感じ、ロボットに任せるはずの仕事を自分でやっていた。苦情も故障の報告も出ないまま、使われなくなることがある。</p><p></p><p>■ 結論:使われている数も見続ける<br>白石さんは、頼まれた数と、人が自分で運んだ数を毎日の画面に並べた。遅れた2回の原因を直して見せると、寺島さんは言った。直ったなら、もう一回頼んでみる。<br>壊れていないことと、頼られていることは別に数える。</p>"}
ページのデータ(日本語)ep150.json
{"slug": "ep150", "title": "手順書ではなく、現場を見て数える", "label": "MANGA EP150", "character": "ハコブくん", "description": "検体を運ぶ手順は7つです、と白石さん。一日ハコブくんの横で見ると、拭いて、貼って、押し直して…。メモ帳は28個の手順でびっしりになった。導入の効果を測る前に現場を見て数える意味を描く4コマ漫画、第150話。", "published": "2026-11-14T01:54:00.000Z", "cover": "/media/manga_ep150_cover.webp", "comic": "", "cover_alt": "第150話 7つのはずが28の表紙。書き込みでびっしりのメモ帳を持って、青ざめる白石さん", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep150_p1.webp", "/media/manga_ep150_p2.webp", "/media/manga_ep150_p3.webp", "/media/manga_ep150_p4.webp"], "panel_alts": ["白石さんがホワイトボードの手順の図を指して、7つですと言う", "白石さんがメモを取り、奥で大城さんがハコブくんのドロワーを拭いている", "書き込みでびっしりのメモ帳を持って、白石さんが青ざめる", "長くなったメモを持つ白石さん、ハコブくん、腕を組んで笑う大城さん"], "body": "<p>■ 7つのはずだった<br>会議室で、白石さんは検体を運ぶ手順を書いた。呼ぶ・積む・送る・届く・知らせる・受け取る・戻る。7つです。翌日、一日ハコブくんの横で見ていると、大城さんはドロワーを拭き、伝票をテープで留め、行き先を押し直していた。夕方、メモ帳は28個の手順で埋まった。</p><p></p><p>■ 人が黙って支えている手順がある<br><a href=\"https://interactions.acm.org/archive/view/march-april-2025/the-invisible-work-of-human-robot-collaboration-when-streamlined-processes-meet-the-complexity-of-real-world-practices\">病院の搬送ロボットの運用を観察した報告(ACM Interactions)</a>では、管理側が説明した手順は7段階だったが、実際の運用を見ると28段階あった。差の分は、周りの人がロボットを支える見えない手間だった。</p><p></p><p>■ 結論:効果を測る前に、現場を見て数える<br>白石さんは増えた手順を一つずつ見て、ハコブくんの側で減らせるものに印を付けた。ワタシノ仕事ハ、28個デシタ。大城さんは言った。やっと数えてくれた。<br>手順書の数ではなく、現場で数えた数から始める。</p>"}
ページのデータ(日本語)ep151.json
{"slug": "ep151", "title": "着いたことは、受け取る人に届いて初めて意味がある", "label": "MANGA EP151", "character": "ハコブくん", "description": "夜の救急外来。急ぎの薬を運んだハコブくんが処置室の前で「到着シマシタ」。でも中の大城さんと田中先生は処置の最中で、誰も廊下を見ていない。到着の知らせ方を現場で決める意味を描く4コマ漫画、第151話。", "published": "2026-11-14T01:56:00.000Z", "cover": "/media/manga_ep151_cover.webp", "comic": "", "cover_alt": "第151話 着いたのにの表紙。閉まった処置室の扉の前で、ハコブくんが待っている", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep151_p1.webp", "/media/manga_ep151_p2.webp", "/media/manga_ep151_p3.webp", "/media/manga_ep151_p4.webp"], "panel_alts": ["夜の救急外来。閉まった処置室の扉の前で、ハコブくんが到着を知らせる", "処置室の中で、田中先生が薬はまだかと聞き、大城さんが扉のほうを見る", "扉から出てきた大城さんが、すぐ前にいたハコブくんに驚く", "次の夜、震えるスマホを手に大城さんが出てきて、ハコブくんが待っている"], "body": "<p>■ 着いていたのに、誰も知らなかった<br>夜の救急外来。ハコブくんは急ぎの薬を運び、処置室の前で止まった。到着シマシタ。中では大城さんと田中先生が処置の最中で、廊下を見ている人はいない。薬は、まだか? 大城さんが廊下に出ると、ハコブくんはそこにいた。いつからいたの!</p><p></p><p>■ 知らせ方は、現場で試して作る<br><a href=\"https://www.cgh.com.sg/about-cgh/overview/cgh90thanniversary/care-grows-here/engineering-care-together\">シンガポールのチャンギ総合病院の記事</a>では、救急外来で薬を運ぶロボットの到着が看護師と薬剤師にすぐ伝わるよう、試作と試験を繰り返して知らせ方を作り直している。</p><p></p><p>■ 結論:誰の、どの端末に知らせるかを決める<br>白石さんは、到着の知らせが大城さんの持つ端末と薬剤部の両方に届くようにした。次の夜、端末が震えて大城さんがすぐ出てきた。届イタコトヲ、届ケマシタ。<br>運び終えたかどうかは、受け取る人に伝わったところで数える。</p>"}
ページのデータ(日本語)ep152.json
{"slug": "ep152", "title": "遅れの代償が大きい物は、間に合うと確かめてから任せる", "label": "MANGA EP152", "character": "ハコブくん", "description": "採血の検体をハコブくんに託した寺島さん。昼になって検査室から「まだ届いてない」と電話。ハコブくんは別の階のエレベーターの前で迷っていた。間に合うと確かめてから任せる意味を描く4コマ漫画、第152話。", "published": "2026-11-14T01:58:00.000Z", "cover": "/media/manga_ep152_cover.webp", "comic": "", "cover_alt": "第152話 間に合うかどうかの表紙。エレベーターの前で、困った顔のハコブくんが迷っている", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep152_p1.webp", "/media/manga_ep152_p2.webp", "/media/manga_ep152_p3.webp", "/media/manga_ep152_p4.webp"], "panel_alts": ["寺島さんが採血管の立てを、ハコブくんのドロワーに入れる", "検査室からの電話で、寺島さんが青ざめる", "別の階のエレベーターの前で、ハコブくんが迷っている", "胸に手を当てる寺島さん、ハコブくん、ストップウォッチを持つ白石さん"], "body": "<p>■ 検体が届いていない<br>朝の採血。寺島さんは採った血液をハコブくんに載せた。検査室へ、お願いね。昼、検査室から電話が来る。午前の検体が、まだ届いてないんですけど。ハコブくんは別の階で、現在地ヲ、確カメテイマス。検体はぎりぎり使えたが、寺島さんは首を振った。間に合ったのは、運がよかっただけよね。</p><p></p><p>■ 一度遅れると、もう任せてもらえない<br><a href=\"https://www.proofnews.org/moxi/\">米国の病院の看護ロボットの報道(Proof News)</a>では、ロボットが階をまたぐと迷うため、看護師が採血の検体を任せなくなったと伝えている。遅れた検体は捨てて採り直しになるからだ。</p><p></p><p>■ 結論:決まりの時間内に届くと測ってから任せる<br>白石さんは、検体ごとに何分以内に着けばよいかを検査室に聞き、ハコブくんで何十回も走って測ることにした。確かめ終わるまで、検体は人が運ぶ。間ニ合ウト、測レテカラ運ビマス。</p>"}
ページのデータ(英語)ep148.json
{"slug": "ep148", "title": "Robot Work Includes the People Who Load It", "label": "MANGA EP148EN", "character": "ハコブくん", "description": "Hakobukun waits by the linen room with its drawer open. An emergency pulls the nurses away, and an hour later the drawer is still empty. A manga on counting the people who load a robot as part of its work.", "published": "2026-11-14T01:51:00.000Z", "cover": "/media/manga_ep148en_cover.webp", "comic": "", "cover_alt": "Episode 148 cover: Nobody came to load me. Oshiro and Terashima run past while Hakobukun waits with its drawer open", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep148en_p1.webp", "/media/manga_ep148en_p2.webp", "/media/manga_ep148en_p3.webp", "/media/manga_ep148en_p4.webp"], "panel_alts": ["Hakobukun waits by the linen room with its drawer open, next to a cart of used linen bags", "Terashima and Oshiro run down the corridor to an emergency; Hakobukun keeps waiting behind them", "An hour later Hakobukun is still in the same place; Terashima comes back and apologizes", "Shiraishi holds a loading schedule as Hakobukun heads off to its next job"], "body": "<p>■ A robot without arms can only wait to be loaded<br>Evening on the ward. Hakobukun opens its drawer in front of the linen room: \"Waiting to be loaded.\" Then a patient takes a turn for the worse, and Oshiro and Terashima run off. An hour later, the drawer is still empty. \"Nobody loaded me.\"</p><p></p><p>■ If nobody is there, the work does not get done<br>In <a href=\"https://www.hinnovic.org/post/a-robot-as-a-co-worker\">an article on a study of delivery robots in a U.S. hospital (hinnovic)</a>, the robots could not start until someone loaded them, and on busy wards they were seen as inefficient workers that could not react to urgent situations. A robot's work includes the work of the people who load it.</p><p></p><p>■ Conclusion: Count the loaders in the schedule<br>Shiraishi made a timetable of loading times and who loads. If that person's hands are full, Hakobukun does not wait forever; it goes to another job first. \"When no one can load, I'll come back later.\"<br>When you schedule the robot, schedule the people beside it too.</p>"}
ページのデータ(英語)ep149.json
{"slug": "ep149", "title": "When People Can't Rely on a Robot, They Quietly Do It Themselves", "label": "MANGA EP149EN", "character": "ハコブくん", "description": "Delivery requests for Hakobukun have almost stopped. Terashima walks to the pharmacy herself: it was late twice. No fault reports, yet it had stopped being used. A manga on watching how often a robot is actually used.", "published": "2026-11-14T01:53:00.000Z", "cover": "/media/manga_ep149en_cover.webp", "comic": "", "cover_alt": "Episode 149 cover: No one calls me anymore. Hakobukun on its charging dock in a corner, Shiraishi thinking", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep149en_p1.webp", "/media/manga_ep149en_p2.webp", "/media/manga_ep149en_p3.webp", "/media/manga_ep149en_p4.webp"], "panel_alts": ["Shiraishi checks a tablet; the bar chart of requests falls to almost nothing", "Terashima walks to the pharmacy herself, carrying a paper bag", "Hakobukun waits on its charging dock in a corner while Shiraishi thinks", "Shiraishi shows the tablet, Terashima nods with arms folded, and Hakobukun looks pleased"], "body": "<p>■ Nothing is broken. It just isn't called<br>Checking the records, Shiraishi finds almost no delivery requests for Hakobukun in the past few days. On the ward, Terashima is heading to the pharmacy herself: \"It was late twice, so going myself is more reliable.\" Hakobukun sits on its charging dock. \"No one is calling me.\"</p><p></p><p>■ When people can't rely on it, they go back to the old way<br>In <a href=\"https://vbn.aau.dk/ws/files/461098840/SHTI_286_SHTI210639.pdf\">a study of delivery robots at a Danish hospital (Tornbjerg et al.)</a>, 8 of 16 kitchen staff felt they could not rely on the robots and did the robots' tasks themselves. A robot can fall out of use without a single complaint or fault report.</p><p></p><p>■ Conclusion: Keep watching how often it is used<br>Shiraishi put the number of requests next to the number of trips people made themselves, fixed the cause of the two delays, and showed Terashima. \"If it's fixed, I'll try asking again.\"<br>Count \"not broken\" and \"relied on\" separately.</p>"}
ページのデータ(英語)ep150.json
{"slug": "ep150", "title": "Count the Steps on the Floor, Not in the Manual", "label": "MANGA EP150EN", "character": "ハコブくん", "description": "Shiraishi says carrying a specimen takes seven steps. After a day beside Hakobukun, her memo pad is full: wipe, tape, press again… There were 28. A manga on counting real steps before measuring a robot's effect.", "published": "2026-11-14T01:55:00.000Z", "cover": "/media/manga_ep150en_cover.webp", "comic": "", "cover_alt": "Episode 150 cover: Seven steps? It was 28. Shiraishi turns pale, holding a memo pad crammed with notes", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep150en_p1.webp", "/media/manga_ep150en_p2.webp", "/media/manga_ep150en_p3.webp", "/media/manga_ep150en_p4.webp"], "panel_alts": ["Shiraishi points at the steps on the whiteboard: seven", "Shiraishi takes notes while Oshiro wipes Hakobukun's drawer", "Shiraishi turns pale, holding a memo pad crammed with notes", "Shiraishi with a long strip of notes, Hakobukun, and Oshiro smiling with arms folded"], "body": "<p>■ It was supposed to be seven<br>In the meeting room, Shiraishi wrote out the steps for carrying a specimen: call, load, send, arrive, notify, receive, return. \"Seven steps.\" The next day she spent the whole day beside Hakobukun. Oshiro wiped the drawer, taped on the slip, pressed the destination again… By evening, her memo pad held 28 steps.</p><p></p><p>■ Some steps are quietly carried by people<br>In <a href=\"https://interactions.acm.org/archive/view/march-april-2025/the-invisible-work-of-human-robot-collaboration-when-streamlined-processes-meet-the-complexity-of-real-world-practices\">a report observing hospital delivery robots (ACM Interactions)</a>, management described a seven-step process, but observation showed 28 steps in actual operation. The gap was the invisible work of the people around the robot.</p><p></p><p>■ Conclusion: Count on the floor before measuring the effect<br>Shiraishi went through the extra steps one by one and marked the ones Hakobukun's side could remove. \"My job was 28 steps.\" Oshiro: \"Finally, someone counted.\"<br>Start from the number you counted on the floor, not the one in the manual.</p>"}
ページのデータ(英語)ep151.json
{"slug": "ep151", "title": "Arriving Means Nothing Until Someone Knows", "label": "MANGA EP151EN", "character": "ハコブくん", "description": "Night in the emergency department. Hakobukun brings urgent medicine and announces its arrival outside the treatment room, but everyone inside is busy. A manga on deciding how a robot tells people it has arrived.", "published": "2026-11-14T01:57:00.000Z", "cover": "/media/manga_ep151en_cover.webp", "comic": "", "cover_alt": "Episode 151 cover: When did you get here?! Hakobukun waits in front of the closed treatment room door", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep151en_p1.webp", "/media/manga_ep151en_p2.webp", "/media/manga_ep151en_p3.webp", "/media/manga_ep151en_p4.webp"], "panel_alts": ["Night in the emergency department; Hakobukun announces its arrival in front of the closed door", "Inside, Dr. Tanaka asks if the medicine is here yet; Oshiro glances at the door", "Oshiro steps out and is startled to find Hakobukun right there", "The next night, Oshiro comes out holding a buzzing phone, and Hakobukun is waiting"], "body": "<p>■ It had arrived, and nobody knew<br>Night in the emergency department. Hakobukun brings urgent medicine and stops outside the treatment room: \"I have arrived.\" Inside, Oshiro and Dr. Tanaka are busy with a patient, and no one is watching the corridor. \"Is the medicine here yet?\" When Oshiro steps out, Hakobukun is right there. \"When did you get here?!\"</p><p></p><p>■ Build the alert by testing it on site<br>In <a href=\"https://www.cgh.com.sg/about-cgh/overview/cgh90thanniversary/care-grows-here/engineering-care-together\">an article from Changi General Hospital in Singapore</a>, the team reworked the arrival alerts of a medication delivery robot in the emergency department through prototyping and repeated testing, so that nurses and pharmacists would be notified promptly.</p><p></p><p>■ Conclusion: Decide whose device gets the alert<br>Shiraishi set it up so the arrival alert reaches the phone Oshiro carries and the pharmacy. The next night the phone buzzed and Oshiro came straight out. \"I delivered the news that I arrived.\"<br>A delivery is done when the person receiving it knows.</p>"}
ページのデータ(英語)ep152.json
{"slug": "ep152", "title": "Before Trusting a Robot With Time-Critical Items, Measure It", "label": "MANGA EP152EN", "character": "ハコブくん", "description": "Terashima hands blood samples to Hakobukun. At noon the lab calls: they haven't arrived. Hakobukun is lost by the elevators on another floor. A manga on confirming delivery times before trusting a robot.", "published": "2026-11-14T01:59:00.000Z", "cover": "/media/manga_ep152en_cover.webp", "comic": "", "cover_alt": "Episode 152 cover: Will it make it in time? Hakobukun looks lost in front of the elevators", "comic_alt": "", "format": "vertical", "panels": ["/media/manga_ep152en_p1.webp", "/media/manga_ep152en_p2.webp", "/media/manga_ep152en_p3.webp", "/media/manga_ep152en_p4.webp"], "panel_alts": ["Terashima places a rack of blood sample tubes in Hakobukun's drawer", "A call from the lab; Terashima goes pale", "Hakobukun is lost in front of the elevators on another floor", "Terashima with a hand on her chest, Hakobukun, and Shiraishi holding a stopwatch"], "body": "<p>■ The samples haven't arrived<br>Morning blood draws. Terashima loads the samples into Hakobukun: \"To the lab, please.\" At noon the lab calls: \"The morning samples haven't arrived yet.\" Hakobukun is on another floor, checking its current location. The samples were just barely usable, but Terashima shakes her head. \"We only made it by luck.\"</p><p></p><p>■ One delay, and the trust is gone<br><a href=\"https://www.proofnews.org/moxi/\">A report on a nursing robot in U.S. hospitals (Proof News)</a> says nurses stopped sending blood draws with the robot because it got lost moving between floors. Late samples have to be discarded and drawn again.</p><p></p><p>■ Conclusion: Measure that it arrives in time, then trust it<br>Shiraishi asked the lab how many minutes each kind of sample can wait, and timed Hakobukun dozens of times. Until that is confirmed, people carry the samples. \"I'll carry them once I've measured that I'm on time.\"</p>"}
SNS を予約した
| 話 | 日本語の X(日本時間) | 英語の X(米国東部時間) |
|---|---|---|
| 148 | 12/14 20:00 | 2/15 11:00 |
| 149 | 12/15 20:00 | 2/16 11:00 |
| 150 | 12/16 20:00 | 2/17 11:00 |
| 151 | 12/19 19:30 | 2/18 11:00 |
| 152 | 12/20 19:30 | 2/19 11:00 |
日本語は、前の話(第143〜147話)と同じく平日の 20:00 に入れました。12/17・12/18 の夜は記事の投稿で埋まっていたので、151・152 は週末の 19:30 にしています。マンガは LinkedIn に出さない決まりなので、LinkedIn の文は json に作っただけで予定表には入れていません。r2r2r-content への commit は d295dd4 です。
commit d295dd4188be02aa46b34d988c7e780c093aadbe
Author: PixelstoMotors <studio@adaptdesign.jp>
Date: Sat Nov 14 10:48:59 2026 +0900
4コマ第148〜152話のSNS(日本語X 12/14〜12/20・英語X 2/15〜2/19)とショートのXの型
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LevEXTjc44BADYdkHD3BY8
sns/MANGA_ep148_sns_posts.json | 29 +++++++++++++++++++
sns/MANGA_ep149_sns_posts.json | 29 +++++++++++++++++++
sns/MANGA_ep150_sns_posts.json | 29 +++++++++++++++++++
sns/MANGA_ep151_sns_posts.json | 29 +++++++++++++++++++
sns/MANGA_ep152_sns_posts.json | 29 +++++++++++++++++++
sns/SHORT_ep148_sns_posts.json | 13 +++++++++
sns/SHORT_ep149_sns_posts.json | 13 +++++++++
sns/SHORT_ep150_sns_posts.json | 13 +++++++++
sns/SHORT_ep151_sns_posts.json | 13 +++++++++
sns/SHORT_ep152_sns_posts.json | 13 +++++++++
sns/schedule.json | 65 ++++++++++++++++++++++++++++++++++++++++++
diff --git a/sns/schedule.json b/sns/schedule.json
index 6a12b46..e18c087 100644
--- a/sns/schedule.json
+++ b/sns/schedule.json
@@ -3583,6 +3583,71 @@
"source": "sns/LOG507_sns_posts.json",
"platform": "x",
"post_at": "2027-01-02T12:30:00+09:00"
+ },
+ {
+ "id": "MANGA_ep148-x",
+ "source": "sns/MANGA_ep148_sns_posts.json",
+ "platform": "x",
+ "post_at": "2026-12-14T20:00:00+09:00"
+ },
+ {
+ "id": "MANGA_ep148-x-en",
+ "source": "sns/MANGA_ep148_sns_posts.json",
+ "platform": "x",
+ "lang": "en",
+ "post_at": "2027-02-15T11:00:00-05:00"
+ },
+ {
+ "id": "MANGA_ep149-x",
+ "source": "sns/MANGA_ep149_sns_posts.json",
+ "platform": "x",
+ "post_at": "2026-12-15T20:00:00+09:00"
+ },
+ {
+ "id": "MANGA_ep149-x-en",
+ "source": "sns/MANGA_ep149_sns_posts.json",
+ "platform": "x",
+ "lang": "en",
+ "post_at": "2027-02-16T11:00:00-05:00"
+ },
+ {
+ "id": "MANGA_ep150-x",
+ "source": "sns/MANGA_ep150_sns_posts.json",
+ "platform": "x",
+ "post_at": "2026-12-16T20:00:00+09:00"
+ },
+ {
+ "id": "MANGA_ep150-x-en",
+ "source": "sns/MANGA_ep150_sns_posts.json",
+ "platform": "x",
+ "lang": "en",
+ "post_at": "2027-02-17T11:00:00-05:00"
+ },
+ {
+ "id": "MANGA_ep151-x",
+ "source": "sns/MANGA_ep151_sns_posts.json",
+ "platform": "x",
+ "post_at": "2026-12-19T19:30:00+09:00"
+ },
+ {
+ "id": "MANGA_ep151-x-en",
+ "source": "sns/MANGA_ep151_sns_posts.json",
+ "platform": "x",
+ "lang": "en",
+ "post_at": "2027-02-18T11:00:00-05:00"
+ },
+ {
+ "id": "MANGA_ep152-x",
+ "source": "sns/MANGA_ep152_sns_posts.json",
+ "platform": "x",
+ "post_at": "2026-12-20T19:30:00+09:00"
+ },
+ {
+ "id": "MANGA_ep152-x-en",
+ "source": "sns/MANGA_ep152_sns_posts.json",
+ "platform": "x",
+ "lang": "en",
+ "post_at": "2027-02-19T11:00:00-05:00"
}
]
}
MANGA_ep148_sns_posts.json
{
"meta": {
"episode": 148,
"date": "2026-11-14",
"title": "第148話 積む人がいない",
"url": "https://pixelstomotors.com/manga/ep148",
"title_en": "Episode 148 Robot Work Includes the People Who Load It",
"url_en": "https://pixelstomotors.com/english-4-koma/ep148"
},
"posts": {
"x": "リネン庫の前で、ドロワーを開けて待つ配送ロボット。\n\nでもロボットに腕はない。急変でみんな走っていって、1時間たっても空のまま。「誰モ、積ミマセンデシタ」\n4コマ『ハコブくん』第148話\nhttps://pixelstomotors.com/manga/ep148",
"linkedin": "夕方の病棟。ハコブくんはリネン庫の前でドロワーを開けて、積み込みを待っていた。ところが廊下の奥で急変があって、看護師の大城さんと寺島さんは走っていく。1時間たっても、ドロワーは空のまま。「誰モ、積ミマセンデシタ」。病院で物を運ぶロボット、ハコブくんの4コママンガ(フィクション)の第148話だよ。\n\n元にしたのは、米国の病院で搬送ロボットを調べた研究の紹介記事。ロボットは人が積まないと仕事が始まらず、急な対応の多い病棟では、急な事態に動けない働き手と見られていた。腕のないロボットの仕事には、積む人の手間が最初から入っているんだよね。\n\nマンガでは、エンジニアの白石さんが積み込みの時間と担当を表にする。担当の手がふさがったら、ハコブくんは待ち続けずに別の仕事へ回る。「積ム人ガイナイ時ハ、後デ来マス」。\n\nロボットの予定を組むとき、そばで手を貸す人の予定まで入っていますか?\n\nhttps://pixelstomotors.com/manga/ep148",
"facebook": "ロボットに腕がないって、こういうことなんだよね。積まれるまで、ただ待つしかない。\n\n急変の日、リネン庫の前で1時間待ちぼうけのハコブくんを描いたよ。積む人の手間まで数に入れて予定を組む話。\n\nhttps://pixelstomotors.com/manga/ep148",
"x_en": "A delivery robot with no arms, waiting by the linen room.\n\nThen an emergency. An hour later, the drawer is still empty.\n\nHakobukun · Ep. 148\n#webcomic #robotics",
"x_en_images": [
"/media/manga_ep148en_p1.webp",
"/media/manga_ep148en_p2.webp",
"/media/manga_ep148en_p3.webp",
"/media/manga_ep148en_p4.webp"
],
"x_en_alts": [
"Hakobukun waits by the linen room with its drawer open, next to a cart of used linen.",
"Terashima and Oshiro run to an emergency; Hakobukun keeps waiting behind them.",
"An hour later Hakobukun is still there; Terashima apologizes.",
"Shiraishi holds a loading schedule as Hakobukun heads to its next job."
],
"x_en_reply": "Read it with the design note behind the gag: https://pixelstomotors.com/english-4-koma/ep148"
}
}
MANGA_ep149_sns_posts.json
{
"meta": {
"episode": 149,
"date": "2026-11-14",
"title": "第149話 呼ばれなくなった",
"url": "https://pixelstomotors.com/manga/ep149",
"title_en": "Episode 149 When People Can't Rely on a Robot, They Quietly Do It Themselves",
"url_en": "https://pixelstomotors.com/english-4-koma/ep149"
},
"posts": {
"x": "故障の報告はゼロ。なのに、配送の依頼もほぼゼロ。\n\n「この前2回遅れたから、自分で行ったほうが確実なの」\nロボットは、壊れなくても使われなくなる。4コマ『ハコブくん』第149話\nhttps://pixelstomotors.com/manga/ep149",
"linkedin": "エンジニアの白石さんが記録を見ると、ここ数日、ハコブくんへの配送の依頼がほとんどない。病棟へ行くと、看護師の寺島さんが自分で薬剤部へ向かうところだった。「この前2回遅れたから、自分で行ったほうが確実なの」。故障の報告は1件もない。ただ、使われなくなっていた。病院で物を運ぶロボット、ハコブくんの4コママンガ(フィクション)の第149話だよ。\n\n元にしたのは、デンマークの病院の搬送ロボットの研究。厨房スタッフ16人のうち8人が、ロボットを当てにできないと感じて、ロボットに任せるはずの仕事を自分でやっていた。苦情が出ないまま、静かに使われなくなる。これがいちばん気づきにくい。\n\nマンガでは、白石さんが頼まれた数と、人が自分で運んだ数を並べて毎日見えるようにする。遅れた2回の原因を直して見せると、寺島さんは「直ったなら、もう一回頼んでみる」。\n\n導入したロボット、壊れていない数と、頼られている数を別々に見ていますか?\n\nhttps://pixelstomotors.com/manga/ep149",
"facebook": "故障もしてないのに、呼ばれなくなるロボット。ちょっとさみしい。\n\n2回遅れただけで「自分で行ったほうが確実」になる。病院の研究でも、半分の人がロボットを当てにせず自分でやっていたそう。\n\n「ワタシハ、呼バレテイマセン」のハコブくん、描いていて切なかった。\n\nhttps://pixelstomotors.com/manga/ep149",
"x_en": "No fault reports. Almost no delivery requests either.\n\n\"It was late twice, so I just go myself.\"\n\nHakobukun · Ep. 149\n#webcomic #robotics",
"x_en_images": [
"/media/manga_ep149en_p1.webp",
"/media/manga_ep149en_p2.webp",
"/media/manga_ep149en_p3.webp",
"/media/manga_ep149en_p4.webp"
],
"x_en_alts": [
"Shiraishi sees delivery requests falling to almost nothing on a tablet.",
"Terashima walks to the pharmacy herself, carrying a paper bag.",
"Hakobukun waits on its charging dock while Shiraishi thinks.",
"Shiraishi shows Terashima the numbers; Hakobukun looks hopeful."
],
"x_en_reply": "Read it with the design note behind the gag: https://pixelstomotors.com/english-4-koma/ep149"
}
}
MANGA_ep150_sns_posts.json
{
"meta": {
"episode": 150,
"date": "2026-11-14",
"title": "第150話 7つのはずが28",
"url": "https://pixelstomotors.com/manga/ep150",
"title_en": "Episode 150 Count the Steps on the Floor, Not in the Manual",
"url_en": "https://pixelstomotors.com/english-4-koma/ep150"
},
"posts": {
"x": "「検体を運ぶ手順は、7つです」\n\n一日、ロボットの横で見ていたら、拭いて、貼って、押し直して…数えたら28個あった。\n4コマ『ハコブくん』第150話\nhttps://pixelstomotors.com/manga/ep150",
"linkedin": "エンジニアの白石さんが、検体を運ぶ手順をホワイトボードに書いた。呼ぶ・積む・送る・届く・知らせる・受け取る・戻る。「7つです」。翌日、一日ハコブくんの横で見ていると、看護師の大城さんはドロワーを拭き、伝票をテープで留め、行き先を押し直していた。夕方、メモ帳は手順でびっしり。28個あった。病院で物を運ぶロボット、ハコブくんの4コママンガ(フィクション)の第150話だよ。\n\n元にしたのは、病院の搬送ロボットの運用を観察した報告。管理側が説明した手順は7段階だったのに、実際の運用を見ると28段階あった。差の分は、周りの人が黙って支えている手間だった。\n\n大城さんの「いつもやってるから、手順だと思ってなかった」が、たぶん現場のいちばん正直な答え。効果を測る前に、まず現場で数える。\n\nロボットの導入で、手順書と現場の手順を比べたことはありますか?\n\nhttps://pixelstomotors.com/manga/ep150",
"facebook": "手順は7つのはずが、現場で数えたら28個。\n\nいつもやっていることほど、本人には手順に見えないんだよね。導入の効果を測る前に、まず横で一日見てみる話を描いたよ。\n\nhttps://pixelstomotors.com/manga/ep150",
"x_en": "\"Carrying a specimen takes 7 steps.\"\n\nThen she watched for a whole day. There were 28.\n\nHakobukun · Ep. 150\n#webcomic #robotics",
"x_en_images": [
"/media/manga_ep150en_p1.webp",
"/media/manga_ep150en_p2.webp",
"/media/manga_ep150en_p3.webp",
"/media/manga_ep150en_p4.webp"
],
"x_en_alts": [
"Shiraishi points at seven steps on the whiteboard.",
"Shiraishi takes notes as Oshiro wipes Hakobukun's drawer.",
"Shiraishi turns pale over a memo pad crammed with notes.",
"Shiraishi with a long strip of notes, Hakobukun, and a smiling Oshiro."
],
"x_en_reply": "Read it with the design note behind the gag: https://pixelstomotors.com/english-4-koma/ep150"
}
}
MANGA_ep151_sns_posts.json
{
"meta": {
"episode": 151,
"date": "2026-11-14",
"title": "第151話 着いたのに",
"url": "https://pixelstomotors.com/manga/ep151",
"title_en": "Episode 151 Arriving Means Nothing Until Someone Knows",
"url_en": "https://pixelstomotors.com/english-4-koma/ep151"
},
"posts": {
"x": "夜の救急外来。急ぎの薬を運んだロボットは、ちゃんと着いていた。\n\n扉の向こうは処置の真っ最中で、誰も廊下を見ていないだけで。「いつからいたの!」\n4コマ『ハコブくん』第151話\nhttps://pixelstomotors.com/manga/ep151",
"linkedin": "夜の救急外来。ハコブくんは急ぎの薬を運んで、処置室の前で「到着シマシタ」。でも中では看護師の大城さんと田中先生が処置の最中で、廊下を見ている人はいない。「薬は、まだか?」。大城さんが廊下に出ると、ハコブくんはそこにいた。「いつからいたの!」。病院で物を運ぶロボット、ハコブくんの4コママンガ(フィクション)の第151話だよ。\n\n元にしたのは、シンガポールのチャンギ総合病院の記事。救急外来で薬を運ぶロボットの到着が、看護師と薬剤師にすぐ伝わるよう、試作と試験を繰り返して知らせ方を作り直している。\n\nマンガでは、到着の知らせが大城さんの持つ端末と薬剤部の両方に届くようにする。次の夜、端末が震えて大城さんがすぐ出てくる。「届イタコトヲ、届ケマシタ」。着いたことは、受け取る人に伝わって初めて意味を持つ。\n\nロボットの「完了」、誰に伝わったところで数えていますか?\n\nhttps://pixelstomotors.com/manga/ep151",
"facebook": "ちゃんと着いてたのに、誰も気づいていなかったハコブくん。\n\n「いつからいたの!」「少シ前カラ」。着いたことを受け取る人に届けるまでが仕事、という話を描いたよ。\n\nhttps://pixelstomotors.com/manga/ep151",
"x_en": "The robot arrived on time.\n\nNobody knew. Everyone was busy behind the door.\n\nHakobukun · Ep. 151\n#webcomic #robotics",
"x_en_images": [
"/media/manga_ep151en_p1.webp",
"/media/manga_ep151en_p2.webp",
"/media/manga_ep151en_p3.webp",
"/media/manga_ep151en_p4.webp"
],
"x_en_alts": [
"Hakobukun announces its arrival outside a closed treatment room door.",
"Inside, Dr. Tanaka asks if the medicine is here yet.",
"Oshiro steps out and is startled to find Hakobukun right there.",
"Next night, Oshiro comes out holding a buzzing phone."
],
"x_en_reply": "Read it with the design note behind the gag: https://pixelstomotors.com/english-4-koma/ep151"
}
}
MANGA_ep152_sns_posts.json
{
"meta": {
"episode": 152,
"date": "2026-11-14",
"title": "第152話 間に合うかどうか",
"url": "https://pixelstomotors.com/manga/ep152",
"title_en": "Episode 152 Before Trusting a Robot With Time-Critical Items, Measure It",
"url_en": "https://pixelstomotors.com/english-4-koma/ep152"
},
"posts": {
"x": "採血の検体をロボットに託した昼、検査室から電話。「まだ届いてないんですけど」\n\nロボットは別の階で、現在地を確かめていた。\n4コマ『ハコブくん』第152話\nhttps://pixelstomotors.com/manga/ep152",
"linkedin": "朝の採血。看護師の寺島さんは採った血液をハコブくんに載せた。「検査室へ、お願いね」。昼、検査室から電話。「午前の検体が、まだ届いてないんですけど」。ハコブくんは別の階のエレベーターの前で、現在地を確かめていた。病院で物を運ぶロボット、ハコブくんの4コママンガ(フィクション)の第152話だよ。\n\n元にしたのは、米国の病院の看護ロボットの報道。ロボットが階をまたぐと迷うため、看護師が採血の検体を任せなくなった。遅れた検体は捨てて、患者さんから採り直しになるから。遅れの代償が大きい物ほど、一度の遅れで信頼が戻らない。\n\nマンガでは、エンジニアの白石さんが検体ごとに何分以内に着けばよいかを検査室に聞き、ハコブくんで何十回も走って測る。確かめ終わるまでは人が運ぶ。「間ニ合ウト、測レテカラ運ビマス」。\n\n遅れが許されない物、ロボットに任せる前に何を確かめますか?\n\nhttps://pixelstomotors.com/manga/ep152",
"facebook": "迷子のハコブくん。エレベーターの前で「現在地ヲ、確カメテイマス」。\n\n検体は時間との勝負。今回は間に合ったけど、運がよかっただけ。任せる前に、間に合うかを測る話を描いたよ。\n\nhttps://pixelstomotors.com/manga/ep152",
"x_en": "Blood samples, a robot, and a call from the lab:\n\"They haven't arrived yet.\"\n\nHakobukun · Ep. 152\n#webcomic #robotics",
"x_en_images": [
"/media/manga_ep152en_p1.webp",
"/media/manga_ep152en_p2.webp",
"/media/manga_ep152en_p3.webp",
"/media/manga_ep152en_p4.webp"
],
"x_en_alts": [
"Terashima puts blood sample tubes into Hakobukun's drawer.",
"A call from the lab: the samples haven't arrived. Terashima goes pale.",
"Hakobukun is lost in front of the elevators on another floor.",
"Terashima, Hakobukun, and Shiraishi holding a stopwatch."
],
"x_en_reply": "Read it with the design note behind the gag: https://pixelstomotors.com/english-4-koma/ep152"
}
}
SHORT_ep148〜152_sns_posts.json(ショートの X の型)
{
"meta": {
"kind": "youtube_short",
"episode": 148,
"title": "ショート 第148話 積む人がいない",
"youtube_title": "待っていても、積む人が来ない #病院 #ロボット",
"manga_url": "https://pixelstomotors.com/manga/ep148"
},
"posts": {
"x_template": "ドロワーを開けて待つ配送ロボット。急変でみんな走っていって、1時間たっても空のまま。\n\n腕がないので、ひたすら待つしかありません(笑) 4コマ『ハコブくん』のショート\n\n{url}\n#病院 #ロボット"
},
"note": "YouTube のショートの X 投稿。url と posts.x は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。縦長4コマ(2026-11-14)"
}
{
"meta": {
"kind": "youtube_short",
"episode": 149,
"title": "ショート 第149話 呼ばれなくなった",
"youtube_title": "故障はないのに、ロボットが呼ばれなくなった #病院 #ロボット",
"manga_url": "https://pixelstomotors.com/manga/ep149"
},
"posts": {
"x_template": "故障の報告はゼロ。なのに依頼もほぼゼロ。\n\n「この前2回遅れたから、自分で行ったほうが確実なの」 4コマ『ハコブくん』のショート\n\n{url}\n#病院 #ロボット"
},
"note": "YouTube のショートの X 投稿。url と posts.x は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。縦長4コマ(2026-11-14)"
}
{
"meta": {
"kind": "youtube_short",
"episode": 150,
"title": "ショート 第150話 7つのはずが28",
"youtube_title": "手順は7つのはずが、数えたら28 #病院 #ロボット",
"manga_url": "https://pixelstomotors.com/manga/ep150"
},
"posts": {
"x_template": "「手順は7つです」→ 一日横で見たら28個。\n\n数えるロボットの画面もパンクしました 4コマ『ハコブくん』のショート\n\n{url}\n#病院 #ロボット"
},
"note": "YouTube のショートの X 投稿。url と posts.x は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。縦長4コマ(2026-11-14)"
}
{
"meta": {
"kind": "youtube_short",
"episode": 151,
"title": "ショート 第151話 着いたのに",
"youtube_title": "ロボットは着いたのに、誰も知らない #病院 #ロボット",
"manga_url": "https://pixelstomotors.com/manga/ep151"
},
"posts": {
"x_template": "急ぎの薬を運んだロボット、ちゃんと着いてたのに誰も気づかない。\n\n「いつからいたの!」 4コマ『ハコブくん』のショート\n\n{url}\n#病院 #ロボット"
},
"note": "YouTube のショートの X 投稿。url と posts.x は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。縦長4コマ(2026-11-14)"
}
{
"meta": {
"kind": "youtube_short",
"episode": 152,
"title": "ショート 第152話 間に合うかどうか",
"youtube_title": "その検体、ロボットで間に合う? #病院 #ロボット",
"manga_url": "https://pixelstomotors.com/manga/ep152"
},
"posts": {
"x_template": "採血の検体を託したら、昼に「まだ届いてない」と電話。\n\nロボットは別の階で迷子中でした 4コマ『ハコブくん』のショート\n\n{url}\n#病院 #ロボット"
},
"note": "YouTube のショートの X 投稿。url と posts.x は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。縦長4コマ(2026-11-14)"
}
マンガ5話にかかった費用を、1回の頼みごとに調べた
Gemini の単価と、ドルから円にしたレート
Gemini の費用は、返事の使用量(入力・出力のトークン数)と、Google の料金のページの単価から出しました。トークンは、AI が文章や絵を数える単位です。
| 項目 | 値 |
|---|---|
| モデル | gemini-3.1-flash-image(Nano Banana 2) |
| 入力の単価 | 100万トークンあたり $0.50 |
| 出力の画像の単価 | 100万トークンあたり $60(1K の絵1枚は 1,120 トークンで約 $0.067) |
出力の残り(画像でない分)の単価 | 100万トークンあたり $3 |
| バッチ | ふつうの半額 |
| レート | 1ドル=158.84円(日本銀行の外国為替市況、2026-11-11 の中心相場。見つかった中でいちばん新しい値) |
Gemini の費用を出したスクリプト(gemini_cost_148_152.py)
"""第148〜152話で Gemini に頼んだ絵の費用を、返事の使用量から出す(2026-11-14)
単価(Google の料金のページ・gemini-3.1-flash-image・100万トークンあたり):入力 $0.50、出力の画像 $60、出力の残り(画像でない分)$3。バッチは半額。
レート:1ドル=158.84円(日本銀行 外国為替市況 2026-11-11 の中心相場)"""
import json, glob, os, collections
V = os.path.expanduser("~/mnt/PixelstoMotors/ハコブくん/4コママンガ作成データ/縦長")
R = 158.84
rows = []
for e in range(148, 153):
for f in sorted(glob.glob(f"{V}/第{e}話/生成/第{e}話_P*_20261114_*.json")):
u = json.load(open(f))["response"].get("usageMetadata", {})
img = {d["modality"]: d["tokenCount"] for d in u.get("candidatesTokensDetails", [])}.get("IMAGE", 0)
inp = u["promptTokenCount"]; rest = u["candidatesTokenCount"] - img
batch = ("b1" in f) or ("b2" in f)
usd = (inp * 0.5e-6 + img * 60e-6 + rest * 3e-6) * (0.5 if batch else 1)
rows.append((os.path.basename(f), "batch" if batch else "std", inp, img, rest, round(usd, 4), round(usd * R, 1)))
for r in rows: print(r)
t = sum(r[5] for r in rows); print(len(rows), "回 $%.4f 約%.0f円" % (t, t * R))
1回の頼みごとの費用(全64回)
| ファイル(返事の記録) | 頼み方 | 入力 | 出力の画像 | 出力の残り | ドル | 円 |
|---|---|---|---|---|---|---|
第148話_P1_20261114_004803b1.json | バッチ | 3,064 | 1,120 | 530 | $0.0352 | 5.6円 |
第148話_P1_20261114_004803b2.json | バッチ | 3,064 | 1,120 | 674 | $0.0354 | 5.6円 |
第148話_P2_20261114_004803b1.json | バッチ | 4,201 | 1,120 | 404 | $0.0353 | 5.6円 |
第148話_P2_20261114_004803b2.json | バッチ | 4,201 | 1,120 | 615 | $0.0356 | 5.7円 |
第148話_P3_20261114_004803b1.json | バッチ | 4,440 | 1,120 | 650 | $0.0357 | 5.7円 |
第148話_P3_20261114_004803b2.json | バッチ | 4,440 | 1,120 | 599 | $0.0356 | 5.7円 |
第148話_P3_20261114_005443.json | ふつう | 4,589 | 1,120 | 785 | $0.0718 | 11.4円 |
第148話_P3_20261114_005445.json | ふつう | 4,589 | 1,120 | 703 | $0.0716 | 11.4円 |
第148話_P4_20261114_004803b1.json | バッチ | 3,610 | 1,120 | 610 | $0.0354 | 5.6円 |
第148話_P4_20261114_004803b2.json | バッチ | 3,610 | 1,120 | 773 | $0.0357 | 5.7円 |
第149話_P1_20261114_004803b1.json | バッチ | 1,926 | 1,120 | 454 | $0.0348 | 5.5円 |
第149話_P1_20261114_004803b2.json | バッチ | 1,926 | 1,120 | 452 | $0.0348 | 5.5円 |
第149話_P2_20261114_004803b1.json | バッチ | 1,971 | 1,120 | 370 | $0.0346 | 5.5円 |
第149話_P2_20261114_004803b2.json | バッチ | 1,971 | 1,120 | 414 | $0.0347 | 5.5円 |
第149話_P3_20261114_004803b1.json | バッチ | 4,231 | 1,120 | 582 | $0.0355 | 5.6円 |
第149話_P3_20261114_004803b2.json | バッチ | 4,231 | 1,120 | 633 | $0.0356 | 5.7円 |
第149話_P3_20261114_005449.json | ふつう | 4,348 | 1,120 | 566 | $0.0711 | 11.3円 |
第149話_P3_20261114_005457.json | ふつう | 4,348 | 1,120 | 591 | $0.0711 | 11.3円 |
第149話_P4_20261114_004803b1.json | バッチ | 4,539 | 1,120 | 578 | $0.0356 | 5.7円 |
第149話_P4_20261114_004803b2.json | バッチ | 4,539 | 1,120 | 621 | $0.0357 | 5.7円 |
第149話_P4_20261114_012715.json | ふつう | 4,696 | 1,120 | 641 | $0.0715 | 11.4円 |
第149話_P4_20261114_012719.json | ふつう | 4,696 | 1,120 | 878 | $0.0722 | 11.5円 |
第150話_P1_20261114_004803b1.json | バッチ | 1,933 | 1,120 | 367 | $0.0346 | 5.5円 |
第150話_P1_20261114_004803b2.json | バッチ | 1,933 | 1,120 | 385 | $0.0347 | 5.5円 |
第150話_P1_20261114_004950.json | ふつう | 2,026 | 1,120 | 518 | $0.0698 | 11.1円 |
第150話_P1_20261114_005031.json | ふつう | 2,026 | 6,720 | 2,589 | $0.4120 | 65.4円 |
第150話_P2_20261114_004803b1.json | バッチ | 4,389 | 1,120 | 607 | $0.0356 | 5.7円 |
第150話_P2_20261114_004803b2.json | バッチ | 4,389 | 1,120 | 486 | $0.0354 | 5.6円 |
第150話_P3_20261114_004803b1.json | バッチ | 2,039 | 1,120 | 728 | $0.0352 | 5.6円 |
第150話_P3_20261114_004803b2.json | バッチ | 2,039 | 1,120 | 440 | $0.0348 | 5.5円 |
第150話_P3_20261114_005448.json | ふつう | 2,088 | 1,120 | 512 | $0.0698 | 11.1円 |
第150話_P3_20261114_005451.json | ふつう | 2,088 | 1,120 | 427 | $0.0695 | 11.0円 |
第150話_P4_20261114_004803b1.json | バッチ | 4,742 | 1,120 | 503 | $0.0355 | 5.6円 |
第150話_P4_20261114_004803b2.json | バッチ | 4,742 | 1,120 | 644 | $0.0358 | 5.7円 |
第150話_P4_20261114_005453.json | ふつう | 4,841 | 1,120 | 531 | $0.0712 | 11.3円 |
第150話_P4_20261114_005459.json | ふつう | 4,841 | 1,120 | 494 | $0.0711 | 11.3円 |
第150話_P4_20261114_012716.json | ふつう | 5,013 | 1,120 | 615 | $0.0716 | 11.4円 |
第150話_P4_20261114_012717.json | ふつう | 5,013 | 1,120 | 747 | $0.0719 | 11.4円 |
第151話_P1_20261114_004803b1.json | バッチ | 2,763 | 1,120 | 517 | $0.0351 | 5.6円 |
第151話_P1_20261114_004803b2.json | バッチ | 2,763 | 1,120 | 550 | $0.0351 | 5.6円 |
第151話_P2_20261114_004803b1.json | バッチ | 2,533 | 1,120 | 404 | $0.0348 | 5.5円 |
第151話_P2_20261114_004803b2.json | バッチ | 2,533 | 1,120 | 508 | $0.0350 | 5.6円 |
第151話_P3_20261114_004803b1.json | バッチ | 4,233 | 1,120 | 524 | $0.0354 | 5.6円 |
第151話_P3_20261114_004803b2.json | バッチ | 4,233 | 1,120 | 412 | $0.0353 | 5.6円 |
第151話_P3_20261114_005449.json | ふつう | 4,344 | 1,120 | 606 | $0.0712 | 11.3円 |
第151話_P3_20261114_005450.json | ふつう | 4,344 | 1,120 | 554 | $0.0710 | 11.3円 |
第151話_P4_20261114_004803b1.json | バッチ | 3,710 | 1,120 | 612 | $0.0354 | 5.6円 |
第151話_P4_20261114_004803b2.json | バッチ | 3,710 | 1,120 | 645 | $0.0355 | 5.6円 |
第151話_P4_20261114_004948.json | ふつう | 3,765 | 1,120 | 506 | $0.0706 | 11.2円 |
第151話_P4_20261114_004950.json | ふつう | 3,765 | 1,120 | 683 | $0.0711 | 11.3円 |
第152話_P1_20261114_004803b1.json | バッチ | 4,269 | 1,120 | 623 | $0.0356 | 5.7円 |
第152話_P1_20261114_004803b2.json | バッチ | 4,269 | 1,120 | 671 | $0.0357 | 5.7円 |
第152話_P1_20261114_012717.json | ふつう | 4,424 | 1,120 | 528 | $0.0710 | 11.3円 |
第152話_P1_20261114_012718.json | ふつう | 4,424 | 1,120 | 725 | $0.0716 | 11.4円 |
第152話_P2_20261114_004803b1.json | バッチ | 1,947 | 1,120 | 456 | $0.0348 | 5.5円 |
第152話_P2_20261114_004803b2.json | バッチ | 1,947 | 1,120 | 431 | $0.0347 | 5.5円 |
第152話_P3_20261114_004803b1.json | バッチ | 2,719 | 1,120 | 498 | $0.0350 | 5.6円 |
第152話_P3_20261114_004803b2.json | バッチ | 2,719 | 1,120 | 458 | $0.0350 | 5.6円 |
第152話_P4_20261114_004803b1.json | バッチ | 4,653 | 1,120 | 527 | $0.0356 | 5.6円 |
第152話_P4_20261114_004803b2.json | バッチ | 4,653 | 1,120 | 738 | $0.0359 | 5.7円 |
第152話_P4_20261114_005450.json | ふつう | 4,765 | 1,120 | 657 | $0.0716 | 11.4円 |
第152話_P4_20261114_005451.json | ふつう | 4,765 | 1,120 | 710 | $0.0717 | 11.4円 |
第152話_P4_20261114_012716.json | ふつう | 4,937 | 1,120 | 636 | $0.0716 | 11.4円 |
第152話_P4_20261114_012725.json | ふつう | 4,937 | 1,120 | 843 | $0.0722 | 11.5円 |
| 合計(64回) | 235,496 | 77,280 | 38,738 | $3.4605 | 約550円 |
段階ごと・話ごとの Gemini の費用
| 段階 | 頼んだ回数 | 描かれた絵 | 費用 |
|---|---|---|---|
| バッチの下書き | 40回 | 40枚 | 224円($1.411) |
| 自分の確認で描き直し | 4回 | 9枚 | 99円($0.624) |
別のエージェントの確認で描き直し | 12回 | 12枚 | 135円($0.853) |
| エイイチの指摘で描き直し | 8回 | 8枚 | 91円($0.574) |
| 表紙の吹き出しを消す編集 | 5回 | 0枚(月の上限で断られた) | 0円 |
| 合計 | 69回 | 69枚 | 550円($3.461) |
| 話 | 頼んだ回数(断られた分を除く) | 費用 |
|---|---|---|
| 148 | 10回 | 68円 |
| 149 | 12回 | 90円 |
| 150 | 16回 | 189円 |
| 151 | 12回 | 90円 |
| 152 | 14回 | 113円 |
第150話がいちばん高いのは、1コマ目の描き直しの1回で絵が6枚返ってきたためです。その返事の使用量は次のとおりでした。
54.1 {'promptTokenCount': 2026, 'candidatesTokenCount': 9309, 'totalTokenCount': 11335, 'cachedContentTokenCount': 544, 'promptTokensDetails': [{'modality': 'TEXT', 'tokenCount': 1510}, {'modality': 'IMAGE', 'tokenCount': 516}], 'cacheTokensDetails': [{'modality': 'TEXT', 'tokenCount': 406}, {'modality': 'IMAGE', 'tokenCount': 138}], 'candidatesTokensDetails': [{'modality': 'IMAGE', 'tokenCount': 6720}], 'serviceTier': 'standard'}
[[['thoughtSignature'], ['thoughtSignature'], ['thoughtSignature'], ['thoughtSignature'], ['thoughtSignature'], ['thoughtSignature']]]
出力の画像のトークンが 6,720(1,120 の6倍)で、返事の中に絵の部分が6つありました。かかった時間も54秒で、ふつうの1枚(13〜20秒)より長くかかっています。描く道具(vbuild.py)は返ってきた最後の1枚だけを保存するので、ほかの5枚は見られません。
11月の Gemini の支払い
Google から届いた支払いのメールを並べると、11月は次のとおりです。Google AI Studio の支払いは、先にお金を入れて使った分が引かれる形で、残高が800円を下回ると800円を足す(1か月の上限5,000円)設定にしています。
| 日付 | 内容 |
|---|---|
| 11月1日 | 800円を足した |
| 11月4日 | 800円を足した(3回) |
| 11月5日 | 800円を足した |
| 11月7日 | 800円を足した |
| 11月8日 | 「1か月の請求額の上限に達しました」で、足すのが止まった |
11月に足した額は4,800円です。今回の550円は、止まる前に足してあった残高から引かれ、表紙の編集のときに残りが足りなくなりました。次に絵を描く前に、上限を上げる必要があります。
声(ElevenLabs)の費用
5話で読ませた文字は、合わせて423字でした。
| 話 | 文字数 |
|---|---|
| 148 | 91字 |
| 149 | 102字 |
| 150 | 93字 |
| 151 | 60字 |
| 152 | 77字 |
| 合計 | 423字 |
ElevenLabs は月額の料金で、1か月に使える文字数(クレジット)が決まっています。Starter は月6ドルで3万クレジット、Creator は月22ドルで12万1千クレジットです(2026年10月の料金のページを読んだ一覧)。1字1クレジットとすると、Starter なら1字 $0.0002、Creator なら1字約 $0.00018 で、423字は約12〜13円です。今使っているプランを API の鍵では読めなかったので、両方の値を書いています。月額そのものは毎月かかる固定の費用で、ここには入れていません。同時に頼みすぎて断られた分には、費用はかかっていません。
X の API の費用
X の投稿は、リンクなしで1本 $0.015 です(article_rules.md の「X のリンク」)。日本語5本と英語5本の10本で $0.15、約24円です。予約したもので、投稿されるとき(12月と2月)に X のクレジットから引かれます。
合計と、前の5話との比べ
| 費用 | 額 |
|---|---|
| Gemini(絵) | 約550円 |
| ElevenLabs(声) | 約13円 |
| X の API(10本) | 約24円 |
Cloudflare R2(画像50枚・8.3MB) | 0円(無料の枠の中) |
| 合計 | 約590円(1話あたり約120円) |
Claude と ElevenLabs の月額、X のクレジットの残りなど、毎月かかる固定の費用は入れていません。
| 話 | Gemini に描かせた絵 | Gemini の費用 | エイイチの指摘 | 出し方 |
|---|---|---|---|---|
第138〜142話(LOG448) | 67枚 | 約460円 | ― | 見積もり |
第143〜147話(LOG468) | 120枚 | 約1,100円 | 5回 | 1枚約11円とバッチ半額で見積もり |
| 第148〜152話 | 69枚 | 約550円 | 1回 | 1回ずつの使用量から計算 |
LOG468 では「次の話で、エイイチの指摘の数と描き直しの枚数で確かめる」と書いていました。今回の描き直しは24回(絵29枚)で、前回の80枚の約3分の1です。指摘は5回から1回になりました。ただし、今回は別のエージェントの確認で12回描き直していて、前回はそれがエイイチの指摘のあとに来ていた、という順番の違いもあります。
次の5話の前に、Gemini の上限と、絵が何枚返ったかを確かめる
次は第153話からです。描く前に、Google AI Studio の月の上限を上げます。描く道具には、1回の返事に絵が何枚入っていたかを記録に残す行を足し、2枚以上返ったときに分かるようにします。費用は今回と同じく、1回ずつの使用量から出して、1話約120円と比べます。