--- scenes_kabe_v1.py 2026-11-02 16:11:42.137351787 +0900 +++ scenes_kabe.py 2026-11-02 16:14:36.072069820 +0900 @@ -75,17 +75,15 @@ def hook(T, E): fly = (T(2, 0.1), T(3, 0.15)) return (dassen(BG + "1時間に6回.jpg", fly[0] + 0.05, fly[1] - 0.05, words="!1時間に|6回。", word_style="top:120px;font-size:130px", src_note=GEM) - + paper(tag("考察ノート") + '
' - + line("仮に、成功率", T(0, 0.2), size=32, weight=500) - + f'
{land("99%", T(0, 0.9))}
' - + f'
' - + card("fact", '1時間に600回働くと ' - f'0回 人が駆けつける', T(1, 0.6), None, w=880) - + '
' - + card("mi", inkl("それ、優秀なのかな", T(3, 0.3), 0.06), T(3, 0.1), "エイイチ", w=520, anim="wipe") - + card("hb", "僕も、自信がなくなってきた", T(4, 0.6), "ハコブくん", w=560, style="font-size:30px") + + paper(tag("考察ノート") + '
' + + line("仮に、成功率", T(0, 0.2), size=34, weight=500) + + f'
0%
' + + f'
{ink("1時間に600回働くと、", T(1, 0.3), 0.06)}
' + + f'
{land("6回", T(1, 3.0), "font-size:120px;font-weight:900")}{ink("人が駆けつける", T(1, 3.5), 0.07)}
' + '
' + src("例の計算(X の議論の指摘をもとに)", T(0, 0.5)), 0.0, flights=[fly]) - + counter_js("c6", T(1, 2.6), T(1, 4.2), 6, dec=0)) + + stamp("優秀?", T(3, 0.3), "right:380px;top:560px;font-size:64px") + + shake_js([(T(3, 0.65), 0.3)]) + + counter_js("c99", T(0, 1.0), T(0, 2.6), 99, dec=0)) block("hook", [0, 1, 2, 3, 4], hook) @@ -118,38 +116,44 @@ # ================= 2 持ち込み(脱線: 朝の街・ボタン1回目) ================= def bring(T, E): fly = (T(13, 0.3), E(13) - 0.1) + col = lambda kind, head, sub, t: (f'
' + f'{head}
{sub}
') return (dassen(BG + "朝の街.jpg", fly[0] + 0.05, fly[1], words="一夜で、|
|!来ない。", word_style="top:150px;font-size:120px", src_note=GEM) - + paper(tag("持ち込み") + '
' - + line("エイイチが持ち込んだ、X の議論", T(10, 0.4), size=28, weight=500) - + qline("ロボットにも、ChatGPT の瞬間は来る?", T(11, 0.4)) - + card("hb", "明日の朝、僕にも来る", T(13, 0.4), "ハコブくん", w=460, botsu=E(13) + 0.1, fade=T(14, 0.3), style="font-size:30px") - + card("fact", inkl("できるようになる瞬間は来ても、広がるには時間がかかる", T(14, 0.5), 0.04), T(14, 0.2), "議論の声", w=880) - + '
' - + card("hb", "ブラウザを開けば試せる", T(15, 0.4), "ChatGPT", w=400, style="font-size:28px") - + card("fact", "置く場所・止まったときの対処・店のやり方", T(16, 0.5), "ロボット", w=480, style="font-size:28px") - + '
', 0.0, flights=[fly]) + + paper(tag("持ち込み") + '
' + + line("エイイチが持ち込んだ、X の議論", T(10, 0.4), size=28, weight=500, style="color:#5a564f") + + f'
{ink("ロボットにも、", T(11, 0.4), 0.06)}
' + f'{land("ChatGPT の瞬間", T(11, 1.4), "font-size:84px;font-weight:900")}{ink("は来る?", T(11, 2.4), 0.08)}
' + + '
' + + f'
' + + card("hb", "明日の朝、僕にも来る", T(13, 0.4), "ハコブくん", w=460, botsu=E(13) + 0.1, fade=T(14, 0.3), style="font-size:30px") + '
' + + f'
' + + col("hb", "ChatGPT", "開けば、すぐ試せる", T(15, 0.4)) + + col("fact", "ロボット", "置く場所・止まったとき・店のやり方", T(16, 0.5)) + + '
', 0.0, flights=[fly]) + btn(T(16, S(16) + 0.2), T(17, -0.25), T(17, 1.2))) block("bring", [10, 11, 12, 13, 14, 15, 16, 17], bring) # ================= 3 やり取り1:なぜ配膳ロボットが先に広がったか ================= def why(T, E): - return paper(tag("やり取り 1 / どんな仕事から?") + '
' - + qline("どんな仕事から、広がるのか", T(18, 0.3)) - + card("hb", "失敗が許せて、繰り返しの多い作業", T(18, 2.6), "ハコブくん", w=640) - + card("mi", inkl("データも取りやすい。入れるハードルも低い。/お金もかからない", T(19, 0.4), 0.04), T(19, 0.15), "見立て ・ エイイチ", w=880, anim="wipe") - + card("mi", inkl("サービスロボットが広がり始めたのも、/このあたり", T(20, 0.4), 0.045), T(20, 0.15), "見立て ・ エイイチ", w=820, anim="wipe") + big = lambda txt, t: (f'
' + f'{txt}
') + return paper(tag("やり取り 1 / どんな仕事から?") + '
' + + qline("どんな仕事から、広がるのか", T(18, 0.3), size=48) + + f'
{big("失敗が
許せる", T(18, 2.8))}{big("繰り返しが
多い", T(18, 4.2))}
' + + card("mi", inkl("データも取りやすい。入れるハードルも低い。/広がり始めたのも、このあたり", T(19, 0.4), 0.045), T(19, 0.15), "見立て ・ エイイチ", w=860, anim="wipe") + '
', 0.0) block("why", [18, 19, 20], why) def first(T, E): - c = lambda txt, t: card("fact", txt, t, None, w=290, style="font-size:28px;padding:16px 18px") - return paper(tag("ファミレスの配膳ロボット") + '
' - + qline("条件が、全部そろっていた", T(21, 0.8)) - + card("mi", inkl("とうとうロボットが店舗に入った!", T(22, 0.5), 0.06), T(22, 0.2), "エイイチ(初めて店で見たとき)", w=760, anim="wipe", style="font-size:38px;font-weight:700") - + card("hb", "同じロボットとして、ありがとうございます", T(23, 1.2), "ハコブくん", w=640, style="font-size:28px") - + f'
{c("止まっても、
料理が少し遅れるだけ", T(24, 0.3))}{c("毎日、
何百回も往復する", T(24, 2.6))}{c("ホールの人が
集まらない", T(24, 4.2))}
' - + '
', 0.0) + c = lambda txt, t: (f'
{txt}
') + return (paper(tag("ファミレスの配膳ロボット") + '
' + + qline("条件が、全部そろっていた", T(21, 0.8), size=50) + + card("mi", inkl("とうとうロボットが店舗に入った!", T(22, 0.5), 0.06), T(22, 0.2), "エイイチ(初めて店で見たとき)", w=820, anim="wipe", style="font-size:42px;font-weight:700") + + f'
{c("止まっても、
料理が少し遅れるだけ", T(24, 0.3))}{c("毎日、
何百回も往復する", T(24, 2.6))}{c("ホールの人が
集まらない", T(24, 4.2))}
' + + '
', 0.0) + + stamp("感激", T(22, 3.0), "right:380px;top:300px;font-size:64px") + + shake_js([(T(22, 3.35), 0.3)])) block("first", [21, 22, 23, 24], first) @@ -160,8 +164,8 @@ + paper(tag("一番難しい所") + '
' + qline("一番難しい所を、ロボットにやらせていない", T(25, 0.3), size=40) + '
' - + card("fact", '料理をテーブルに
置く
お客さん', T(26, 0.3), None, w=400) - + card("fact", 'トレーに載せる
店員さん', T(26, 2.2), None, w=400) + + card("fact", '料理をテーブルに置く
お客さん', T(26, 0.3), None, w=420) + + card("fact", 'トレーに載せる
店員さん', T(26, 2.2), None, w=420) + '
' + card("hb", "料理も、僕が置く", T(27, 0.6), "ハコブくん", w=420, botsu=T(28, 0.9), fade=T(28, 1.1), style="font-size:30px") + card("mi", inkl("だから、人に任せた", T(28, 0.9), 0.06), T(28, 0.75), "エイイチ", w=480, anim="wipe") @@ -172,13 +176,27 @@ block("last", [25, 26, 27, 28, 29], last) # ================= 4 山場:扱えるか ================= +def card_mi_float(T): + """店のスタッフさんでも使えてる(エイイチ)を紙の上部に""" + return (f'
' + + card("mi", inkl("店のスタッフさんでも使えてる。ポイント高い", T(32, 0.4), 0.05), T(32, 0.15), "エイイチ", w=820, anim="wipe", fade=T(33, 0.0)) + + '
') + + def easy(T, E): - return paper(tag("もう1つの強み") + '
' - + card("fact", inkl("テーブル番号のボタンを押すだけ。/止まったら、どかす", T(31, 0.3), 0.04), T(31, 0.1), "使い方", w=880) - + card("mi", inkl("店のスタッフさんでも使えてる。ポイント高い", T(32, 0.4), 0.05), T(32, 0.15), "エイイチ", w=820, anim="wipe") - + card("fact", inkl("研修もマニュアルも、ほとんどいらない", T(33, 0.3), 0.05), T(33, 0.1), "入れたあと", w=720) - + card("hb", inkl("賢くても、止まったときにどうすればいいか/分からなければ、広がらない", T(34, 0.8), 0.04), T(34, 0.5), "裏を返すと", w=900) - + '
', 0.0) + press = T(31, 1.6) + return (BTN_CSS + paper(tag("もう1つの強み") + '
' + + line("使い方は、テーブル番号のボタンを押すだけ", T(31, 0.2), size=34, weight=700) + + f'
' + ''.join( + f'
{k + 1}
' for k in range(4)) + '
' + + card("mi", inkl("店のスタッフさんでも使えてる。ポイント高い", T(32, 0.4), 0.05), T(32, 0.15), "エイイチ", w=820, anim="wipe") + + f'
{ink("研修もマニュアルも、", T(33, 0.3), 0.06)}{land("ほぼ不要", T(33, 2.0), "font-size:70px;font-weight:900")}
' + + card("hb", inkl("賢くても、止まったときにどうすればいいか/分からなければ、広がらない", T(34, 0.8), 0.04), T(34, 0.5), "裏を返すと", w=900) + + '
', 0.0) + + f'
ピッ
' + ) block("easy", [30, 31, 32, 33, 34], easy) @@ -219,12 +237,13 @@ # ================= 5 やり取り2:足りなくなるのは誰か(ボタン2回目) ================= def who(T, E): - return (paper(tag("やり取り 2 / 足りなくなるのは誰か") + '
' - + line("動き回る仕事のロボットは、機体が安くなってきた", T(44, 2.0), size=32, weight=700) - + card("mi", inkl("移動系は早く、安くなる。/その分、入れる営業やエンジニアが足りなくなる", T(45, 0.4), 0.04), T(45, 0.15), "見立て ・ エイイチ", w=900, anim="wipe") + return (paper(tag("やり取り 2 / 足りなくなるのは誰か") + '
' + + line("動き回る仕事のロボットは、機体が", T(44, 2.0), size=34, weight=700) + + f'
{land("安く↓", T(44, 4.6))}
' + + card("mi", inkl("その分、入れる営業や/エンジニアが足りなくなる", T(46, 0.4), 0.05), T(45, 0.15), "見立て ・ エイイチ", w=760, anim="wipe") + card("mi", inkl("利益が残るのは、/作る側より、入れて回す側", T(47, 0.4), 0.05), T(47, 0.15), "見立て ・ エイイチ", w=820, anim="wipe", style="font-size:38px;font-weight:700") + '
', 0.0) - + stamp("この見立ては、エイイチから", T(47, S(47) + 0.1), "left:740px;top:640px") + + stamp("この見立ては、エイイチから", T(47, S(47) + 0.1), "left:1060px;top:150px") + shake_js([(T(47, S(47) + 0.45), 0.3)])) block("who", [44, 45, 46, 47], who) @@ -293,10 +312,19 @@ def door2(T, E): - return paper(tag("扉を通らない手") + '
' - + card("fact", inkl("求められるのは、調理場と客席の仕切り。/形は、地域の決まりや保健所の判断で変わる", T(65, 0.4), 0.035), T(65, 0.15), "決まり", w=900) - + card("hb", inkl("両側から取り出せる棚を客席側に置き、/トレーを置くだけ", T(66, 1.6), 0.04), T(66, 1.3), "扉を通らない", w=880) - + card("mi", inkl("現場設計だね。/直接、洗い場まで行けたら最高", T(67, 0.4), 0.05), T(67, 0.15), "見立て ・ エイイチ", w=780, anim="wipe") + lab = lambda txt, t: f'
{ink(txt, t, 0.05)}
' + seg = lambda txt, w, bg, fg, t: (f'
{txt}
') + return paper(tag("扉を通らない手") + '
' + + line("求められるのは、調理場と客席の仕切り", T(65, 0.4), size=34, weight=700) + + line("形は、地域の決まりや保健所の判断で変わる", T(65, 3.4), size=26, weight=500, style="color:#5a564f") + + '
' + + '
' + + f'
{lab("洗い場側", T(66, 1.0))}
{lab("両側から取り出せる棚", T(66, 1.8))}
{lab("客席側", T(66, 1.0))}
' + + '
' + + seg("調理場", 300, "#cfc8ba", "#22201c", T(66, 1.2)) + seg("棚", 300, "#22201c", "#f5f3ee", T(66, 2.6)) + seg("ロボット", 300, "#ece9e2", "#22201c", T(66, 4.4)) + + '
' + + '
' + + card("mi", inkl("現場設計だね。/直接、洗い場まで行けたら最高", T(67, 0.4), 0.05), T(67, 0.15), "見立て ・ エイイチ", w=760, anim="wipe") + line("新しい店や改装のときに、通り道ごと設計する", T(68, 0.8), size=30, weight=700) + '
' + src("出どころ:食品衛生法の施設基準(例:那覇市・北九州市の基準)", T(65, 0.3)), 0.0) block("door2", [65, 66, 67, 68], door2) @@ -323,10 +351,10 @@ # ================= 8 残った問い(ボタン3回目・自分で押す) ================= def rest(T, E): - return paper(tag("残った問い") + '
' - + card("mi", inkl("この辺の問題を解決する力を持つ人が、/重宝されそう", T(74, 0.4), 0.045), T(74, 0.15), "見立て ・ エイイチ", w=880, anim="wipe") - + qline("店とロボットのあいだに立つ役", T(75, 0.4), size=44) - + line("名前も、求人の枠も、まだない", T(75, 4.2), size=28, weight=500, style="color:#5a564f") + return paper(tag("残った問い") + '
' + + card("mi", inkl("この辺の問題を解決する力を持つ人が、/重宝されそう", T(74, 0.4), 0.045), T(74, 0.15), "見立て ・ エイイチ", w=860, anim="wipe") + + qline("店とロボットのあいだに立つ役", T(75, 0.4), size=46) + + f'
{ink("名前も、求人の枠も、", T(75, 3.8), 0.06)}{land("まだない", T(75, 5.2), "font-size:64px;font-weight:900")}
' + card("mi", inkl("大型のお店から、スタートしたい", T(77, 0.3), 0.06), T(77, 0.1), "エイイチ", w=620, anim="wipe") + card("hb", '考察ノートの全文
pixelstomotors.com / LOG389
', T(79, 0.3), "サイトの記事", w=600) + '
', 0.0) @@ -405,6 +433,7 @@ # ================= 効果音 ================= # (文, 文の頭から何秒, 音, ナレーションより何dB) SE = [ + (3, 0.3, "se_pop", -8), (22, 3.0, "se_pop", -8), (31, 1.6, "se_ding", -10), (44, 4.6, "se_pop", -10), (11, 1.4, "se_pop", -12), (2, 0.1, "se_whoosh", -10), (3, 0.15, "se_whoosh", -14), (13, 0.3, "se_whoosh", -10), (13, 99, "se_pop", -12), (16, S(16) + 0.2, "se_pop", -12), (17, -0.25, "se_ding", -10), @@ -427,7 +456,9 @@ _end = _tl.end(_b["sents"][-1]) - _tl.start(_b["sents"][0]) - 0.4 SHEET[_b["name"]] = [_end] _B = {b["name"]: b for b in BLOCKS} -SHEET["hook"] = [_rel(_B["hook"], 2, 1.5), SHEET["hook"][0]] +SHEET["hook"] = [_rel(_B["hook"], 1, 5.0), _rel(_B["hook"], 2, 1.5), SHEET["hook"][0]] +SHEET["easy"] = [_rel(_B["easy"], 32, 1.5), _rel(_B["easy"], 31, 1.8), SHEET["easy"][0]] +SHEET["door2"] = [_rel(_B["door2"], 66, 6.0), SHEET["door2"][0]] SHEET["bring"] = [_rel(_B["bring"], 13, 2.0), _rel(_B["bring"], 16, S(16) + 0.6), SHEET["bring"][0]] SHEET["last"] = [_rel(_B["last"], 27, S(27) - 0.1), _rel(_B["last"], 27, S(27) + 1.0), SHEET["last"][0]] SHEET["who2"] = [_rel(_B["who2"], 48, S(48) + 0.6), SHEET["who2"][0]]