解説動画を謎解きの型に変えた ― ハコブくんの隣に、自分のドット絵と AI の声で出る

この記事の素材(コード・ログ・データ 9ファイル・まとめてダウンロードあり)

ニュースを謎として置き、3つの手がかりで解いていく型の解説動画を、13分41秒の1本として仕上げた。題材は2026年4月の北京の人型ロボットのハーフマラソン(優勝のロボットは50分26秒・人間の男子の世界記録候補より速い)と、家で洗濯物を任せられる人型ロボットがまだ見当たらないことの逆転で、台本は別のエージェントの照合と codex の事実確認を2回通してから声にした。画面の右下には、写真でも本人の声でもなく、100ドットの自分の絵と、番組で使っている別の AI 音声を当てた自分を出した。

Pixels to Motors の YouTube は、案内役のロボット「ハコブくん」が話す解説動画を、これまで1節の型(フック→自己紹介→問い→先に結論→目次→本編→見立て→答え)で作ってきました。LOG394 で再生数を追うのをやめ、入口の広い話題から入って自分の研究につなげる方針に変えたあと、最初の1本をどの型で作るかを決める必要がありました。参考にしたのは、海外のニュースを謎解きの形で話す18分の番組の文字起こしです。構成だけを取り出すと、冒頭で数字と不思議を置き、たとえを1つ、手がかりを3つ、答えは全体の75〜80%の所、という骨組みでした。謎解きが好きな人は一定数いる、という読みで、この骨組みに Pixels to Motors らしさ(出どころの札・自分の机の上の記録・見立て)を足した形にしました。

もう1つ決めたのは、自分をどう出すかです。写真は嫌、本人の声は通らない、でも「エイイチの感想は……」と言われる場面で本人が出ないのは変、という3つの条件がありました。答えは、ChatGPT で作った絵を元に手で直した100ドットのドット絵と、番組のマンガのショートで使っている別の AI 音声(槙原の声)を当てる、でした。ドット絵は話している間だけ口と目が動き、指をさすのは大事な所だけ、出る場面は「自分で確かめた所・現場の証言・見立て」の3つに限っています。

やったことなぜ結果
参考番組の文字起こしから構成だけを取り、謎解きの型にした
入口の広い話題で、答えまで見てもらうため
数字と謎→エイイチ登場→札の約束→たとえ1つ→手がかり3つ→現場の証人→解く→見立て→答え、の11パート
台本を11版まで直した
別のエージェントの照合(17か所)と codex 2回(17件→3件)の事実の指摘を入れるため
筋は3版のまま。codex の構成の提案は入れなかった
自分のドット絵を4枚作り、口と目を声で動かした
写真でも本人の声でもない形で、本人を出すため
100ドット・4ポーズ・口は3段・話す間だけ動く
自分のセリフ4文を AI 音声で入れた
「エイイチの感想は……」のあとに本人の声があるほうが自然なため
槙原の声を流用。ハコブくんの口はその間止まる
字幕の縁取りの穴・札の重なり・前の絵の透け・動きの場面の指紋を直した
確認用で見つかった4つの不具合
render.py・scenes.py・assemble.py を直した
よその映像の使い方を決めた
ほかのチャンネルが報道映像を背景に流しているのを見て、規約を聞かれたため
自分7:よそ3。会社の素材か引用の2通りだけ。台帳を付ける

謎解きの型は、答えを先に言わない代わりに、出どころの札と自分の記録で信じられる土台を先に作る形になりました。 話の出どころは画面の左上の札で出し(大会や会社の発表・ニュース・論文や本・エイイチの記録と見立て)、「どこまで信じるかは札を見て決めてください」と冒頭で言っています。

この型で視聴が続くかは、まだ分かりません。公開後に、30秒時点の視聴者維持率と平均視聴率を、1節の型で作った前の本編と比べます。

動画の冒頭。紙色の画面に「世界記録より速い/洗濯物はまだ」、左下にハコブくん。字幕は「人間の世界記録より速く走るロボットがいるのに、」
動画の1:00ごろ。真ん中に「性能は、すごい/仕事とは別?」、右下にドット絵のエイイチ(腕組み・口を開けている)。左上に「エイイチの記録と見立て」の札

作業ログ ― 参考番組の構成を取り出し、謎解きの型の1本目を仕上げるまで

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

ファイルの一覧(9本)

01_11_codex_make_docs.py.txt ― 台本:11版までの直しと、codex は事実確認だけ / codex の依頼文を作る make_docs.py(2回目の依頼)・8,673字

02_11_codex.txt ― 台本:11版までの直しと、codex は事実確認だけ / 事実確認のメモ(出典を開いて確かめた記録)・4,522字

03_11_codex_1.txt ― 台本:11版までの直しと、codex は事実確認だけ / codex 検証結果 1回目(17件・「直してから」)・9,889字

04_11_codex_2.txt ― 台本:11版までの直しと、codex は事実確認だけ / codex 検証結果 2回目(3件・「直してから」)・5,091字

05_11_codex_narration.py.txt ― 台本:11版までの直しと、codex は事実確認だけ / 台本の最終版 narration.py(11版・97文)・15,738字

06_4_tts_eleven.py.txt ― 本人の声:番組の別の声を流用して、4文だけ入れた / 声を作る tts_eleven.py(Mac で動かす・_制作ベース)・5,154字

07_ei_talk.py_ei_talk.py.txt ― 口と目を声で動かす ei_talk.py / ei_talk.py(口と目を動かす部品)・5,519字

08_sec01.py.txt ― 指さしは大事な所だけ / scenes.py(場面の図・札・エイイチの小窓)・18,846字

09_sec01.md ― 概要欄と投稿文 / 概要欄_下書き.md・4,148字

ここから下は作業の記録です。効果の数字はまだなく、「見込める効果」はすべて見込みです。視聴の数字は公開後に YouTube アナリティクスで確かめます。

参考番組の18分から、構成だけを取り出した

海外のニュース(GMO の回)を謎解きの形で話す18分の番組の文字起こしを渡され、「文章の構成についてだけ分析し、現行のうちの YouTube と何が違うか」を比べました。取り出した骨組みは次のとおりです。

参考番組時間の目安うちの解説回(1節の型)
変な事実を数字で置く。答えは言わない
0〜8%
フックのあと「先に結論」を言う
たとえを1つ置き、その上に手がかりを並べる
8〜15%
目次で「3つあります」と数を言う
手がかり1・2・3。途中で聞き手の早とちりを1つ入れて直す
15〜75%本編3節。節ごとに結論を言う
答え(山場)。過去の指摘や研究者の言葉で裏を取る
75〜85%見立て
聞き手が次に見るときの目の付け所を渡す
85〜100%答えと視聴者に渡す問い

違いの中心は「答えを先に言うか、山場で言うか」でした。うちの決まり(video_rules.md の C 節「冒頭30秒で答えか数字を出す」)とぶつかるので、この型では「冒頭で数字と謎を出し、答えは山場で出す」と読むことをエイイチに確かめ、承認をもらいました。

謎解きの面白さを動画に入れ込んでるという構成ですかね(謎解きが好きな層は一定数いる)この骨組みで動画を作ってみましょう。型を分析して、さらに Pixels to Motors らしさを加える案を考えてください。

Pixels to Motors らしさとして足したのは4つです。

  • 出どころの札。数字や主張を出す場面に、大会や会社の発表(黒)・ニュース(青)・論文や本(灰の枠)・エイイチの記録と見立て(オレンジ)の4種類の札を出す
  • 現場の証人。3つ目の手がかりの中で、自分の机の上のロボットアーム(mechArm 270-Pi)の記録を呼ぶ
  • ハコブくんの早とちり。手がかりの途中で、間違った推理を1つ置いて次で直す
  • 見立て。解説回と同じく「ここからはエイイチの見立てです」と言ってから話す

題材は、世間が知っている話から入ることにした

最初に出した題材の候補は、自分の研究寄りのもの(フィジカルAI研究室の学習の記録など)でした。エイイチの判断は、まず世間に分かりやすいネタから始めて、そのあとに自分のネタにしていく、でした。

もっと世間わかりやすいネタからスタートして、その後に自分ネタにしていきたいね

ターゲットが狭すぎる

候補 A〜C を出し、A「世界記録と洗濯物」(フィジカルAIとは何かが謎解きで分かる。入口としていちばん広い)に決まりました。謎は「人型ロボットがハーフマラソンで人間の世界記録より速く走ったのに、家で洗濯物を任せられる人型ロボットはなぜまだないのか」。たとえは「ロボットの学校」(走る=体育、洗濯物をたたむ=家庭科)の1つだけ。手がかりは、練習する場所・相手の形・お手本の数の3つです。

自分を出す方法:写真でも本人の声でもなく、ドット絵と別の AI 音声

オレを登場させる?動画の右側に(リアル写真は嫌)

エイイチが持ってきたのは、ChatGPT で作った自分のドット絵でした。出る場面は3つ(自分で確かめた所・現場の証言・見立て)だけ、表情の差分は5枚くらい、ハコブくんの絵柄ともう少し合わせたい、という条件でした。

エイイチが最初に持ってきたドット絵。黒髪に眼鏡、黒いインナーに灰色のジャケットで腕を組んでいる

最初に3Dっぽく描き直した案は「ドット絵の良さがなくなっている」で戻しになりました。ドット絵の良さは残したまま、服に残っていた手の残像を消し、左胸のポケットを外し(ポケットのないジャケットのため)、ジャケットの色と影の量を元の絵に合わせました。できたのは、100×100ドット・16色の4枚です。

ドット絵の4ポーズ。左から腕組み・うなずく・指さす・ひらめく

頷く絵は最初、襟が顎の後ろに回っていて「頷くところが変だね」と言われ、襟を顎の前に描き直しました。

台本:11版までの直しと、codex は事実確認だけ

台本は narration.py に1文ずつ(場面・表情・字幕・後ろの間)で書きます。1版から11版までの変化を、ファイルの先頭の記録から抜き出すと次のとおりです。

版直したこときっかけ
1版謎解きの型で書いた題材 A に決定
2版エイイチの実感を4つ入れた本人に聞いた答え
3版
照合で17か所直した。1年で速くなった理由を「仮想の練習」から「機体づくりと投資」へ
別のエージェントの照合
4版
codex の提案で題・問い・章を組み替えた
codex 1回目
5版
4版をやめ、3版の筋に事実の直しだけを入れた
エイイチ「codex は事実確認をベースに」
6版
冒頭〜早とちりの言い回しを柔らかく
エイイチ「まだ固い」
7版
地面の言い方・答えの「理由の1つ」・Helix 2.5 の日付
codex 2回目(3件)
8版
1文目「家の洗濯物には勝てていない」を言い換え
エイイチ「意味が分からない」
9版
冒頭の感想の前にエイイチの紹介を足した
エイイチ「出だしで出したい」
10版
場面の名前を分けた(動きの場面のため)
画面づくり
11版
エイイチの言葉4つを、ハコブくんの前置き+本人の声に分けた
エイイチ「おれの声を作って入れたい」

4版から5版への戻しが、この回でいちばん大きな判断でした。codex 1回目は17件の指摘で、事実の指摘(世界記録候補・一部の補助・Helix 2.5 の30軒・1X の量産開始)に加えて、題と問いの言い換え・人の作業動画の章の追加・据え置きの専用ロボットの追加・確かめる3つの言い換え、という構成の提案も出していました。それを全部入れた4版を見たエイイチの判断です。

codexは事実確認をベースにしてください。内容を変えるのはやめてください(多少はいいけど、codexに任せるとただのニュースのようになってします)

  • ねらい:codex の役割を事実確認に限り、話の筋・たとえ・見立ては人(エイイチ)と台本を書いた側が持つ
  • 変わったこと:依頼文の冒頭に「事実確認をしてください。筋・構成・見立ては変えない。組み替えや新しい話題・事例を足す提案は要らない」と書き、観点を事実と言い過ぎだけにした。2回目の依頼には「再び指摘しないで」と書いた
  • 見込める効果:codex の指摘が3件に減り、どれも事実の確度の話だった。謎解きの筋が残ったまま、数字と言い切りだけが直った

この決まりは video_rules.md の0節の手順5に足しました。

codex の依頼文を作る make_docs.py(2回目の依頼)

01_11_codex_make_docs.py.txt8,673字・131行・python
"""台本の読み物(台本_*.md)と codex 敵対的検証の依頼(codex_*.md)を、narration.py から作り直す。
台本を直したら、動画の作業フォルダで  python3 make_docs.py
2026-10-28: 「何台入れたら店は変わる」の make_docs.py を写して書き換えた(謎解きの型の1本目・1回目の依頼)
2026-10-28: 2回目の依頼にした(台本5版)。エイイチの指示で、codex には事実確認だけを頼む(話の筋・構成・見立ての提案は求めない)
"""
import sys, json, os
sys.path.insert(0, '.')
from narration import SEGS, parse
別のタブで開く保存

照合のメモ(別のエージェントが出典と1文ずつ突き合わせた)

# 照合(2026-10-28・台本2版を、書いたのとは別のエージェントが出典と1文ずつ突き合わせた)

一番大きい指摘: 「1年で3倍速くなった理由」を仮想の世界での練習にしていた。出典(Scientific American)の専門家は、伸びは工学と投資(冷やし方・モーター)と言い、仮想の練習は走れる土台として語っている → 3版で直した

直したこと(3版):
- S003 世界記録: 56分51秒は大会の後(8月)に出た記録で公認手続き中 → 「最高記録」「公認の手続き中」・6分あまり
- S018 条件: 「走り込み」は出典を超える → 電池・機体交換(罰則つき)・伴走の車・道順が決まっていた
- S027 細かい手: 出典なし → 「作られ始めている」に弱めた
- S030・S031: チューリッヒ工科大学と NVIDIA・GPU 1枚を積んだ計算機1台
- S034: HONOR の学ばせ方は「公表していない」→「今回調べた発表や報道には見当たらない」
- S035: 2本足のロボットも2021年に仮想の練習で走れるようになっていた(SciAm の研究者の発言)でつないだ
- S036: 「相手はほぼ地面だけ」→ 足が触れる相手は固い地面・仮想と本物のずれは残る
- 新 c1_speed: 1年の伸びは機体づくりと投資(専門家)
- 新 c2_cloth: 布を本物に近く動かす仮想の研究も進んでいる(RGBench 自体がその研究)
- S044・S060: 「中心」「しかない」を弱めた
- S048: π0 の1万時間は、いろいろな作業の合計
- S051: 1X NEO は会社自身の説明(覚えていない作業は担当者が遠くから導く)
- S052: ゴールドバーグの10万年の意味(言葉のAIの文章は人が読むと約10万年分・ロボットにはそれに近い量もない)
- S067: 「やさしい側に移った、と見る研究者」→ ゴールドバーグの発言(走る・宙返りではうまくいく、器用な手作業ではうまくいかない)
- 新: 別の研究者(ミシガン大・ディン助教)の「人より速く走るほうが難しく思えるのは思い込み」
- S071: 「先に進んでいた」→「さっきの実験も」
- 答え: 機体づくりと投資を足し、「まだ」の定義を言い直した

問題なしと確かめた所: 閃電は自律ナビ(新華社・AP・36Kr)・3倍あまり(9642秒÷3026秒=3.19)・RGBench・Figure の発表・モラベックの趣旨・1.2倍の採点

事実確認のメモ(出典を開いて確かめた記録)

02_11_codex.txt4,522字・52行・text
# 事実確認(2026-10-28・別のエージェントが出典を開いて確かめた)

## 2026年4月19日 北京亦庄 人型ロボット・ハーフマラソン
- 優勝 閃電(Lightning)・荣耀(HONOR)・齐天大圣队、50分26秒(正味)。100チーム超・300台超。距離21.0975km
- 遠隔操作の機体はタイムを1.2倍して採点。速さだけなら遠隔操作の HONOR 機の48分19秒が最速
- 自律は約4割(中国新聞網・China Daily「近四成」、Scientific American は38%)
- 電池交換は補給所内なら罰則なし(時間は含む)。補給所外は1回目5分・2回目10分の罰則
- 転倒・接触: スタートで1台転倒・1台が柵に衝突(AP・TechCrunch)。Scientific American は閃電が柵に当たり倒れスタッフが起こしたと書く
別のタブで開く保存

codex 検証結果 1回目(17件・「直してから」)

03_11_codex_1.txt9,889字・252行・text
# codex 敵対的検証 結果 1回目(世界記録と洗濯物)

- 日時: 2026-10-28 13:33(JST)
- 依頼文: codex_敵対的検証依頼_世界記録と洗濯物.md(md5 178594e1a06558f56c6adf233c774ba3・23,970 バイト)
- 題(依頼文の1行目): # 敵対的検証依頼:YouTube台本「人型ロボットは人間より速く走ったのに、なぜ洗濯物はたためないのか(仮題)」
- codex: codex-cli 0.164.0-alpha.11.1
- モデル: gpt-6.1-sol
- 考える深さ: high
別のタブで開く保存

codex 検証結果 2回目(3件・「直してから」)

04_11_codex_2.txt5,091字・79行・text
# codex 敵対的検証 結果 2回目(世界記録と洗濯物)

- 日時: 2026-10-28 14:30(JST)
- 依頼文: codex_敵対的検証依頼_世界記録と洗濯物.md(md5 22a0a3fed0d7809a2c46e84e6c0d4a59・26,255 バイト)
- 題(依頼文の1行目): # 敵対的検証依頼:YouTube台本「人型ロボットは人間より速く走ったのに、なぜ洗濯物はたためないのか(仮題)」
- codex: codex-cli 0.164.0-alpha.11.1
- モデル: gpt-6.1-sol
- 考える深さ: high
別のタブで開く保存

台本の最終版 narration.py(11版・97文)

05_11_codex_narration.py.txt15,738字・273行・python
# -*- coding: utf-8 -*-
# 台本「人型ロボットは人間より速く走ったのに、なぜ洗濯物はたためないのか」(仮題)— 謎解きの型の1本目
#   2026-10-28 11版。エイイチの指示「おれの声を作って入れたい。今ある誰かの声を流用でいい」。エイイチの言葉4つを、ハコブくんの前置き+エイイチの声(槙原の声を流用)に分けた。
#     言葉は本人の答えのとおり(口調だけ話し言葉に)。声は voice_eleven/ハコブ_11版/(ハコブ)と voice_eleven/エイイチ/(槙原)
#   2026-10-28 10版。場面の名前を分けた(hook_time・hook_answer・map2・solve_run・solve_fold)
#   2026-10-28 9版。エイイチの提案で、冒頭の感想の前に紹介の1文(ei_intro)を足し、ここでエイイチ(ドット絵)が初めて登場する。名前の札も出す。
#     声は voice_eleven/ハコブ_足し後/(文7を足して番号を付け直した写し)。元の ハコブ/ は残す
#   2026-10-28 8版。1文目「家の洗濯物には、まだ勝てていない」は意味が分かりにくい(エイイチ)→「…いるのに、家の洗濯物を任せられるロボットは、まだ見当たらない」。声は文0だけ作り直す
別のタブで開く保存

冒頭は3回書き直した

声を作ったあとの確認で、冒頭に直しが3回入りました。

  1. 「台本の最初をもっと人を惹きつけるような内容に変えてください。まだ固い内容にしすぎです」。事実と筋は5版のまま、冒頭から早とちりまでの言い回しとテンポだけを直しました(逆説の一行から入る・作り話のようですが本当の話・視聴者に聞く・犯人は足でも手でもない、の予告)
  2. 1文目「家の洗濯物には、まだ勝てていない」は意味が分かりにくい。「人間の世界記録より速く走るロボットがいるのに、家の洗濯物を任せられるロボットは、まだ見当たらない」に
  3. 「53秒あたりでエイイチの感想はとなるから、ここでおれが登場するような流れにしたらどうかな?出だしで出したいかな」。感想の前に「ここで、もう1人紹介させてください。この番組を作っている、エイイチです」を足し、ここでドット絵が真ん中に大きく出る場面(ei_intro)にしました
エイイチの登場の場面。紙色の画面の真ん中に、枠つきでドット絵が大きく出て、下に「エイイチ/この番組を作っている人」

文を足すと、声の mp3 の番号がずれます。足した文だけを ElevenLabs で作り、番号を付け直した写し(voice_eleven/ハコブ_足し後)を作って取り込みました。元のフォルダは残します。

本人の声:番組の別の声を流用して、4文だけ入れた

おれの声を作って入れたい。今ある誰かの声を流用でいいよ!

本人の声の複製は使わない決まり(video_rules.md 3-1)なので、マンガのショートで看護師さんやエンジニアの声に使っている自作の声のうち、槙原の声(Voice ID Sryf5xKmMsQChU3HsLhZ)を当てました。入れたのは本人の言葉そのままの4文です。

  1. ロボットの性能は、すごく上がっているけど、その能力は、仕事には関係なさそうだね。少なくとも、直接は。
  2. カメラが上の1台だけなので、アームやグリッパーでブロックが隠れたりして、つかむ精度や確率を上げられなくて、苦労したよ。
  3. 中国の人型ロボットの派手な動きは、出資を集める意図が強い。現場で仕事ができるかは、仕事ごとに確かめる必要があります。
  4. どの家庭でも、ということになるには、5年くらいはかかりそうかなと感じています。

narration.py では、これらの文を EI_LINES(文の頭で探す)に入れ、声を作るときは --voice を替えて --lines で番号を指定します。書き出し(assemble.py)はこの番号の文の間、ハコブくんの口の計算から声を外します。

# narration.py の末尾(EI_LINES)
EI_LINES = [i for i, seg in enumerate(SEGS) if seg[2].startswith((
    "ロボットの性能は、すごく上がっているけど",
    "カメラが上の1台だけなので",
    "中国の人型ロボットの派手な動きは",
    "どの家庭でも、ということになるには",
))]

Mac で動かした声づくりのコマンドは次のとおりです(API キーは Mac の中だけ)。

read -s ELEVENLABS_API_KEY && export ELEVENLABS_API_KEY
python3 ../_制作ベース/tts_eleven.py --voice gWJpc8whMBqnF7Y0kc9f --name ハコブ_11版 --lines 8 65 80 83
python3 ../_制作ベース/tts_eleven.py --voice Sryf5xKmMsQChU3HsLhZ --name エイイチ --lines 9 66 81 84

声を作る tts_eleven.py(Mac で動かす・_制作ベース)

06_4_tts_eleven.py.txt5,154字・114行・python
"""ハコブくんの声(ElevenLabs)で、台本を1文ずつ音声にする。エイイチの Mac で動かす(API キーを Claude に渡さないため)。

準備(1回だけ)
  1. ElevenLabs の有料プランに入る(無料プランの音声は商用に使えない)
  2. Voice Design で声を作って保存し、その声の Voice ID を控える(Voices の一覧で声を開くと出る)
  3. ターミナルで API キーを入れる(キーは画面やファイルに残さない):  export ELEVENLABS_API_KEY=(キー)

使い方(動画の作業フォルダで。例: 動画/AIエージェントの取り違え/)
別のタブで開く保存

読みが直らない文は、種を変えるか言い換える

確認用で「1:30 の人型(ひとがた)をちゃんと言えてない」と指摘が出ました。読みの辞書(ELEVEN_READ)には前から ('人型', 'ひとがた') が入っていて、ほかの文では通っていたのに、この文(S011)だけ抑揚が崩れていました。同じ文を作り直しても、ほぼ同じ声が返ってきました。

1:30の人型のひとがたの遠征変わってなくない?

原因は tts_eleven.py が毎回同じ種(--seed 7)を使っていることです。同じ文・同じ設定なら同じ読みになるので、「作り直し」は直しになりません。種を 21 と 42 に変えて2通り作っても「だめ」だったので、この文だけ「人の形をしたロボット」に言い換え、字幕も同じ言葉にしました。

  • ねらい:読みが崩れた文を、同じ文の作り直しではなく、確実に変わる手で直す
  • 変わったこと:直す順を「種を変える → 言い換える」にし、video_rules.md の 1-4 に書いた
  • 見込める効果:「作り直したのに変わらない」で往復する回数が減る

画面:札は左上、エイイチは右下に大きく

画面はパターン2(大文字型)+動きあり。出どころの札は最初、右上のロゴの下に置いていましたが、ロゴと競るので左上に移しました(「右上のロゴの下の情報は左に引っ越して」)。札を左に移したので、台本の「画面の右上に札で出します」も「左上」に直し、その1文だけ声を作り直しました。

札の約束の場面。「出どころの札(画面の左上に出します)」の下に、黒・青・灰の枠・オレンジの4つの札が縦に並ぶ

エイイチの小窓は、枠線と名前の吹き出しを外し(「右端に表示する時にはカードの枠線とエイイチをテキスト吹き出しはいらないよ」)、大きさは300pxから420pxにしました。

おれの画像も少し大きくていいね。実際にはハコブくんより背が高いし

現場の証人の場面。自分の机の上のアームの映像の上に黒い板で「上カメラ1台/アームや指でブロックが隠れる」。右下にドット絵のエイイチ

口と目を声で動かす ei_talk.py

話している時はおれの口や目が動くようにしてください。

ハコブくんと同じように、声の大きさで口を動かします。やり方は、100ドットの絵の口の所だけを描いた透明な絵を3枚作り(閉じる・いつもの笑顔・大きく開く)、声の大きさを0.1秒ごとに測って段を選び、motion_kit の data-a="fade" で重ねていく、です。1段ずつしか変えないので、閉じた口から大きく開いた口へ一気には飛びません。目は、話している間は1.6〜2.6秒おき、話していない間は3.3秒おきにまばたきします。

口の3段。左から閉じる・いつもの笑顔・大きく開く。元の絵の口の線と歯だけを肌の色で消し、その上に口を描く

最初の版は、閉じた口を作るときに口のまわりを一色の肌色で塗ったので、顔に四角い跡が出ました。元の口の線(黒)と歯(白)だけを肌の色に置き換える形に直すと、まわりの影が残って自然になりました。歯の所が透明なままだと、背景に映像がある場面で透けるので、顔の中の小さな穴は白で埋めています。

ei_talk.py(口と目を動かす部品)

07_ei_talk.py_ei_talk.py.txt5,519字・162行・python
# エイイチ(ドット絵)が話している間、口と目を動かす部品(2026-10-28 エイイチの指示「話している時はおれの口や目が動くように」)
# 口は3段(閉じる・いつもの笑顔・大きく開く)を、声の大きさで 0.1 秒ごとに選ぶ(1段ずつしか変えない)。
# 目は、話し始めと、話している間ときどきまばたきする。
# どれも 100 ドットの絵の「その部分だけ」を描いた透明な PNG を、時間で重ねていく(motion_kit の data-a="fade")。
import os, io, base64, wave
import numpy as np
from PIL import Image
別のタブで開く保存

指さしは大事な所だけ

ずっと指さしてるのはおかしいので、指差すときは大事な時だけにしてください。

変な顔の時があるので修正(口が曲がってる)

見立ての場面では、最初はポーズを場面ごとに固定していました(指さす・うなずく・ひらめく)。指さしを「出資を集める意図が強い」と言い切る所の約3秒と、「別のものさしで」の頭の約3秒に限り、ふだんは腕組みにしました。口が曲がって見えたのは、うなずく絵の元の口が左右でずれていて、その上に話す口を重ねたためです。うなずく絵は話す場面には使わないことにしました。

絵を途中で替えるとき、最初は新しい絵を上に重ねるだけにしていたので、新しい絵の透明な所(腕組みの絵の、指さしの手があった所)から前の絵の手が見えていました。絵ごとにまとまり(div)を作り、替える時刻に前のまとまりを消して(data-a="out")次を出す形にしました。motion_kit.py に out(消える)を足しています。

// motion_kit.py の JS に足した1行
else if (a === 'out') { o = 1 - E(p); }   // 消える(2026-10-28 エイイチのドット絵の絵の入れ替えで足した)
見立ての場面。「派手な動きは/出資集め」の文字と、右下で指をさすエイイチ。字幕は「中国の人型ロボットの派手な動きは、出資を集める意図が強い。」

scenes.py(場面の図・札・エイイチの小窓)

08_sec01.py.txt18,846字・294行・python
# -*- coding: utf-8 -*-
# 動画「人型ロボットは人間より速く走ったのに、なぜ洗濯物はたためないのか(仮題)」の場面(謎解きの型の1本目)
PATTERN = 2   # 画面パターン2(大文字型・video_rules.md 4-4c)。2026-10-28 エイイチが決定(大文字型+動きあり)
MOVE = True   # 画面型の動き(4-4d)を使う
# 画面の文字は「名前・数字・一言」だけ。中身は声と字幕に任せる
# 他社のロボット・大会の映像や写真・ロゴは使わない(許可がないため)。図はコードで描いた模式図だけ
# 謎解きの型(2026-10-28):
#   - 出どころの札(左上): 大会や会社の発表(黒)/ニュース(青)/論文や本(灰の枠)/エイイチの記録と見立て(オレンジ)
別のタブで開く保存

sound.py(BGM と効果音の置き方)

# 音の置き方(audio_mix.py が読む。書き方は audio_mix.py の先頭)
# 2026-10-28 「世界記録と洗濯物」: 「何台入れたら店は変わる」の sound.py を写した(同じ曲・同じ決まり)。謎解きの型の1本目
#   足したもの: エイイチ(ドット絵)が初めて出る所にぽん(se_pop)、「犯人は足でも手でもない」にちん(se_ding)
#   章の音(ポロロン)の場面を、この回の章(今日の謎・手がかり3つ・謎が解ける・見立て・答え・アウトロ)に合わせた

# 大きさ: 話している間はナレーションより23dB小さく、間は16dB小さく
BGM = [
    dict(file='sound/bgm_明るいB_2.mp3', start=0, end=None, level=-23, gap=-16, fade_in=0.6, fade_out=3.0),
]

SE = [
    # (文番号(0から), 文の頭から何秒後, 音, ナレーションより何dB)
    (7, 0.0, 'se_pop', -8),     # ei_intro: エイイチが右下にぽんと出る
    (18, 0.0, 'se_ding', -10),  # teaser: 犯人は、足でも手でもない
]

# 場面が切り替わるたびに「ホワーン」(se_rise)。同じ人・同じ映像が続く所は鳴らさない
SCENE_SE = dict(file='se_rise', level=-6, offset=-0.15, skip=['title_eiichi', 'ei_react', 'ei_intro', 'teaser'])

# 大きな流れの変わり目は、ホワーンの代わりに別の音(自己紹介はキラリン・ほかはポロロン)
CHAPTER_SE = dict(file='se_chapter_marimba', files={'title': 'se_chapter_glock'}, level=-8, offset=-0.3,
                  scenes=['title', 'question', 'c1', 'c2', 'c3', 'solve', 'mitate', 'answer', 'outro'])

確認用で見つかった4つの不具合

字幕の縁取りの穴。 「む」の輪や「。」の中に、縁取りの黒で埋まらない白い点が残っていました(「「む」の黒ふちのゴミを削除して(他の文字でも見受けられます)」)。2026-10-19 に決めた「縁取りの中の穴は黒で埋める」が、本編の字幕にはまだ入っていませんでした。render.py に fill_holes を足し、字幕の画像を書いた直後に、画面の端とつながらない小さな透明な所を縁取りの色で塗ります。

直す前の字幕「なぜ、たたむのは、まだなのか。」。「む」の輪と「。」の中に白い点が残っている
直した後の同じ字幕。輪の中が黒で埋まっている
# render.py に足した fill_holes
def fill_holes(path, ink=(13, 13, 13), maxarea=400):
    """縁取りの中の穴(「。」「む」の輪など)を縁取りの色で埋める(2026-10-19 の決まり・2026-10-28 に字幕へ入れた)。
    縁取りに囲まれた透明な所(画面の端とつながらない・小さい所)だけを塗る"""
    import numpy as _np
    from PIL import Image as _Im
    from scipy import ndimage as _nd
    a = _np.array(_Im.open(path).convert('RGBA')).astype(_np.float32)
    al = a[..., 3] / 255.0
    lab, n = _nd.label(al < 0.98)
    if not n:
        return
    edge = set(_np.unique(_np.concatenate([lab[0], lab[-1], lab[:, 0], lab[:, -1]]))) | {0}
    sz = _nd.sum(_np.ones_like(al), lab, range(1, n + 1))
    keep = _np.array([0] + [(k not in edge and sz[k - 1] <= maxarea) for k in range(1, n + 1)])
    m = keep[lab].astype(bool)
    if not m.any():
        return
    for c in range(3):
        a[..., c][m] = a[..., c][m] * al[m] + ink[c] * (1 - al[m])
    a[..., 3][m] = 255
    _Im.fromarray(a.clip(0, 255).astype(_np.uint8)).save(path)

札の重なり。 4つの札を縦に並べる場面で、札どうしが重なっていました(「全部重なっっているのを修正」)。札の行の高さを決めていなかったためで、display:inline-block と行の高さを入れて間をあけました。

ハコブくんの口。 エイイチの声の間はハコブくんの口を止める決まりを assemble.py に入れていましたが、最初の確認用では効いていませんでした。from narration import EI_LINES が、作業フォルダではなく _制作ベース の見本の narration.py を読むことがあったためです。ファイルの場所を指定して読む形に直しました。

動きの場面の指紋。 動きの場面(motion_kit.py が書き出す mp4)を作り直しても、全体の書き出しで前の断片が使われていました。assemble.py は断片のファイル名に中身の指紋を入れて作り直しを省きますが、指紋に映像の中身が入っていませんでした。映像の大きさと更新時刻を指紋に足しました。

# assemble.py の直した所
# ハコブくん以外の声(narration.py の EI_LINES)の文は、口を動かさない(2026-10-28「世界記録と洗濯物」)
# 作業フォルダの narration.py を名前で読む(_制作ベースにも同じ名前の見本があり、import だとそちらを読むことがある)
import importlib.util as _ilu
_sp = _ilu.spec_from_file_location('_narr_here', os.path.join(os.getcwd(), 'narration.py'))
_nm = _ilu.module_from_spec(_sp); _sp.loader.exec_module(_nm)
EI_LINES = list(getattr(_nm, 'EI_LINES', []))
print('ハコブくんの口を止める文:', EI_LINES)
mouth_pcm = pcm.astype(np.float32) / 32768.0
for o in idx:
    if o['i'] in EI_LINES:
        a0 = int(o['start'] / FPS * SR); a1 = int((o['start'] + o['frames']) / FPS * SR)
        mouth_pcm[a0:a1] = 0
params = hk.animate(timeline, mouth_pcm)
# assemble.py の job() の指紋に足した2行
    if VIDEO.get(o['scene']) and os.path.exists(VIDEO[o['scene']][0]):   # 映像の中身が変わったら作り直す(動きの場面を書き出し直しても、前の断片が使われていた。2026-10-28)
        _st = os.stat(VIDEO[o['scene']][0]); fp.append((_st.st_size, int(_st.st_mtime)))

よその映像の使い方を決めた

作業の途中で、ほかのチャンネルが Unitree の宣伝映像や ABC7 の報道映像を背景にずっと流している動画を見せられ、「規約的にどうなんですか」と聞かれました。答えは、引用の条件(主従・明瞭な区分・必然性・出所・改変しない)を満たしにくく、YouTube の「再利用されたコンテンツ」の決まりで収益化を断られやすい、でした。

自分のはベースにしつつもスポットで他の映像も使いたいね7:3くらいの割合かな

video_rules.md に「6-1 よその映像の使い方」を足しました。自分の映像を土台に、よその映像はスポットで 7:3 くらい。使ってよいのは、会社が配っている素材を利用条件の範囲で使う、引用の条件を満たして短く画面の中の窓で見せる、の2通りだけ。背景にずっと流さない。使ったクリップは台帳に1行ずつ書く。この動画では、大会や会社のロボットの映像は使わず、自分の机の上の映像だけを使っています。

サムネイルとタイトル

サムネイルは2案作りました。案Aは自分の机の上のアームの写真、案Bはコードで描いたトラックとタオルの山(生成AIの画像は使っていません)。エイイチは案Bを選びました。アームの写真は「走る」とも「たたむ」とも関係がなく、文字だけで引っぱる形になっていたためです。

サムネイル案A。自分の机の上のロボットアームの写真の上に「人間の世界記録より速いのに/走れるのに/洗濯物はまだ/謎を解く」、右下にハコブくんと「なぜ?」の札
サムネイル案B(採用)。コードで描いたオレンジのトラックと青いタオルの山、右上にストップウォッチ。文字は案Aと同じ

タイトルは3案から「走るのは人間超え、たたむのはまだ。人型ロボットの謎を3つの手がかりで解く」に決まりました。

サムネイルの背景(コードで描いた HTML)

<!doctype html><html><head><meta charset="utf-8"><style>
*{margin:0}body{width:1920px;height:1080px;background:#F5F5F0;font-family:'Noto Sans CJK JP',sans-serif;overflow:hidden;position:relative}
</style></head><body>
<svg width="1920" height="1080" viewBox="0 0 1920 1080">
 <defs><linearGradient id="sky" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#F5F5F0"/><stop offset="1" stop-color="#E9E9E2"/></linearGradient></defs>
 <rect width="1920" height="1080" fill="url(#sky)"/>
 <!-- 右: トラック(遠近)-->
 <g transform="translate(0,0)">
  <path d="M700,1080 L1920,1080 L1920,560 L1300,560 Z" fill="#C4471F" opacity=".92"/>
  <path d="M760,1080 L1920,1080 L1920,600 L1330,600 Z" fill="none"/>
  <g stroke="#F5F5F0" stroke-width="6" opacity=".85">
   <path d="M1300,560 L700,1080" /><path d="M1455,560 L1005,1080"/><path d="M1610,560 L1310,1080"/><path d="M1765,560 L1615,1080"/>
  </g>
  <g stroke="#F5F5F0" stroke-width="5" opacity=".6"><path d="M1240,620 L1920,620"/><path d="M1150,700 L1920,700"/><path d="M1020,810 L1920,810"/><path d="M850,950 L1920,950"/></g>
 </g>
 <!-- 右上: ストップウォッチ -->
 <g transform="translate(1600,250)">
  <rect x="-30" y="-178" width="60" height="40" rx="8" fill="#0D0D0D"/>
  <circle r="150" fill="#fff" stroke="#0D0D0D" stroke-width="16"/>
  <circle r="118" fill="none" stroke="#D6D6D1" stroke-width="4"/>
  <g stroke="#0D0D0D" stroke-width="8" stroke-linecap="round"><path d="M0,0 L0,-95"/><path d="M0,0 L62,38"/></g>
  <circle r="12" fill="#C4471F"/>
 </g>
 <!-- 左: たたんだタオルの山 -->
 <g transform="translate(900,600)">
  <g fill="#1A6C98"><rect x="0" y="300" width="560" height="120" rx="24"/><rect x="0" y="300" width="560" height="40" rx="20" fill="#15587C"/></g>
  <g fill="#F5F5F0"><rect x="30" y="190" width="520" height="110" rx="22" stroke="#0D0D0D" stroke-width="8"/><rect x="30" y="190" width="520" height="34" rx="17" fill="#D6D6D1"/></g>
  <g fill="#1A6C98"><rect x="10" y="80" width="540" height="110" rx="22"/><rect x="10" y="80" width="540" height="34" rx="17" fill="#15587C"/></g>
  <!-- 上にくしゃっとした1枚 -->
  <path d="M60,80 C120,-40 260,-20 330,30 C400,-30 520,0 540,60 C560,90 520,100 480,86 C420,110 300,100 240,96 C180,120 90,110 60,80 Z" fill="#F5F5F0" stroke="#0D0D0D" stroke-width="8" stroke-linejoin="round"/>
  <path d="M130,70 C190,40 260,60 300,45" fill="none" stroke="#0D0D0D" stroke-width="5" stroke-linecap="round" opacity=".5"/>
 </g>
</svg></body></html>

thumb.py(サムネイルの文言)

# サムネイルの文言と背景(thumbnail.py が読む)。2026-10-28「世界記録と洗濯物」(謎解きの型の1本目)
# 案A: 背景はエイイチの机の上のアーム(自前の映像 DAY124 の1コマ)。案B: コードで描いた「トラックとタオル」(サムネ素材/code_走るとたたむ.html)。生成AIの画像は使っていない
import os
PHOTO = os.environ.get('THUMB_BG', 'サムネ素材/code_走るとたたむ.png')   # 2026-10-28 エイイチが案Bに決定
PHOTO_POS_FULL = '50% 50%'
HAKOBU = True
LABEL = 'なぜ?'
KICKER = '人間の世界記録より速いのに'
LINES = ['走れるのに', '<span class="red">洗濯物はまだ</span>', '謎を解く']
VARIANTS = ['photo']
SIZE_L1, SIZE_L2, SIZE_L3 = 170, 230, 150
TXT_TOP = 70
HK_BOTTOM = -300
LABEL_BOTTOM = 158
LABEL_RIGHT = 450
LABEL_TAIL = 'bubble'
LABEL_FS = 60

概要欄と投稿文

概要欄には、ナレーションが AI 音声であることに加えて、「エイイチの声も AI 音声で、本人の声ではなく番組で使っている別の声を当てている」「右下のドット絵は生成AIで作った絵をもとに手で直したもの」「大会や会社のロボットの映像は使っていない」を書きました。目次は15個、字数は3,903字です。

概要欄_下書き.md

09_sec01.md4,148字・80行・text
<!--
YouTube の概要欄の下書き(2026-10-28「世界記録と洗濯物」・謎解きの型の1本目)。{t:文番号} は、その文が始まる時間に置きかわる(文番号は 0 から数える tts の番号)。
python3 <_制作ベース>/description.py で 概要欄.txt を作り、それを貼る。
エイイチの声は 槙原の声(ElevenLabs の自作の声)を流用。ドット絵は ChatGPT で作った絵を元に手で直した。
-->
2026年4月、北京。人型ロボットのハーフマラソンで、優勝したロボットのタイムは50分26秒。人間の男子の世界記録候補(56分51秒・公認手続き中)より速いタイムです。なのに、家で洗濯物を任せられる人型ロボットは、今日までに確かめた公開資料では、まだ見当たりません。走るのは人間を追い越したのに、なぜ、たたむのは、まだなのか。この逆転を、3つの手がかりで解いていきます。

今日の謎:走るのは人間を追い越したのに、なぜ、たたむのは、まだなのか
別のタブで開く保存

動画の中で確かめる3つ

動画の最後で、人型ロボットのすごい動画を次に見たときに確かめる3つを渡しています。

  1. 自分で動いているのか、人が遠くから操作しているのか
  2. 何回中何回できたのか
  3. お手本の数は、どれだけ集めたのか
動画の終わりの場面。「すごい動画を見たら、確かめる3つ」の下に「1 自分で動く? 2 何回中何回? 3 お手本の数は?」

この3つは、謎解きの答えをそのまま裏返したものです。走れるのに、たためない理由が「練習する場所・相手の形・お手本の数」なら、次の動画を見るときに確かめるのもその3つになります。

保存した場所

  • 作り方のファイル(narration.py・scenes.py・ei_talk.py・sound.py・thumb.py・make_docs.py・codex の依頼と結果・台本・概要欄): iCloud 動画/世界記録と洗濯物/
  • 動画(アップロード用・確認用): KIOXIA videos/世界記録と洗濯物/
  • 動画の作り方の決まり: _制作ベース/video_rules.md(94回目・1-4 謎解きの型・6-1 よその映像の使い方)
  • X の予約の文: GitHub PixelstoMotors/r2r2r-content の sns/VIDEO_world-record-and-laundry_sns_posts.json