---
title: "サービスロボット導入シミュレーション Log#14 | 動画は2回目へ、次は3Dの店で止まる所を見る"
slug: serving-robot-video-part2
date: 2026-10-25
day: 382
meta_description: "配膳ロボットの解説動画の2回目を、試算 v2.7 で作り直した。ホールを1人減らせたのは皿を集めて回る使い方の3台からで、浮く人件費より費用が月7.5万円高かった。公開前にサイトの試算が v2.8 になり、結論が合わない所が出た。"
tags: [サービスロボット導入シミュレーション, 配膳ロボット, YouTube, 解説動画, 人件費, 補助金, codex, ハコブくん, ElevenLabs, Playwright, ffmpeg, Claude]
cover: "/media/LOG382_cover.jpg"
series: "導入シミュレーション"
ai_consult: true
---

配膳ロボットを入れたら、ホールのスタッフを1人減らせるのか。ファミレスの混む2時間をパソコンの中で再現して確かめると、減らせる条件は見つかりました。ロボットが食事中に席を回って、お客さんに空いた皿を載せてもらう使い方で、ロボットが3台のときです。ところが、1人減って浮く人件費は月約14.1万円、ロボット3台を借りる費用は月約21.6万円で、**1人減らせても、差し引きは月約7.5万円の持ち出しでした。**

この記事は、その結果を伝える YouTube の解説動画（13分35秒）を作った記録です。動画は、配膳ロボットの導入を試算するシリーズの2回目にあたります。1回目では、スタッフ3人のままロボットを0台から6台まで増やし、料理を運ぶだけなら、どの台数でも3人を2人にすると店が回らない、という結果を伝えました。その最後で「まず、人は減らせるのか、月いくら浮くのか」と次の回を予告しています。

じつはこの2回目の動画は、一度できあがっていました。3日前に作った「配膳ロボットで1人減らせるか」という単発の動画で、まだ公開していませんでした。その後、試算の作りを直して数字が変わったため（料理はまずロボットを待つ、という決まりを入れた版。v2.7）、シリーズの2回目として作り直すことにしました。数字を差し替えるだけのつもりが、前の版の冒頭の「料理は早く届くのに、席に着くまでが延びる」は、新しい数字では成り立ちませんでした（料理の届く速さは58秒から54秒で、ほとんど変わらない）。話の芯を組み直し、お金の章を新しく足しています。

台本は、別の AI（codex）に「台本を論破するつもりで」検証してもらい、2回直しました。指摘の中心は数字の写し間違いではなく、パソコンの中で「必要な人数が1人減る」ことを、実際の店で「1人分の給料が減る」ことまで広げて話していた点でした。

| やったこと | なぜ | 結果 |
|---|---|---|
| 未公開の動画を、シリーズ2回目として台本から作り直した | 試算の数字が変わり、1回目の予告（減らせるか・月いくら浮くか）に合わせるため | 「料理を運ぶだけでは減らせない → 皿を集めて回ると3台で減る → お金は残らない」の3章にした |
| 台本の数字を、別の AI に全部計算し直してもらった | 数字の取り違えを、書いた本人とは別の目で見つけるため | 数字の食い違いは0。言い方を4か所直した |
| codex に2回検証してもらった | 言い過ぎや抜けている前提を見つけるため | 1回目22件・2回目13件の指摘。どちらも「直してから・条件つきで成立」 |
| 声を作ったあと、13文を抜いた | 16分29秒あり、目安（13〜14分）を超えたため | 13分35秒になった |
| 背景に流す試算ページの録画を6本録り直した | 1回目の録画では、この回の条件が映っていないため | 画面のほぼ全部で、この回の条件の試算が後ろに流れる |

【画像】LOG382_01_eight_frames.jpg 仕上げた動画の8つの場面。宮崎県の飲食店の人の言葉、この回の問い、結論、料理を運ぶだけの2人＋2台、皿を集めて回る使い方の台数ごとの棒、混雑の日、月−7.5万円、冒頭の言葉と試算はそのまま比べられない、の場面

ところが、記事にまとめる前に、もう一度サイトの試算を開くと、試算が次の版（v2.8）に変わっていました。会計をレジで1組ずつさばく作りを入れた版です。初めに表示されるレジ1つの条件では、2人＋ロボット1台でも、料理を運ぶだけで「店が回る」になります。動画の結論とは逆です。レジを2つにすると、動画とほぼ同じ結果になります。**動画をこのまま出すか、v2.8 の数字で直すかは、まだ決めていません。** その比べは、記事の後半に全部載せています。動画の最後では、次の回の予告として、店の図面から3Dの店を建ててロボットを走らせ、この試算に入っていない「通路で止まる所」を見る、と伝えています。


## 作業ログ ― 第2回にする前の動画と、試算の版

この記事の作業は、1つの会話の中で、台本の書き直しから YouTube に上げるものをそろえるまで進めました。効果の欄（ねらい・変わったこと・見込める効果）のうち、数字があるものは測った値、ないものは見込みです。

- 作り直す前の動画：「配膳ロボットで1人減らせるか」（2026-10-22 に作った8版・試算 v2.4・13分39秒・未公開）
- 1回目の動画：「配膳ロボット何台で店は変わる？ 2台まで変わり、人は減らせなかった【導入シミュレーション 第1回】」（試算 v2.7・2026-11-09 19:30 に公開予約）
- この回の数字：サイトの試算 v2.7（p2m-site の public/sim/serving-robot.html に埋め込みの結果・16,425条件・各40回の平均・md5 88adf2b2）
- 作業フォルダ：iCloud `PixelstoMotors/デジタルツイン学習R2R2R/動画/配膳ロボットで1人減らせるか/`。前の版のファイルは `動画/_旧版/置き換え前_20261025_配膳ロボットで1人減らせるか_第2回化/` に移した
- 重いファイル：KIOXIA `r2r2r-data/videos/配膳ロボットで1人減らせるか/`

始まりは、次の問いでした。

> 何台入れたら店は変わるの動画の台本って続き分あるんでしたっけ？

作業フォルダを見ると、続きにあたる台本は前の版の1本だけで、前日に決めた「第2回にして、最新の試算の数字に直す」には、まだ手が付いていませんでした。そこから作り直しを始めています。


## 台本を v2.7 の数字で書き直し、お金の章を足した

### 数字は、試算ページに埋め込まれた結果から読んだ

試算のページ（serving-robot.html）には、全部の条件の結果が JSON で埋め込まれています。ページと同じ決め方（ロボット0台は「料理を運ぶだけ・1卓ずつ」の行、ほかは「1往復で最大3つ・壊れやすい皿は誰が運んでもよい」の行。「店が回らない」は ng=1）で読み、費用はページの費用の欄の既定値で計算しました。

#### numbers_v27_for_script.py

```python
# 第2回の台本に使った数字を、試算 v2.7（サイトの試算ページに埋め込みの結果）から読み、費用の式で計算する
# 使い方: python3 numbers_v27_for_script.py <v2.7 の serving-robot.html>
# 決め方は試算ページと同じ（find: ロボット0台は「料理を運ぶだけ・1卓ずつ・誰でも」の行、ほかは「最大3つ・誰でも」。店が回らない＝ng=1）
import json, sys
s = open(sys.argv[1], encoding='utf-8').read()
i = s.find('const D = ') + len('const D = ')
D, _ = json.JSONDecoder().raw_decode(s[i:])
k = D['k']; rows = [dict(zip(k, x)) for x in D['r']]
IDX = {(r['store'], r['staff'], r['robots'], r['arrivals_per_h'], r['mode'], r['trays'], r['fragile_by']): r for r in rows}
def find(st, rb, arr, mode):
    key = ('family', st, 0, arr, 'serve', 1, 'any') if rb == 0 else ('family', st, rb, arr, mode, 3, 'any')
    return IDX[key]
def fm(r):
    return (f"入店 {r['entry_wait_mean']:.2f}分・席はあるのに {r['staff_wait_mean']:.2f}分・満席 {r['full_wait_mean']:.2f}分・"
            f"料理 {r['dish_wait_mean']*60:.1f}秒・歩く {r['walk_km_per_staff']:.2f}km・回らない {r['ng']}")
def min_staff(rb, arr, mode):
    for st in D['stores']['family']['staff_all']:
        if find(st, rb, arr, mode)['ng'] == 0:
            return st
print('model', D['common']['model'], '条件の数', len(rows))
print('3人・0台             ', fm(find(3, 0, 35, 'serve')))
print('2人・2台・運ぶだけ   ', fm(find(2, 2, 35, 'serve')))
print('2人・2台・まとめた皿 ', fm(find(2, 2, 35, 'bus')))
print('2人・6台・運ぶだけ   ', fm(find(2, 6, 35, 'serve')))
for n in range(1, 7):
    print(f'2人・{n}台・集めて回る ', fm(find(2, n, 35, 'patrol')))
print('3人・2台・運ぶだけ   ', fm(find(3, 2, 35, 'serve')))
for arr in (35, 45):
    for mode in ('serve', 'bus', 'patrol'):
        print(f'店が回る最少のスタッフ {arr}組/時・{mode}: ' + ','.join(str(min_staff(n, arr, mode)) for n in range(7)))
# 費用（試算ページの COST の既定）
WAGE, PEAKS, DAYS = 1177, 2, 30
RENT, MAINT, CHARGE = 60000, 10000, 2000
BUY, SUB_RATE, SUB_CAP, YEARS = 2500000, 0.5, 7500000, 5
labor = lambda h: h * PEAKS * DAYS * WAGE
rent = lambda n, p=RENT: n * (p + MAINT + CHARGE)
print()
print('浮く人件費（2時間）', labor(2), '（4時間）', labor(4))
print('3台を月6万円で借りる', rent(3), '差し引き', labor(2) - rent(3))
print('3台を月3万円で借りる', rent(3, 30000), '差し引き', labor(2) - rent(3, 30000))
print('4時間ずつ・月6万円', labor(4) - rent(3))
print('2台を月6万円で借りる', rent(2), '差し引き', labor(2) - rent(2))
print('3人＋2台（人は減らさない）の追加', rent(2))
total = 3 * BUY; sub = min(total * SUB_RATE, SUB_CAP); first = total - sub; run = 3 * (MAINT + CHARGE)
print('買う：本体', total, '補助金', sub, '自己負担', first, '保守と充電', run,
      '取り戻す月数', round(first / (labor(2) - run), 1), '補助金なし', round(total / (labor(2) - run), 1),
      '5年で割った月の差し引き', round(labor(2) - (first / (YEARS * 12) + run)))
```

#### numbers_v27_for_script_output.txt

```text
model v2.7 条件の数 16425
3人・0台              入店 8.58分・席はあるのに 7.41分・満席 0.93分・料理 57.9秒・歩く 3.88km・回らない 0
2人・2台・運ぶだけ    入店 14.26分・席はあるのに 13.24分・満席 0.79分・料理 53.5秒・歩く 3.48km・回らない 1
2人・2台・まとめた皿  入店 14.30分・席はあるのに 13.26分・満席 0.82分・料理 59.9秒・歩く 2.90km・回らない 1
2人・6台・運ぶだけ    入店 15.37分・席はあるのに 14.16分・満席 0.97分・料理 31.0秒・歩く 3.59km・回らない 1
2人・1台・集めて回る  入店 17.02分・席はあるのに 15.45分・満席 1.33分・料理 132.6秒・歩く 3.50km・回らない 1
2人・2台・集めて回る  入店 11.68分・席はあるのに 10.47分・満席 0.97分・料理 74.2秒・歩く 2.62km・回らない 1
2人・3台・集めて回る  入店 7.54分・席はあるのに 6.85分・満席 0.46分・料理 51.7秒・歩く 2.46km・回らない 0
2人・4台・集めて回る  入店 7.21分・席はあるのに 6.35分・満席 0.62分・料理 39.5秒・歩く 2.52km・回らない 0
2人・5台・集めて回る  入店 9.78分・席はあるのに 8.71分・満席 0.84分・料理 33.6秒・歩く 2.60km・回らない 0
2人・6台・集めて回る  入店 8.77分・席はあるのに 7.56分・満席 0.98分・料理 31.7秒・歩く 2.58km・回らない 0
3人・2台・運ぶだけ    入店 3.16分・席はあるのに 2.35分・満席 0.58分・料理 61.5秒・歩く 2.35km・回らない 0
店が回る最少のスタッフ 35組/時・serve: 3,3,3,3,3,3,3
店が回る最少のスタッフ 35組/時・bus: 3,3,3,3,3,3,3
店が回る最少のスタッフ 35組/時・patrol: 3,3,3,2,2,2,2
店が回る最少のスタッフ 45組/時・serve: 4,3,3,3,3,3,3
店が回る最少のスタッフ 45組/時・bus: 4,3,3,3,3,3,3
店が回る最少のスタッフ 45組/時・patrol: 4,3,3,3,3,3,3

浮く人件費（2時間） 141240 （4時間） 282480
3台を月6万円で借りる 216000 差し引き -74760
3台を月3万円で借りる 126000 差し引き 15240
4時間ずつ・月6万円 66480
2台を月6万円で借りる 144000 差し引き -2760
3人＋2台（人は減らさない）の追加 144000
買う：本体 7500000 補助金 3750000.0 自己負担 3750000.0 保守と充電 36000 取り戻す月数 35.6 補助金なし 71.3 5年で割った月の差し引き 42740
```

### 前の版（v2.4）から変わった数字

| 見るもの | 前の版（v2.4） | この回（v2.7） |
|---|---|---|
| 3人・ロボットなし：席に着くまで | 8.6分 | 8.6分 |
| 2人＋2台・料理を運ぶだけ：料理が卓に届くまで | 40秒（58秒から縮む） | 54秒（ほとんど変わらない） |
| 2人＋2台・料理を運ぶだけ：席に着くまで | 15.0分 | 14.3分 |
| 2人・皿を集めて回る3台：席に着くまで | 8.4分 | 7.5分 |
| 2人・皿を集めて回る2台：席は空いているのに待った時間 | 10.8分 | 10.5分 |

v2.7 では、料理ができたら、まずロボットを待ちます。2分たってもロボットが空かなければ、人も運べるようになります。前の版の「料理は早く届くのに」という冒頭は、この決まりで成り立たなくなりました。冒頭は、配膳ロボットを入れた宮崎県の飲食店の人がテレビの取材で話した言葉（「1人にはならないですけれども、0.5だとか、0.25にはなるので」）から入る形に替えています。

### 1回目と重なる話を外し、3つの章にした

1回目と重なる、試算の道具（SimPy）の説明、ロボットを6台にしたら回るかのクイズ、焼肉の食べ放題と洗い場が遠い店の話は外しました。本編は次の3章です。

1. 料理を運ぶだけだと、なぜ1人減らせないのか（片付けと案内が人に残る）
2. 皿を集めて回ると、何が変わるのか（食べ終わったあとの片付けが軽くなり、3台で2人でも回る）
3. 1人減ったら、月いくら浮くのか（浮く人件費より、ロボットの費用が高い）

- ねらい：1回目の最後の予告（減らせるか・月いくら浮くか）に、2回目で答える
- 変わったこと：前の版になかった費用の章を足し、「人は減らせても、お金は残らない」という結論にした
- 見込める効果：導入を考える飲食店や、ロボットを提案する会社が気にする「結局いくらか」まで話が届く。見てもらえたかは、公開後の視聴の続き具合で確かめる

### 台本を書いた本人とは別の AI に、数字を全部計算し直してもらった

台本を書いたあと、別のエージェントに、埋め込みの結果と費用の式から台本の数字を1つずつ計算し直してもらいました。依頼したのは、数字の照合と、言い過ぎ・定義とのずれ・皿を集めて回る使い方が設定によって変わるか・元を取るまでの期間の4点です。返ってきた報告の全文です。

#### agent_check_report.md（別のエージェントの照合の報告・全文）

```markdown
台本の数字はすべて D.json と費用の式から計算し直しました。数字の食い違いは一つもありません。ただ、言い方の問題が4つあり、そのうち2つは直した方がいい所です。（ng ＝ 席はあるのに待った時間 staff_wait_mean が10分以上、という決まりは、16,425行すべてで成り立っていました。）

| 文番号 | 台本の数字 | データの値 | 判定 | メモ |
|---|---|---|---|---|
| S004 | 混む2時間 | peak_min 120 | 一致 | |
| S012 | 2人・料理を運ぶだけ、どの台数でも回らない | 1〜6台すべて ng（0台も ng） | 一致 | |
| S018 | 10分以上で「回らない」 | ng の決まりと同じ | 一致 | |
| S020 | 35卓・35組・40回 | 35卓・35組/時・ページに「40回の平均」 | 一致 | |
| S022/S083 | 皿を集めて回る、3台以上で2人 | 既定の設定では 3〜6台が ng=0 | 一致（条件つき） | 下の3を参照 |
| S023/S061/S062 | 月約14.1万円 | 2×2×30×1,177＝141,240円 | 一致 | |
| S023/S064 | 3台で月21.6万円 | 3×72,000＝216,000円 | 一致 | |
| S024/S065/S084 | 月約7.5万円の持ち出し | −74,760円 | 一致 | |
| S035 | 料理 58秒→54秒 | 0.965分→0.892分 | 一致 | |
| S036 | 8.6分→14.3分 | 8.58→14.26 | 一致 | |
| S037 | そのうち13.2分 | 13.24 | 一致 | |
| S042 | 下げ膳にも、2台で14.3分「線を超えました」 | 入店 14.30／席はあるのに 13.26・ng | 言い方 | 線は「席はあるのに待った時間」で引くので、14.3分（入店までの時間）を線と比べるのはずれる。13.3分と言うべき所。3〜6台も ng |
| S044/S077/S083 | 料理を運ぶだけ、6台でも回らない | 2人6台 ng（14.16） | 一致 | |
| S049 | 2台で10.5分、少しだけ超えた | 10.47・ng | 一致 | |
| S050 | 3台で7.5分、3人0台の8.6分より短い | 7.54 対 8.58 | 一致 | |
| S051 | 料理 52秒、4〜6台も線の内側 | 0.862分。席はあるのに 6.35／8.71／7.56 | 一致 | 5台は入店 9.78分で 8.6分より長い。台本は「短い」とは言っていないので問題なし |
| S053 | 3.9km→2.5km | 3.88→2.46 | 一致 | |
| S056 | 45組なら、どの台数でも2人では回らない。4人→3人 | 2人の席はあるのに 14.7〜24.6分・すべて ng。最少人数 4/3/3/3/3/3/3 | 一致 | 料理を運ぶだけ・下げ膳にもでも同じ 4→3 |
| S067 | 月約1.5万円のプラス | 141,240−126,000＝+15,240円 | 一致 | |
| S068 | 月約28.2万円、月約6.6万円のプラス | 282,480円／+66,480円 | 一致 | 試算は2時間だけ。4時間2人で回るかは試算の外まで伸ばした話 |
| S069 | 375万円、月約4.3万円のプラス、約3年 | 375万円、月98,500円 → +42,740円、375万÷(141,240−36,000)＝35.6か月 | 一致（言い方） | 下の4を参照 |
| S070 | 混雑の日は2人では回らない | 上と同じ | 一致 | |
| S073 | 3人2台で 8.6→3.2分 | 3.16 | 一致 | 前回の 3.2分とも合う |
| S006/S060 | 人件費よりロボットの費用が高い | 借りる場合は −7.5万円。買う場合は +4.3万円 | おおむね一致 | すぐ後に「借りる値段しだい」と断っているので許容 |

**お願いされた4点**

1. **言い過ぎ**：大きな言い過ぎはありません。S046「2人でも回るようになります」は、3台以上・既定の設定のときだけです。直前と直後の文が補っています。
2. **決まりとのずれ**：S042 だけです。入店までの時間（14.3分）を10分の線と比べています。線の対象は席はあるのに待った時間（13.3分）です。結論（超えた）は変わりません。
3. **皿を集めて回る使い方の「3台で2人」**：成り立つのは、壊れやすい皿を誰が運んでもよいときだけです。既定の「1往復で最大3つ」でも、「1往復で1つ」でも同じです。

   | 設定 | 2人で回る台数 | 席はあるのに待った時間（1〜6台） |
   |---|---|---|
   | 最大3つ・誰でも（既定） | 3〜6台 | 15.45／10.47／6.85／6.35／8.71／7.56 |
   | 最大1つ・誰でも | 3〜6台 | 7.69 などで、3台以上はすべて10分未満 |
   | 最大3つ・壊れやすい皿は人 | 3台だけ | 4〜6台は 10.43／10.28／10.57 で ng |
   | 最大1つ・壊れやすい皿は人 | 5台だけ（9.81） | 3台 10.16、4台 10.19、6台 10.7 で ng |

4. **元を取るまでの期間**：375万円 ÷（141,240 − 36,000）＝ 35.6か月です。「約3年」は妥当です。

**直すべき所**

- **S042**：「席に着くまで14.3分。こちらも線を超えました」を、「席はあるのに待った時間が13.3分。こちらも線を超えました」に直す。
- **S022/S083 の「3台以上」**：前提の一言を足す。例えば「デザートやドリンクもロボットが運んでよい、という前提で」です。壊れやすい皿を人が運ぶ設定だと、4〜6台では回りません。
- **S069（直した方がよい）**：言い方の問題です。「月約4.3万円のプラス」は、5年で割った買う額を引いた後の数字です。「約3年」は、保守と充電だけを引いた月約10.5万円で割った数字です。並べると、聞く人が 375万÷4.3万＝約7年と取り違えます。例えば「保守と充電を引いて月約10.5万円浮くので、約3年で取り戻せる」と、割る数を示すとよいです。
- **S068（任意）**：「試算は混む2時間だけで、4時間まで2人で回るかは確かめていない」と一言足すと正確です。
```

報告のとおり、まとめた皿も運ぶ使い方は「席は空いているのに待った時間が13.3分」と言い直し、皿を集めて回る使い方の結果はデザートやドリンクもロボットが運んでよい前提だと足し、買う場合の約3年は割る数（月約10.5万円）を言う形に直しました。


## codex に2回検証してもらった

Mac の「codex 係」（5分ごとに作業フォルダの印を探し、検証の依頼文を codex に渡すスクリプト）に、2回かけました。依頼文は make_docs.py が台本から作ります（全文は記事の最後）。

| 回 | かかった時間 | 検索の回数 | 指摘の数 | 判定 |
|---|---|---|---|---|
| 1回目 | 33分32秒 | 34 | 22 | 直してから・条件つきで成立 |
| 2回目 | 6分37秒 | 16 | 13 | 直してから（作り直しは不要）・条件つきで成立 |

### 1回目の指摘は、試算のコードを開いて確かめた

1回目の中心の指摘は、「お客さんが一定の量の皿を載せてくれる」という言い方では、結論を支える前提の強さが伝わらない、というものでした。試算のコード（haizen_sim.py v2.7）を開くと、そのとおりでした。食事中の回収（collect_visit）は、空いた皿があるか・お客さんが断るかを見ずに、回収を1回数えます。食べ終わったあとの下げ膳（bus）は、人の往復の回数を「2 − 回収の回数」に減らし、0回なら皿をまとめる40秒も省きます。つまり、2回回収できれば、食べ終わったあとに下げる皿は残らない設定です。

もう1つ、料理をロボットに載せる人の時間と、集めた皿を洗い場で降ろす人の時間が、コードのどこにもないことも確かめました（人が料理を置く staff_place_s は、人が運ぶときだけ）。

#### haizen_sim.py v2.7 の 300〜546 行目（料理を運ぶ・食事中の回収・下げ膳・1組の流れ）

```python
    # v2.6 までは、はじめから「先に空いた方」だったため、受け渡し口の横で待つスタッフが多く運んでいた。
    # ロボットが出るときは、受け渡し口で待っている料理を段の数までまとめて載せ、近い卓から回る。
    def deliver(self, d, fragile=False, counted=True):
        env, p = self.env, self.p
        rec = {"d": d, "ready": env.now, "fragile": fragile, "counted": counted,
               "taken": env.event(), "arrived": env.event()}
        robot_ok = self.robots is not None and not (fragile and p["fragile_by"] == "staff")
        if not robot_ok:
            sreq = self.staff.request(priority=1)
            yield sreq
            yield env.process(self._staff_carry(rec, sreq))
            return
        rreq = self.robots.request(priority=0)
        rec["sreq"], rec["rreq"] = None, rreq
        self.pass_q.append(rec)
        yield rreq | rec["taken"] | env.timeout(p["robot_first_wait_s"])   # まずロボットだけを待つ
        if not (rreq.triggered or rec["taken"].triggered):                # 2分たった：ここからはスタッフも運べる
            sreq = self.staff.request(priority=1)
            rec["sreq"] = sreq
            yield rreq | sreq | rec["taken"]
        sreq = rec["sreq"]
        if rec["taken"].triggered:          # ほかの料理と一緒にロボットに載った
            yield rec["arrived"]
            return
        self.pass_q.remove(rec)
        if rreq.triggered:                  # ロボットが運ぶ
            if sreq is not None:
                self._drop(sreq, self.staff)
            batch = [rec]
            for o in list(self.pass_q):
                if len(batch) >= p["trays"]:
                    break
                self.pass_q.remove(o)
                self._drop(o["rreq"], self.robots)
                if o["sreq"] is not None:
                    self._drop(o["sreq"], self.staff)
                o["taken"].succeed()
                batch.append(o)
            env.process(self._robot_run(batch, rreq))
            yield rec["arrived"]
            return
        rreq.cancel()                       # スタッフが運ぶ
        yield env.process(self._staff_carry(rec, sreq))

    @staticmethod
    def _drop(req, res):
        if req.triggered:
            res.release(req)
        else:
            req.cancel()

    def _robot_run(self, batch, rreq):
        env, p = self.env, self.p
        start = env.now
        batch.sort(key=lambda r: r["d"])
        pos = 0.0
        for i, rec in enumerate(batch):
            leg = rec["d"] - pos + (p["hop_m"] if i else 0)
            yield env.timeout(max(leg, 0) / p["robot_speed"])
            if i == 0:
                yield env.process(self.maybe_stop(rec["d"]))
            if rec["counted"]:
                self.dish_waits.append((env.now - rec["ready"]) / 60)
            self.robot_trips += 1
            self.fragile_robot += rec["fragile"]
            rec["arrived"].succeed()
            yield env.timeout(p["robot_handoff_s"])
            pos = rec["d"]
        yield env.timeout(pos / p["robot_speed"])
        self.robot_busy_s += env.now - start
        self.robots.release(rreq)

    def _staff_carry(self, rec, sreq):
        env, p = self.env, self.p
        self.staff_trips += 1
        go = rec["d"] / p["staff_speed"]
        yield env.timeout(go)
        if rec["counted"]:
            self.dish_waits.append((env.now - rec["ready"]) / 60)
        rec["arrived"].succeed()
        yield env.timeout(p["staff_place_s"] + go)
        self.staff_walk_m += 2 * rec["d"]
        self.staff_busy_s += 2 * go + p["staff_place_s"]
        self.staff.release(sreq)

    # ---- 巡回回収（食事中にロボットが来て、客が空いた皿を載せる）
    def collect_visit(self, d, deadline, box):
        env, p = self.env, self.p
        req = self.robots.request(priority=2)
        timer = env.timeout(max(deadline - env.now, 0))
        res = yield req | timer
        if req not in res:
            req.cancel()
            return
        start = env.now
        t = d / p["robot_speed"]
        back = (d + p["dish_extra_m"]) / p["robot_speed"]
        yield env.timeout(t)
        yield env.process(self.maybe_stop(d))
        yield env.timeout(p["guest_load_s"] + back)
        self.robot_busy_s += env.now - start
        self.robots.release(req)
        self.collects += 1
        box[0] += 1

    # ---- 下げ膳（客が帰ってから卓が使えるようになるまで）
    def bus(self, d, collected, counted=True):
        env, p = self.env, self.p
        start = env.now
        trips = max(p["bus_trips"] - collected, 0)
        if p["mode"] == "bus" and self.robots is not None and trips > 0:
            # v2.4: スタッフの手が空いて片付けに向かうときに、空いているロボットがいれば一緒に卓へ向かわせる
            with self.staff.request(priority=2) as sreq:
                yield sreq
                s0 = env.now
                rreq = self.robots.request(priority=1)
                if rreq.triggered:
                    self.robot_bus += 1
                    arrive, loaded = env.event(), env.event()
                    env.process(self._robot_bus_trip(d, rreq, arrive, loaded))
                    # スタッフは卓まで行き、皿をまとめ、ロボットが着いたら載せ、卓を拭いて戻る
                    yield env.timeout(d / p["staff_speed"] + p["clear_s"])
                    yield arrive
                    yield env.timeout(p["load_s"])
                    loaded.succeed()                 # 載せ終えた。ロボットは洗い場へ
                    yield env.timeout(p["wipe_s"])
                    done_at = env.now
                    yield env.timeout(d / p["staff_speed"])
                    self.staff_walk_m += 2 * d
                    self.staff_busy_s += env.now - s0
                    if counted:
                        self.turns.append((done_at - start) / 60)
                    return
                rreq.cancel()
                # 空いているロボットがいない：そのまま人だけで下げる（皿の量に応じて往復）
                self.staff_bus += 1
                walk = 2 * (d + p["dish_extra_m"]) * trips
                tt = walk / p["staff_speed"] + p["clear_s"] + p["wipe_s"]
                self.staff_walk_m += walk
                self.staff_busy_s += tt
                yield env.timeout(tt)
            if counted:
                self.turns.append((env.now - start) / 60)
            return
        # 人だけで下げる（皿の量に応じて往復）。皿がもうなければ拭きに行くだけ
        self.staff_bus += 1
        walk = 2 * (d + p["dish_extra_m"]) * trips if trips > 0 else 2 * d
        work = (p["clear_s"] if trips > 0 else 0) + p["wipe_s"]
        yield env.process(self.staff_job(2, walk, work))
        if counted:
            self.turns.append((env.now - start) / 60)

    def _robot_bus_trip(self, d, rreq, arrive, loaded):
        env, p = self.env, self.p
        start = env.now
        t = d / p["robot_speed"]
        yield env.timeout(t)
        yield env.process(self.maybe_stop(d, helper_waiting=True))
        arrive.succeed()
        yield loaded                                  # v2.4: スタッフが載せ終えるまで卓で待つ
        back = (d + p["dish_extra_m"]) / p["robot_speed"]
        yield env.timeout(back + 15)  # 洗い場で降ろすのは厨房側
        self.robot_busy_s += env.now - start
        self.robots.release(rreq)

    # ---- 1組の流れ
    def group(self):
        env, p, rng = self.env, self.p, self.rng
        arrive = env.now
        counted = (self.t0 <= arrive < self.t1) if p["sustain"] else True   # 数える時間に来た組だけを記録する
        if counted:
            self.counted += 1
        # 図面のある店は卓ごとの距離から選ぶ。ほかの店は今までどおり（乱数の使い方も同じ）
        d = rng.choice(p["dist_list"]) if p.get("dist_list") else rng.uniform(*p["dist_m"])
        self._acc()
        table = self.tables.request()
        yield table
        blocked = self.blocked.pop(table, 0.0)
        if counted:
            w = (env.now - arrive) / 60
            self.seat_waits.append(w)
            self.seat_wait_by_arrival.append((arrive, w))
        # 案内（v2.4）: スタッフの手が空いたら卓まで一緒に歩く。卓に着いた時点を「席に着いた」とする。
        # 説明（guide_s）と受け渡し口への戻りは、スタッフの手がふさがる時間には入れ、お客さんの注文はそのあとに進む（v2.2 と同じ）
        g0 = env.now
        with self.staff.request(priority=1) as greq:
            yield greq
            gwait = env.now - g0
            yield env.timeout(d / p["staff_speed"])
            seated_at = env.now
            yield env.timeout(p["guide_s"] + d / p["staff_speed"])
            self.staff_walk_m += 2 * d
            self.staff_busy_s += 2 * d / p["staff_speed"] + p["guide_s"]
        if counted:
            self.blocked_waits.append(blocked / 60)
            self.guide_waits.append(gwait / 60)
            self.entry_waits.append((seated_at - arrive) / 60)
        firsts = [env.process(self._cook_then_deliver(c, d, False, counted)) for c in p["first_dishes"]]
        yield simpy.AllOf(env, firsts)
        eat = tri(rng, p["eat_min"]) * 60
        end = env.now + eat
        # 食事中の追加注文・呼び出し・巡回回収
        extras = []
        for _ in range(p["extra_orders"]):
            extras.append(env.process(self._order_later(rng.uniform(0, eat * 0.7), d, p["extra_cook"], False, counted)))
        n_fragile = int(p["fragile"]) + (rng.random() < p["fragile"] - int(p["fragile"]))
        for _ in range(n_fragile):
            extras.append(env.process(self._order_later(rng.uniform(0.3, 0.85) * eat, d, p["fragile_cook"], True, counted)))
        calls = sum(rng.random() < p["call_rate"] / 2 for _ in range(2))
        for _ in range(calls):
            env.process(self._call_later(rng.uniform(0, eat), d))
        collected = [0]
        if p["mode"] == "patrol" and self.robots is not None:
            for k in range(p["bus_trips"]):
                at = eat * (k + 1) / (p["bus_trips"] + 1)
                env.process(self._collect_later(at, d, end, collected))
        yield env.timeout(eat)
        if extras:
            yield simpy.AllOf(env, extras)
        yield env.process(self.staff_job(1, 0, p["pay_s"]))
        self._acc()
        self.dirty += 1                      # 客は帰った。片付けが済むまで卓は使えない
        yield env.process(self.bus(d, collected[0], counted))
        self._acc()
        self.dirty -= 1
        self.tables.release(table)
        self.done += 1
        if counted:
            self.counted_done += 1
            self._check_finished()

    def _cook_then_deliver(self, cook, d, fragile=False, counted=True):
        yield self.env.timeout(tri(self.rng, cook) * 60)
        yield self.env.process(self.deliver(d, fragile, counted))

    def _order_later(self, delay, d, cook, fragile, counted=True):
        yield self.env.timeout(delay)
        yield self.env.process(self._cook_then_deliver(cook, d, fragile, counted))

    def _call_later(self, delay, d):
        yield self.env.timeout(delay)
        yield self.env.process(self.staff_job(1, 2 * d, self.p["call_s"]))

    def _collect_later(self, delay, d, deadline, box):
        yield self.env.timeout(delay)
        yield self.env.process(self.collect_visit(d, deadline, box))
```

この2点を台本に入れたほか、1回目の指摘で直したことは次のとおりです。

- お金は「料理を載せる人や皿を降ろす人の勤務を増やさずに、実際のシフトで1人分の給料を減らせた場合の仮の計算」と言う。2時間だけ人を減らすシフトは試していない
- 混雑の日（1時間に45組）も、要る人数はロボットなしの4人が3人になり、1人減る。前の版の「毎日1人減らせるとは限らない」の言い方を直した
- 買う場合は本体3台で750万円、補助金を受け取れれば自己負担375万円。代金は先に払う。補助金なしでは約6年で、5年使う前提に収まらない
- 借りる値段の「相場の真ん中が6万円台」は出典で確かめられないので外し、仮に置いた値と言う
- 「ロボットが1人分を丸ごと受け持てる」は外し、冒頭の「0.5人分」という実感と試算はそのまま比べられない、と言う
- 3台という答えは10分の線に左右される（2台は10.5分で、線のすぐ上）。調べたのは6台まで。40回の平均で、日ごとのばらつきは示していない

採らなかったのは、見立ての1文目の言い換えです。「人を減らせるかは、ロボットに何を受け持たせるかで決まる」は本人の言葉なのでそのまま残し、次の文で「何を受け持たせ、人の仕事をどう組み直すか」を足しました。

#### codex_検証結果_1回目.md

```markdown
# codex 敵対的検証 結果 1回目（配膳ロボットで1人減らせるか）

- 日時: 2026-10-25 09:08（JST）
- 依頼文: codex_敵対的検証依頼_配膳ロボットで1人減らせるか.md（md5 c94c3d8bf6741b6e5afc39fbc7adc34c・27,552 バイト）
- 題（依頼文の1行目）: # 敵対的検証依頼：YouTube台本「配膳ロボットは「0.5人分」？ ― 1人減らせる条件と、月いくら浮くかを試算した（配膳ロボット導入シミュレーション 第2回）」
- codex: codex-cli 0.163.0-alpha.11
- モデル: gpt-6.1-sol
- 考える深さ: high
- ウェブ検索: あり（検索した回数 34）
- かかった時間: 33分32秒
- 使ったトークン: 177,452
- 指摘の数: 22（うち出典のリンクが付いたもの 6）
- 出典の URL: 7件（別々・文の中に張られた回数 7）

---
判定は**「直してから」**です。主要な数値の転記よりも、**モデル内の人数削減を、実際のシフト削減・給与削減・「ロボットが何人分か」へ広げる部分**に問題があります。

公開中の試算ページ本体は取得できず、**公開画面で同じ条件を選んだ値との一致は未確認**です。ただし、手元の[v2.7 HTML](</Users/shimazueiichi/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/simulation/v2_7/serving-robot.v27.html:406>)の16,425条件を抽出し、[Pythonコード](</Users/shimazueiichi/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/simulation/v2_7/haizen_sim.py:385>)と費用の式を確認しました。以下で「HTML」「コード」と書くのは、このローカル資料です。シミュレーションの再実行はしていません。

---

**[❌ NG] S047・S052・S054**
問題：「一定の量の皿を載せてくれる」では、結論を支える仮定の強さが伝わりません。この設定では、食事中の回収が2回成功すると、退店後に下げる皿がゼロとなり、皿をまとめる40秒も不要になります。
根拠：コードの`collect_visit`は、空いた皿の有無・量・客の拒否を判定せず、回収成功を1回加算します。`bus`は、人の下げ膳往復を「2−成功回数」で減らし、残りゼロなら皿をまとめる作業を省きます。単に運搬が軽くなる以上の変更です。
修正案：「今回の設定では、食事中の回収が2回成功すると、退店後に下げる皿は残らず、皿をまとめる40秒も要らなくなります。最後まで皿が残る店でも3台で足りるかは、確かめていません。」

**[❌ NG] S021・S047・S052・S061〜S062**
問題：ロボットに仕事を移した結果、厨房側に残る作業が人数計算から抜けています。「ホールが1人減る」と「店全体で1人分の支払いが減る」を同一視できません。
根拠：コードには、料理をロボットに積んで出発させる人の作業時間がありません。巡回回収後に洗い場で皿を降ろす作業も計上されず、スタッフがまとめた皿を運ぶ方式にはある、洗い場での荷降ろし15秒さえ巡回方式にはありません。
修正案：「ホールの人数だけを比べています。料理をロボットに載せたり、回収した皿を洗い場で降ろしたりする人の負担は、この人数に入っていません。そこを含めて、店全体の支払いが減るかは別に確かめる必要があります。」

**[❌ NG] S004・S014・S061・S071**
問題：この試算は、「2時間だけスタッフを減らすシフト」を試していません。S071の「シフトの組み方で変わる」だけでは、計算したものと未検証のものの違いが弱すぎます。
根拠：コードは、来客を120分で止めたあとも、全組の片付けが終わるまで同じスタッフ数で動きます。2時間後に人数を戻す試算や、営業全体の勤務時間の比較はしていません。S053自身も集計が2時間を超えることを説明しています。
修正案：「試算では、2時間だけお客さんが来て、そのあとの片付けまで同じ人数で動きます。ここから先のお金は、実際のシフトで1日4時間、月120時間の給与支払いを減らせた場合の、仮の計算です。」

**[❌ NG] S057・S070**
問題：「混雑日は2人で回らない」から、「毎日1人減らせるとは限らない」へ進む比較が不適切です。混雑日の比較対象は、ロボットなしの4人です。
根拠：HTMLでは、巡回方式の最少人数は、普通が3人→2人、混雑が4人→3人です。両方とも必要人数は1人減っています。「2人に固定できない」と「1人減らせない」は別です。
修正案：「混雑の日には、2人にはできません。ただ、ロボットなしなら4人必要なところが3人なので、必要人数の差は、この条件でも1人です。実際に支払いを減らせるかは、その日の来客とシフトで決まります。」

**[❌ NG] S069**
問題：「初めに375万円」は、補助後の自己負担額と、購入時に必要な支払いを混同しています。
根拠：本体代は3台で750万円です。公式手続きは、導入・支払い・実績報告を経て、補助額確定後に請求・交付という順序です。また、補助率は「1/2以下」で、登録製品ごとの上限などもあります。[公式の申請手順](https://shoryokuka.smrj.go.jp/catalog/flow/)、[公募要領・7ページ](https://shoryokuka.smrj.go.jp/assets/pdf/application_guidelines_catalog.pdf)
修正案：「買う場合、本体代は3台で750万円。補助金を375万円受け取れれば、最終的な自己負担は375万円です。ただし、購入代金は先に支払う必要があります。毎月10万5,240円の支出を減らし続けられるなら、補助後の自己負担を約3年で取り戻す計算です。」

**[❌ NG] S063**
問題：指定された出典の現行記事では、「月3〜12万円」「中央値6万円台」を裏付けられません。「真ん中」という統計的な説明を残す根拠がありません。
根拠：確認できた記事は、購入約150〜300万円、リース月約3〜10万円とし、レンタルは販売会社によると説明しています。中央値の調査方法や、その数値は確認できませんでした。10月24日時点の保存原文は未確認です。[お名前.comの記事](https://www.onamae.com/business/article/306061/)
修正案：「今回は、1台月6万円で借りると仮に置きました。実際の値段は、機種や契約期間、保守を含むかどうかで変わります。」

**[❌ NG] S003・S074・S085**
問題：この試算は、「ロボットが人の何人分か」を測っていません。特に「ロボットが1人分を丸ごと受け持てる」は、結果の説明として誤りです。
根拠：測っているのは、3台のロボット、客の協力、残ったスタッフへの仕事の再配分を合わせたときの必要配置人数です。1台の代替能力や、1人分の全業務の引き受けではありません。冒頭の現場の実感とも、数量として対応させられません。
修正案：「冒頭の0.5人分という実感と、今回の配置人数は、そのまま比べられません。今回見たのは、3台とお客さんの協力を組み合わせたら、必要なホールの人数が1人減るか、ということです。」

**[⚠️ 要注意] S018・S022・S049・S083**
問題：「3台が必要」という結論は、10分という線に大きく左右されます。また「3台以上」は、調べていない7台以上まで含む言い方です。
根拠：2台の判定対象は10.475分です。線を11分にすると2台でも通り、費用は月14.4万円、差し引きは月2,760円の持ち出しになります。3台の場合の月74,760円との差は大きく、10分は単なる説明上の注記ではありません。
修正案：「10分の線で分けると、調べた0台から6台の中では、3台から6台が線の内側でした。ただ、2台も10.5分。線を11分にすれば2台でよくなり、持ち出しも月約3,000円まで小さくなります。」

**[⚠️ 要注意] S020・S049〜S051・S083**
問題：40回の平均が線を下回ることと、毎回安定して営業できることが混ざっています。「3台で確実に足りる」と受け取られる余地があります。
根拠：確認した集計には、各回の入店待ちのばらつきや、各回で10分を超えた割合がありません。巡回方式の判定対象も、3〜6台で6.851・6.349・8.712・7.564分と単調ではなく、台数差をどこまで区別できるかは未確認です。
修正案：「これは40回の平均で線を下回った、という結果です。何回に1回は線を超えるのか、日ごとのばらつきまでは、ここでは示していません。」

**[⚠️ 要注意] S004・S019〜S020**
問題：ピーク開始時の店内に、すでに客や仕事がある状態を再現していません。「混む時間帯の2時間」という説明から想像される状態と違います。
根拠：HTMLの前提は「空いた店」に120分だけ来客し、全員の処理が終わるまで動かす方式です。営業途中のピーク、前の時間帯から残った仕事、ピーク後にも続く来客は含まれません。
修正案：「空席の店から始めて、2時間だけお客さんが来る形です。すでに客がいる営業途中のピークでも、同じ人数で足りるかは確かめていません。」

**[⚠️ 要注意] S033・S038・S044・S077**
問題：「片付けが残るから減らせない」という説明だけでは、仕事の割り振り方が結果を作っていることが伝わりません。
根拠：コードは、料理をまずロボットに2分待たせ、下げ膳を案内・会計などより低い優先順位にしています。人の配膳は1皿ずつですが、ロボットは最大3皿をまとめます。優先順位や人のまとめ運びを変えた比較は未確認です。
修正案：「今回の仕事の順番と運び方では、片付けが追いつきませんでした。案内と片付けの優先順を変えたり、人もまとめて運んだりした場合までは、比べていません。」

**[⚠️ 要注意] S018・S056・S083**
問題：「店が回る」の判定は、営業全体の品質を保証しません。平均の人手待ちだけが改善しても、料理や接客が悪化する条件を通します。
根拠：例として、混雑・3人・料理運搬1台は人手待ち9.348分で合格ですが、入店待ちは17.445分、料理の到着は平均2.28分、3分超の料理は22.3％です。「判定に通る」と「許容できる営業」は一致しません。
修正案：「ここでの『回る』は、人手が原因の待ち時間だけで分けた呼び名です。料理の遅れや、長く待つお客さんの割合まで含めて、営業できると判断したわけではありません。」

**[⚠️ 要注意] S047〜S048・S054〜S055**
問題：食べ放題で客が協力する事例は、ファミレスでも同じ量を回収できる根拠にはなりません。協力する動機と、食事中に空く皿の量が違います。
根拠：かみむら牧場の事例は、食器が大量にたまる食べ放題で、ロボットを下膳専用にし、料理は特急レーンで届けています。料理と回収を同じロボットに受け持たせる今回の条件とも違います。[メーカーの導入事例](https://www.softbankrobotics.com/jp/product/delivery/cases/kamimura/)
修正案：「実例は、食器がたまりやすい食べ放題の店です。下げ膳専用で使う例でもあります。今回のファミレスで、料理も運びながら同じように皿を回収できるかは、まだ分かりません。」

**[⚠️ 要注意] S066〜S069**
問題：プラスになる条件を3つ並べる一方、購入について補助金なしの結果を示さないため、比較が有利な側に寄っています。
根拠：同じ費用の式では、補助金なしの単純回収期間は約71.3か月です。ページの5年使用という前提内には回収できません。補助金ありの35.6か月という割り算自体は合っています。
修正案：「買って補助金を半分受け取れれば、単純計算で約3年です。補助金なしでは約5年11か月で、今回置いた5年の使用期間には収まりません。」

**[⚠️ 要注意] S023・S064・S067・S069**
問題：費用は仮定として計算できますが、実際に比較可能な契約一式を確認した数字にはなっていません。保守の二重計上や、安い機種でも同じ仕事ができるという混同が起こります。
根拠：販売会社の公表例には、月58,000円に保守・サポートを含み、最低3年契約とするものがあります。ただし2024年の告知で、現在の適用は未確認です。初期設定・教育・消耗品・税の扱いも、台本の比較にはそろっていません。[販売会社の告知](https://www.maido-system.net/archives/8114/)
修正案：「これは見積書ではなく、料金を仮に置いた比較です。保守込みの契約なら追加しません。月3万円の場合も、今回の仕事ができる機種を、その条件で借りられると仮定した計算です。導入時の設定や教育などの費用は含めていません。」

**[⚠️ 要注意] S058・S065・S069**
問題：通路での譲り合いだけを注意すると、3台が毎日使えることや、故障時の人員確保まで検証済みのように見えます。
根拠：モデルには短い一時停止と救出はありますが、長時間故障、修理待ち、充電による離脱はありません。3台のうち1台が長時間使えない場合を、そのまま「3台で回る」と扱えません。2台条件はすでに10分を超えています。
修正案：「短い停止や、人が動かして助ける場面は入れています。ただ、故障や充電で1台が長く使えない場合は試していません。そのときに必要な人員や費用も別です。」

**[⚠️ 要注意] S062・S065〜S068**
問題：最低賃金の全国加重平均を使った例から、店の採算へ広げる際の説明が不足しています。除いた人件費が、実際に削減できる費用とも限りません。
根拠：1,177円は出典と一致します。ただし地域別最低賃金の全国加重平均で、店の実際の時給ではありません。同じ120時間削減・月21.6万円なら、支払いが減る時間単価が1,800円で差し引きゼロになります。社会保険料などは、勤務時間を減らしても同率では減らない場合があります。[JILPT](https://www.jil.go.jp/kokunai/blt/backnumber/2026/10/special_03.html)
修正案：「時給は、地域別最低賃金の全国加重平均を借りた仮の値です。自分の店では、実際に減らせる給与や手当で置き換えてください。同じ120時間なら、減る支払いが1時間1,800円で、今回のロボット費用と並びます。」

**[⚠️ 要注意] S076〜S079**
問題：「何を受け持たせるかで決まる」は、見立てとしても原因を一つに絞りすぎです。台本自身が、来客数・客の協力・作業時間・通路によって答えが変わると示しています。
根拠：また、人による食事中の下げ膳、仕事の優先順位の変更などを比較していないため、「客による巡回回収こそが解決策」とまでは言えません。S079の普及理由も、今回の試算が証明した因果ではありません。
修正案：「人を減らせるかは、ロボットに何を受け持たせ、人の仕事をどう組み直すかで、大きく変わる。エイイチは、そう見ています。ただ、来客の波や客の協力も含めて、店ごとに確かめる必要があります。」

**[⚠️ 要注意] S072〜S073・S080**
問題：人件費以外の導入理由を挙げても、月7.5万円の負担に見合うという説明にはなりません。負担やサービスが必ず改善するとも限りません。
根拠：歩行距離や待ち時間はモデルの出力ですが、疲労・満足度・定着・売上は測っていません。客に作業を頼む負担や、スタッフがロボットの面倒を見る負担も評価対象です。
修正案：「歩く距離や待ち時間は、試算では減りました。ただ、負担やサービスが実際に良くなるかは、店で確かめる必要があります。月7.5万円を追加で払うなら、その変化が見合うのか、ほかの方法とも並べて決めます。」

**[⚠️ 要注意] S081**
問題：紹介する観察シートだけでは、今回の結論を左右する「客の協力」を十分に測れません。
根拠：手元の観察シートHTMLには、誰が皿を載せるかや片付け時間の項目はありますが、協力した割合・回収量・退店後の残皿量を記録する専用項目はありません。また試算との比較欄には、v2.7と異なる配膳分担や片付け時間の表示が残っています。公開版は未確認です。
修正案：「止まり方や片付け時間を数える観察シートを作りました。今回の回収方式を確かめるには、それに加えて、客が載せた割合と、退店後に残った皿の量も記録する必要があります。」

**[⚠️ 要注意] S001〜S002**
問題：発言の要旨は確認できましたが、台本の逐語引用は未確認です。記事本文と台本では語尾などが違います。
根拠：MRTの公式記事は同趣旨の発言を掲載し、4月27日放送分と明記しています。一方、指定YouTubeの音声・文字起こしは取得できませんでした。[MRT公式記事](https://newsdig.tbs.co.jp/articles/mrt/32630?display=1)
修正案：「宮崎県の飲食店の店長は、テレビの取材で、1人分にはならなくても、0.5人分や0.25人分にはなる、という趣旨の話をしていました。」
※逐語引用を残すなら、公開前に元音声との照合が必要です。

**[⚠️ 要注意] S027〜S044**
問題：第2回としては、前回の再説明が長く、新しく検証すべき回収の仮定と費用の条件に時間を割けていません。
根拠：料理運搬では2人にできないことは前回の結論で、今回はS012でも説明済みです。結論の先出し、目次、一言の要約、本説明、まとめでも反復しています。
修正案：「前回、料理を運ぶだけでは、2人にすると片付けと案内が追いつきませんでした。今回は、スタッフがまとめた皿も運ばせます。それでも2台では、人手が原因の待ち時間が13.3分で、10分の線を超えました。では、食事中に皿を減らしておいたら、どうなるか。」
この形に縮め、本人の経験を残すならS040〜S041を短く差し込めます。

---

数値の検算結果は次のとおりです。**以下は公開画面との照合ではなく、ローカルHTMLとの照合結果**です。

| 対象 | 確認結果 |
|---|---|
| S035〜S037 | 料理57.9→53.5秒、入店8.581→14.262分、人手待ち13.238分。台本の丸めと一致 |
| S042〜S043 | 人手待ち13.257分。13.3分と一致 |
| S044 | 料理運搬6台でも人手待ち14.165分で線を超える |
| S049〜S051 | 2台10.475分、3台の入店7.543分・料理51.7秒。4〜6台も判定対象は10分未満 |
| S053 | 1人あたり3.884→2.465km。台本と一致 |
| S056 | 混雑時の巡回方式の最少人数は、0〜6台で4・3・3・3・3・3・3人 |
| S073 | 3人・料理運搬2台の入店待ち3.156分。3.2分と一致 |
| S023〜S024・S061〜S065 | 人件費141,240円、借用等216,000円、差額−74,760円 |
| S067〜S069 | 安い借用＋15,240円、時間倍増＋66,480円、補助後の単純回収35.6か月。算術は一致 |

S043の「ハコブくんも卓は拭けません」は、事実説明との区切りが明確で、**冗談自体を削除する必要はありません**。S054の但し書きは必要ですが、上記のとおり、実際に置いた回収条件まで具体化する必要があります。

1. **このまま公開してよいか：直してから。**
2. **公開前に必ず直す文番号：** S003・S004・S014・S021・S022・S047・S052・S054・S057・S061〜S064・S069〜S071・S074・S083〜S085。特に、回収の仮定、店全体の作業負担、給与支払いへの換算は省略できません。
3. **結論そのもの：条件つきで成立。** 「このモデル、この作業分担、10分の線なら、3〜6台で必要なホール人数が3人から2人になる」「指定の費用条件なら月74,760円の持ち出し」は成立します。**実店舗で3台あれば1人分の給与を減らせること、ロボットが人1人分を丸ごと代替することは、まだ成立していません。**
```

### 2回目は「別の条件の費用を結びつけていた」を見つけた

2回目で必ず直すように言われたのは4か所でした。料理の時間は「料理ができてから卓に届くまで」と言う（注文から届くまでと取り違えないように・2か所）、補助金は条件を満たして受け取れた場合で、導入をきっかけに解雇すると対象外や返還になる条件があると言う、そして、人を減らさずに3人＋2台にする話のすぐあとに「月7.5万円」を置いていた所です。3人のまま2台足すなら、費用は月14.4万円の追加で、月7.5万円は「1人減らして3台」の差し引きでした。

そのほか、線を11分にすると2台で足り、持ち出しは月約3,000円になること、導入時の設定や研修の費用は入れていないこと、借りる契約でも支援の対象になるものがあること、人が食事中に皿を下げる方法とは比べていないことを足しました。

#### codex_検証結果_2回目.md

```markdown
# codex 敵対的検証 結果 2回目（配膳ロボットで1人減らせるか）

- 日時: 2026-10-25 09:31（JST）
- 依頼文: codex_敵対的検証依頼_配膳ロボットで1人減らせるか.md（md5 219f39a23913e9d1be3c64d291ee0e87・30,692 バイト）
- 題（依頼文の1行目）: # 敵対的検証依頼：YouTube台本「配膳ロボットは「0.5人分」？ ― 1人減らせる条件と、月いくら浮くかを試算した（配膳ロボット導入シミュレーション 第2回）」
- codex: codex-cli 0.163.0-alpha.11
- モデル: gpt-6.1-sol
- 考える深さ: high
- ウェブ検索: あり（検索した回数 16）
- かかった時間: 6分37秒
- 使ったトークン: 127,590
- 指摘の数: 13（うち出典のリンクが付いたもの 4）
- 出典の URL: 4件（別々・文の中に張られた回数 5）

---
判定は**「直してから」**です。新たに見つかった明確な誤りは、**S074で、効果と費用の比較条件が混ざっていること**です。ほかに、補助金の条件と、料理の時間の説明は公開前に直す必要があります。

公開中の試算ページは取得できず、**公開画面で条件を選んだ値との一致は未確認**です。以下の数値確認は、手元の[v2.7 HTML](</Users/shimazueiichi/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/simulation/v2_7/serving-robot.v27.html:406>)の16,425条件と、[v2.7コード](</Users/shimazueiichi/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/simulation/v2_7/haizen_sim.py:302>)によります。シミュレーションの再実行はしていません。

**[❌ NG] S074**  
問題：「3人のままロボット2台」の改善を説明した直後に、別条件の「月7.5万円」を置いています。この改善が月7.5万円で買えるように読めます。  
根拠：月74,760円の持ち出しは、スタッフを1人減らしてロボット3台を使う場合です。3人を維持して2台追加する場合、人件費削減はなく、追加費用は月144,000円です。  
修正案：「人を減らさず、3人にロボット2台を足すと、席に着くまでは8.6分から3.2分に縮みました。歩く距離も減ります。この場合、今回の費用では月14.4万円の追加です。負担やサービスが実際に良くなり、その費用に見合うかは、店で確かめて決めることになります。」

**[⚠️ 要注意] S070**  
問題：補助金の説明に、「人を減らす」という今回の主題に直接関わる制度条件が抜けています。また、補助率が1/2以下であることだけでは、375万円受給できる裏付けにはなりません。  
根拠：現行公募要領の18〜19ページには、導入を契機とする積極的な解雇の制限と、人員整理・解雇によって返還が生じる場合が記載されています。7ページには製品ごとの補助上限もあります。**配置人数を減らすだけで直ちに対象外になる、という意味ではありません。** [公式公募要領](https://shoryokuka.smrj.go.jp/assets/pdf/application_guidelines_catalog.pdf)  
修正案：「補助対象の機種で、申請条件と製品ごとの上限を満たし、375万円を受け取れれば、自己負担は375万円です。ただ、導入をきっかけに従業員を解雇する場合には、補助対象外や返還になる条件があります。ここで比べる配置人数と、解雇は分けて考える必要があります。」

**[⚠️ 要注意] S034・S050**  
問題：「料理が58秒で届く」の起点が、台本中で説明されていません。注文してから届くまで、と誤解される数字です。  
根拠：コードの料理待ちは、調理が終わって`deliver`に入った時刻から、卓に到着するまでです。調理時間は別に発生しています。  
修正案：S034を「料理ができてから卓に届くまでは、3人・ロボットなしの58秒に対して、2人・ロボット2台で54秒。ほとんど変わりません。」、S050を「料理ができてから届くまでも、58秒から52秒になりました。」

**[⚠️ 要注意] S051・S066・S085**  
問題：10分の線で必要台数が変わることは説明されていますが、**採算の見え方も大きく変わる**ことが伝わっていません。月7.5万円の持ち出しを結論にする動画では、費用までつなぐ価値があります。  
根拠：線を11分にして2台を採用すると、ロボット費用は月144,000円。人件費141,240円との差は、月2,760円の持ち出しです。線を緩めることが実店舗で妥当かは、別の判断です。  
修正案：S051の末尾に「同じ費用で計算すると、2台なら持ち出しは月約3,000円です。必要台数だけでなく、お金の答えも、この線に左右されます。」

**[⚠️ 要注意] S021・S062・S068・S070**  
問題：未計上の作業は明記されましたが、それを担うために増える支払いと、人件費削減額との関係がまだ離れています。「ホールで1人減った」と「店全体で14.1万円減った」の間には、条件が残ります。  
根拠：料理の積み込みや回収食器の荷降ろしを、追加の勤務時間で処理すれば、その支払いが差し引かれます。特にS068のプラス15,240円は、時給1,177円で月約13時間の追加支払いがあれば消える幅です。既存勤務内で吸収できるなら、この追加支払いは発生しません。  
修正案：S062に「料理を載せる人や、皿を降ろす人の勤務を増やさず、店全体の給与支払いを月120時間分減らせた、と仮定します。」

**[⚠️ 要注意] S064〜S071**  
問題：月額費用と本体価格の仮置きは明確になりましたが、導入時の設定・教育などの費用が計算に入っていないことは、説明されていません。「約3年」は、それらも含めた回収期間にはなっていません。  
根拠：費用の式に入るのは、借用料または本体代、補助金、保守、充電です。初期設定、教育に使う勤務時間、導入に伴う設備変更などの欄はありません。  
修正案：「導入時の設定や研修、必要になった店の改装などの費用は、この計算には入れていません。買う場合の約3年も、それらを除いた単純な計算です。」

**[⚠️ 要注意] S064・S070〜S071**  
問題：借用は補助なし、購入は補助ありという比較自体は可能ですが、借りる契約にも支援対象になるものがあることが抜けています。購入だけの利点だと受け取られる余地があります。  
根拠：現行公募要領の16ページには、条件を満たすファイナンス・リースと、年額借料で登録された製品の賃貸借に関する規定があります。今回の機種・契約が対象になるかは未確認です。 [公式公募要領](https://shoryokuka.smrj.go.jp/assets/pdf/application_guidelines_catalog.pdf)  
修正案：「借りる方は、補助金なしで計算しています。借りる契約でも支援対象になるものがあるので、実際の比較では契約ごとに確かめる必要があります。」

**[⚠️ 要注意] S077〜S078**  
問題：見立てへの最も強い反論は、「効いたのはロボットそのものより、客に皿をまとめてもらい、食後の仕事を減らしたことではないか」です。今回の比較だけでは、ロボットを使う方法が最善だとは分かりません。  
根拠：比較した条件には、人による食事中の下げ膳、客が返却場所へ持っていく方式、仕事の優先順位を変えた方式がありません。S052は客の寄与を説明していますが、代替方法との比較は残っています。  
修正案：S077の本人の言葉は残し、S078の後に「ただ、人が食事中に皿を下げたり、お客さんに返却してもらったりする方法とは、比べていません。ロボットを使うのが一番よいかは、別の問いです。」

**[⚠️ 要注意] S054・S082**  
問題：客が「皿を載せた割合」だけでは、今回の回収の仮定を確かめられません。1枚載せてもらうことと、退店後の下げ膳が不要になることは、違います。  
根拠：コードは回収回数を数え、2回成功すれば残りの下げ膳往復をゼロにします。実際の皿の枚数・大きさ・残量は追っていません。  
修正案：「お客さんが皿を載せた割合に加えて、退店後にどれだけ皿が残ったか、人が何往復したか、片付けが何秒短くなったかも数える必要があります。」

**[⚠️ 要注意] S003**  
問題：「本当に、無理なのか」は、冒頭の店の人が「配置を1人減らすのは無理」と断言したようなつなぎです。その発言から、複数台と運用変更を組み合わせた配置削減の可否までは導けません。  
根拠：確認できたMRT公式記事は、運べないときにロボットが助けるという文脈です。S075で比較不能と説明しても、冒頭では反証対象の範囲を広げています。 [MRT公式記事](https://newsdig.tbs.co.jp/articles/mrt/32630?display=1)  
修正案：「では、使い方や台数を変えたら、ホールの配置を1人減らせる場合はあるのでしょうか。」

**[⚠️ 要注意] S020・S034**  
問題：検証依頼にはある「1往復で最大3つ」の設定が、読み上げ台本では抜けています。同じ数字を再現するための条件として、一度は示した方がよいです。  
根拠：ローカルHTMLの初期設定と今回の検算は`trays=3`です。1つずつ運ぶ設定では、個々の待ち時間が変わります。  
修正案：「料理は、1往復で最大3つまでまとめて運ぶ設定です。」

**[⚠️ 要注意] S053**  
問題：「送り出すまでの距離」では、退店後の片付けまで含む集計だと伝わりません。また、これは各スタッフを個別に追った距離ではなく、総歩行距離を人数で割った値です。  
根拠：コードは全処理が終わるまでのスタッフ総歩行距離を、スタッフ数で割っています。  
修正案：「スタッフ1人あたりの歩く距離も、平均3.9キロから2.5キロに減りました。2時間に来たお客さんの、退店後の片付けまでを含む距離です。」

**[⚠️ 要注意] S027〜S032・S044〜S045・S060〜S061**  
問題：結論の先出し、目次、節タイトル、「一言で言うと」が重なっています。前回の説明も含め、今回追加した重要な条件説明より、構成案内に時間を使っています。  
根拠：S022〜S026ですでに結果と費用を説明し、S027〜S031で再度予告しています。各節でも問いと答えを繰り返しています。  
修正案：S027〜S031を「まず、料理を運ぶだけでは残った仕事を見ます。次に、食事中の皿の回収。そして、費用です。」にまとめ、S032・S044・S060の読み上げは省く構成を勧めます。

前回の主要指摘については、回収2回で残皿ゼロになる設定、積み込み・荷降ろしの未計上、2時間限定シフトの未検証、混雑時の4人→3人、補助前の支払い、補助なし約6年、10分の線への依存、平均のばらつき、空の店からの開始、長時間故障・充電の除外が、今回は説明されています。これらを未修正として再度NGにする理由はありません。

数値と出典の確認結果は次のとおりです。

| 対象 | 確認結果 |
|---|---|
| S034〜S036 | 調理後57.9→53.52秒、入店8.581→14.262分、人手待ち13.238分。丸めは一致 |
| S041 | 人手待ち13.257分。13.3分で一致 |
| S048〜S050 | 2台の人手待ち10.475分、3台の入店7.543分、料理51.72秒。4〜6台も人手待ち10分未満 |
| S053 | 1人あたり3.884→2.465km。一致 |
| S057 | 混雑時の巡回方式は、0台で最少4人、1〜6台で最少3人。一致 |
| S074 | 3人・料理運搬2台の入店3.156分は一致。結び付けた費用が別条件 |
| S023〜S024・S062〜S066 | 人件費141,240円、ロボット216,000円、差額−74,760円。一致 |
| S068〜S071 | ＋15,240円、＋66,480円、補助あり35.63か月、なし71.27か月。算術は一致 |

S063の1,177円は、指定のJILPT記事にある**2026年度改定額の全国加重平均**と一致します。記事では各地の順次発効も説明されています。 [JILPT](https://www.jil.go.jp/kokunai/blt/backnumber/2026/10/special_03.html)

S046〜S047の食べ放題での巡回回収と下膳専用運用は、メーカーの一次資料で確認できました。ただし、料理も運ぶファミレスでの再現性を裏付ける事例ではありません。 [ソフトバンクロボティクス導入事例](https://www.softbankrobotics.com/jp/product/delivery/cases/kamimura/)

S001〜S002の発言の趣旨はMRT公式記事と整合します。**指定YouTubeの音声・文字起こしの逐語照合は未確認**です。今回、提供された文字起こしを誤りと判断する根拠はありません。

S042の「ハコブくんも、卓は拭けません」は、事実説明との区切りが明確です。この一言が但し書きを弱めるとは判断しません。

1. **このまま公開してよいか：直してから。** 全体の作り直しは不要です。
2. **公開前に必ず直す文番号：S034・S050・S070・S074。** 加えて、公開ページとローカルv2.7の一致は、公開画面で最終照合が必要です。S051の費用感度の補足も強く勧めます。
3. **結論そのもの：条件つきで成立。** このモデル・回収設定・10分の線なら、必要なホール人数が3人から2人になり、指定の費用条件なら月74,760円の持ち出しになります。実店舗で同じ配置と給与削減を実現できること、ロボットを使う方法が最善であることまでは、示していません。
```


## 声は16分29秒あり、13文を抜いて13分35秒にした

台本を確かめてもらったあと、Mac で ElevenLabs のハコブくんの声を93文ぶん作りました。長さを測ると16分29秒で、目安の上限（13〜14分）を2分半ほど超えていました。声を作り直さずに、次の13文を抜く案を出し、そのまま決まりました。

| 抜いた文 | 中身 | 秒 |
|---|---|---|
| S013 | 1回目からの続きを言う文 | 9 |
| S025・S026 | 「割に合わないと言いたいわけじゃない…」 | 18 |
| S038 | 「空いた卓には皿が残ったまま…」 | 11 |
| S047 | 食べ放題の店の事例 | 14 |
| S051 | 「2台の10.5分は線のすぐ上…」（お金の章に同じ話がある） | 12 |
| S052 | 「食事中に皿が減っていくので…」 | 10 |
| S053 | 歩く距離 3.9→2.5キロ | 12 |
| S056 | 「これは40回の平均です」 | 8 |
| S061 | 3つ目の章の「一言で言うと」 | 7 |
| S073 | 設定・研修の費用は入れていない／2時間だけのシフトは試していない | 17 |
| S079 | 見立ての中の、結果の繰り返し | 18 |
| S084 | 観察シート | 24 |

codex に必ず直すように言われた文と、本人の言葉の文は、どれも残しています。抜いた設定・研修の費用と観察シートは、概要欄に書きました。声は、番号を付け直した別のフォルダ（voice_eleven/ハコブ_抜き後/）に写し、元の voice_eleven/ハコブ/ は残しています。

抜いたあと、見立ての所で「ただ、」で始まる文が2つ続きました（「ただ、人が食事中に皿を下げたり…」「ただ、導入したばかりなら…」）。2つ目の頭を「それに、」に直し、その1文だけ声を作り直しています。

- ねらい：動画を冗長にしない（細かい説明が続くと視聴者が飽きる）
- 変わったこと：93文・16分29秒 → 80文・13分35秒（書き出した動画の長さ。声の長さと間の合計では13分51秒）
- 見込める効果：最後まで見てもらえる割合が上がる見込み。公開後に YouTube の視聴の続き具合で確かめる

#### voice_lengths_抜き後.txt（抜いたあとの80文の声の長さと、後ろの間・積み上げた時間）

```text
000	S001	hook	6.11	0.35	6.5
001	S002	hook_voice	5.41	1.2	13.1
002	S003	hook_q	5.88	1.2	20.1
003	S004	hook_try	9.40	0.35	29.9
004	S005	hook_found	7.55	1.2	38.7
005	S006	hook_cost	12.59	1.8	53.0
006	S007	title	3.87	0.35	57.3
007	S008	title	6.27	1.2	64.7
008	S009	title_eiichi	10.76	1.8	77.3
009	S010	question	8.12	1.2	86.6
010	S011	series	2.59	0.35	89.6
011	S012	series	11.73	1.2	102.5
012	S013	define	7.55	0.35	110.4
013	S014	define2	5.64	0.35	116.4
014	S015	define2	5.88	0.35	122.6
015	S016	define2	5.88	1.2	129.7
016	S017	define3	20.35	1.2	151.2
017	S018	scope	12.28	0.35	163.9
018	S019	scope	15.65	0.35	179.9
019	S020	scope	12.51	1.2	193.6
020	S021	answer	13.48	0.35	207.4
021	S022	answer_cost	12.75	0.35	220.5
022	S023	answer_cost	4.13	1.2	225.8
023	S024	toc	1.72	0.35	227.9
024	S025	toc	3.55	0.35	231.8
025	S026	toc	3.00	0.35	235.1
026	S027	toc	2.77	0.35	238.3
027	S028	toc	8.52	1.8	248.6
028	S029	c1	5.07	1.2	254.9
029	S030	c1	6.53	1.2	262.6
030	S031	entry	14.52	0.35	277.5
031	S032	entry	6.19	1.2	284.8
032	S033	why	6.61	0.35	291.8
033	S034	why2	11.31	1.2	304.3
034	S035	honne1	9.48	0.35	314.1
035	S036	honne1	7.89	1.2	323.2
036	S037	bus	13.32	0.35	336.9
037	S038	bus	10.61	1.2	348.7
038	S039	c1_end	3.24	1.8	353.8
039	S040	c2	4.68	1.2	359.6
040	S041	c2	5.72	1.2	366.6
041	S042	patrol	8.28	0.35	375.2
042	S043	patrol2	8.28	0.35	383.8
043	S044	patrol3	8.91	1.2	393.9
044	S045	patrol3	9.64	0.35	403.9
045	S046	patrol_note	22.99	0.35	427.2
046	S047	honne2	6.11	1.2	434.6
047	S048	crowd	16.12	0.35	451.0
048	S049	crowd	7.47	1.2	459.7
049	S050	robot_note	14.29	1.8	475.8
050	S051	c3	4.36	1.2	481.4
051	S052	labor	17.48	0.35	499.2
052	S053	labor	13.32	0.35	512.8
053	S054	robotcost	10.19	0.35	523.4
054	S055	robotcost	8.36	0.35	532.1
055	S056	net	7.71	1.2	541.0
056	S057	sens	3.08	0.35	544.4
057	S058	sens	10.76	0.35	555.5
058	S059	sens	16.77	0.35	572.7
059	S060	sens	11.31	0.35	584.3
060	S061	sens_buy	22.13	0.35	606.8
061	S062	sens_buy	19.88	1.2	627.9
062	S063	merit	3.00	0.35	631.2
063	S064	merit	25.08	1.2	657.5
064	S065	shop_back	19.23	1.8	678.5
065	S066	mitate	2.43	1.2	682.2
066	S067	mitate1	6.43	0.35	688.9
067	S068	mitate1	10.19	1.2	700.3
068	S069	honne3	10.27	0.35	711.0
069	S070	honne3	10.68	1.2	722.8
070	S071	mitate_cost	14.29	1.8	738.9
071	S072	answer2	6.53	0.35	745.8
072	S073	answer2	14.11	0.35	760.3
073	S074	answer2	20.04	1.2	781.5
074	S075	question_next	11.23	1.2	793.9
075	S076	next	9.33	1.2	804.5
076	S077	try	9.09	1.8	815.3
077	S078	outro	4.28	0.35	820.0
078	S079	outro	5.80	0.35	826.1
079	S080	outro	4.13	1.2	831.5
合計 831.5秒 = 13分51秒
```


## 画面は1回目と同じ「流れ続ける映像＋黒いカード」

画面の形は、パターン（大文字型と説明型）と動き（ありなし）を選んでもらい、1回目と同じ形に決まりました。背景に試算ページの録画か Unity の店の映像を流し続け、文字は黒い角丸のカードに載せる形です（1回目の作り方は LOG378）。

### 背景に流す試算ページを、この回のために6本録った

1回目の録画は、スタッフ3人のまま台数を増やす操作が中心で、この回の条件（2人・皿を集めて回る・混雑・費用）が映っていません。試算のページをクラウドの作業環境で開き、画面ありのブラウザを仮想の画面（Xvfb）に出して ffmpeg で録る形で、6本を録りました。

| 録画 | 操作 | 使った場面 |
|---|---|---|
| sim_entry2 | 3人・0台 → 2人・2台（料理を運ぶだけ） | 料理を運ぶだけの2人＋2台 |
| sim_bus | 2人・2台：まとめた皿も運ぶ | まとめた皿も運ぶ使い方 |
| sim_patrol6 | 2人・皿を集めて回る：1台 → 6台 | 台数ごとの棒・結論の前の場面 |
| sim_crowdp | 混雑・皿を集めて回る3台：2人 → 3人 | 混雑の日 |
| sim_cut | 「スタッフを1人減らして」の比べ | 冒頭近く |
| sim_cost | 費用の欄：3台 → 月3万円 → 4時間 → 買う・補助金 | 費用の章 |

【画像】LOG382_02_sim_recordings.jpg 6本の試算ページの録画を、それぞれ6コマずつ並べた一覧。上から、料理を運ぶだけの2人＋2台、まとめた皿も運ぶ、皿を集めて回る1〜6台、混雑の日、スタッフを1人減らした比べ、費用の欄

費用の欄の録画は、1本目では見出しの文字を探す処理がページの上の別の文字に当たり、最初の数秒がページの頭のままでした。費用の欄の要素（#cost）の位置で移るように直して録り直しています。録画は場面より短いと頭に戻ってしまうので、どれも最後のコマを60秒延ばしました。費用の表が出ている所だけを切り出して延ばしたもの（costhold）と、月3万円・4時間に切り替える所を切り出したもの（costsens）も作っています。

#### src/rec_背景の録画.py

```python
# 第2回「配膳ロボットで1人減らせるか」の背景の録画（試算 v2.7 のページをローカルで開いて録る）
# 使い方: p2m-site/public/sim で python3 -m http.server 8765 を動かし、xvfb-run -s '-screen 0 1920x1400x24' python3 rec2.py [名前 ...]
# 第1回の src/rec_背景の録画.py を写して書き換えた（2026-10-25）。ページは p2m-site public/sim/serving-robot.html（md5 88adf2b2・v2.7）
import asyncio, sys, os, subprocess
from playwright.async_api import async_playwright
URL = 'http://localhost:8765/serving-robot.html'
CUR = """(() => { if (document.getElementById('fakecur')) return;
 const c=document.createElement('div'); c.id='fakecur';
 c.style.cssText='position:fixed;left:960px;top:700px;width:34px;height:34px;margin:-17px 0 0 -17px;border-radius:50%;background:rgba(240,90,40,.35);border:3px solid #F05A28;z-index:99999;pointer-events:none;transition:left .7s ease, top .7s ease, transform .15s';
 document.body.appendChild(c);})()"""
async def cur_to(pg, loc):
    await loc.scroll_into_view_if_needed()
    bb = await loc.bounding_box(); x, y = bb['x']+bb['width']/2, bb['y']+bb['height']/2
    await pg.evaluate(f"(()=>{{const c=document.getElementById('fakecur');c.style.left='{x}px';c.style.top='{y}px'}})()")
    await pg.wait_for_timeout(800)
async def click(pg, loc, wait=1400):
    await cur_to(pg, loc)
    await pg.evaluate("(()=>{const c=document.getElementById('fakecur');c.style.transform='scale(.7)';setTimeout(()=>c.style.transform='',150)})()")
    await loc.click(); await pg.wait_for_timeout(wait)
async def scroll_to(pg, y, ms=1200):
    await pg.evaluate(f"window.scrollTo({{top:{y},behavior:'smooth'}})"); await pg.wait_for_timeout(ms)
async def ytext(pg, text):
    return await pg.evaluate(f"(()=>{{const w=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);let n;while(n=w.nextNode()){{if(n.textContent.trim().startsWith({text!r})){{const r=n.parentElement.getBoundingClientRect();return r.top+window.scrollY}}}}return 0}})()")
async def seg(pg, sid, v, wait=1500):
    inp = pg.locator(f'#{sid} input[value="{v}"]')
    if await inp.count():
        await click(pg, pg.locator(f'#{sid} label[for="' + (await inp.get_attribute('id')) + '"]'), wait)
    else:
        await click(pg, pg.locator(f'#{sid} button.more'), 900)
        await click(pg, pg.locator(f'#{sid}-panel button[data-v="{v}"]'), wait)
async def nth(pg, sid, i, wait=1500): await click(pg, pg.locator(f'#{sid} label').nth(i), wait)
async def mode(pg, i, wait=1500): await click(pg, pg.locator(f'#modes label[for="mode-{i}"]'), wait)
RS, ST = 'seg-robots', 'seg-staff'
RES = 600

async def clip(name, fn):
    os.makedirs('out', exist_ok=True)
    async with async_playwright() as p:
        b = await p.chromium.launch(headless=False, args=['--window-position=0,0','--window-size=1920,1300','--hide-scrollbars','--force-device-scale-factor=1'])
        ctx = await b.new_context(no_viewport=True); pg = await ctx.new_page()
        await pg.goto(URL, wait_until='networkidle')
        await pg.add_style_tag(content='html{scroll-behavior:auto} ::-webkit-scrollbar{display:none}')
        await pg.evaluate(CUR); await pg.wait_for_timeout(1200)
        top = await pg.evaluate('window.outerHeight-window.innerHeight'); ih = await pg.evaluate('window.innerHeight')
        if ih < 1080: raise SystemExit(f'inner {ih}')
        pre = getattr(fn, 'pre', None)
        if pre: await pre(pg)
        rec = subprocess.Popen(['ffmpeg','-v','error','-y','-f','x11grab','-framerate','30','-video_size','1920x1080','-draw_mouse','0','-i',os.environ.get('DISPLAY',':99')+f'.0+0,{top}',
                                '-c:v','libx264','-preset','veryfast','-crf','14','-pix_fmt','yuv420p',f'out/{name}.mp4'], stdin=subprocess.PIPE)
        await pg.wait_for_timeout(700); await fn(pg); rec.communicate(b'q')
        await ctx.close(); await b.close(); print('done', name, flush=True)

def pre_scroll(y):
    async def f(pg): await pg.evaluate(f"window.scrollTo(0,{y})"); await pg.wait_for_timeout(600)
    return f

async def c_entry2(pg):        # 3人・0台 → 2人・2台（料理を運ぶだけ）
    await seg(pg, RS, 0, 2200); await seg(pg, ST, 2, 1600); await seg(pg, RS, 2, 3000)
c_entry2.pre = pre_scroll(RES)
async def c_bus(pg):           # 2人・2台：まとめた皿も運ぶ
    await seg(pg, ST, 2, 1500); await mode(pg, 1, 3500)
c_bus.pre = pre_scroll(RES)
async def c_patrol6(pg):       # 2人・食事中に集めて回る：1→6台
    await seg(pg, ST, 2, 1200); await mode(pg, 2, 1500)
    for n in (1, 2, 3, 4, 5, 6): await seg(pg, RS, n, 1700)
    await pg.wait_for_timeout(1200)
c_patrol6.pre = pre_scroll(RES)
async def c_crowdp(pg):        # 混雑・集めて回る・3台：2人 → 3人
    await nth(pg, 'seg-arr', 2, 1500); await mode(pg, 2, 1500); await seg(pg, RS, 3, 1500)
    await seg(pg, ST, 2, 2600); await seg(pg, ST, 3, 2600)
c_crowdp.pre = pre_scroll(RES)
async def c_cost(pg):          # 費用の欄：集めて回る・3台 → 月3万円 → 4時間 → 買う・補助金
    await mode(pg, 2, 1000); await seg(pg, RS, 3, 1000)
    y = await pg.evaluate("document.getElementById('cost').getBoundingClientRect().top+window.scrollY")
    await scroll_to(pg, y-20, 2200); await pg.wait_for_timeout(3500)
    await nth(pg, 'seg-cprice', 0, 3200); await nth(pg, 'seg-cprice', 1, 1500)
    await nth(pg, 'seg-chours', 1, 3200); await nth(pg, 'seg-chours', 0, 1500)
    await nth(pg, 'seg-cpay', 1, 2000); await nth(pg, 'seg-csub', 1, 3500)
    await scroll_to(pg, y-20, 1500); await pg.wait_for_timeout(2500)
async def c_cut(pg):           # 「スタッフを1人減らして」の比べ：集めて回る・3人 → ロボット2台・3台
    await mode(pg, 2, 1200)
    y = await pg.evaluate("document.getElementById('ctable').getBoundingClientRect().top+window.scrollY")
    await scroll_to(pg, y-260, 2000)
    await nth(pg, 'seg-crob', 1, 2500); await nth(pg, 'seg-crob', 2, 3500)
CL = dict(entry2=c_entry2, bus=c_bus, patrol6=c_patrol6, crowdp=c_crowdp, cut=c_cut, cost=c_cost)
async def main():
    for k in (sys.argv[1:] or CL): await clip('sim_'+k, CL[k])
asyncio.run(main())
```

### 背景の録画に、台本と違う条件の数字が映っていた

書き出した確認用の動画から場面ごとに1コマずつ取り出して見ると、結論の場面と答えの場面の後ろに、試算ページの「ロボット2台・差し引き −14.4万円」が映っていました。台本は「3台・−7.5万円」です。録画の下のほうに、別の条件の費用の欄が写り込んでいました。この2場面の背景は、皿を集めて回る1〜6台の録画と、費用の表の録画に替えています。背景の録画も、映っている数字を台本と照らす必要がありました。

### 場面ごとの静止画の一覧で、カードの収まりを確かめた

46の場面のカードを、背景の映像の真ん中のコマに重ねて一覧にしました。各場面に、強い動き（大きい文字を叩きつける）か、中くらいか、動きなしかの札を付けています。強い動きは10場面で、続けて置いた所はありません。カードの下の端がハコブくんの区画にかからないかも、書き出す前に確かめています（はみ出したのは「来るたびに必ず載せる」の場面の1つで、補足の行を短くして収めた）。

【画像】LOG382_03_cost_cards.jpg お金の章から最後までの場面の一覧。ロボット3台の月21.6万円、差し引き−7.5万円、前提を変えたときの3行、買う場合、人を減らさずに足した場合、見立て、答え、次の回、の各カード

### 46の場面を2つに分けて並べて書き出した

動きのある場面（46）は、書き出すコマ数がほぼ同じになるよう2組に分け、クラウドの作業環境で並べて動かしました。圧縮の設定を速いもの（veryfast）にした写しを使い、約15分で書き出せています。続けて、背景の断片と字幕・ハコブくんを重ねる書き出し（assemble.py）で、確認用まで作りました。

書き出しの途中で、確認用を作る段（30MB 以下になるまで圧縮の強さを変えて何度も作り直す）に時間がかかったため、途中で止めました。すると、止めた時点の書きかけの断片が壊れたまま残り、次の書き出しでつなぐと、映像が壊れていました。

```text
$ ffmpeg -v error -i out.mp4 -f null - 2>&1 | head -3
[h264 @ 0x558e4c426f80] Invalid NAL unit size (0 > 35916).
[h264 @ 0x558e4c426f80] missing picture in access unit with size 35920
[h264 @ 0x558e4c426f80] Invalid NAL unit size (0 > 35916).
```

背景を差し替えた場面の断片（020・071〜073）を消し、確認用を作る段を外した写しで書き出し直したところ、同じ確かめでエラーは0件でした。確認用は、できあがった本編から1回だけ圧縮して作っています（26.2MB）。

【画像】LOG382_04_youtube_thumbnail.jpg YouTube のサムネイル。Unity で建てた仮のファミレスを斜めから見た画面に「配膳ロボットで スタッフを 1人減らせる？ 試算した」の文字と、右下にハコブくん、吹き出しに「0.5人分？」


## 概要欄・タイトル・サムネイル・X の投稿をそろえた

確認用はそのまま合格になりました。タイトルは3案から「配膳ロボットは「0.5人分」？ 1人減らせる条件と、月いくら浮くか【導入シミュレーション 第2回】」に、サムネイルは前の版の案（スタッフを1人減らせる？）に決まりました。お金の問いを前に出した案（1人減らせたら 月いくら浮く？）も並べましたが、選ばれていません。

アップロード用の本編（crf 20・75MB）は、gzip にしてから18MB ずつに分けて Mac に送り、つないだあとの指紋（md5 ef41cb2d）が送る前と同じことを確かめてから、KIOXIA のアップロード用のフォルダに置きました。前の版のショート3本は v2.4 の数字のままだったので、`ショート/` から `_取り込み/ショート_8版/` に移しています（2回目のショートは作っていない）。

### 概要欄.txt

目次の時間は、書き出した動画の時刻から自動で入れています。1回目の URL は公開予約中のものです。

```text
配膳ロボットを入れたら、ホールのスタッフを1人減らせるのか。減らせたら、月いくら浮くのか。シリーズ「配膳ロボット導入シミュレーション」の2回目です。

ファミレスの混む2時間をパソコンの中で再現すると、スタッフを3人から2人にしても店が回ったのは、ロボットが食事中に席を回って、お客さんに空いた皿を載せてもらう使い方で、3台から6台のときでした。料理を運ぶだけなら、6台でも2人では回りませんでした。
ところが、1人減って浮く人件費（月約14.1万円）より、ロボット3台を借りる費用（月約21.6万円）の方が高く、差し引きは月約7.5万円の持ち出し。借りる値段や、人を減らせる時間しだいで、答えは逆になります。

試算はサイトで、店・人数・台数・使い方・費用の前提を変えて試せます。
https://pixelstomotors.com/series8

▼目次
0:00 「0.5だとか、0.25にはなる」
0:51 この番組について
1:15 今日の問い：1人減らせるのか、月いくら浮くのか
3:09 先に結論
4:02 1. 料理を運ぶだけだと、なぜ1人減らせないのか
5:45 2. 皿を集めて回ると、何が変わるのか
7:04 混雑の日は
7:45 3. 1人減ったら、月いくら浮くのか
8:49 前提を変えると
10:15 お金にしていない変化
11:05 エイイチの見立て
12:04 冒頭の問いへの答え
13:19 エンディング

▼この動画で扱う範囲
・パソコンの中の試算です（Python の SimPy で、お客さんが来てから帰るまでの出来事を時間の順に再現）。数字の多くは、公開されている導入事例やメーカーの仕様をもとにした仮の値で、実際の店で測ったものではありません
・店は35卓のファミレスで、お客さんが1人もいない状態から始め、1時間に35組のペースで2時間だけ受け入れ、片付けが終わるまでを、同じ人数で計算しています。どの条件も40回回した平均で、日ごとのばらつきは示していません
・「店が回らない」は、席は空いているのに片付けや案内を待たせた時間が平均10分以上の条件です。この10分は、比べるためにエイイチが決めた線で、実際の店の営業を決める基準ではありません。満席で待つ時間や料理の遅れは入れていません
・比べているのは、試算に入れたホールの仕事を何人でこなせるかです。料理をロボットに載せる手間、集めた皿を洗い場で降ろす手間、厨房との兼務、休憩は入れていません
・食事中に皿を集めて回る使い方は、ロボットが席に来るたびにお客さんが皿を載せてくれる、と置いています（2回集めると、食べ終わったあとに下げる皿は残らない設定）。デザートやドリンクもロボットが運んでよい前提です
・お金は、料理を載せる人や皿を降ろす人の勤務を増やさずに、実際のシフトで1人分の給料を減らせた場合の仮の計算です。2時間だけ人を減らすシフトが組めるかは試していません。時給は2026年度の最低賃金の全国加重平均（1,177円）で、社会保険料や交通費は入れていません
・ロボットの費用（1台月6万円で借りる・保守月1万円・充電月2,000円・買う場合は1台250万円）は仮に置いた値で、見積もりではありません。導入時の設定や研修の費用は入れていません
・補助金（中小企業省力化投資補助金 カタログ注文型）は、条件を満たして半分を受け取れた場合です。代金は先に払い、補助金はあとから受け取ります。導入をきっかけに従業員を解雇すると、対象外や返還になる条件があります。借りる契約でも支援の対象になるものがあります
・ロボットどうしが細い通路で道を譲り合う時間や、故障・充電で1台が長く使えない場合は入っていません。台数の多い条件は、効果を楽観的に見積もっている可能性があります
・人が食事中に皿を下げる方法や、お客さんに皿を返してもらう方法とは比べていません

▼出典
・宮崎県の飲食店の人の言葉：MRT宮崎放送「人手不足の救世主？「配膳ロボット」宮崎県内でも活躍広がる 2022.4.27（水）」 https://www.youtube.com/watch?v=ZB66Qqu7Twg （映像は使っていません）
・最低賃金（2026年度・全国加重平均 1,177円）：労働政策研究・研修機構 https://www.jil.go.jp/kokunai/blt/backnumber/2026/10/special_03.html
・中小企業省力化投資補助金（カタログ注文型）公募要領 https://shoryokuka.smrj.go.jp/assets/pdf/application_guidelines_catalog.pdf ・申請の流れ https://shoryokuka.smrj.go.jp/catalog/flow/

▼関連する記事（作業ログ）
・試算を作った回：https://pixelstomotors.com/record/serving-robot-simulation-simpy
・店で数える観察シート：https://pixelstomotors.com/record/serving-robot-observation-sheet
・試算を点検した回：https://pixelstomotors.com/record/audit-simulator-before-unity

▼シリーズ「配膳ロボット導入シミュレーション」
・第1回 配膳ロボット何台で店は変わる？（2026年11月9日 公開予定）：https://www.youtube.com/watch?v=Ayq0zDZcaWo

▼この番組について
「フィジカルAI解説｜Pixels to Motors」は、フィジカルAIのニュースや実機の記録から、現場で使える形を考える番組です。
エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。その中で分かったことと、そこから考えた見立てを、案内役のハコブくんがお伝えします。

・ナレーションは AI 音声（ElevenLabs）です。話しているのは Pixels to Motors のキャラクター、ハコブくんです
・BGM は ElevenLabs Music で作った曲、効果音はコードで作った音です
・画面の映像は、サイトの試算ページを操作した録画と、Unity で作った仮のファミレスの映像です

▼ロボットの開発・導入のご相談
メール：pixelstomotors@adaptdesign.jp

▼リンク
Webサイト：https://pixelstomotors.com
GitHub：https://github.com/PixelstoMotors
X：https://x.com/adaptdesignjp
LinkedIn：https://www.linkedin.com/in/eiichi-shimazu

チャンネル登録・高評価もよろしくお願いします。コメントは、エイイチが全部読んでいます。

#フィジカルAI #配膳ロボット #サービスロボット
```

### X は、YouTube の公開予約に合わせて自動で出る

X の文は、r2r2r-content の `sns/VIDEO_serving-robots-one-less_sns_posts.json` に置きました。YouTube で公開予約すると、予定のタスクが公開の時刻で予定表に入れ、URL も入れて出します。最初の文は X の数え方（全角2・URL 23）で296になり、上限の280を超えたので縮めました（251）。push は、手元の写しが古く1回はねられ、取り込み直してから通しています（commit d1c2680）。

#### sns/VIDEO_serving-robots-one-less_sns_posts.json

```json
{
  "meta": {
    "kind": "youtube_video",
    "title": "配膳ロボットで1人減らせるか（配膳ロボット導入シミュレーション 第2回）",
    "youtube_title": "配膳ロボットは「0.5人分」？ 1人減らせる条件と、月いくら浮くか【導入シミュレーション 第2回】",
    "title_match": [
      "配膳ロボット",
      "0.5人分"
    ],
    "seconds": 815,
    "url": "",
    "youtube_id": ""
  },
  "posts": {
    "x_template": "配膳ロボットで、ホールを1人減らせる？\n\nファミレスの混む2時間を試算したら、減らせたのは食事中に皿を集めて回る使い方で3台から。でも借りると、浮く人件費より月7.5万円高い…\n浮かない結果も、ちゃんと見せたいね。\n#配膳ロボット #飲食店\n{url}"
  },
  "note": "YouTube の本編の X 投稿。url と posts.x は tools/sync_youtube_shorts.py が YouTube の公開予約を見て入れる。LinkedIn は動画を直接アップロードする決まりなので入れない（文は iCloud の 動画/配膳ロボットで1人減らせるか/投稿文_X_LinkedIn.txt）"
}
```

#### 投稿文_X_LinkedIn.txt（動画の投稿文。LinkedIn は動画を直接上げ、手で出す）

```text
# 「配膳ロボットは「0.5人分」？ 1人減らせる条件と、月いくら浮くか【導入シミュレーション 第2回】」の投稿文（2026-10-25）
# X は自動で出る（GitHub r2r2r-content の sns/VIDEO_serving-robots-one-less_sns_posts.json。YouTube で公開予約すると、公開の時刻に URL 入りで出る）。手で貼らない。
# LinkedIn のコメント欄の【URL】だけは、公開後に手で入れる。X は140字以内（URL は23字で数える）。
# 動画の投稿文は日本語だけ。LinkedIn は動画を直接アップロードする。本文に動画の URL は入れず、最後はチャンネルへのリンク。YouTube 版の URL はコメント欄の補足にだけ書く。

────────────────────────
■ X
────────────────────────
配膳ロボットで1人減らせるか試算。
減らせたのは、食事中に皿を集めて回る使い方で3台から。
でも3台借りると、浮く人件費より月7.5万円高い。
答えは借りる値段と減らせる時間しだい。
【URL】
#R2R2R #PixelsToMotors

────────────────────────
■ LinkedIn
────────────────────────
配膳ロボットで、ホールのスタッフを1人減らせるのか。試算では、減らせる条件は見つかりました。ただ、お金は残りませんでした。

35卓のファミレスの混む2時間を、Python（SimPy）で再現しました。1つの条件を40回計算した平均です。前回は、スタッフ3人のままロボットを0台から6台まで増やし、料理を運ぶだけなら、どの台数でも3人を2人にすると店は回らない、という結果でした。

料理を運ぶだけのロボットで2人＋2台にすると、料理ができてから卓に届くまでは58秒から54秒でほとんど変わらず、お客さんが席に着くまでは8.6分から14.3分に延びました。そのうち13.2分は、席は空いているのに、片付けや案内の手が空かずに待った時間です。

使い方を変えて、ロボットが食事中に席を回り、お客さんに空いた皿を載せてもらうと、3台で席に着くまで7.5分。3人・ロボットなしの8.6分より短くなりました。ただしこれは、ロボットが来るたびにお客さんが皿を載せてくれる、と置いた試算です。混雑の日は、この使い方でも2人では回りません（ロボットなしの4人が3人になる、という意味では1人減ります）。

では、1人減ったら月いくら浮くのか。時給1,177円（2026年度の最低賃金の全国加重平均）で、混む2時間を1日2回、30日分減らせたとすると、月約14.1万円。ロボット3台を1台月6万円で借りると、保守と充電を入れて月約21.6万円。差し引きは月約7.5万円の持ち出しです。

前提を変えると答えは逆になります。月3万円で借りられれば月約1.5万円のプラス、昼と夜に4時間ずつ減らせれば月約6.6万円のプラス。買って補助金で半分を受け取れれば、約3年で取り戻す計算です。どれも、実際のシフトで給料を減らせた場合の仮の計算で、導入時の設定や研修の費用は入れていません。

人を減らせるかは、ロボットに何を受け持たせるかで決まる、と私は見ています。そしてお金については、人件費が浮かない結果もそのまま見せるべきだと考えています。店がロボットを入れる理由は、人件費だけでなく、人手不足やスタッフの負担、サービスにもあるからです。

これはパソコンの中の試算で、実際の店で測ったものではありません。数字の多くは公開されている事例や仕様をもとにした仮の値で、「店が回らない」の線（席は空いているのに待たせた時間が平均10分以上）は私が決めたものです。次の回は、店の図面から Unity で3Dの店を建てて、通路で止まる所を見ていきます。

YouTube のほかの動画: https://www.youtube.com/@PixelstoMotors

────────────────────────
■ LinkedIn コメント欄の補足
────────────────────────
冒頭の言葉：MRT宮崎放送「人手不足の救世主？「配膳ロボット」宮崎県内でも活躍広がる 2022.4.27（水）」。最低賃金：労働政策研究・研修機構。補助金：中小企業省力化投資補助金（カタログ注文型）公募要領。試算はサイトで、使い方・台数・費用の前提を変えて試せます：https://pixelstomotors.com/series8 全部の前提と目次は YouTube 版の概要欄に：【URL】
```


## 公開の前に、サイトの試算が v2.8 に変わっていた

記事にまとめる前にサイトの試算を開き直すと、同じ日の 15:20 に、別の作業（LOG379）で試算が v2.8 に変わっていました。会計をレジで1組ずつさばく作りが入り、レジの数（1つか2つ）を選べるようになっています。標準ファミレスの初めの表示はレジ1つです。動画の数字（v2.7）と、v2.8 のレジ1つ・レジ2つを、同じ条件で並べました。

#### compare_v27_v28_video.py

```python
# 第2回の動画（試算 v2.7）の数字が、サイトの試算 v2.8（2026-10-25 15:20 公開・LOG379）でどうなるかを並べる
# 使い方: python3 compare_v27_v28_video.py <v2.7 の serving-robot.html> <v2.8 の serving-robot.html>
#   v2.7: p2m-site 2bc3cd4 の public/sim/serving-robot.html（md5 88adf2b2）／v2.8: p2m-site add3fe3（md5 e4e4f5b1）
# 標準ファミレス（35卓）・1往復で最大3つ・壊れやすい皿は誰が運んでもよい（試算ページの初めの表示と同じ）
import json, sys

def load(path):
    s = open(path, encoding='utf-8').read()
    i = s.find('const D = ') + len('const D = ')
    D, _ = json.JSONDecoder().raw_decode(s[i:])
    k = D['k']
    rows = [dict(zip(k, x)) for x in D['r']]
    has_reg = 'registers' in k
    idx = {}
    for r in rows:
        key = (r['store'], r['staff'], r['robots'], r['arrivals_per_h'], r['mode'], r['trays'], r['fragile_by'], r.get('registers'))
        idx[key] = r
    return D, idx, has_reg

def find(idx, st, rb, arr, mode, reg):
    key = ('family', st, 0, arr, 'serve', 1, 'any', reg) if rb == 0 else ('family', st, rb, arr, mode, 3, 'any', reg)
    return idx.get(key)

def min_staff(D, idx, rb, arr, mode, reg):
    for st in D['stores']['family']['staff_all']:
        r = find(idx, st, rb, arr, mode, reg)
        if r and r['ng'] == 0:
            return st
    return None

D7, I7, _ = load(sys.argv[1])
D8, I8, _ = load(sys.argv[2])
print('v2.7 model', D7['common'].get('model'), '／ v2.8 model', D8['common'].get('model'),
      '／ v2.8 標準ファミレスのレジの初めの数', D8['stores']['family'].get('registers'), '選べる数', D8['stores']['family'].get('registers_all'))
views = [('v2.7', D7, I7, None), ('v2.8 レジ1', D8, I8, 1), ('v2.8 レジ2', D8, I8, 2)]
conds = [('3人・0台', 3, 0, 35, 'serve'), ('2人・0台', 2, 0, 35, 'serve'),
         ('2人・2台・料理を運ぶだけ', 2, 2, 35, 'serve'), ('2人・2台・まとめた皿も運ぶ', 2, 2, 35, 'bus'),
         ('2人・6台・料理を運ぶだけ', 2, 6, 35, 'serve')] + \
        [(f'2人・{n}台・皿を集めて回る', 2, n, 35, 'patrol') for n in range(1, 7)] + [('3人・2台・料理を運ぶだけ', 3, 2, 35, 'serve')]
print()
print('入店待ち（分）／席は空いているのに待った（分）／店が回らない（1）。v2.8 は後ろに会計の待ち（分）')
print(f"{'条件':<22}" + ''.join(f'{v[0]:>24}' for v in views))
for name, st, rb, arr, mode in conds:
    cells = []
    for _, D, I, reg in views:
        r = find(I, st, rb, arr, mode, reg)
        c = f"{r['entry_wait_mean']:6.2f} / {r['staff_wait_mean']:6.2f} / {r['ng']}" if r else '—'
        if r and 'pay_wait_mean' in r:
            c += f" / 会計 {r['pay_wait_mean']:5.2f}"
        cells.append(c)
    print(f'{name:<22}' + ''.join(f'{c:>34}' for c in cells))
print()
print('店が回る最少のスタッフ（ロボット 0〜6台）')
for arr, crowd in ((35, '普通'), (45, '混雑')):
    for mode, mname in (('serve', '料理を運ぶだけ'), ('bus', 'まとめた皿も運ぶ'), ('patrol', '皿を集めて回る')):
        line = f'{crowd}・{mname:<10}'
        for vname, D, I, reg in views:
            line += f'  {vname}: ' + ','.join(str(min_staff(D, I, n, arr, mode, reg)) for n in range(7))
        print(line)
```

#### compare_v27_v28_video_output.txt

```text
v2.7 model v2.7 ／ v2.8 model v2.8 ／ v2.8 標準ファミレスのレジの初めの数 1 選べる数 [1, 2]

入店待ち（分）／席は空いているのに待った（分）／店が回らない（1）。v2.8 は後ろに会計の待ち（分）
条件                                        v2.7                v2.8 レジ1                v2.8 レジ2
3人・0台                                  8.58 /   7.41 / 0      7.86 /   4.93 / 0 / 会計 10.18      8.83 /   7.97 / 0 / 会計  1.25
2人・0台                                 28.25 /  25.82 / 1     25.54 /  19.54 / 1 / 会計 10.81     25.76 /  23.83 / 1 / 会計  2.65
2人・2台・料理を運ぶだけ                         14.26 /  13.24 / 1     12.70 /   7.75 / 0 / 会計 15.83     14.45 /  13.40 / 1 / 会計  1.77
2人・2台・まとめた皿も運ぶ                        14.30 /  13.26 / 1     11.62 /   7.02 / 0 / 会計 14.04     14.61 /  13.38 / 1 / 会計  1.72
2人・6台・料理を運ぶだけ                         15.37 /  14.16 / 1     12.57 /   7.78 / 0 / 会計 15.48     14.41 /  13.47 / 1 / 会計  1.70
2人・1台・皿を集めて回る                         17.02 /  15.45 / 1     12.68 /   8.39 / 0 / 会計 13.50     16.39 /  14.44 / 1 / 会計  1.56
2人・2台・皿を集めて回る                         11.68 /  10.47 / 1     10.29 /   5.80 / 0 / 会計 12.89     11.99 /  11.09 / 1 / 会計  1.40
2人・3台・皿を集めて回る                          7.54 /   6.85 / 0      6.57 /   3.23 / 0 / 会計 11.18      7.59 /   6.93 / 0 / 会計  1.26
2人・4台・皿を集めて回る                          7.21 /   6.35 / 0      5.19 /   3.03 / 0 / 会計  9.90      7.31 /   6.62 / 0 / 会計  1.26
2人・5台・皿を集めて回る                          9.78 /   8.71 / 0      5.50 /   3.02 / 0 / 会計 10.95      8.69 /   7.92 / 0 / 会計  1.23
2人・6台・皿を集めて回る                          8.77 /   7.56 / 0      6.23 /   3.06 / 0 / 会計 10.50      9.59 /   8.07 / 0 / 会計  1.37
3人・2台・料理を運ぶだけ                          3.16 /   2.35 / 0      2.56 /   0.89 / 0 / 会計  6.74      2.98 /   2.41 / 0 / 会計  0.89

店が回る最少のスタッフ（ロボット 0〜6台）
普通・料理を運ぶだけ     v2.7: 3,3,3,3,3,3,3  v2.8 レジ1: 3,2,2,2,2,2,2  v2.8 レジ2: 3,3,3,3,3,3,3
普通・まとめた皿も運ぶ    v2.7: 3,3,3,3,3,3,3  v2.8 レジ1: 3,2,2,2,2,2,2  v2.8 レジ2: 3,3,3,3,3,3,3
普通・皿を集めて回る     v2.7: 3,3,3,2,2,2,2  v2.8 レジ1: 3,2,2,2,2,2,2  v2.8 レジ2: 3,3,3,2,2,2,2
混雑・料理を運ぶだけ     v2.7: 4,3,3,3,3,3,3  v2.8 レジ1: 3,3,3,3,3,3,3  v2.8 レジ2: 4,3,3,3,3,3,3
混雑・まとめた皿も運ぶ    v2.7: 4,3,3,3,3,3,3  v2.8 レジ1: 3,3,3,3,3,3,3  v2.8 レジ2: 4,3,3,3,3,3,3
混雑・皿を集めて回る     v2.7: 4,3,3,3,3,3,3  v2.8 レジ1: 3,3,2,2,2,2,2  v2.8 レジ2: 4,3,3,3,3,3,3
```

【図解】LOG382_v27_v28_compare.html

レジ1つでは、2人＋ロボット1台でも、どの使い方でも「店が回る」になります。席は空いているのに待った時間は、料理を運ぶだけの2人＋2台で 13.24分（v2.7）から 7.75分（v2.8 レジ1つ）に縮み、そのかわり会計の待ちが約16分あります。会計の列にお客さんがたまる分、片付けと案内を待つ時間が10分の線より短くなる形です（LOG379 でも「レジ1つにすると『店が回らない』がかえって減った」と書いている）。レジ2つでは、動画の結論（料理を運ぶだけでは減らせない・皿を集めて回ると3台から・混雑の日は4人が3人）がそのまま成り立ち、数字も近いです（皿を集めて回る3台で席に着くまで 7.54分 → 7.59分）。

動画は「試算はサイトのシリーズのページで試せます」と案内しています。いまのページを初めの表示のまま開くと、動画と逆の結果が出ます。1回目の動画（11月9日に公開予約）も、同じ v2.7 の数字です。動画を v2.8 のレジ2つの数字に直すか、レジ1つで作り直すか、概要欄で断ってこのまま出すかを選んでもらい、まずは記事を書くことになりました。


## 次の回（第3回）は、図面から建てた3Dの店で通路で止まる所を見る

この回の試算には、ロボットどうしが細い通路で道を譲り合う時間が入っていません（概要欄の「この動画で扱う範囲」にも書いた）。台数の多い条件ほど、効果を楽観的に見ている可能性があります。動画の最後のハコブくんの予告は次の1文です（narration.py の next）。

```text
次の回では、店の図面から3Dの店を建てて、ロボットを走らせます。今日の試算に入っていない、通路で止まる所を見ていきます。
```

3Dの店は、試算と同じ店の形のデータ（p2m-site の public/sim/layouts/）を Unity が読んで建てます。止まる所が分かれば、「3台から2人で回る」という答えが、通路の広さでどこまで動くかを見られます。


## video_rules.md に足したこと（90回目）

動画の制作ルール（video_rules.md）の更新履歴に、この回の1行を足しました。iCloud の `動画/_制作ベース/video_rules.md` とプロジェクトの `claude/video_rules.md` の両方に保存しています。

```text
- 2026-10-25（90回目）: 未公開だった「配膳ロボットで1人減らせるか」を、シリーズ「配膳ロボット導入シミュレーション」第2回として作り直した（13分35秒・パターン2＋動きあり・4-4e の背景映像＋カード）。数字は試算 v2.7。第1回の予告（減らせるか・月いくら浮くか）に合わせ、本編を「料理を運ぶだけでは減らせない → 皿を集めて回ると3台で減る → 浮く人件費より費用が高い（月約7.5万円の持ち出し）」にし、費用の節を足した。台本は別のエージェントに試算のデータで全部の数字を計算し直してもらい（食い違いなし）、codex に2回かけた（1回目22件・2回目13件。どちらも「直してから・条件つきで成立」。指摘は試算のコード haizen_sim.py で確かめた。客が皿を載せる置き方・載せる手間は入っていない・お金はシフトで給料を減らせた場合の仮の計算・補助金の条件と解雇・別条件の費用を結びつけない）。声は16分29秒あり、13文を抜いて13分35秒（voice_eleven/ハコブ_抜き後）。背景の試算ページは、この回のために6本録り直した（src/rec_背景の録画.py・KIOXIA の _取り込み/背景_第2回/）。費用の欄の録画は、表が出ている所を切り出して最後のコマを延ばした物（costhold・costsens）を作って使った。背景の録画に台本と違う条件の数字（2台の −14.4万円）が映っていた場面は、別の録画に替えた（背景の録画も、映っている数字を台本と照らす）。書き出しはクラウドの作業環境で、動きの場面46を2つに分けて並べて書き出した（約15分）。assemble.py を途中で止めると、確認用を作り直す段の書きかけの mp4 が壊れたまま残る（Invalid NAL unit）。止めたときは、壊れた断片（chunks/）を消して書き出し直す。前の版のショート3本は v2.4 の数字なので、KIOXIA の _取り込み/ショート_8版/ に移した（第2回のショートは作っていない・9-0）。タイトルは案A、サムネイルは前の版の案A（エイイチの決定）。X は sns/VIDEO_serving-robots-one-less_sns_posts.json
```


## まだ決めていないこと・確かめていないこと

- 動画（2回目・1回目）を、サイトの試算 v2.8 に合わせるかどうか。レジ2つなら結論は変わらず数字だけ少し動く。レジ1つなら結論が逆になる
- お客さんが食事中に、ほんとうにロボットへ皿を載せてくれるか。試算は「来るたびに載せる」と置いている。事例は食べ放題の店（ロボットは下げる専用）で、料理も運ぶファミレスでの例は見つかっていない
- 料理をロボットに載せる人・集めた皿を降ろす人の手間と、導入時の設定・研修の費用。どれも試算とお金の計算に入っていない
- 宮崎県の飲食店の人の言葉は、YouTube の文字起こしのまま使っている。codex は元の音声を確かめられなかった（公式記事で趣旨は一致）
- 動画の効果（最後まで見てもらえたか・相談につながったか）は、公開後の数字で確かめる


## この記事で作った・直したファイルの全文

### 動画/配膳ロボットで1人減らせるか/narration.py（台本・12版）

```python
# -*- coding: utf-8 -*-
# 台本「配膳ロボットは「0.5人分」？ ― 1人減らせる条件と、月いくら浮くか」— シリーズ「配膳ロボット導入シミュレーション」第2回（/series8 の試算が元の解説回）
#   2026-10-25 12版。全文の声（93文）が16分29秒だったので、声を作り直さずに13文を抜いた（エイイチが決めた。約13分50秒の見込み）:
#     抜いた文（11版の番号・0から）: 12 今日はその先・24〜25 立場（割に合わないとは言わない）・37 空いた卓には皿が残ったまま・46 食べ放題の事例・50 2台の10.5分は線のすぐ上・
#       51 片付けが軽くなる理由・52 歩く距離・55 40回の平均・60 節3の一言・72 設定や研修の費用／2時間だけのシフト・78 見立ての中の結果の繰り返し・83 観察シート
#     声は voice_eleven/ハコブ_抜き後/ に番号を付け直して写した（元の voice_eleven/ハコブ/ は残す）。間: 11（前回の振り返り）・36（2人で追いつかない）を 1.2秒、82（見立ての終わり）を 1.8秒に
#     設定や研修の費用・観察シートは概要欄で触れる
#     「ただ、」が2文続いたので、68（honne3）の頭を「それに、」にした（エイイチが決めた。--name ハコブ_抜き後 --lines 68 で作り直す）
#   2026-10-25 11版。codex 2回目（「直してから」・作り直しは不要・結論「条件つきで成立」・13件。数字は一致・1回目の主な指摘は直っている）を受けた:
#     - 必ず直す4つ: 料理の時間は「料理ができてから卓に届くまで」と言う（2か所）／補助金は条件を満たした場合・解雇すると対象外や返還の条件がある（公募要領 18〜19ページ）／
#       人を減らさずに3人＋2台を足す場合は、月7.5万円ではなく月14.4万円の追加（別の条件の費用を結びつけていた）
#     - 10分の線を11分にすると2台で足り、持ち出しは月約3,000円（2 × 72,000 − 141,240 ＝ 2,760円）
#     - 浮く人件費は、料理を載せる人・皿を降ろす人の勤務を増やさずに給料を減らせた場合と言う／導入時の設定や研修の費用は入れていない／借りる契約でも支援の対象になるものがある
#     - 見立てのあとに、人が食事中に下げる・客に返してもらう方法とは比べていない（ハコブくんの文。エイイチの言葉は変えない）
#     - 冒頭の問いの言い方（店の人の言葉を「無理」と言い切っていない）・1往復で3つ・歩く距離は1人あたりの平均で帰ったあとの片付けまで・観察シートは残った皿の量も
#     - 採らなかった: 目次と「一言で言うと」を省く構成（チャンネルの型）
#   2026-10-25 10版。codex 1回目（「直してから」・結論「条件つきで成立」・22件。数字の検算は一致）を受けた。指摘は試算のコード（v2_7/haizen_sim.py）で確かめた:
#     - 皿を集めて回る使い方の置き方を具体的に言う（collect_visit は皿の有無や客の拒否を見ずに回収を1回数え、bus は 2−回収数 で人の往復を減らし、0なら皿をまとめる40秒も省く）
#     - ロボットに料理を載せる・集めた皿を洗い場で降ろす人の手間はコードにない（staff_place_s は人が配る時だけ）→ scope で言う
#     - お金は「実際のシフトで1人減らせた場合の仮の計算」・2時間だけ減らすシフトは試していない・4時間は試算の外
#     - 混雑の日も要る人数は1人減る（4→3）。「毎日1人減らせるとは限らない」は外し、給料を減らせるかは来客とシフトで決まる、に
#     - 買う場合は本体750万円・補助金375万円を受け取れれば自己負担375万円・代金は先に払う・補助金なしは約6年（750万÷105,240＝71.3か月）で5年に収まらない
#     - 借りる値段の「相場・真ん中が6万円台」は出典で確かめられないので外し、仮に置いた値と言う（お名前.com の記事は月約3〜10万円）
#     - 「ロボットが1人分を丸ごと受け持てる」は外し、冒頭の実感と試算はそのまま比べられない（3台＋客の協力で要る人数が1人減るか）と言う
#     - 3台は10分の線に左右される（2台 10.5分。線を11分にすれば2台）・「3台以上」→「3台から6台」（調べた範囲）・40回の平均でばらつきは示していない
#     - 空の店から始めることを scope に戻した・故障や充電で1台が長く使えない場合は入っていない・食べ放題の例は下げる専用・料理の遅れは線に入れていない
#     - 節1を縮めた（前回の話の繰り返し・ロボットの載せ方の説明を外した）。人件費以外の変化は「見合うかは店で確かめる」・観察シートは皿を載せた割合も数える必要
#     - 採らなかった: 見立ての「何を受け持たせるかで決まる」の言い換え（エイイチの言葉なのでそのまま。続くハコブくんの文で「人の仕事をどう組み直すか」を足した）／
#       時給の差し引きゼロの計算（1,800円）・料理の遅れが悪化する混雑の例（冗長）／宮崎の言葉は、エイイチが渡した YouTube の文字起こしのまま（codex は音声を取得できず未確認）
#     - 2台を借りる場合: 2 × 72,000 ＝ 144,000円 → 差し引き −2,760円（台本では言っていない）
#   2026-10-25 9版b。別のエージェントの照合（数字の食い違いなし・言い方4つ）を受けて直した: 下げ膳にもは席はあるのに13.3分と言う／
#     皿を集めて回るはデザート・ドリンクもロボットが運んでよい前提と言う／買う場合の約3年は割る数（月約10.5万円）を言う／4時間は試算の外と断る
#   2026-10-25 9版（第2回として作り直し）。エイイチが「未公開の『配膳ロボットで1人減らせるか』を第2回にして、最新の試算の数字に直す」に決めた（2026-10-24）。
#     8版（v2.4 の数字・単発の回）は _旧版/置き換え前_20261025_配膳ロボットで1人減らせるか_第2回化/ に置いた
#     - 数字をすべて試算 v2.7 に直した（料理はまずロボットを待つ決まり）。2人2台・料理を運ぶだけの料理の待ちは 40秒 → 54秒になり、冒頭の「料理は早く届くのに」は成り立たなくなった
#     - 第1回と重なる所を外した: SimPy の説明・3つの使い方の説明の大半・6台のクイズ（第1回 S055）・焼肉の食べ放題と洗い場が遠い店（第1回 S064〜S066）
#     - 第1回の予告（S060「2人とロボット3台で線を下回った。この話は次の回で」・S076「まず、人は減らせるのか、月いくら浮くのか」）に合わせ、
#       本編を「料理を運ぶだけでは減らせない → 皿を集めて回ると減らせる → 減ったら月いくら浮くか」の3つにした。費用の節は新しく足した
#     - 宮崎県の店の人の言葉（0.5・0.25）をフックに移し、費用の節の終わりで呼び戻す
#     - 混雑の日（45組）は、皿を集めて回る使い方でも2人では回らない、を足した（毎日1人減らせるとは限らない）
#     - エイイチの実感（honne1〜3・define2）は8版のまま。費用の見方（mitate_cost）は、エイイチの言葉（2026-10-23）
#       「店がロボットを入れる目的は人件費を下げることだけでなく、人手不足の解消・スタッフの作業軽減・店舗のサービス向上もある。人件費が浮かない結果も正直に見せる」から
#     - 8版のかみむら牧場・2回集めると食後にまとめる手間がなくなる計算・観察シートのボタンの説明・Warpify は外した（冗長・v2.7 で確かめ直していない）
#   数字の出どころ: サイトの試算 v2.7（p2m-site の public/sim/serving-robot.html に埋め込みの結果・16,425条件×40回。2026-10-25 に読んだ。p2m-site 2bc3cd4）
#     条件は試算ページの既定と同じ「普通の混み具合・1往復で最大3つ・壊れやすい皿は誰が運んでもよい」（servingSim.ts の find と同じ）
#     入店待ち＝entry_wait_mean／席はあるのに待った＝staff_wait_mean／料理＝dish_wait_mean／歩く距離＝walk_km_per_staff
#     - 標準ファミレス（35卓・35組/時）3人0台: 入店 8.58分（席はあるのに 7.41）・料理 0.965分（58秒）・歩く 3.88km
#     - 2人2台 料理を運ぶだけ: 入店 14.26（13.24）・料理 0.892分（54秒）→ 店が回らない
#     - 2人2台 下げ膳にも: 入店 14.30（13.26）→ 回らない。2人6台 料理を運ぶだけ: 15.37（14.16）→ 回らない
#     - 2人 皿を集めて回る 1〜6台: 入店 17.02/11.68/7.54/7.21/9.78/8.77・席はあるのに 15.45/10.47/6.85/6.35/8.71/7.56（3台から回る）
#       3台: 料理 0.862分（52秒）・歩く 2.46km
#     - 混雑（45組/時）店が回る最少のスタッフ（皿を集めて回る）0〜6台: 4/3/3/3/3/3/3（2人ではどの台数でも回らない）
#     - 3人2台 料理を運ぶだけ: 入店 3.16分（第1回の 3.2分）
#     - 費用（試算ページ・servingSim.ts の COST の既定）: 1台 月6万円で借りる・保守 月1万円（仮置き）・充電 月2,000円・時給 1,177円（2026年度の最低賃金の全国加重平均）
#       浮く人件費＝減った人数 × 2時間（ピーク）× 1日2回 × 30日 × 1,177円 ＝ 141,240円（月約14.1万円）。4時間なら 282,480円
#       3台借りる: 3 ×（60,000＋10,000＋2,000）＝ 216,000円 → 差し引き −74,760円（約7.5万円の持ち出し）
#       1台 月3万円: 126,000円 → ＋15,240円／4時間ずつ: 282,480 − 216,000 ＝ ＋66,480円
#       買う（1台250万円・補助金で1/2）: 初めに 375万円・375万 ÷（141,240 − 保守と充電 36,000 ＝ 105,240）＝ 35.6 → 約36か月（5年で割った月の差し引きは ＋42,740円。並べると取り違えるので台本では言わない）
#     - 皿を集めて回る使い方で2人3台が回るのは「壊れやすい皿は誰が運んでもよい」とき（既定）。人が運ぶ設定では最大3つで3台だけ、最大1つで5台だけが回る（別のエージェントの照合・2026-10-25）
#     - 店が回らない＝席はあるのに待った時間が平均10分以上（LOG359・試算ページの印）。ロボットどうしが細い通路で待つことは試算に入っていない（試算ページの注記）
#   出典（台本の中の事実）:
#     - hook / shop_back: MRT宮崎放送「人手不足の救世主？「配膳ロボット」宮崎県内でも活躍広がる 2022.4.27（水）」（YouTube https://www.youtube.com/watch?v=ZB66Qqu7Twg ・1分12秒〜）
#       店の人「1人にはならないですけれども、0.5だとか0.25にはなるので…」（エイイチが見つけた。映像は使わない）
#     - patrol_ex: 客が皿を載せて回る使い方の事例は焼肉の食べ放題の店（和民・かみむら牧場。LOG351）
#     - robotcost: 借りる値段の相場 月3〜12万円・中央値6万円台（お名前.com ビジネス・試算ページの費用の前提）
#     - labor: 2026年度の最低賃金 全国加重平均 1,177円（労働政策研究・研修機構・試算ページの費用の前提）
#     - sens3: 中小企業省力化投資補助金（カタログ注文型）補助率1/2以下（補助金ポータル・試算ページの費用の前提）
#     - define2: エイイチの言葉（LOG359）
#     - obs: LOG353（観察シート）
# 何の動画か（5行・video_rules.md 2節16）
#   1. 配膳ロボットで、ホールのスタッフを1人減らせるのか。減らせたら月いくら浮くのか（シリーズ2回目・前回は「料理を運ぶだけなら何台でも2人では回らない」）
#   2. 料理を運ぶだけだと、片付けと案内が人に残り、2人では「席は空いているのに入れない」店になる
#   3. 食事中に席を回って皿を集める使い方なら、3台で2人でも回る（7.5分・3人ロボットなしの8.6分より短い）。混雑の日は回らない
#   4. 浮く人件費は月約14万円、3台借りると月約21.6万円で、月約7.5万円の持ち出し。借りる値段・減らせる時間・買うと補助金で、プラスにもなる
#   5. 見立て: 減らせるかは、何を受け持たせるかで決まる。人件費が浮かない結果も見せ、人件費以外の変化と並べて決める
# 話すのはハコブくん。エイイチは三人称で呼ぶ（video_rules.md 3-1）
#
# 各要素: (場面の名前, 表情, 字幕の文, 後ろの間[秒])  間を省略すると 0.35 秒
# 字幕の文の中の「｜」: 1文を読み上げたまま、字幕だけをそこで次の1枚に替える
FACES = ("base", "smile", "surprise", "doubt", "think", "trouble", "joy", "wink")

SEGS = [
 # 0 フック
 ("hook", "base", "配膳ロボットを入れた、宮崎県の飲食店の人は、テレビの取材で、こう話していました。"),
 ("hook_voice", "smile", "「1人にはならないですけれども、0.5だとか、0.25にはなるので」。", 1.2),
 ("hook_q", "doubt", "では、使い方や台数を変えたら、ホールのスタッフを1人、減らせることはあるのか。", 1.2),
 ("hook_try", "think", "そこで、ファミレスの混む時間帯の2時間を、パソコンの中で再現して、スタッフを3人から2人にしても、店が回る条件を探しました。"),
 ("hook_found", "surprise", "条件は、見つかりました。ロボットに、料理だけでなく、食事中の空いた皿も集めさせたときです。", 1.2),
 ("hook_cost", "trouble", "ところが、月いくら浮くかを計算すると、浮く人件費より、ロボットの費用の方が高くなりました。｜ただし、借りる値段や、人を減らせる時間しだいで、答えは逆になります。", 1.8),
 # 1 自己紹介
 ("title", "smile", "Pixels to Motors。案内役のハコブくんです。"),
 ("title", "base", "この番組では、フィジカルAIのニュースや実機の記録から、現場で使える形を考えます。", 1.2),
 ("title_eiichi", "base", "エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。｜その中で分かったことと、そこから考えた見立てを、ハコブくんがお伝えします。", 1.8),
 # 2 今日の問い
 ("question", "surprise", "今日の問いは、配膳ロボットで、ホールのスタッフを1人減らせるのか。減らせたら、月いくら浮くのか、です。", 1.2),
 ("series", "base", "この動画は、シリーズの2回目です。"),
 ("series", "base", "前回は、スタッフ3人のまま、ロボットを0台から6台まで増やしました。｜料理を運ぶだけなら、どの台数でも、3人を2人にすると、店は回りませんでした。", 1.2),
 ("define", "base", "ここで言う「減らせる」は、混む時間帯の2時間に、ホールの人を1人減らしても、店が回ることです。"),
 ("define2", "base", "では、店が回るとは、どういう状態か。エイイチの言葉では、こうです。"),
 ("define2", "smile", "「混んでいても、5分から10分で入れて、席が埋まっている。これは回っている」。"),
 ("define2", "trouble", "「席は余っているのに、スタッフが足りなくて案内できない。これが、回っていない」。", 1.2),
 ("define3", "base", "この試算では、席は空いているのに、片付けや案内を待たせた時間が、平均で10分以上になったら、「店が回らない」と数えます。｜この10分は、エイイチが決めた比べるための線で、実際の店の営業を決める基準ではありません。満席で待つ時間や、料理の遅れは、この線には入れていません。", 1.2),
 ("scope", "base", "前回と同じく、これはパソコンの中の試算です。｜数字の多くは、公開されている導入事例やメーカーの仕様をもとにした仮の値で、実際の店で測ったものではありません。"),
 ("scope", "base", "店は、35卓のファミレス。お客さんが1人もいない状態から始めて、1時間に35組のペースで2時間だけ受け入れ、片付けが終わるまでを計算します。1つの条件を40回計算して、平均を出しています。"),
 ("scope", "base", "比べるのは、試算に入れたホールの仕事を何人でこなせるかです。｜料理をロボットに載せたり、集めた皿を洗い場で降ろしたりする手間や、厨房との兼務、休憩までは入っていません。", 1.2),
 # 3 結論と立場
 ("answer", "base", "先に結論を言うと、この店の普通の日に、スタッフを3人から2人に減らせたのは、食事中に席を回って、お客さんに空いた皿を載せてもらう使い方で、ロボットが3台から6台のときでした。"),
 ("answer_cost", "think", "1人減って浮く人件費は、月約14.1万円。ロボット3台を、1台月6万円で借りると、保守と充電を入れて、月約21.6万円です。"),
 ("answer_cost", "trouble", "差し引きは、月約7.5万円の持ち出しになりました。", 1.2),
 # 4 目次
 ("toc", "base", "大きく3つあります。"),
 ("toc", "base", "料理を運ぶだけだと、なぜ1人減らせないのか。"),
 ("toc", "base", "皿を集めて回ると、何が変わるのか。"),
 ("toc", "base", "1人減ったら、月いくら浮くのか。"),
 ("toc", "smile", "特に3つ目は、人が減っても、お金が残らないことがある、という話です。最後に、エイイチの見立てを話します。", 1.8),
 # 5 節1：料理を運ぶだけだと、なぜ1人減らせないのか
 ("c1", "base", "1つ目、料理を運ぶだけだと、なぜ1人減らせないのか、です。", 1.2),
 ("c1", "base", "一言で言うと、運ぶのはロボットに任せられても、片付けと案内が、人に残るからです。", 1.2),
 ("entry", "base", "前回の、料理を運ぶだけのロボットで、2人にロボット2台。1往復で料理を3つまで運ぶ設定です。｜料理ができてから卓に届くまでは、58秒から54秒で、ほとんど変わりません。"),
 ("entry", "surprise", "そして、店に来てから席に着くまでは、8.6分から14.3分に延びました。", 1.2),
 ("why", "base", "そのうち13.2分は、席は空いているのに、片付けや案内の手が空かずに待った時間です。"),
 ("why2", "think", "食べ終わった卓の皿を下げて拭くのも、入口のお客さんを席へ案内するのも、人です。今回の仕事の順番と運び方では、2人で、そこが追いつきませんでした。", 1.2),
 ("honne1", "think", "ここで、エイイチ自身の経験を1つ。昔働いていたファミレスでも、混む時間に一番手が足りなかったのは、片付けだったそうです。"),
 ("honne1", "smile", "席は空いているのに、片付けが追いつかず、入口でお客さんが待っている。その光景も、実際にあったそうです。", 1.2),
 ("bus", "base", "では、片付けに向かうスタッフが、空いているロボットに、まとめた皿も運ばせたらどうか。ロボット2台で、席は空いているのに待った時間が13.3分。こちらも、線を超えました。"),
 ("bus", "smile", "皿を洗い場まで運ぶのは、ロボットが手伝えます。でも、卓で皿をまとめて、拭くのは人のまま。ちなみに、ハコブくんも、卓は拭けません。", 1.2),
 ("c1_end", "think", "片付けの手が空かないと、人は減らせないんです。", 1.8),
 # 6 節2：皿を集めて回ると、何が変わるのか
 ("c2", "base", "2つ目、皿を集めて回ると、何が変わるのか、です。", 1.2),
 ("c2", "base", "一言で言うと、食べ終わったあとの片付けが軽くなって、2人でも回るようになります。", 1.2),
 ("patrol", "base", "この使い方では、ロボットが食事中に席を回り、お客さんに、空いた皿を載せてもらいます。料理も運びます。"),
 ("patrol2", "base", "この使い方のロボット2台では、席は空いているのに待った時間が10.5分。線を、少しだけ超えました。"),
 ("patrol3", "surprise", "3台にすると、席に着くまで、平均7.5分。スタッフ3人でロボットなしの8.6分より、短くなりました。", 1.2),
 ("patrol3", "smile", "料理ができてから届くまでも、58秒から52秒になりました。調べた6台までは、4台から6台でも、線の内側でした。"),
 ("patrol_note", "base", "ただ、この試算では、ロボットが席に来るたびに、お客さんが皿を載せてくれる、と置いています。｜2回集めれば、食べ終わったあとに下げる皿は残らず、皿をまとめる手間もなくなる設定です。皿が最後まで残る店でも、3台で足りるかは、確かめていません。デザートやドリンクもロボットが運んでよい、という前提でもあります。"),
 ("honne2", "smile", "エイイチいわく、「余裕がある人は載せてくれるけど、載せてくれない人も、一定数いそう」。", 1.2),
 ("crowd", "base", "混み具合でも変わります。1時間に45組来る混雑の日は、この使い方でも、2人では回りませんでした。｜ただ、ロボットなしなら4人要るところが、3人で回ります。要る人数が1人減るのは、混雑の日も同じです。"),
 ("crowd", "think", "日によって要る人数が変わるので、実際に給料を減らせるかは、その日の来客と、シフトの組み方で決まります。", 1.2),
 ("robot_note", "base", "そして、この試算には、ロボットどうしが細い通路で道を譲り合う時間や、故障や充電で1台が長く使えない場合は、入っていません。台数の多い条件は、効果を楽観的に見積もっているかもしれません。", 1.8),
 # 7 節3：1人減ったら、月いくら浮くのか
 ("c3", "base", "3つ目、1人減ったら、月いくら浮くのか、です。", 1.2),
 ("labor", "base", "ここからは、料理を載せる人や皿を降ろす人の勤務を増やさずに、実際のシフトで1人分の給料を減らせた、とした場合の仮の計算です。｜浮く人件費は、1人分の時給を、混む2時間、1日2回、30日分で数えます。"),
 ("labor", "base", "時給は、2026年度の最低賃金の全国平均、1,177円を借りました。社会保険料や交通費は入れていません。これで、月約14.1万円です。"),
 ("robotcost", "base", "ロボットは、1台を月6万円で借りる、と仮に置きました。実際の値段は、機種や契約期間、保守が含まれるかどうかで変わります。"),
 ("robotcost", "base", "保守を仮に月1万円、充電の電気代を月2,000円足すと、3台で月21.6万円になります。"),
 ("net", "trouble", "差し引きは、月約7.5万円の持ち出しです。1人減らせても、この前提では、お金は残りません。", 1.2),
 ("sens", "base", "ただ、ここは前提で大きく変わります。"),
 ("sens", "base", "1台を月3万円で借りられれば、差し引きは、月約1.5万円のプラスです。今回の仕事ができる機種を、その値段で借りられれば、ですが。"),
 ("sens", "smile", "混む2時間だけでなく、昼と夜に4時間ずつ人を減らせれば、浮く人件費は月約28.2万円になり、月約6.6万円のプラスです。｜ただ、試算は混む2時間だけで、4時間を2人で回せるかは、確かめていません。"),
 ("sens", "base", "それに、10分の線を11分にすれば、ロボットは2台で足り、持ち出しは月約3,000円まで小さくなります。お金の答えも、この線に左右されます。"),
 ("sens_buy", "base", "買う場合は、1台250万円で、3台なら750万円。補助金の条件を満たして、半分の375万円を受け取れれば、自己負担は375万円です。｜保守と充電を引いても、浮く人件費が月約10.5万円残るので、自己負担を取り戻すのに、約3年かかる計算です。"),
 ("sens_buy", "think", "補助金がなければ、約6年。今回置いた、5年使う前提には、収まりません。｜代金は先に払い、補助金はあとから受け取る仕組みで、導入をきっかけに従業員を解雇すると、対象外や返還になる条件もあります。借りる契約でも、支援の対象になるものがあります。", 1.2),
 ("merit", "base", "そして、お金にしていない変化もあります。"),
 ("merit", "base", "人を減らさずに、3人にロボット2台を足すと、前回見たとおり、席に着くまでは8.6分から3.2分に縮みました。｜歩く距離も減ります。この場合は、今回の費用で、月14.4万円の追加です。｜スタッフの負担やサービスが実際に良くなり、その費用に見合うかは、試算では測っていません。店で確かめて決めることになります。", 1.2),
 ("shop_back", "think", "冒頭の、「0.5だとか、0.25にはなる」という実感と、今回の試算は、そのままは比べられません。｜今回見たのは、ロボット3台と、お客さんの協力を合わせて、要るホールの人数が1人減るか、です。ロボット1台が何人分か、ではありません。", 1.8),
 # 8 見立て
 ("mitate", "base", "ここからは、エイイチの見立てです。", 1.2),
 ("mitate1", "think", "人を減らせるかは、ロボットに何を受け持たせるかで決まる。エイイチは、そう見ています。"),
 ("mitate1", "think", "ただ、人が食事中に皿を下げたり、お客さんに返してもらったりする方法とは、比べていません。ロボットを使うのが一番よいかは、別の問いです。", 1.2),
 ("honne3", "base", "それに、導入したばかりなら、スタッフも慣れる時間が要ります。いきなり手間のかかる作業を任せるより、まず仕事を絞って始めることにも意味がある。"),
 ("honne3", "think", "だから今、料理を運ぶ、皿を下げる、と仕事を限ったロボットの使い方が、わりと広がっているんだろう。エイイチは、そうも考えています。", 1.2),
 ("mitate_cost", "base", "お金については、人件費が浮かない結果も、そのまま見せるべきだと、エイイチは考えています。｜店がロボットを入れる理由は、人件費だけでなく、人手不足や、スタッフの負担、サービスにもあるからです。", 1.8),
 # 9 問いへの回答・まとめ
 ("answer2", "base", "じゃあ、冒頭の問いに答えますね。配膳ロボットで、ホールのスタッフを1人減らせるのか。"),
 ("answer2", "think", "今回の35卓のファミレスの普通の日なら、食事中に皿を集めて回る使い方で、3台から6台のときに、要るホールの人数が1人減りました。料理を運ぶだけなら、6台でも減りませんでした。"),
 ("answer2", "base", "月いくら浮くのか。1台月6万円で3台借りて、混む2時間を1日2回減らせたとすると、月約7.5万円の持ち出し。借りる値段や、減らせる時間しだいで、プラスにもなります。｜お客さんの協力も、止まり方も、シフトの組み方も、仮の前提です。", 1.2),
 ("question_next", "base", "次に配膳ロボットのニュースを見たら、聞いてみてください。そのロボットで、人のどの仕事が減ったのか。そして、残った仕事を、誰が受け持っているのか。", 1.2),
 ("next", "smile", "次の回では、店の図面から3Dの店を建てて、ロボットを走らせます。今日の試算に入っていない、通路で止まる所を見ていきます。", 1.2),
 ("try", "smile", "この試算は、サイトのシリーズのページで、使い方や台数、費用の前提を変えて試せます。リンクは、概要欄に置いておきます。", 1.8),
 # 10 アウトロ
 ("outro", "smile", "この動画が役に立ったら、高評価とチャンネル登録をお願いします。"),
 ("outro", "base", "ロボットの開発や導入の相談は、概要欄の連絡先から、エイイチに直接どうぞ。"),
 ("outro", "wink", "コメントは、エイイチが全部読んでいます。それではまた。", 1.2),
]

# 「エイイチ」を残す文（自己紹介・目次の最後・見立ての入り・アウトロの2文のほかに、名前が要る文）。文の頭で探す（video_rules.md 3-1）
NAME_OK = [i + 1 for i, seg in enumerate(SEGS) if seg[2].startswith((
    "では、店が回るとは、どういう状態か。エイイチの言葉",
    "この試算では、席は空いているのに、片付けや案内を",
    "ここで、エイイチ自身の経験を1つ",
    "エイイチいわく、「余裕がある人は",
    "人を減らせるかは、ロボットに何を受け持たせるかで決まる",
    "だから今、料理を運ぶ、皿を下げる",
    "お金については、人件費が浮かない結果も",
    "そして、お客さんがどれだけ皿を載せてくれるかや",
    "エイイチは、止まり方や片付けの時間を",
))]

# 読み上げ用の読み（仮音声 Open JTalk 用。字幕は元の表記のまま）
READ = [
 ("Pixels to Motors", "ピクセルズ トゥー モーターズ"),
 ("YouTube", "ユーチューブ"),
 ("Unity", "ユニティ"),
 ("フィジカルAI", "フィジカルエーアイ"),
 ("AI", "エーアイ"),
 ("1人", "ひとり"), ("2人", "ふたり"), ("1つ", "ひとつ"), ("2つ", "ふたつ"), ("3つ", "みっつ"),
 ("1,177", "せんひゃくななじゅうなな"), ("2,000", "にせん"),
 ("栄一", "えいいち"),
 ("「", ""), ("」", ""), ("『", ""), ("』", ""), ("｜", ""), ("…", ""),
]

# ElevenLabs の声で読み間違えた語だけ、読みを直す（tts_eleven.py が使う。字幕は変えない）
ELEVEN_READ = [
    ('エイイチ', '栄一'),   # video_rules.md 3-1（2026-10-12 決定）
    ('額だけ', 'がくだけ'),
    ('裏表', 'うらおもて'),
    ('R2R2R', 'リアルツーレンダーツーリアル'),
    ('SIer', 'エスアイヤー'),
    ('ロボットの側', 'ロボットのがわ'),
    ('4コママンガ', 'よんコマまんが'),
    ('OpenAI', 'オープンエーアイ'),
    ('Claude Code', 'クロード コード'),
    ('Claude', 'クロード'),
    ('描く', 'えがく'), ('描き', 'えがき'),
    ('物差し', 'ものさし'), ('力制御', 'ちからせいぎょ'), ('人型', 'ひとがた'),
    ('Mac', 'マック'),
    ('SimPy', 'シムパイ'),
    ('Python', 'パイソン'),
    ('Unity', 'ユニティ'),
    # この回で先回りして足す読み（声を作る前に --try で確かめる）
    ('1,177円', '1177円'),
    ('月2,000円', '月2000円'),
]

# 間延び対策：ひと息が長い文だけ、読み上げ用に読点を足す（字幕は変えない）
OVERRIDE = {
 "エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。｜その中で分かったことと、そこから考えた見立てを、ハコブくんがお伝えします。":
   "エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。その中で分かったことと、そこから考えた見立てを、ハコブくんが、お伝えします。",
}


def reading(t):
    t = OVERRIDE.get(t, t)
    for a, b in READ:
        t = t.replace(a, b)
    return t


def parse(seg):
    """1行を (場面, 表情, 字幕, 間) にそろえる。表情の欄がない古い形 (場面, 字幕[, 間]) も読む"""
    if len(seg) >= 3 and seg[1] in FACES:
        scene, face, text = seg[0], seg[1], seg[2]
        pause = seg[3] if len(seg) > 3 else 0.35
    else:
        scene, face, text = seg[0], "base", seg[1]
        pause = seg[2] if len(seg) > 2 else 0.35
    return scene, face, text, pause
```

### 動画/配膳ロボットで1人減らせるか/scenes.py

```python
# -*- coding: utf-8 -*-
# 動画「配膳ロボットは「0.5人分」？」（シリーズ「配膳ロボット導入シミュレーション」第2回・作業フォルダ名「配膳ロボットで1人減らせるか」）の場面
PATTERN = 2   # 画面パターン2（大文字型・video_rules.md 4-4c）
MOVE = True   # 画面型の動き（4-4d）を強弱を付けて使う（2026-10-25 エイイチが選んだ）
# 2026-10-25: 第1回「何台入れたら店は変わる」の scenes.py（4-4e：背景に映像を長く流し、文字はカード）を写して書いた（エイイチが「第1回と同じ形」を選んだ）
# 背景の映像:
#   src/sim_*.mp4  試算 v2.7 のページを、この回のために録画（src/rec_背景の録画.py。p2m-site public/sim/serving-robot.html・md5 88adf2b2）
#                  entry2: 3人0台→2人2台（料理を運ぶだけ）／bus: 2人2台・まとめた皿も運ぶ／patrol6: 2人・皿を集めて回る 1→6台／
#                  crowdp: 混雑・集めて回る3台・2人→3人／cut:「スタッフを1人減らして」の比べ（下に2台の費用 −14.4万円が映るので、結論の場面には使わない）／cost: 費用の欄（3台→月3万円→4時間→買う・補助金）
#                  costhold: cost の5〜10秒（費用の表）を止めて延ばしたもの／costsens: cost の10〜24秒（月3万円・4時間）を止めて延ばしたもの
#                  録画は場面より短いと頭に戻るので、どれも最後のコマを60秒延ばした（tpad）
#                  open・two は第1回の録画（3人0→3台・2人0→6台）
#   Unity の店の映像は第1回と同じ（KIOXIA videos/何台入れたら店は変わる/_取り込み/背景）
# 強弱（4-4d）: 強（10・続けない）＝ hook_voice・hook_found・question・answer・entry・crowd・net・shop_back・mitate1・answer2／中＝棒が出る patrol2・patrol3
import os as _os, sys as _sys
_here = _os.path.dirname(_os.path.abspath(__file__))
for _c in (_os.environ.get("P2M_BASE", ""), _os.path.join(_here, "..", "base"), _os.path.join(_here, "..", "_制作ベース")):
    if _c and _os.path.exists(_os.path.join(_c, "scene_kit.py")):
        _sys.path.insert(0, _c); break
from scene_kit import *
from scene_kit import _p2page
from motion_kit import use_motion, CAP

T1 = "<b>1</b>運ぶだけ"
T2 = "<b>2</b>皿を集める"
T3 = "<b>3</b>月いくら"
T4 = "<b>4</b>エイイチの見立て"

SIM = lambda n, **k: dict(dict(file=f"src/sim_{n}.mp4", dim=0.55, slow=1.0), **k)   # 試算ページの録画
UO = dict(file="src/unity_oblique.mp4", dim=0.55, slow=1.2)    # Unity の店（斜め）
UT = dict(file="src/unity_top.mp4", dim=0.5, slow=1.2)         # Unity の店（真上）
CAP_SIM = "試算ページ（pixelstomotors.com/series8・試作 v2.7）"
CAP_U = "Unity の仮のファミレス（このシリーズの後の回で扱う）"
SRC_SIM = "数字：試算 v2.7（各条件40回の平均・仮の前提）"

_IDX = []


def _idx():
    """声の長さから割り付けた文の一覧（timing.layout）。重いので、tts/index.json と narration.py が同じなら作業フォルダの _timing_cache.pkl を使う"""
    if _IDX:
        return _IDX[0]
    import hashlib, pickle
    from timing import load, layout
    key = ""
    try:
        key = hashlib.md5(open(_os.path.join(_here, "tts/index.json"), "rb").read() + open(_os.path.join(_here, "narration.py"), "rb").read()).hexdigest()
        cp = _os.path.join(_here, "_timing_cache.pkl")
        if _os.path.exists(cp):
            k, idx = pickle.load(open(cp, "rb"))
            if k == key:
                _IDX.append(idx); return idx
    except Exception:
        pass
    idx = load(); layout(idx); _IDX.append(idx)
    try:
        pickle.dump((key, idx), open(_os.path.join(_here, "_timing_cache.pkl"), "wb"))
    except Exception:
        pass
    return idx


def _when(scene, k, f):
    """場面の頭から、その場面の k 番目の文の読み上げの f 割の所までの秒（声を取り込む前は 0）"""
    try:
        from timing import FPS
        lines, fr = [], 0
        for o in _idx():
            if o['scene'] == scene:
                lines.append((fr, o['speech'])); fr += o['frames']
        a, sp = lines[min(k, len(lines) - 1)]
        return (a + sp * f) / FPS
    except Exception:
        return 0.0


def bars(vals, labels, unit="分", kicker="", sub="", tag=None, colors=None, times=None, sub_t=None, vmax=None, src=SRC_SIM, fmt="{:.1f}"):
    """台数ごとの棒（縦）。ハコブくんの区画（左下）を避けるため、図は左を空けて右寄りに置く。
    times: 棒ごとに出す秒（None なら最初から出ている＝静止画）／sub_t: 下の一言を出す秒"""
    vmax = vmax or max(vals) * 1.08
    H = 340
    cols = []
    for i, (v, l) in enumerate(zip(vals, labels)):
        c = (colors or {}).get(i, "#9A9A94")
        h = max(6, int(H * v / vmax))
        ta = f' data-a="pop" data-t="{times[i]:.2f}" data-d="0.4"' if times else ""
        cols.append(f'<div{ta} style="display:flex;flex-direction:column;align-items:center;justify-content:flex-end;width:176px;height:{H + 92}px">'
                    f'<div style="font-size:60px;font-weight:900;color:{c};margin-bottom:10px">{fmt.format(v)}<span style="font-size:32px">{unit}</span></div>'
                    f'<div style="width:120px;height:{h}px;background:{c};border-radius:10px 10px 0 0"></div></div>')
    lab = "".join(f'<div style="width:176px;text-align:center;font-size:44px;font-weight:900;color:#0D0D0D;margin-top:14px">{l}</div>' for l in labels)
    k = f'<div class="p2k muted" style="margin-bottom:16px">{kicker}</div>' if kicker else ""
    st = f' data-a="up" data-t="{sub_t:.2f}"' if sub_t is not None else ""
    sb = f'<div class="p2sub"{st} style="font-size:46px;margin-top:22px">{sub}</div>' if sub else ""
    body = (f'<div class="p2wrap" style="padding-left:260px">{k}'
            f'<div style="display:flex;align-items:flex-end;gap:14px;border-bottom:4px solid #0D0D0D">{"".join(cols)}</div>'
            f'<div style="display:flex;gap:14px">{lab}</div>{sb}</div>')
    return _p2page(body, tag, src)


# 動画シーンに重ねるテロップ（透過）
O = {
 "title": overlay('<div class="lt"><img class="a" src="' + LOGO + '"><div class="b">フィジカルAI解説</div><div class="c">案内役：ハコブくん（AI音声）</div></div>'),
 "title_eiichi": overlay('<div class="lt"><img class="a" src="' + LOGO + '"><div class="b">エイイチ</div><div class="c">デザイナー／ロボティクスの研究・開発</div></div>'),
 "outro": overlay('<div class="lt"><img class="a" src="' + LOGO + '"><div class="b">相談は概要欄の連絡先から</div><div class="c">高評価・チャンネル登録／コメントはエイイチが全部読んでいます</div></div>'),
}

# 映像を流す場面 (映像, 開始秒, 透かし)。開始秒 None は前の場面の続き
VIDEO = {
 "title": ("src/unity_oblique.mp4", 2.0, False),
 "title_eiichi": ("src/unity_oblique.mp4", None, False),
 "outro": ("src/unity_top.mp4", 4.0, False),
}

# 動きのある場面（motion_kit.py が src/motion_{場面}.mp4 に書き出す）
# 2026-10-24 エイイチの指示：「背景にシミュレーションの動画を長く使う（今までより圧倒的に増やす）」「テキストは背景をカードタイプで」
#   → 自己紹介とアウトロのほかは、すべての場面で、シミュレーションの映像（Unity の店・試算ページ・試算のコード）を背景に流し、
#     その上に黒いカード（白い文字・青の強調）を置く。同じ映像は続く場面でつなげて流す（場面ごとに頭へ戻さない）
#   上の S（紙の図）は、動きを書き出す前の確かめ用に残している
import subprocess as _sp

# 背景の映像の置き場所（重いので KIOXIA。iCloud には置かない）
_BG_CANDS = [_os.environ.get("P2M_BG", ""),
             _os.path.join(_here, "..", "bg", "背景"),
             _os.path.expanduser("~/mnt/r2r2r-data/videos/何台入れたら店は変わる/_取り込み/背景"),
             "/Volumes/KIOXIA/r2r2r-data/videos/何台入れたら店は変わる/_取り込み/背景"]
BGDIR = next((c for c in _BG_CANDS if c and _os.path.isdir(c)), _BG_CANDS[1])

# 映像の名前 → (ファイル, 何の映像かの札)
U_OLD = "Unity の仮のファミレス（初期の版・シリーズの後の回で扱う）"
U_NEW = "Unity で建てたファミレス（図面のある店③・シリーズの後の回で扱う）"
BG = {
 "u357o": (f"{BGDIR}/LOG357_v1_stage2_oblique.mp4", U_OLD),
 "u357t": (f"{BGDIR}/LOG357_v2_stage2_top.mp4", U_OLD),
 "u364a": (f"{BGDIR}/LOG364_v3_run3_people_and_robots.mp4", U_NEW),
 "u364b": (f"{BGDIR}/LOG364_v4_run4_robots_back_and_forth.mp4", U_NEW),
 "u364c": (f"{BGDIR}/LOG364_v5_run5_return_lane.mp4", U_NEW),
 "four": (f"{BGDIR}/four-views.mp4", U_NEW),
 "obl": (f"{BGDIR}/fv-oblique.mp4", U_NEW),
 "busy": (f"{BGDIR}/top-busy.mp4", U_NEW),
 "pass": (f"{BGDIR}/top-pass.mp4", U_NEW),
 "term": (f"{BGDIR}/terminal.mp4", "試算のコード（SimPy）を回しているところ"),
}
for _k in ("entry2", "bus", "patrol6", "crowdp", "cut", "cost", "costhold", "costsens", "open", "two"):
    BG["s_" + _k] = (_os.path.join(_here, f"src/sim_{_k}.mp4"), CAP_SIM)

_DUR = {}


def _clip_len(f):
    if f not in _DUR:
        try:
            _DUR[f] = float(_sp.check_output(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", f]).decode().strip())
        except Exception:
            _DUR[f] = 9999.0
    return _DUR[f]


_START = {}


def _scene_start(scene):
    """動画の頭から、その場面の始まりまでの秒（声を取り込む前は 0）"""
    try:
        from timing import FPS
        if not _START:
            fr = 0
            for o in _idx():
                _START.setdefault(o["scene"], fr / FPS); fr += o["frames"]
        return _START.get(scene, 0.0)
    except Exception:
        return 0.0


def _bg(scene):
    for key, ss0, scs in RUNS:
        if scene in scs:
            f, cap = BG[key]
            el = _scene_start(scene) - _scene_start(scs[0])
            ss = (ss0 + el) % max(1.0, _clip_len(f) - 0.5)
            # 試算ページの録画は、操作が終わったら最後のコマで止まっていてよいので、頭に戻さない
            if key.startswith("s_"):
                ss = min(ss0 + el, max(0.0, _clip_len(f) - 0.5))
            return dict(file=f, ss=round(ss, 2), dim=(0.5 if key.startswith("s_") else 0.62), slow=1.0), cap
    return None, ""


# ---- カード（黒い板に白い文字・強調は青）----
HL, WARN = "#C4471F", "#62BFF5"   # 基本はオレンジ（元の #C4471F）、追加の差し色に水色（2026-10-24 エイイチの指示）
CARD_CSS = f"""
.cw{{position:absolute;left:0;right:0;top:150px;bottom:300px;display:flex;align-items:center;justify-content:center}}
.cd{{background:rgba(8,8,8,.86);border-radius:30px;padding:46px 84px 52px;text-align:center;color:#fff;max-width:1560px;box-shadow:0 10px 40px rgba(0,0,0,.35)}}
.cd .k{{font-size:42px;font-weight:700;color:#BDBDBD;margin-bottom:22px;letter-spacing:.03em}}
.cd .b{{font-weight:900;line-height:1.16;letter-spacing:-.01em}}
.cd .s{{font-size:44px;font-weight:700;color:#D0D0D0;margin-top:26px;line-height:1.35}}
.cd .hl{{color:{HL}}} .cd .wn{{color:{WARN}}}
.cd .pill{{display:inline-block;font-size:38px;font-weight:900;padding:8px 28px;border-radius:999px;background:#F5F5F0;color:#0D0D0D;margin-bottom:28px}}
.cd .pr{{display:flex;align-items:center;justify-content:center;gap:60px}}
.cd .pr .w{{font-weight:900;line-height:1.1}}
.cd .pr .d{{font-size:42px;font-weight:700;color:#BDBDBD;margin-top:16px}}
.cd .pr .m{{font-size:96px;font-weight:900;color:#8A8A8A}}
.cd .li{{text-align:left;display:inline-block}}
.cd .li div{{font-weight:900;margin:8px 0}}
.cd .li span{{color:{HL};margin-right:30px}}
.cap{{position:absolute;left:96px;top:64px;background:rgba(8,8,8,.72);color:#fff;font-size:30px;font-weight:700;padding:12px 24px;border-radius:10px}}
.tg{{position:absolute;right:56px;top:64px;background:rgba(8,8,8,.72);color:#fff;font-size:30px;font-weight:900;padding:12px 24px;border-radius:10px}}
.tg b{{color:{HL};margin-right:12px}}
.sr{{position:absolute;right:56px;top:126px;color:#eee;font-size:24px;font-weight:700;text-shadow:0 1px 4px #000}}
"""
_COL = {"": "#fff", "blue": HL, "red": WARN, "muted": "#BDBDBD"}


def _wrap(inner, cap="", tag=None, src="", pop=0.05, big_at=None):
    """カード1枚の重ね絵（透過）。pop: カードが出る秒。big_at: 大きい文字を叩きつける秒（強の場面）"""
    if big_at is not None:
        inner = inner.replace('class="b"', f'class="b" data-a="slam" data-t="{big_at:.2f}" data-d="0.45"', 1)
    c = f'<div class="cap">{cap}</div>' if cap else ""
    tg = f'<div class="tg">{tag}</div>' if tag else ""
    sr = f'<div class="sr">{src}</div>' if src else ""
    body = f'<style>{CARD_CSS}</style>{c}{tg}{sr}<div class="cw"><div class="cd" data-a="pop" data-t="{pop:.2f}" data-d="0.4">{inner}</div></div>'
    return overlay(body)


def _hl(s):
    return s.replace('<span class="blue">', '<span class="hl">').replace('<span class="red">', '<span class="wn">')


def C_word(lines, kicker="", sub="", size=130, kc=None):
    k = f'<div class="k"{" style=color:" + _COL[kc] if kc else ""}>{kicker}</div>' if kicker else ""
    s = f'<div class="s">{sub}</div>' if sub else ""
    return f'{k}<div class="b" style="font-size:{size}px">{_hl("<br>".join(lines))}</div>{s}'


def C_num(num, unit="", kicker="", sub="", size=230):
    k = f'<div class="k">{kicker}</div>' if kicker else ""
    s = f'<div class="s">{sub}</div>' if sub else ""
    u = f'<span style="font-size:{int(size * 0.42)}px;color:{HL};margin-left:10px">{unit}</span>' if unit else ""
    return f'{k}<div class="b" style="font-size:{size}px">{num}{u}</div>{s}'


def C_pair(a, b, da="", db="", ca="", cb="blue", mid="→", kicker="", sub="", size=140):
    k = f'<div class="k">{kicker}</div>' if kicker else ""
    s = f'<div class="s">{sub}</div>' if sub else ""
    side = lambda w, d, c: f'<div><div class="w" style="font-size:{size}px;color:{_COL[c]}">{w}</div>' + (f'<div class="d">{d}</div>' if d else "") + "</div>"
    return f'{k}<div class="b pr">{side(a, da, ca)}<div class="m">{mid}</div>{side(b, db, cb)}</div>{s}'


def C_list(items, kicker="", size=96):
    k = f'<div class="k">{kicker}</div>' if kicker else ""
    li = "".join(f'<div style="font-size:{size}px"><span>{n}</span>{x}</div>' for n, x in items)
    return f'{k}<div class="b li">{li}</div>'


def C_quiz(lines, pill, size=140):
    return f'<div class="pill">{pill}</div><div class="b" style="font-size:{size}px">{"<br>".join(lines)}</div>'


def C_chap(no, word, sub):
    return f'<div class="k" style="color:{HL};font-size:52px">{no}</div><div class="b" style="font-size:190px">{word}</div><div class="s">{sub}</div>'


def C_bars(vals, labels, kicker="", colors=None, times=None, vmax=None, sub="", sub_t=None):
    vmax = vmax or max(vals) * 1.08; Hh = 205; cols = []
    for i, (v, l) in enumerate(zip(vals, labels)):
        c = (colors or {}).get(i, "#9A9A94"); h = max(6, int(Hh * v / vmax))
        ta = f' data-a="pop" data-t="{times[i]:.2f}" data-d="0.4"' if times else ""
        cols.append(f'<div{ta} style="display:flex;flex-direction:column;align-items:center;justify-content:flex-end;width:160px;height:{Hh + 80}px">'
                    f'<div style="font-size:54px;font-weight:900;color:{c};margin-bottom:8px">{v:.1f}<span style="font-size:28px">分</span></div>'
                    f'<div style="width:104px;height:{h}px;background:{c};border-radius:10px 10px 0 0"></div></div>')
    lab = "".join(f'<div style="width:160px;text-align:center;font-size:40px;font-weight:900;margin-top:12px">{l}</div>' for l in labels)
    k = f'<div class="k">{kicker}</div>' if kicker else ""
    st = f' data-a="up" data-t="{sub_t:.2f}"' if sub_t is not None else ""
    s = f'<div class="s"{st} style="font-size:40px">{sub}</div>' if sub else ""
    return (f'{k}<div style="display:flex;gap:12px;align-items:flex-end;border-bottom:4px solid #ddd;justify-content:center">{"".join(cols)}</div>'
            f'<div style="display:flex;gap:12px;justify-content:center">{lab}</div>{s}')


def C_listt(items, kicker="", size=96, times=None):
    """C_list の各行を、話に合わせて1行ずつ出す（times: 行ごとの秒）"""
    k = f'<div class="k">{kicker}</div>' if kicker else ""
    li = "".join(f'<div style="font-size:{size}px" data-a="pop" data-t="{t:.2f}" data-d="0.4"><span>{n}</span>{x}</div>' for (n, x), t in zip(items, times))
    return f'{k}<div class="b li">{li}</div>'


# 場面ごとのカード：(中身, 強の場面なら大きい文字を叩きつける時（(文, 割合)・秒）, 章の札, 出典)
GRAY, BL, OR = "#9A9A94", HL, WARN
NL6 = ["1台", "2台", "3台", "4台", "5台", "6台"]
STW = [15.5, 10.5, 6.9, 6.3, 8.7, 7.6]   # 2人・皿を集めて回る：席は空いているのに待った時間（分）1〜6台（試算 v2.7）
_p2 = [_when("patrol2", 0, f) for f in (0.15, 0.45)]
_p3 = [0.0, 0.0] + [_when("patrol3", 0, f) for f in (0.1, 0.3, 0.45, 0.6)]
SRC_COST = "費用は試算ページの既定（どれも仮置き）"
CARDS = {
 "hook": (C_word(['宮崎県の', '<span class="blue">飲食店の人</span>'], "配膳ロボットを入れた店の、テレビの取材での言葉", "MRT宮崎放送（2022年4月27日）", 140), None, None, ""),
 "hook_voice": (C_word(['「0.5だとか、', '<span class="blue">0.25にはなる</span>」'], "「1人にはならないですけれども」", "", 130), 0.05, None, "出典：MRT宮崎放送（YouTube）"),
 "hook_q": (C_quiz(['1人、', '減らせることは？'], "使い方や台数を変えたら"), None, None, ""),
 "hook_try": (C_pair("3人", "2人", "ロボットなし", "＋ロボット", "", "blue", "→", "ファミレスの混む2時間を、パソコンの中で", "それでも店が回る条件を探した", 160), None, None, ""),
 "hook_found": (C_word(['皿も', '<span class="blue">集めさせる</span>'], "条件は見つかった", "食事中に席を回って、空いた皿を集める", 160), (0, 0.35), None, SRC_SIM),
 "hook_cost": (C_word(['費用の方が', '<span class="red">高い</span>'], "ところが、月いくら浮くかを計算すると", "借りる値段や、減らせる時間しだいで逆になる", 160), None, None, ""),
 "question": (C_quiz(['1人減らせる？', '月いくら浮く？'], "今日の問い", 140), 0.1, None, ""),
 "series": (C_list([("前回", "3人のまま0→6台"), ("今回", "使い方を変える・お金")], "シリーズ2回目", 96), None, None, ""),
 "define": (C_word(['減らしても', '<span class="blue">店が回る</span>'], "「減らせる」とは", "混む2時間に、ホールの人を1人", 150), None, None, ""),
 "define2": (C_pair("回っている", "回っていない", "5〜10分で入れる・席が埋まる", "席は空いているのに案内できない", "blue", "red", "／", "エイイチの言葉", "", 92), None, None, ""),
 "define3": (C_num("10", "分", "席は空いているのに、片付けや案内を待たせた時間（平均）", "これ以上で「店が回らない」：比べるためにエイイチが決めた線"), None, None, ""),
 "scope": (C_word(['パソコンの中の', '<span class="red">試算</span>'], "前回と同じ範囲", "35卓・1時間35組・空の店から2時間・40回の平均", 150), None, None, ""),
 "answer": (C_word(['皿を集めて', '<span class="blue">3台から</span>'], "先に結論：3人 → 2人にできたのは", "食事中に席を回って、お客さんに皿を載せてもらう使い方", 160), (0, 0.55), None, SRC_SIM),
 "answer_cost": (C_pair("14.1万円", "21.6万円", "浮く人件費（月）", "ロボット3台（月）", "blue", "red", "／", "1台月6万円で借りる・保守と充電込み", "差し引き 月約7.5万円の持ち出し", 130), None, None, SRC_COST),
 "toc": (C_list([("1", "料理を運ぶだけ"), ("2", "皿を集めて回る"), ("3", "月いくら浮く？"), ("4", "エイイチの見立て")], "今日は3つ＋見立て", 90), None, None, ""),
 "c1": (C_chap("1つ目", "運ぶだけ", "なぜ1人減らせないのか"), None, None, ""),
 "entry": (C_pair("8.6分", "14.3分", "3人・ロボットなし", "2人＋2台", "", "red", "→", "店に来てから席に着くまで", "料理ができてから卓に届くまでは 58秒 → 54秒", 150), (1, 0.4), T1, SRC_SIM),
 "why": (C_num("13.2", "分", "そのうち、席は空いているのに待った時間", "片付けや案内の手が空かない"), None, T1, SRC_SIM),
 "why2": (C_word(['下げる・拭く・案内は', '<span class="red">人の仕事</span>'], "今回の仕事の順番と運び方では", "2人では追いつかない", 115), None, T1, ""),
 "honne1": (C_word(['一番足りないのは', '<span class="red">片付け</span>'], "昔ファミレスで働いていたエイイチの経験", "席は空いているのに、入口でお客さんが待つ", 130, "red"), None, T1, ""),
 "bus": (C_pair("13.3分", "線の上", "2人＋2台・まとめた皿も運ぶ", "", "red", "red", "→", "席は空いているのに待った時間", "皿をまとめて拭くのは人のまま（ハコブくんも拭けません）", 150), None, T1, SRC_SIM),
 "c1_end": (C_word(['片付けが空かないと', '<span class="red">減らせない</span>'], "", "", 130), None, T1, ""),
 "c2": (C_chap("2つ目", "皿を集める", "食事中に席を回る使い方"), None, None, ""),
 "patrol": (C_word(['お客さんが', '<span class="blue">皿を載せる</span>'], "ロボットが食事中に席を回る", "料理も運ぶ", 150), None, T2, ""),
 "patrol2": (C_bars(STW[:2], NL6[:2], "2人・皿を集めて回る：席は空いているのに待った時間", {0: OR, 1: OR}, _p2, 17, "2台は 10.5分（線を少しだけ超える）"), None, T2, SRC_SIM),
 "patrol3": (C_bars(STW, NL6, "2人・皿を集めて回る：席は空いているのに待った時間", {0: OR, 1: OR, 2: BL, 3: BL, 4: BL, 5: BL}, _p3, 17,
                    "3台：席に着くまで 7.5分（3人・ロボットなし 8.6分）", _when("patrol3", 1, 0.05)), None, T2, SRC_SIM),
 "patrol_note": (C_word(['来るたびに', '<span class="red">必ず載せる</span>'], "この試算の置き方", "2回集めると、食後に下げる皿は残らない設定", 140), None, T2, ""),
 "honne2": (C_word(['載せてくれない人も', '<span class="red">一定数いそう</span>'], "エイイチいわく", "", 115, "red"), None, T2, ""),
 "crowd": (C_pair("4人", "3人", "ロボットなし", "皿を集めて回る", "", "blue", "→", "混雑の日（1時間に45組）：店が回る最少の人数", "2人では、どの台数でも回らない", 180), (0, 0.6), T2, SRC_SIM),
 "robot_note": (C_list([("・", "細い通路での譲り合い"), ("・", "故障・充電で1台抜ける")], "この試算に入っていないこと", 96), None, T2, ""),
 "c3": (C_chap("3つ目", "月いくら", "1人減ったら、浮くのか"), None, None, ""),
 "labor": (C_num("14.1", "万円", "浮く人件費（月）", "時給1,177円 × 2時間 × 1日2回 × 30日（給料を本当に減らせた場合の仮の計算）"), None, T3, SRC_COST),
 "robotcost": (C_num("21.6", "万円", "ロボット3台（月）", "1台月6万円＋保守1万円＋充電2,000円（どれも仮）"), None, T3, SRC_COST),
 "net": (C_num("−7.5", "万円", "差し引き（月）", "1人減らせても、この前提ではお金は残らない"), (0, 0.2), T3, SRC_COST),
 "sens": (C_listt([("＋1.5", "月3万円で借りられれば"), ("＋6.6", "昼と夜に4時間ずつ減らせれば"), ("−0.3", "線を11分にして2台なら")], "前提を変えると：差し引き（万円／月）", 84,
                  [_when("sens", k, 0.15) for k in (1, 2, 3)]), None, T3, SRC_COST),
 "sens_buy": (C_pair("750万円", "375万円", "3台の本体", "補助金を受け取れたら", "", "blue", "→", "買う場合", "取り戻すのに約3年・補助金なしは約6年（5年使う前提に収まらない）", 140), None, T3, SRC_COST),
 "merit": (C_pair("8.6分", "3.2分", "3人・ロボットなし", "3人＋2台", "", "blue", "→", "人を減らさずに足すと：席に着くまで", "費用は月14.4万円の追加・負担やサービスは店で確かめる", 150), None, T3, SRC_SIM),
 "shop_back": (C_word(['そのままは', '<span class="red">比べられない</span>'], "「0.5だとか、0.25にはなる」と、今回の試算", "今回見たのは、3台＋お客さんの協力で、要る人数が1人減るか", 140), (1, 0.05), T3, ""),
 "mitate": (C_chap("最後に", "見立て", "エイイチの考え"), None, None, ""),
 "mitate1": (C_word(['何を', '<span class="blue">受け持たせるか</span>'], "エイイチの見立て", "人が食事中に下げる方法などとは、比べていない", 140, "red"), (0, 0.1), T4, ""),
 "honne3": (C_word(['まず', '<span class="blue">仕事を絞って</span>'], "導入したばかりなら", "料理を運ぶ・皿を下げる、と仕事を限った使い方が広がる", 140), None, T4, ""),
 "mitate_cost": (C_word(['浮かない結果も', '<span class="blue">そのまま見せる</span>'], "お金について（エイイチの考え）", "入れる理由は人件費だけでなく、人手不足・負担・サービスにも", 115, "red"), None, T4, ""),
 "answer2": (C_word(['皿を集めて3台で', '<span class="blue">1人減る</span>'], "問いへの答え：35卓のファミレス・普通の日", "料理を運ぶだけなら6台でも減らない・お金は月約7.5万円の持ち出し（借りる値段しだい）", 130), (1, 0.3), None, SRC_SIM),
 "question_next": (C_quiz(['どの仕事が', '減ったのか？'], "次にニュースを見たら", 140), None, None, ""),
 "next": (C_list([("次", "図面から3Dの店へ"), ("見る所", "通路で止まる所")], "次の回", 92), None, None, ""),
 "try": (C_word(['試算は', '<span class="blue">サイトで試せる</span>'], "pixelstomotors.com/series8", "リンクは概要欄に", 140), None, None, ""),
}

# 背景の割り当て：(映像の名前, 頭の秒, この映像でつなげて流す場面)
RUNS = [
 ("u357o", 2, ["hook", "hook_voice", "hook_q"]),
 ("four", 0, ["hook_try"]),
 ("s_patrol6", 9, ["hook_found"]),
 ("s_cost", 4, ["hook_cost"]),
 ("u364a", 0, ["question", "series"]),
 ("busy", 0, ["define", "define2", "define3"]),
 ("term", 0, ["scope"]),
 ("s_patrol6", 10, ["answer"]),
 ("s_costhold", 0, ["answer_cost"]),
 ("obl", 0, ["toc"]),
 ("pass", 0, ["c1"]),
 ("s_entry2", 0, ["entry"]),
 ("u364c", 0, ["why", "why2", "honne1"]),
 ("s_bus", 0, ["bus"]),
 ("u364b", 0, ["c1_end"]),
 ("four", 8, ["c2"]),
 ("u357t", 0, ["patrol"]),
 ("s_patrol6", 0, ["patrol2", "patrol3"]),
 ("u364a", 30, ["patrol_note", "honne2"]),
 ("s_crowdp", 0, ["crowd"]),
 ("u364b", 20, ["robot_note"]),
 ("pass", 4, ["c3"]),
 ("s_costhold", 0, ["labor", "robotcost", "net"]),
 ("s_costsens", 0, ["sens"]),
 ("s_cost", 24, ["sens_buy"]),
 ("s_open", 0, ["merit"]),
 ("obl", 10, ["shop_back"]),
 ("u364c", 50, ["mitate", "mitate1", "honne3", "mitate_cost"]),
 ("s_costhold", 0, ["answer2"]),
 ("u364a", 50, ["question_next", "next"]),
 ("s_patrol6", 0, ["try"]),
]

S = {}
MOTION = {}
for _name, (_inner, _big, _tag, _src) in CARDS.items():
    _b, _cap = _bg(_name)
    _ba = None
    if _big is not None:
        _ba = _big if isinstance(_big, (int, float)) else _when(_name, _big[0], _big[1])
    MOTION[_name] = dict(type="html", bg=_b, html=_wrap(_inner, cap=_cap, tag=_tag, src=_src, big_at=_ba))
    S[_name] = _wrap(_inner, cap=_cap, tag=_tag, src=_src)   # 動きを書き出す前の確かめ用（透過の板だけ）
use_motion(MOTION, VIDEO, O, _here, MOVE)
```

### 動画/配膳ロボットで1人減らせるか/make_docs.py（codex の依頼文と読み物の台本を作る）

````python
"""台本の読み物（台本_*.md）と codex 敵対的検証の依頼（codex_*.md）を、narration.py から作り直す。
台本を直したら、動画の作業フォルダで  python3 make_docs.py
2026-10-21: 「AIに昨日の続きをさせる」の make_docs.py を写して書き換えた
2026-10-25: シリーズ第2回として台本を作り直した（9版b・試算 v2.7）。依頼は第2回としての1回目（前の版の1回目・2回目の結果は _旧版/ に置いた）
2026-10-25: codex 1回目を受けて台本を10版にし、2回目の依頼にした
"""
import sys, json, os, datetime
sys.path.insert(0, '.')
from narration import SEGS, parse
NAME = "配膳ロボットで1人減らせるか"
TITLE = "配膳ロボットは「0.5人分」？ ― 1人減らせる条件と、月いくら浮くかを試算した（配膳ロボット導入シミュレーション 第2回）"
ROUND = 2
FJ = {"base": "基本", "smile": "小さな笑み", "surprise": "驚き", "doubt": "ジト目", "think": "目を閉じる",
      "trouble": "困り眉", "joy": "＞▽＜", "wink": "ウインク"}
SEC = [("hook", "0 フック"), ("title", "1 自己紹介"), ("question", "2 今日の問い"), ("answer", "3 結論と立場"),
       ("toc", "4 目次"), ("c1", "5 節1：料理を運ぶだけだと、なぜ1人減らせないのか"),
       ("c2", "6 節2：皿を集めて回ると、何が変わるのか"), ("c3", "7 節3：1人減ったら、月いくら浮くのか"),
       ("mitate", "8 見立て"), ("answer2", "9 問いへの回答・まとめ"), ("outro", "10 アウトロ")]
idx = {o['i']: o for o in json.load(open('tts/index.json'))} if os.path.exists('tts/index.json') else {}
rows, n, t, done, first, last = [], 0, 0.0, set(), {}, {}
for k, s in enumerate(SEGS):
    sc, f, text, p = parse(s)
    for key, name in SEC:
        if sc == key and name not in done:
            rows.append(("sec", name, t)); done.add(name)
    o = idx.get(k)
    t += (o['dur'] + o['pause']) if o else 0
    if text:
        n += 1
        first.setdefault(sc, n); last[sc] = n
        rows.append(("line", n, f, sc, text))


def R(*scs):
    return "・".join((f"S{first[x]:03d}〜S{last[x]:03d}" if first[x] != last[x] else f"S{first[x]:03d}") for x in scs if x in first)


# 読み物の台本
out = [f"# 台本：{TITLE}", "", "話し手はハコブくん（エイイチは三人称）。各行は「文番号｜表情｜場面｜字幕の文」。字幕の「｜」は、読み上げは1文のまま字幕だけ次の枚に替える位置。", ""]
for r in rows:
    if r[0] == "sec":
        m, ss = divmod(int(r[2]), 60); out += ["", f"## {r[1]}" + (f"（{m}:{ss:02d}〜）" if idx or r[1] == "0 フック" else ""), ""]
    else:
        out.append(f"- S{r[1]:03d}｜{FJ[r[2]]}｜{r[3]}｜{r[4]}")
if idx:
    m, ss = divmod(int(t), 60)
    out += ["", f"全体の長さ（いまの音声）：{m}分{ss:02d}秒"]
open(f"台本_{NAME}.md", "w").write("\n".join(out) + "\n")

# codex 敵対的検証の依頼
body = []
for r in rows:
    body.append(f"\n### {r[1]}\n" if r[0] == "sec" else f"S{r[1]:03d}　{r[4].replace('｜', '')}")
chars = sum(len(r[4].replace('｜', '')) for r in rows if r[0] == "line")
md = f"""# 敵対的検証依頼：YouTube台本「{TITLE}」

## あなたへの依頼

これから公開する解説動画（見込み 約12分）の台本を、**この台本を論破するつもりで**検証してください。褒める必要はありません。見落としを1つでも多く見つけることが目的です。

- チャンネル：フィジカルAI解説｜Pixels to Motors。書き手はエイイチ（台本の文は主に Claude が書き、エイイチが確定する）。本業のデザイナーをしながら、ロボティクスの研究と開発をしている個人
- 話し手：ナレーションはキャラクターのハコブくん（AI 音声。病院で物を運ぶロボットのキャラクター）。エイイチを三人称で呼ぶ
- 視聴者：ロボティクスに関心のある経営者・PM・マネージャー・開発者。飲食店の経営者と、配膳ロボットを提案するメーカー・販売会社
- シリーズ「配膳ロボット導入シミュレーション」の2回目。1回目「配膳ロボット、何台入れたら店は変わる？」は、スタッフ3人のままロボットを0〜6台増やし、料理を運ぶだけならどの台数でも3人を2人にすると店が回らない、と話し、「2人とロボット3台で線を下回る使い方がある。この話は次の回で」「次の回からは、まず、人は減らせるのか、月いくら浮くのか」と予告した
- この回の材料：エイイチがサイト（https://pixelstomotors.com/series8 ・試算ページ https://pixelstomotors.com/sim/serving-robot.html ）に公開している、配膳ロボットの導入の試算（試作 v2.7）。Python の SimPy（離散イベントシミュレーション）で飲食店のピークを再現し、16,425条件を1条件40回ずつ回した平均。料理はまずロボットを待ち、2分たってもロボットが来なければ人も運べる決まり（v2.7）。数字の多くは公開事例やメーカーの仕様をもとにした仮の値で、実際の店で測った値ではない。費用は同じページの「費用」の欄の既定値（1台 月6万円で借りる・保守 月1万円・充電 月2,000円・時給1,177円・混む2時間×1日2回×30日）。試算ページで同じ条件を選ぶと、台本の数字を確かめられます
- 台本の結論：35卓のファミレス・普通の混み具合（35組/時）の2時間で、スタッフを3人から2人に減らしても「店が回る」（席は空いているのに待たせた時間が平均10分未満。エイイチが決めた比べるための線）のは、食事中に席を回って客に空いた皿を載せてもらう使い方で3台以上のとき（7.5分。3人・ロボットなしの8.6分より短い）。料理を運ぶだけ・スタッフがまとめた皿も運ぶ使い方では、2人では回らない。混雑（45組/時）では、どの使い方でも2人では回らない（ロボットなしの4人が3人になる）。1人減って浮く人件費は月約14.1万円、ロボット3台を借りると月21.6万円で、差し引き月約7.5万円の持ち出し。1台月3万円なら月約1.5万円のプラス、4時間ずつ減らせれば月約6.6万円のプラス、買って補助金で半分なら約3年で取り戻す計算。見立ては、人を減らせるかはロボットに何を受け持たせるかで決まり、人件費が浮かない結果もそのまま見せ、人件費以外の変化と並べて決める
- 台本を書いたあと、書いたのとは別のエージェントに、試算の結果（ページに埋め込みのデータ）と費用の式で台本の数字をすべて計算し直してもらった（数字の食い違いなし）。言い方の指摘4つを直した（まとめた皿も運ぶ使い方は「席はあるのに待った時間 13.3分」と言う／皿を集めて回る使い方の結果はデザート・ドリンクもロボットが運んでよい前提だと言う（壊れやすい皿を人が運ぶ設定では、2人で回るのは最大3つで3台だけ・最大1つで5台だけ）／買う場合の約3年は割る数を言う／4時間は試算の外と断る）
- 検証日：{datetime.date.today().isoformat()}。参照できない場合は「未確認」と明記し、推測で OK を出さないでください
- **これは第2回の台本の{ROUND}回目の検証です。** 1回目（「直してから」・結論「条件つきで成立」・数字の検算は一致）の指摘は、試算のコード（haizen_sim.py v2.7）で確かめてから直した: 皿を集めて回る使い方の置き方（来るたびに載せる・2回で食後に下げる皿が残らず、皿をまとめる手間もなくなる設定）を具体的に言う／ロボットに料理を載せる・集めた皿を洗い場で降ろす手間は入っていないと言う／お金は実際のシフトで1人減らせた場合の仮の計算・2時間だけ減らすシフトは試していない／混雑の日も要る人数は4→3で1人減る、に直した／買う場合は本体750万円・補助金を受け取れれば自己負担375万円・代金は先払い・補助金なしは約6年で5年に収まらない／借りる値段の相場と中央値は外し、仮に置いた値と言う／「ロボットが1人分を丸ごと受け持てる」を外し、冒頭の実感と試算はそのまま比べられないと言う／3台は10分の線に左右される（線を11分にすれば2台）・調べたのは6台まで・40回の平均でばらつきは示していない／空の店から始めることを戻した・故障や充電は入っていない・食べ放題の例は下げる専用・料理の遅れは線に入れていない／節1を縮めた／人件費以外の変化は見合うかを店で確かめる・観察シートは皿を載せた割合も数える必要。採らなかった: 見立ての1文目の言い換え（エイイチの言葉なのでそのまま。続く文で「人の仕事をどう組み直すか」を足した）・時給の差し引きゼロの計算と混雑の料理の遅れの例（冗長）・宮崎の言葉はエイイチが渡した YouTube の文字起こしのまま。**1回目の指摘が直っているか、新しい誤りや言い過ぎが入っていないか、公開してよい段階かを中心に見てください**。文番号は1回目とずれています。エイイチ本人の実感（{R('define2','honne1','honne2','honne3','mitate_cost')}）は本人の答えで、事実として裏付けを探す対象ではありません

## 検証してほしい観点

### A. 事実
A1. 試算の数字（{R('dish','entry','why','bus','patrol2','patrol3','patrol_walk','crowd','merit')}）が、試算ページで同じ条件を選んだ値と合うか。条件はすべて「普通の混み具合・1往復で最大3つ・デザートとドリンクもロボットが運ぶ」（ページの最初の画面と同じ）。入店待ち＝店に来てから案内されて席に着くまで
A2. 費用の数字（{R('answer_cost','labor','robotcost','net','sens','sens_buy')}）が、試算ページの費用の欄で同じ条件を選んだ値と合うか。最低賃金（2026年度の全国加重平均 1,177円）・補助金（省力化投資補助金 カタログ注文型・1/2以下）が出典の範囲か
A3. 公開事例（{R('hook','hook_voice','patrol')}）が出典の範囲か
### B. 論理
B1. 問い（{R('question','define','define2','define3')}）と答え（{R('answer','answer2')}）がそろっているか。10分の線で答えが変わる条件（2台の10.5分など）を言い切っていないか
B2. 「1人減らせる」→「人件費が浮く」のつなぎ（{R('labor','sens_note')}）が成り立つか。試算は混む2時間だけを見ているのに、ひと月の人件費に広げていることの限界を十分に言っているか
B3. 費用の比べ（{R('net','sens','sens_buy','merit')}）が、片方に寄っていないか。持ち出しの結論と、プラスになる条件の並べ方が公平か
B4. 冒頭の言葉（0.5・0.25）と試算の結果を結ぶ文（{R('hook_q','shop_back')}）が、言い過ぎていないか
### C. 抜けている反論・視点
C1. 「試算は現場の運用を単純にしすぎていて、実際の店では違うのでは」（スタッフの役割の分け方・キッチンとの兼務・ピーク外の仕事・導入の初めの費用・故障）
C2. 「客が皿を載せてくれる」前提が、ファミレスで成り立つか（事例は食べ放題の店）
C3. 見立て（{R('mitate1','honne3','mitate_cost','obs')}）への一番強い反論
### D. 言い方
D1. 断定が強すぎる文、逆に曖昧で意味のない文
D2. 冗長な所。いまの見込みは約12分（字幕の本文で約{chars:,}字）。1回目と重なりすぎている所
D3. 軽い一言（{R('bus')} の一部）が、事実の文や但し書きを弱めていないか

## 回答の書式

指摘ごとに次の形で書いてください。重大なものから順に並べてください。

```
[❌ NG / ⚠️ 要注意] 文番号（例：S043）
問題：何が問題か（1〜2文）
根拠：確認した出典（試算ページの値・ウェブの原文）または推論の筋道
修正案：差し替える文（台本の話し言葉の調子に合わせて）
```

最後に次の3点をまとめてください。
1. このまま公開してよいか（はい／直してから／大きく作り直すべき）
2. 公開前に必ず直すべき指摘の文番号
3. 台本の結論そのものへの評価（成立している／条件つきで成立／成立していない）と、その理由

---

## 台本が使った出典

| 主張 | 文番号 | 出典 |
|---|---|---|
| 配膳ロボットを入れた宮崎県の飲食店の人の言葉「1人にはならないですけれども、0.5だとか0.25にはなる」 | {R('hook','hook_voice','shop_back')} | MRT宮崎放送「人手不足の救世主？「配膳ロボット」宮崎県内でも活躍広がる 2022.4.27（水）」 https://www.youtube.com/watch?v=ZB66Qqu7Twg （1分12秒〜。YouTube の文字起こし）。試算と比べる文は、測ったものが違うと断っている |
| 前回の内容（3人のまま0〜6台・料理を運ぶだけなら2人では回らない・3人2台で8.6→3.2分） | {R('series','c1_end','merit')} | 第1回の台本（同じ試算 v2.7） |
| 「店が回る／回らない」の定義（エイイチの言葉）・10分の線 | {R('define2','define3')} | LOG359 https://pixelstomotors.com/record/audit-simulator-before-unity （エイイチ「混雑してても店が回ってるというのは5-10分で入れる状態。で席数が埋まっている状況。店が回ってない状態というのは席が余ってるけどスタッフが足りなくて案内出来ない状態と言えるかな」・「10分以上でいいよ（5分だと厳し目かな）」） |
| 試算の数字 | {R('dish','entry','why','bus','patrol2','patrol3','patrol_walk','crowd','merit')} | 試算ページ（試作 v2.7・ページに埋め込みのデータ）。標準ファミレス35卓・普通35組/時: 3人0台 入店8.58分（席はあるのに7.41）・料理0.965分・歩く3.88km／2人2台 料理を運ぶだけ 14.26（13.24）・料理0.892分／2人2台 まとめた皿も運ぶ 14.30（13.26）／2人6台 料理を運ぶだけ 15.37（14.16）／2人 皿を集めて回る 1〜6台: 入店 17.02・11.68・7.54・7.21・9.78・8.77、席はあるのに 15.45・10.47・6.85・6.35・8.71・7.56、3台の料理0.862分・歩く2.46km／混雑45組/時の店が回る最少のスタッフ（皿を集めて回る）0〜6台: 4・3・3・3・3・3・3／3人2台 料理を運ぶだけ 3.16 |
| 費用 | {R('answer_cost','labor','robotcost','net','sens','sens_buy')} | 試算ページの「費用」の欄（既定・どれも仮置き: 1台 月6万円で借りる・保守 月1万円（仮置き）・充電 月2,000円・時給1,177円・ピークの間×1日2回×30日。買う: 1台250万円・補助金1/2・5年）。浮く人件費＝減った人数×2時間×2回×30日×1,177円＝141,240円。3台借りる＝3×72,000＝216,000円。買う: 本体750万円・補助金375万円・自己負担375万円・375万÷(141,240−36,000)＝35.6か月、補助金なし 750万÷105,240＝71.3か月。補助金の手続き（支払いのあとに交付）は https://shoryokuka.smrj.go.jp/catalog/flow/ 、最低賃金は労働政策研究・研修機構、補助金は補助金ポータル（省力化投資補助金 カタログ注文型） |
| 客が皿を載せて回る使い方の事例は食べ放題の店 | {R('patrol')} | 作業ログ LOG351 https://pixelstomotors.com/record/serving-robot-simulation-simpy （焼肉の和民・かみむら牧場） |
| ロボットどうしが細い通路で待つ時間は入っておらず、台数が多いほど良く出る | {R('robot_note')} | 試算ページの注意書き |
| 店がロボットを入れる理由は人件費だけでない（人手不足・負担・サービス） | {R('mitate_cost')} | エイイチの考え（2026-10-23）。試算ページの「人件費のほかに、ロボットを入れて良くなること」 |
| 観察シート | {R('obs')} | LOG353 https://pixelstomotors.com/record/serving-robot-observation-sheet ・https://pixelstomotors.com/sim/serving-robot-observation.html |
| 見立て | {R('mitate1','honne3')} | エイイチの考え（2026-10-21 本人に聞いた答え：「ロボットに何を受け持たせるかで決まる。店舗スタッフも不慣れなので、いきなり煩雑な作業をやらせるより、タスクを限定した方がいい。だから今の配膳や下げ膳のロボットの運用が割と広がっているんだろうとも思う」） |

---

## 台本全文（動画で読み上げる版）
""" + "\n".join(body) + "\n"
open(f"codex_敵対的検証依頼_{NAME}.md", "w").write(md)
print("文", n, "字", chars)
````

### 動画/配膳ロボットで1人減らせるか/台本_配膳ロボットで1人減らせるか.md（読み物の台本）

```markdown
# 台本：配膳ロボットは「0.5人分」？ ― 1人減らせる条件と、月いくら浮くかを試算した（配膳ロボット導入シミュレーション 第2回）

話し手はハコブくん（エイイチは三人称）。各行は「文番号｜表情｜場面｜字幕の文」。字幕の「｜」は、読み上げは1文のまま字幕だけ次の枚に替える位置。


## 0 フック（0:00〜）

- S001｜基本｜hook｜配膳ロボットを入れた、宮崎県の飲食店の人は、テレビの取材で、こう話していました。
- S002｜小さな笑み｜hook_voice｜「1人にはならないですけれども、0.5だとか、0.25にはなるので」。
- S003｜ジト目｜hook_q｜では、使い方や台数を変えたら、ホールのスタッフを1人、減らせることはあるのか。
- S004｜目を閉じる｜hook_try｜そこで、ファミレスの混む時間帯の2時間を、パソコンの中で再現して、スタッフを3人から2人にしても、店が回る条件を探しました。
- S005｜驚き｜hook_found｜条件は、見つかりました。ロボットに、料理だけでなく、食事中の空いた皿も集めさせたときです。
- S006｜困り眉｜hook_cost｜ところが、月いくら浮くかを計算すると、浮く人件費より、ロボットの費用の方が高くなりました。｜ただし、借りる値段や、人を減らせる時間しだいで、答えは逆になります。

## 1 自己紹介

- S007｜小さな笑み｜title｜Pixels to Motors。案内役のハコブくんです。
- S008｜基本｜title｜この番組では、フィジカルAIのニュースや実機の記録から、現場で使える形を考えます。
- S009｜基本｜title_eiichi｜エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。｜その中で分かったことと、そこから考えた見立てを、ハコブくんがお伝えします。

## 2 今日の問い

- S010｜驚き｜question｜今日の問いは、配膳ロボットで、ホールのスタッフを1人減らせるのか。減らせたら、月いくら浮くのか、です。
- S011｜基本｜series｜この動画は、シリーズの2回目です。
- S012｜基本｜series｜前回は、スタッフ3人のまま、ロボットを0台から6台まで増やしました。｜料理を運ぶだけなら、どの台数でも、3人を2人にすると、店は回りませんでした。
- S013｜基本｜define｜ここで言う「減らせる」は、混む時間帯の2時間に、ホールの人を1人減らしても、店が回ることです。
- S014｜基本｜define2｜では、店が回るとは、どういう状態か。エイイチの言葉では、こうです。
- S015｜小さな笑み｜define2｜「混んでいても、5分から10分で入れて、席が埋まっている。これは回っている」。
- S016｜困り眉｜define2｜「席は余っているのに、スタッフが足りなくて案内できない。これが、回っていない」。
- S017｜基本｜define3｜この試算では、席は空いているのに、片付けや案内を待たせた時間が、平均で10分以上になったら、「店が回らない」と数えます。｜この10分は、エイイチが決めた比べるための線で、実際の店の営業を決める基準ではありません。満席で待つ時間や、料理の遅れは、この線には入れていません。
- S018｜基本｜scope｜前回と同じく、これはパソコンの中の試算です。｜数字の多くは、公開されている導入事例やメーカーの仕様をもとにした仮の値で、実際の店で測ったものではありません。
- S019｜基本｜scope｜店は、35卓のファミレス。お客さんが1人もいない状態から始めて、1時間に35組のペースで2時間だけ受け入れ、片付けが終わるまでを計算します。1つの条件を40回計算して、平均を出しています。
- S020｜基本｜scope｜比べるのは、試算に入れたホールの仕事を何人でこなせるかです。｜料理をロボットに載せたり、集めた皿を洗い場で降ろしたりする手間や、厨房との兼務、休憩までは入っていません。

## 3 結論と立場

- S021｜基本｜answer｜先に結論を言うと、この店の普通の日に、スタッフを3人から2人に減らせたのは、食事中に席を回って、お客さんに空いた皿を載せてもらう使い方で、ロボットが3台から6台のときでした。
- S022｜目を閉じる｜answer_cost｜1人減って浮く人件費は、月約14.1万円。ロボット3台を、1台月6万円で借りると、保守と充電を入れて、月約21.6万円です。
- S023｜困り眉｜answer_cost｜差し引きは、月約7.5万円の持ち出しになりました。

## 4 目次

- S024｜基本｜toc｜大きく3つあります。
- S025｜基本｜toc｜料理を運ぶだけだと、なぜ1人減らせないのか。
- S026｜基本｜toc｜皿を集めて回ると、何が変わるのか。
- S027｜基本｜toc｜1人減ったら、月いくら浮くのか。
- S028｜小さな笑み｜toc｜特に3つ目は、人が減っても、お金が残らないことがある、という話です。最後に、エイイチの見立てを話します。

## 5 節1：料理を運ぶだけだと、なぜ1人減らせないのか

- S029｜基本｜c1｜1つ目、料理を運ぶだけだと、なぜ1人減らせないのか、です。
- S030｜基本｜c1｜一言で言うと、運ぶのはロボットに任せられても、片付けと案内が、人に残るからです。
- S031｜基本｜entry｜前回の、料理を運ぶだけのロボットで、2人にロボット2台。1往復で料理を3つまで運ぶ設定です。｜料理ができてから卓に届くまでは、58秒から54秒で、ほとんど変わりません。
- S032｜驚き｜entry｜そして、店に来てから席に着くまでは、8.6分から14.3分に延びました。
- S033｜基本｜why｜そのうち13.2分は、席は空いているのに、片付けや案内の手が空かずに待った時間です。
- S034｜目を閉じる｜why2｜食べ終わった卓の皿を下げて拭くのも、入口のお客さんを席へ案内するのも、人です。今回の仕事の順番と運び方では、2人で、そこが追いつきませんでした。
- S035｜目を閉じる｜honne1｜ここで、エイイチ自身の経験を1つ。昔働いていたファミレスでも、混む時間に一番手が足りなかったのは、片付けだったそうです。
- S036｜小さな笑み｜honne1｜席は空いているのに、片付けが追いつかず、入口でお客さんが待っている。その光景も、実際にあったそうです。
- S037｜基本｜bus｜では、片付けに向かうスタッフが、空いているロボットに、まとめた皿も運ばせたらどうか。ロボット2台で、席は空いているのに待った時間が13.3分。こちらも、線を超えました。
- S038｜小さな笑み｜bus｜皿を洗い場まで運ぶのは、ロボットが手伝えます。でも、卓で皿をまとめて、拭くのは人のまま。ちなみに、ハコブくんも、卓は拭けません。
- S039｜目を閉じる｜c1_end｜片付けの手が空かないと、人は減らせないんです。

## 6 節2：皿を集めて回ると、何が変わるのか

- S040｜基本｜c2｜2つ目、皿を集めて回ると、何が変わるのか、です。
- S041｜基本｜c2｜一言で言うと、食べ終わったあとの片付けが軽くなって、2人でも回るようになります。
- S042｜基本｜patrol｜この使い方では、ロボットが食事中に席を回り、お客さんに、空いた皿を載せてもらいます。料理も運びます。
- S043｜基本｜patrol2｜この使い方のロボット2台では、席は空いているのに待った時間が10.5分。線を、少しだけ超えました。
- S044｜驚き｜patrol3｜3台にすると、席に着くまで、平均7.5分。スタッフ3人でロボットなしの8.6分より、短くなりました。
- S045｜小さな笑み｜patrol3｜料理ができてから届くまでも、58秒から52秒になりました。調べた6台までは、4台から6台でも、線の内側でした。
- S046｜基本｜patrol_note｜ただ、この試算では、ロボットが席に来るたびに、お客さんが皿を載せてくれる、と置いています。｜2回集めれば、食べ終わったあとに下げる皿は残らず、皿をまとめる手間もなくなる設定です。皿が最後まで残る店でも、3台で足りるかは、確かめていません。デザートやドリンクもロボットが運んでよい、という前提でもあります。
- S047｜小さな笑み｜honne2｜エイイチいわく、「余裕がある人は載せてくれるけど、載せてくれない人も、一定数いそう」。
- S048｜基本｜crowd｜混み具合でも変わります。1時間に45組来る混雑の日は、この使い方でも、2人では回りませんでした。｜ただ、ロボットなしなら4人要るところが、3人で回ります。要る人数が1人減るのは、混雑の日も同じです。
- S049｜目を閉じる｜crowd｜日によって要る人数が変わるので、実際に給料を減らせるかは、その日の来客と、シフトの組み方で決まります。
- S050｜基本｜robot_note｜そして、この試算には、ロボットどうしが細い通路で道を譲り合う時間や、故障や充電で1台が長く使えない場合は、入っていません。台数の多い条件は、効果を楽観的に見積もっているかもしれません。

## 7 節3：1人減ったら、月いくら浮くのか

- S051｜基本｜c3｜3つ目、1人減ったら、月いくら浮くのか、です。
- S052｜基本｜labor｜ここからは、料理を載せる人や皿を降ろす人の勤務を増やさずに、実際のシフトで1人分の給料を減らせた、とした場合の仮の計算です。｜浮く人件費は、1人分の時給を、混む2時間、1日2回、30日分で数えます。
- S053｜基本｜labor｜時給は、2026年度の最低賃金の全国平均、1,177円を借りました。社会保険料や交通費は入れていません。これで、月約14.1万円です。
- S054｜基本｜robotcost｜ロボットは、1台を月6万円で借りる、と仮に置きました。実際の値段は、機種や契約期間、保守が含まれるかどうかで変わります。
- S055｜基本｜robotcost｜保守を仮に月1万円、充電の電気代を月2,000円足すと、3台で月21.6万円になります。
- S056｜困り眉｜net｜差し引きは、月約7.5万円の持ち出しです。1人減らせても、この前提では、お金は残りません。
- S057｜基本｜sens｜ただ、ここは前提で大きく変わります。
- S058｜基本｜sens｜1台を月3万円で借りられれば、差し引きは、月約1.5万円のプラスです。今回の仕事ができる機種を、その値段で借りられれば、ですが。
- S059｜小さな笑み｜sens｜混む2時間だけでなく、昼と夜に4時間ずつ人を減らせれば、浮く人件費は月約28.2万円になり、月約6.6万円のプラスです。｜ただ、試算は混む2時間だけで、4時間を2人で回せるかは、確かめていません。
- S060｜基本｜sens｜それに、10分の線を11分にすれば、ロボットは2台で足り、持ち出しは月約3,000円まで小さくなります。お金の答えも、この線に左右されます。
- S061｜基本｜sens_buy｜買う場合は、1台250万円で、3台なら750万円。補助金の条件を満たして、半分の375万円を受け取れれば、自己負担は375万円です。｜保守と充電を引いても、浮く人件費が月約10.5万円残るので、自己負担を取り戻すのに、約3年かかる計算です。
- S062｜目を閉じる｜sens_buy｜補助金がなければ、約6年。今回置いた、5年使う前提には、収まりません。｜代金は先に払い、補助金はあとから受け取る仕組みで、導入をきっかけに従業員を解雇すると、対象外や返還になる条件もあります。借りる契約でも、支援の対象になるものがあります。
- S063｜基本｜merit｜そして、お金にしていない変化もあります。
- S064｜基本｜merit｜人を減らさずに、3人にロボット2台を足すと、前回見たとおり、席に着くまでは8.6分から3.2分に縮みました。｜歩く距離も減ります。この場合は、今回の費用で、月14.4万円の追加です。｜スタッフの負担やサービスが実際に良くなり、その費用に見合うかは、試算では測っていません。店で確かめて決めることになります。
- S065｜目を閉じる｜shop_back｜冒頭の、「0.5だとか、0.25にはなる」という実感と、今回の試算は、そのままは比べられません。｜今回見たのは、ロボット3台と、お客さんの協力を合わせて、要るホールの人数が1人減るか、です。ロボット1台が何人分か、ではありません。

## 8 見立て

- S066｜基本｜mitate｜ここからは、エイイチの見立てです。
- S067｜目を閉じる｜mitate1｜人を減らせるかは、ロボットに何を受け持たせるかで決まる。エイイチは、そう見ています。
- S068｜目を閉じる｜mitate1｜ただ、人が食事中に皿を下げたり、お客さんに返してもらったりする方法とは、比べていません。ロボットを使うのが一番よいかは、別の問いです。
- S069｜基本｜honne3｜それに、導入したばかりなら、スタッフも慣れる時間が要ります。いきなり手間のかかる作業を任せるより、まず仕事を絞って始めることにも意味がある。
- S070｜目を閉じる｜honne3｜だから今、料理を運ぶ、皿を下げる、と仕事を限ったロボットの使い方が、わりと広がっているんだろう。エイイチは、そうも考えています。
- S071｜基本｜mitate_cost｜お金については、人件費が浮かない結果も、そのまま見せるべきだと、エイイチは考えています。｜店がロボットを入れる理由は、人件費だけでなく、人手不足や、スタッフの負担、サービスにもあるからです。

## 9 問いへの回答・まとめ

- S072｜基本｜answer2｜じゃあ、冒頭の問いに答えますね。配膳ロボットで、ホールのスタッフを1人減らせるのか。
- S073｜目を閉じる｜answer2｜今回の35卓のファミレスの普通の日なら、食事中に皿を集めて回る使い方で、3台から6台のときに、要るホールの人数が1人減りました。料理を運ぶだけなら、6台でも減りませんでした。
- S074｜基本｜answer2｜月いくら浮くのか。1台月6万円で3台借りて、混む2時間を1日2回減らせたとすると、月約7.5万円の持ち出し。借りる値段や、減らせる時間しだいで、プラスにもなります。｜お客さんの協力も、止まり方も、シフトの組み方も、仮の前提です。
- S075｜基本｜question_next｜次に配膳ロボットのニュースを見たら、聞いてみてください。そのロボットで、人のどの仕事が減ったのか。そして、残った仕事を、誰が受け持っているのか。
- S076｜小さな笑み｜next｜次の回では、店の図面から3Dの店を建てて、ロボットを走らせます。今日の試算に入っていない、通路で止まる所を見ていきます。
- S077｜小さな笑み｜try｜この試算は、サイトのシリーズのページで、使い方や台数、費用の前提を変えて試せます。リンクは、概要欄に置いておきます。

## 10 アウトロ

- S078｜小さな笑み｜outro｜この動画が役に立ったら、高評価とチャンネル登録をお願いします。
- S079｜基本｜outro｜ロボットの開発や導入の相談は、概要欄の連絡先から、エイイチに直接どうぞ。
- S080｜ウインク｜outro｜コメントは、エイイチが全部読んでいます。それではまた。
```

