# -*- 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 = "1運ぶだけ"
T2 = "2皿を集める"
T3 = "3月いくら"
T4 = "4エイイチの見立て"
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'
'
f'
{fmt.format(v)}{unit}
'
f'
')
lab = "".join(f'{l}
' for l in labels)
k = f'{kicker}
' if kicker else ""
st = f' data-a="up" data-t="{sub_t:.2f}"' if sub_t is not None else ""
sb = f'{sub}
' if sub else ""
body = (f'{k}'
f'
{"".join(cols)}
'
f'
{lab}
{sb}
')
return _p2page(body, tag, src)
# 動画シーンに重ねるテロップ(透過)
O = {
"title": overlay('
フィジカルAI解説
案内役:ハコブくん(AI音声)
'),
"title_eiichi": overlay('
エイイチ
デザイナー/ロボティクスの研究・開発
'),
"outro": overlay('
相談は概要欄の連絡先から
高評価・チャンネル登録/コメントはエイイチが全部読んでいます
'),
}
# 映像を流す場面 (映像, 開始秒, 透かし)。開始秒 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'{cap}
' if cap else ""
tg = f'{tag}
' if tag else ""
sr = f'{src}
' if src else ""
body = f'{c}{tg}{sr}'
return overlay(body)
def _hl(s):
return s.replace('', '').replace('', '')
def C_word(lines, kicker="", sub="", size=130, kc=None):
k = f'{kicker}
' if kicker else ""
s = f'{sub}
' if sub else ""
return f'{k}{_hl("
".join(lines))}
{s}'
def C_num(num, unit="", kicker="", sub="", size=230):
k = f'{kicker}
' if kicker else ""
s = f'{sub}
' if sub else ""
u = f'{unit}' if unit else ""
return f'{k}{num}{u}
{s}'
def C_pair(a, b, da="", db="", ca="", cb="blue", mid="→", kicker="", sub="", size=140):
k = f'{kicker}
' if kicker else ""
s = f'{sub}
' if sub else ""
side = lambda w, d, c: f'{w}
' + (f'
{d}
' if d else "") + "
"
return f'{k}{side(a, da, ca)}
{mid}
{side(b, db, cb)}
{s}'
def C_list(items, kicker="", size=96):
k = f'{kicker}
' if kicker else ""
li = "".join(f'{n}{x}
' for n, x in items)
return f'{k}{li}
'
def C_quiz(lines, pill, size=140):
return f'{pill}
{"
".join(lines)}
'
def C_chap(no, word, sub):
return f'{no}
{word}
{sub}
'
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'')
lab = "".join(f'{l}
' for l in labels)
k = f'{kicker}
' if kicker else ""
st = f' data-a="up" data-t="{sub_t:.2f}"' if sub_t is not None else ""
s = f'{sub}
' if sub else ""
return (f'{k}{"".join(cols)}
'
f'{lab}
{s}')
def C_listt(items, kicker="", size=96, times=None):
"""C_list の各行を、話に合わせて1行ずつ出す(times: 行ごとの秒)"""
k = f'{kicker}
' if kicker else ""
li = "".join(f'{n}{x}
' for (n, x), t in zip(items, times))
return f'{k}{li}
'
# 場面ごとのカード:(中身, 強の場面なら大きい文字を叩きつける時((文, 割合)・秒), 章の札, 出典)
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(['宮崎県の', '飲食店の人'], "配膳ロボットを入れた店の、テレビの取材での言葉", "MRT宮崎放送(2022年4月27日)", 140), None, None, ""),
"hook_voice": (C_word(['「0.5だとか、', '0.25にはなる」'], "「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(['皿も', '集めさせる'], "条件は見つかった", "食事中に席を回って、空いた皿を集める", 160), (0, 0.35), None, SRC_SIM),
"hook_cost": (C_word(['費用の方が', '高い'], "ところが、月いくら浮くかを計算すると", "借りる値段や、減らせる時間しだいで逆になる", 160), None, None, ""),
"question": (C_quiz(['1人減らせる?', '月いくら浮く?'], "今日の問い", 140), 0.1, None, ""),
"series": (C_list([("前回", "3人のまま0→6台"), ("今回", "使い方を変える・お金")], "シリーズ2回目", 96), None, None, ""),
"define": (C_word(['減らしても', '店が回る'], "「減らせる」とは", "混む2時間に、ホールの人を1人", 150), None, None, ""),
"define2": (C_pair("回っている", "回っていない", "5〜10分で入れる・席が埋まる", "席は空いているのに案内できない", "blue", "red", "/", "エイイチの言葉", "", 92), None, None, ""),
"define3": (C_num("10", "分", "席は空いているのに、片付けや案内を待たせた時間(平均)", "これ以上で「店が回らない」:比べるためにエイイチが決めた線"), None, None, ""),
"scope": (C_word(['パソコンの中の', '試算'], "前回と同じ範囲", "35卓・1時間35組・空の店から2時間・40回の平均", 150), None, None, ""),
"answer": (C_word(['皿を集めて', '3台から'], "先に結論: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(['下げる・拭く・案内は', '人の仕事'], "今回の仕事の順番と運び方では", "2人では追いつかない", 115), None, T1, ""),
"honne1": (C_word(['一番足りないのは', '片付け'], "昔ファミレスで働いていたエイイチの経験", "席は空いているのに、入口でお客さんが待つ", 130, "red"), None, T1, ""),
"bus": (C_pair("13.3分", "線の上", "2人+2台・まとめた皿も運ぶ", "", "red", "red", "→", "席は空いているのに待った時間", "皿をまとめて拭くのは人のまま(ハコブくんも拭けません)", 150), None, T1, SRC_SIM),
"c1_end": (C_word(['片付けが空かないと', '減らせない'], "", "", 130), None, T1, ""),
"c2": (C_chap("2つ目", "皿を集める", "食事中に席を回る使い方"), None, None, ""),
"patrol": (C_word(['お客さんが', '皿を載せる'], "ロボットが食事中に席を回る", "料理も運ぶ", 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(['来るたびに', '必ず載せる'], "この試算の置き方", "2回集めると、食後に下げる皿は残らない設定", 140), None, T2, ""),
"honne2": (C_word(['載せてくれない人も', '一定数いそう'], "エイイチいわく", "", 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(['そのままは', '比べられない'], "「0.5だとか、0.25にはなる」と、今回の試算", "今回見たのは、3台+お客さんの協力で、要る人数が1人減るか", 140), (1, 0.05), T3, ""),
"mitate": (C_chap("最後に", "見立て", "エイイチの考え"), None, None, ""),
"mitate1": (C_word(['何を', '受け持たせるか'], "エイイチの見立て", "人が食事中に下げる方法などとは、比べていない", 140, "red"), (0, 0.1), T4, ""),
"honne3": (C_word(['まず', '仕事を絞って'], "導入したばかりなら", "料理を運ぶ・皿を下げる、と仕事を限った使い方が広がる", 140), None, T4, ""),
"mitate_cost": (C_word(['浮かない結果も', 'そのまま見せる'], "お金について(エイイチの考え)", "入れる理由は人件費だけでなく、人手不足・負担・サービスにも", 115, "red"), None, T4, ""),
"answer2": (C_word(['皿を集めて3台で', '1人減る'], "問いへの答え: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(['試算は', 'サイトで試せる'], "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)