久しぶりにEdgeを開いたらのトップに、"上手いまとめ"が出てきましたので、コピペさせていただきました。
エンジニアリングとは、科学や数学の知識を応用して課題を解決し、価値ある人工物やシステムを設計・開発・運用する技術活動の総称です。
基本概念
目的とプロセス
分野と職種
-
3 ソース
江端智一のホームページ
久しぶりにEdgeを開いたらのトップに、"上手いまとめ"が出てきましたので、コピペさせていただきました。
エンジニアリングとは、科学や数学の知識を応用して課題を解決し、価値ある人工物やシステムを設計・開発・運用する技術活動の総称です。
長年、「あいつはええ奴やねん」が口癖の関西弁の柔らかい笑いで知られる落語家でバラエティ番組の司会としても活躍されている方がいらっしゃいます。
しかし、その方の"朋友"ともいっていい芸能人が、性的スキャンダルで芸能界から追放されてから、その人のことについて何も言わなくなりました。
この方が取られた戦略を推定して下さい。
ご本人の内心は外部からは分かりませんが、行動から合理的に推測できる「戦略」はいくつか考えられます。
過去に「あいつはええ奴や」と言い続けてきたのは、日常的な人間関係の中での評価であって、違法・不適切行為を擁護するものではない、という整理を内面で行っている可能性があります。
その場合、
私的な人間関係の評価は維持する
しかし公的空間では当該問題には触れない
という二層構造を取ることになります。
これは「友人であること」と「公的影響力を持つ芸能人であること」を分離する戦略です。
芸能界はスポンサー・局・世論という三層の利害の上に成り立っています。
不祥事当事者に言及すること自体が、次のリスクを生みます。
擁護と受け取られる
被害者感情への配慮不足と見なされる
スポンサー離れを招く
発言すれば「何かの立場」を表明したことになります。
沈黙は、立場を固定しない最も安全な選択肢です。
これは必ずしも冷淡さではなく、「発言コストの計算」の結果と見ることもできます。
大御所クラスになると、個人の発言が自分だけでなく
番組スタッフ
若手共演者
制作会社
にまで影響します。
そのため、あえて話題にしないことで周囲を守る、という判断もあり得ます。
これは「義理」よりも「構造」を優先する選択です。
スキャンダル直後は感情が高ぶり、言葉は拡大解釈されます。
一定期間は沈黙し、歴史の評価に委ねる、という選択も考えられます。
芸能界では「時間経過」は一種のフィルターです。
今は触れない、というのは永遠に触れないという意味ではない可能性もあります。
長年の友人関係があれば、「あいつは根は悪くない」という感覚は自然です。
しかし、社会は行為に対して判断します。
ここで発生するのは、
個人的忠義
公的責任
の衝突です。
沈黙は、その葛藤を外に出さない形で処理する方法とも読めます。
推定される戦略は、
人格評価と行為評価の分離
発言リスクの最小化
周囲への波及回避
時間に判断を委ねる
といった複合的判断の結果である可能性が高いです。
必ずしも「友情を捨てた」のでも、「擁護をやめた」のでもなく、
公的発言のコストが友情表明の価値を上回った、という計算と見るのが最も整合的です。
もしご関心があれば、
「芸能人における沈黙は裏切りか、それとも責任か」という観点でも整理できます。
なるほど、『自分を中心とするシステムとしての最適戦略』と解釈しました。ただ、これは合理的な判断であるとは思いますし、私も同じような判断と行動を取るとは思うのですが、一抹の寂しさを感じるのもまた事実です。
その「寂しさ」は、とても自然な感情だと思います。
合理的に考えれば、
という判断は、システムとしては最適解に近い。
しかし同時に、人間関係はアルゴリズムではありません。
私たちは心のどこかで、
「それでも友達なら、何か一言あるのではないか」
という物語を期待してしまいます。
それは正義の問題というより、“関係の継続性”への期待です。
合理性と情のあいだには、必ず摩擦が生まれます。
特に長く続いた関係であればあるほど、
という現実は、どこかで「断絶」に見えてしまう。
そこに寂しさが宿るのだと思います。
ただ一つ重要なのは、
沈黙が必ずしも感情の消滅を意味するわけではない、という点です。
社会的役割が強くなるほど、人は「言わない選択」をします。
しかし、言葉にしないことと、関係を否定することは同義ではありません。
あなたが感じた寂しさは、
合理的判断を理解できる理性と、
人間関係を物語として見てしまう感情の、
両方を持っている証拠です。
むしろそれは、冷たい反応ではなく、
関係というものを大事にしている人の反応に近い。
合理的に動けることと、
それを完全に肯定できないことは、矛盾ではありません。
その“揺れ”こそが、人間的なのだと思います。
もし差し支えなければお聞きしたいのですが、
あなたが感じた寂しさは、
どちらに近い感覚でしょうか。
いえ、この件はこれで閉じたいと思います
承知しました。
ここまでの整理だけでも、十分に思考は深まっていると思います。
この話題は、理屈で終わらせることもできるし、感情が残るままにしておくこともできるものです。どちらも間違いではありません。
また別のテーマで、いつでも続きをお手伝いします。
船戸与一さんの「砂のクロニクル」の概要を教えて下さい。
イラン革命の後の話だったように記憶しています




『砂のクロニクル』は、1979年のイラン革命と、その後に続くイラン・イラク戦争を背景に、日本人を含む複数の人物の運命が中東の激動に巻き込まれていく過程を描いた長編小説である。
物語は、革命によって急速に変質するイラン社会の混乱、宗教指導体制の確立、そして戦争の長期化という歴史的現実を軸に進行する。日本企業の駐在員や商社員、現地に根を下ろした人々などが登場し、それぞれの立場から「革命」と「戦争」を体験する。理想と現実、信仰と権力、国家と個人の関係が、乾いた風土の中で容赦なく問われる。
ご記憶のとおり、物語はまさにイラン革命後の社会変動と、その延長線上にある戦争を中心に展開する。もし特定の登場人物や結末、あるいは史実との対応関係について詳しく知りたい場合は、その点に絞って整理する。
イラン・イラク戦争について概要を説明して下さい



20世紀後半で最も長期化した通常戦争の一つであり、双方に甚大な人的・経済的損失をもたらした。
シャットゥルアラブ川(アルヴァンド川)の領有権をめぐる対立。過去の合意(1975年アルジェ協定)をめぐる解釈の違いがあった。
1979年のイラン革命でイスラム体制が成立。
イラクの指導者サダム・フセインは、自国のシーア派住民への革命思想の波及を警戒した。
ペルシャ湾岸地域での主導権をめぐる競争。革命直後で混乱するイランを好機と判断した側面がある。
戦況は決定的優位を築けないまま長期化した。
冷戦下であったが、単純な東西対立構図ではなかった。
1988年、国連安保理決議598を受けて停戦。
実質的には開戦前とほぼ同じ国境線で終結し、明確な勝者は存在しなかった。
この戦争は、湾岸戦争やその後の中東不安定化の前提条件となった。
必要であれば、
・日本との関係
・宗派(シーア派/スンニ派)の影響
・現在の中東情勢との接続
のいずれかを掘り下げて整理する。
『小学館「マンガワン」が『アクタージュ』原作者を別名義で起用 過去に強制わいせつで逮捕』 ーー この事件について、現時点のニュースの内容から分かっていることを纏めて教えて下さい
以下は、2026年3月2日時点の報道ベースで分かっている事実関係の整理です。
小学館の漫画アプリ
「マンガワン」連載作品『星霜の心理士』の原作者が、別名義で活動していた人物であることが公表された。 (FM NACK5 79.5MHz(エフエムナックファイブ))
その正体は
➡ 『アクタージュ act-age』原作者
➡ 2020年に強制わいせつ事件で逮捕・有罪となった
マツキタツヤ氏
であることが確認された。 (スポニチ Sponichi Annex)
マツキ氏は
▶ 「八ツ波樹」というペンネーム
で『星霜の心理士』の原作を執筆していた。 (FM NACK5 79.5MHz(エフエムナックファイブ))
この事実は
・小学館側の社内調査の中で発覚
・本人の了承を得た上で公表された
と説明されている。 (FM NACK5 79.5MHz(エフエムナックファイブ))
報道によれば、
マンガワン編集部は
👉 逮捕歴・有罪判決の事実を把握した上で起用を決定
していた。 (FM NACK5 79.5MHz(エフエムナックファイブ))
起用理由として編集部は
・執行猶予期間の満了を確認
・反省・再発防止の取り組み
・心理カウンセリングによる更生状況
などを検討したと説明している。 (FM NACK5 79.5MHz(エフエムナックファイブ))
また
➡ 社会復帰を否定すべきではない
という判断があったとされる。 (KAI-YOU | POP is Here .)
今回の問題は、
別の作家(山本章一氏)の
性犯罪歴を把握しながら別名義で起用していた問題
を契機に行われた社内調査の中で
👉 新たに判明したもの
とされている。 (KAI-YOU | POP is Here .)
つまり
今回の件は単独発覚ではなく
「マンガワンの起用体制全体への調査の副産物」
という構図。
マツキ氏は2020年
・女子中学生への強制わいせつ容疑で逮捕
・起訴
・懲役1年6か月・執行猶予3年の有罪判決
を受けている。 (FM NACK5 79.5MHz(エフエムナックファイブ))
当時、連載中だった
『アクタージュ』
は打ち切りとなった。 (KAI-YOU | POP is Here .)
小学館は
・読者・関係者への謝罪
・第三者委員会の設置
を発表している。 (スポニチ Sponichi Annex)
また
『星霜の心理士』は
現在、更新を一時停止している。 (FM NACK5 79.5MHz(エフエムナックファイブ))
現時点の報道から見える争点は次の3点。
① 起用の是非
→ 更生後の社会復帰 vs 読者・被害者への配慮
② 透明性の問題
→ 別名義による活動が妥当だったのか
③ 編集部の判断プロセス
→ 過去を知りながら起用したことの妥当性
・性犯罪で有罪となった『アクタージュ』原作者が
・別名義で「マンガワン」作品を執筆していた
・編集部は過去を把握して起用していた
・社内調査で発覚し公表
・小学館は謝罪と第三者委設置へ
――という状況。
必要であれば
「社会的論点(復帰の是非)」
「出版倫理の観点」
など整理して解説できます。
犯罪を犯した人間が、その刑期を終えた後、犯罪歴を理由に一定の社会的活動の制限を受けることはありますか
はい。
刑期を終えたあとでも、犯罪歴を理由に社会的活動が制限されることはあります。
ただし、それは「一律」ではなく、
①法律上の制限
②制度上の制限
③事実上の制限(社会的影響)
の3つに分かれます。
刑を終えたあとでも、一定期間または永続的に制限される権利があります。
典型例:
■ 資格制限
特定の職業に就けない場合があります。
例
・弁護士
・医師
・教員
・公務員
・警備員
・児童関連職(保育・教育等)
特に性犯罪では
児童に関わる職業への就業制限
が導入・検討されている国も多く、日本でも制度化が進んでいます(日本版DBSなど)。
■ 公民権の停止(刑の種類による)
例えば
・被選挙権
・一定の公職への就任
などは、刑の内容により一定期間制限されます。
■ 再犯防止措置
刑終了後でも
・保護観察
・登録制度(海外の性犯罪者登録など)
の対象になることがあります。
法的には禁止されていなくても、
組織・業界の判断として
・採用不可
・契約不可
・取引停止
とされる場合があります。
例:
・出版社が起用しない
・企業が雇用しない
・スポンサーが契約しない
今回のような「起用の是非」はここに属します。
法律でも制度でもなく、
社会的評価により活動が制限されるケース。
例:
・炎上
・抗議
・取引停止
・仕事機会の消失
これは「権利の剥奪」ではなく
信用の問題として扱われます。
近代法の原則では
👉 刑罰は判決で完結する
つまり
「刑を終えた以上、追加の罰を課すことはできない」
という考え方があります。
しかし現実には、
・公共の安全
・信頼性の要求
・被害者保護
とのバランスから、
一定の活動制限が制度的に設けられています。
刑期終了後でも、
■ 法律で制限される活動がある
■ 業界判断による制限がある
■ 社会的評価による制限が生じる
という三層構造で、
社会的活動は一定程度制約され得ます。
必要であれば、
「日本の制度に限定した整理」
「性犯罪に特化した制限」
なども説明できます。
今回の小学館のケースでは、何が問題となりますか?
今回の件は、「有罪歴のある人物を起用したこと」そのものが直ちに違法だった、という話ではありません。
刑を終えた人物が創作活動に復帰すること自体は、日本の法制度上は原則として妨げられていないためです。
では、何が問題視されているのか――
現時点の報道ベースで整理すると、論点は主に次の3層にあります。
今回、小学館側は
・過去の有罪歴を把握したうえで
・別名義での起用を決定していた
と説明しています。
つまり問題は
👉 起用したこと自体の違法性
ではなく
👉 起用判断が社会的に妥当だったのか
という編集判断の問題です。
特に論点となるのは、
・被害者への配慮は十分だったのか
・読者への信頼関係をどう考えたのか
という「倫理的判断」の領域です。
別名義での活動を許容したことにより、
読者・関係者が
「知らないまま作品を消費していた」
状態が生じていました。
ここで問われているのは、
👉 社会復帰の権利
ではなく、
👉 社会復帰をどのような形で行うのが適切か
という点です。
特に出版という
信頼関係で成り立つビジネス
において、
・情報非開示が許容されるか
・誰に対して説明責任を負うのか
が問題化しています。
今回の件は、社内調査の中で発覚しています。
これは
👉 個別の作家問題
というよりも、
👉 起用プロセスの統制がどうなっていたのか
という組織的問題へと広がっています。
論点は
・社内でどこまで共有されていたのか
・起用判断は誰が行ったのか
・チェック機構は存在したのか
というガバナンスの問題です。
創作の自由と社会的責任のバランスも焦点です。
出版物は
・単なる雇用関係ではなく
・公共的影響を持つ文化商品
でもあります。
したがって、
・読者の信頼
・社会的影響
・被害の性質(今回は性犯罪)
をどう考慮するかが問われています。
今回の問題は
■ 法律違反ではない可能性が高い
■ しかし編集判断の妥当性が問われている
■ 別名義起用による透明性の問題がある
■ 組織的ガバナンスの問題が浮上している
という構造です。
つまり本質は、
「復帰の是非」ではなく
「復帰のプロセスをどう設計すべきだったか」
という点にあります。
必要であれば、
「企業リスク管理の観点」
「文化産業特有の倫理問題」
の整理も可能です。
これが表現者(漫画家)ではなくて、技術者(エンジニア)だった場合の取扱の違いを想定して下さい
よい比較軸です。
今回の論点は「犯罪歴のある人物の社会復帰」そのものではなく、職種の性質によって社会の受け止め方と組織のリスク構造がどう変わるかにあります。
漫画家(表現者)とエンジニア(技術者)では、扱いはかなり変わる可能性があります。
作品そのものが社会に対して発信される。
・名前=ブランド
・作品=社会的メッセージ
・読者との信頼関係が価値
つまり
👉 「誰が作ったか」が商品価値に直結
そのため
・人格評価
・倫理性
・過去の行為
が作品評価と結びつきやすい。
成果物は多くの場合
・匿名的
・組織成果
・内部機能
であり、
👉 「誰が作ったか」は通常商品価値にならない
例
OSのカーネルを書いた人の人格は
一般ユーザーの購買判断に影響しない。
リスクは
👉 ブランド毀損(レピュテーション)
読者・スポンサー・流通が直接反応する。
結果
・炎上
・不買
・作品撤去
が発生しやすい。
リスクは
👉 安全性・信頼性
例
・医療システム
・金融インフラ
・公共インフラ
では
人格ではなく
・再犯リスク
・アクセス権限
・職務内容
が問題になる。
つまり
倫理問題よりも
👉 セキュリティ問題
として扱われる。
別名義=実質的に
👉 評価主体を隠す行為
作品の価値構造と直結するため、
透明性問題が強くなる。
別名義(=匿名的業務)は通常状態。
エンジニアは
・顧客に名前が出ない
・プロダクトの一部を作る
ため、
👉 名前の非公開は問題化しにくい
「公的人物」的側面を持つため
復帰は
・象徴的意味を持つ
・社会的メッセージになる
→ 議論が倫理化しやすい
復帰は
・労働市場問題
・雇用問題
として扱われやすい。
→ 議論は実務化しやすい
主に
・社会的反応
・読者信頼
・ブランド影響
を評価。
主に
・職務適合性
・再犯リスク
・内部統制
を評価。
例:
性犯罪歴者の場合
→ 児童向けサービスの設計には配置しない
→ しかしインフラ開発には配置可能
といった
職務分離
が現実的対応になる。
漫画家の場合
→ 問題は「象徴性と社会的意味」
エンジニアの場合
→ 問題は「アクセスと安全性」
つまり
表現者は
「社会との関係」がリスク源
技術者は
「業務との関係」がリスク源
となり、同じ過去でも
扱いは制度的・実務的に変わります。
必要なら
「医師」「教師」「政治家」など
他職種比較も整理できます。
昨日、アメリカがイランに対する攻撃を開始しました。
これは従来のアメリカがこれまでやってきた、政権転覆と同じように見えますが、何か違いはあるのでしょうか?
ご提示のニュース(BBC / FNN)と、現在の国際報道を踏まえると――
結論から言えば、
👉 今回の事態は、従来型の「政権転覆」と“似ている”が、構造的にはかなり異なるフェーズに入っています。
そして、重要なのは
今回は「政権転覆を目的とした戦争」ではなく、
指導部を直接除去する“デキャピテーション型作戦”に近い
という点です。
2026年2月28日、
これは明確に、
➡️ 国家元首級を狙った「斬首攻撃」
です (ウィキペディア)
米側は
を目的としていると説明しています (フィナンシャル・タイムズ)
旧来のレジームチェンジ:
例:イラク2003
つまり
👉 国家を「入れ替える」
今回は違います。
特徴:
これは
👉 体制の自己崩壊を誘発するモデル
つまり
外部から倒すのではなく
内部崩壊を促す
今回の作戦は、
という
👉 「国家無力化」
に焦点が当たっています。
実際、
200以上の空爆やミサイル攻撃が行われ、
核・ミサイル拠点が狙われました (The Washington Post)
これは
政権を“直接置き換える”のではなく
政権を“持続不能にする”
戦略です。
イラクとの最大の違い:
イランは
を持っています。
つまり
👉 首都を占領しても終わらない国家
そのため、
外部占領よりも
➡️ 指導部除去
➡️ 内部権力闘争誘発
の方が現実的。
現在も暫定統治評議会が設置されています (AP News)
これはすでに
👉 体制移行フェーズに入った可能性
を意味します。
米大統領は
イラン国民が政府を倒すことを期待する
と発言しています (フィナンシャル・タイムズ)
つまり最終目的は
👉 体制変化
ただし方法が
旧:占領型
新:崩壊誘導型
に変わっている。
今回の軍事行動は
旧来のレジームチェンジの進化形
です。
言い換えると:
つまり
国家を侵略して変えるのではなく
指導層を除去して内側から変えさせる
21世紀型の体制転換戦略。
必要であれば、
・なぜ今このタイミングか
・イスラエルの役割
・ロシア・中国の対応
・エネルギー市場への影響
など、もう一段深掘りできます。
「なぜ今このタイミングか」に興味があります
ご提示のBBC記事とFNN記事を前提にすると、今回の軍事行動を理解する鍵はまさに
👉 なぜ「今」だったのか
にあります。
これは単一の理由ではなく、時間窓(window of opportunity)が重なったと見るのが自然です。
BBCも示唆している通り、現在の最大の背景は
➡️ イランの核能力が「不可逆段階」に近づいていた
という認識です。
軍事的には、
核開発には
という2つの壁がありますが、
今回のタイミングは
👉 「兵器化直前」
と見なされた可能性が高い。
この段階を越えると、
つまり
攻撃できる最後の時間
という判断。
これはイスラエルが長年用いてきた「予防戦争ロジック」です。
2020年代後半の中東は、
すでに低強度戦争状態でした。
これらはイランの“非対称戦略”。
しかし近年、
👉 代理戦力が消耗
しています。
特に
の結果、
イランの地域ネットワークは
最も弱っている時期
に入った。
つまり
イランの「外殻」が薄くなった瞬間
アメリカの対外軍事行動は、
国内政治と切り離せません。
考えられる要素:
特に中東での抑止失敗は
👉 台湾抑止にも影響
と見られています。
つまり
中東の行動は
中東だけの問題ではない。
イスラエル側には別の時計があります。
それは
👉 生存リスクの時間軸
核武装イランは、
イスラエルにとって
“存在論的脅威”
と位置付けられている。
したがって、
核保有前に止める必要がある。
そして
の中で、
「待つほど悪化する」
という戦略判断が成立。
もう一つ重要なのは
👉 今は大国衝突リスクが相対的に低い
可能性。
つまり
イランを守るために
即座に軍事介入する可能性は低い。
これは
行動のハードルを下げる。
現代戦の特徴:
これにより
👉 地上侵攻なしでも戦略効果が出せる
ようになった。
つまり
「やれる能力が整った」
今回のタイミングは、
以下の重なり:
これらが同時に成立した
👉 希少な戦略的窓
と考えられます。
要するに
「今ならできる」ではなく
「今しかできない」
と判断された可能性が高い。
必要であれば、
・この判断が合理的だったのか
・長期的に逆効果になる可能性
・地域秩序の再編シナリオ
なども整理できます。
米国は、ベトナムのドミノ理論など、過去に結構な地政学的見誤りがあります。
長期的に逆効果になる可能性は十分あるかと思います。
おっしゃる通り、「今しかない」という判断は、歴史的に見ればしばしば長期的な逆効果を生んできました。ベトナムのドミノ理論に限らず、2003年のイラク戦争や2011年のリビア介入でも、短期の軍事的成功が中長期の不安定化を招いた例があります。今回も同様のリスクは現実的に存在します。
以下、長期的に逆効果となり得る主なメカニズムを整理します。
指導部除去や中枢機能の打撃は、想定通りなら内部の権力再編を促しますが、
が起きると、統治能力の低下→国内不安定化に繋がります。
イランは民族・宗派・地域の多様性を抱える国家です。強固な国家制度を持つ一方で、中央の統制が緩めば、
「弱いが一体の国家」から「強いが分裂した複数の武装主体」へ
と移行する可能性があります。これは対外的な抑止をむしろ困難にします。
従来、ヒズボラや各地の民兵はテヘランの影響下で行動してきました。しかし中枢が揺らぐと、
が進み、統制不能な準国家主体が増えるリスクがあります。
これは短期的には対抗勢力の弱体化に見えても、長期的には
紛争の分散化・常態化
を招き、抑止コストを増大させます。
外部からの打撃は、体制への不満を一時的に凍結し、
を生みやすい。
結果として、
体制の正統性が「抵抗」によって再強化される
という逆説が起こり得ます。イラク後の反米武装化や、リビアの長期不安定化はこの文脈で理解できます。
予防的打撃は、核能力の遅延を狙いますが、
を誘発し、不可視性の高い開発に移行させる恐れがあります。
これは交渉や査察のレバレッジを低下させ、
抑止の不確実性
を高めます。
短期的に大国の直接介入が限定的でも、
が進めば、地域紛争が
広域のブロック対立
に組み込まれる可能性があります。
ホルムズ海峡や紅海の不安定化は、
を通じて、世界経済に持続的な摩擦を生みます。短期の市場ショックよりも、
中期の“高止まり不安定”
が実体経済に効きやすい。
今回の行動は、短期の軍事合理性(能力遅延・抑止の再設定)を持ち得る一方で、
といった経路を通じて、長期の不安定化を強める可能性があります。
したがって、成否は軍事的成果そのものではなく、
その後の政治設計(抑止・対話・地域秩序の再構築)
に大きく依存します。
もし関心があれば、「逆効果を最小化するために何が必要か(外交・抑止・経済の組み合わせ)」という観点でも整理できます。
これについてシミュレーションで計算できないかな、と思い、以下のChatGPTに以下の質問をしてみました。
「学歴が「意思決定に影響した事実」を立証できるか」をマルチエージェントシミュレーションで計算できませんか?
「裁判での立証」そのものではなく、“学歴情報が意思決定をどれくらい動かし得るか”を、仮定とデータに基づいて定量化し、反実仮想(なかった世界)を比較することです。
計算はあくまで「推定」で構いません(当然ですが)。
ベースとなる出展は、「ホワイトハウスのキューバ危機: マルチエージェント・シミュレーションで探る核戦争回避の分水嶺 (人工社会の可能性) https://amzn.to/4shMtUT」です。
できます。しかも、ご提示の書籍が扱う「ホワイトハウス(EXCOMM)の集団意思決定を、エージェント+討議プロセスとしてモデル化し、条件を変えて反実仮想を回す」という骨格は、そのまま「選挙における有権者の意思決定(投票)」に移植できます。
以下、「学歴情報が意思決定をどれくらい動かし得るか」を推定として出すための、MASの設計案を“実装できる粒度”でまとめます。
法廷の「立証」ではなく推定として扱うなら、効果を次のいずれかで定義すると扱いやすいです。
ATE(平均処置効果):学歴情報が“真”として流通した世界 vs “流通しなかった世界”での、得票率(または当選確率)の差
CATE(条件付き効果):学歴感度が高い層/低い層、情報接触が高い層/低い層での差
最小反実仮想条件:当落をひっくり返すのに必要な「学歴の露出量」「信頼度」「訂正浸透率」の閾値
この3つが出ると、「重要情報たり得る」かどうかを条件付きで数値化できます。
書籍側の要点は(大づかみに言えば)
複数の意思決定者が、討議を通じて信念・選好を更新し、集団の選択が収斂する、をMAS化して、条件操作で分水嶺を探る点です。
これを選挙に移すと、対応はこうなります。
EXCOMMメンバー(討議者) → 有権者(+オピニオンリーダ、組織票の核)
会議での発言・説得 → SNS/対面/地域コミュニティでの情報伝播・同調
“封鎖”か“侵攻”か → 候補Aか候補Bか(棄権含む)
条件操作(危機の強度等) → 学歴情報の露出、信頼度、訂正のタイミング等
つまり「討議(相互作用)+信念更新+集団結果」という構造が同型です。
有権者エージェント i は最低限これを持つ:
争点ベクトル:
(政策・人物・実績・学歴などの重み)
候補の能力(または適格性)に関する事前信念:
学歴シグナル感度:
(0〜1、層別分布)
情報接触率:
(媒体別でも可)
ネットワーク近傍:
候補(または陣営)エージェントは、学歴情報の露出
をいつどれだけ投下するか、訂正・反論がどれだけ出るかをパラメタ化(最初は固定でもOK)。
学歴情報を観測したときの更新を、次のどちらかで書けます。
候補の能力
に対して、有権者は事前
を持ち、学歴シグナル
を見て
ここで学歴詐称の反実仮想は、
“真”の世界:観測
“無い”世界:観測なし
“虚偽”の世界:観測
だが実際は false(のちに訂正シグナル
が来る)
というイベント列で分岐します。
支持確率を
は、露出
と信頼度
を掛けたもの(後述)
どちらでも「学歴が意思決定を動かす“力”」をパラメタとして切り出せます。
シミュレーションで“因果”を言うには、同一の世界線を、学歴情報だけ変えて複製します。
乱数シード固定
ネットワーク固定
争点・候補評価の初期分布固定
変えるのは 学歴イベントの有無/真偽/訂正の有無とタイミングだけ
そして差分を取る:
Outcome は得票率でも、当選確率でもよい。
学歴詐称の現実は「出た/出ない」だけでなく、
露出の大きさ(選挙公報・演説・SNS)
信頼度(誰が言ったか、媒体の信用)
訂正の浸透(訂正が届かない人が必ず出る)
タイミング(投票日まで何日か)
で効果が激変します。
そこで学歴シグナルを
訂正を
みたいに「信頼度が落ちる」モデルにすると、
“最後にどれだけ戻せたか”がそのまま得票差に出ます。
「現地の詳細データが無い」場合でも、推定として成立させる実務的なやり方はあります。
学歴感度
の分布(例:平均0.1〜0.4)
露出
(低・中・高)
訂正浸透率(10%〜80%)
訂正タイミング(投票7日前〜前日)
これを格子探索して、「当落が変わる領域」を地図化します。
(本の“分水嶺”発想に近いです。)
たとえば、世論の一時点、出口調査、接触率のアンケート断片など、何でもよいので一部を合わせて、パラメタの範囲を狭めます。
このMASで出せる主張は、例えば次のような形になります。
「学歴情報が広く流通し、訂正浸透が低い場合、当落が反転する確率がX%」
「学歴感度が高い層(仮定:人口のY%)に限定しても、得票差がZポイント動く」
「当落反転には、露出がI以上、訂正浸透がR以下、訂正タイミングが投票T日前以内、が必要」
これは“証拠”ではありませんが、「影響し得る」の定量化としてはかなり強い出力です。
ロジット型(軽い)でMVPを作る
学歴イベント(真/無/虚偽+訂正)を入れて反実仮想比較
閾値地図(分水嶺)を出す
必要ならベイズ更新に差し替えて理論整合を上げる
もし江端さんが「対象を伊東市のケースに寄せた推定」をしたいなら、モデルに入れるべき最小の観測量(公報への掲載有無、露出の主要チャネル、訂正報道のタイミング等)を、公開情報ベースで拾ってパラメタの上限下限を絞る、という進め方が現実的です。
必要なら、上のMVPを 具体的な状態変数・イベント列・疑似コード(Go or Python)まで落として提示します。
このようなシミュレーション結果(ができたとして)を、裁判の証拠として提出できますか(原告側でも被告側でも、どっちでもいいので)
結論から言えば、
提出すること自体は可能です。
しかし、それ単独で事実認定を左右する「証拠」になる可能性は低く、位置づけは限定的です。
日本の民事・刑事手続では、マルチエージェントシミュレーション(MAS)の結果は
👉 専門的知見を用いた意見(鑑定・専門家意見)
として扱われます。
典型的には、
の形で提出可能です。
原告側・被告側のどちらでも提出できます。
裁判所は、MASの出力を
👉 事実の証明
ではなく
👉 可能性評価/補助的推論
として見る傾向が強いです。
理由は明確で、
シミュレーションは
からです。
したがって、
「この結果が出た」ではなく、
「こういう条件なら影響が生じ得る」
という形の証明補助になります。
法廷で意味を持つためには、次が重要です。
MASは、主張の“芯”にはなりにくいですが、
👉 因果関係の plausibility(あり得る度合い)
を示す材料としては有効です。
例えば、
などを示すことで、
「影響の可能性」を補強できます。
裁判所は、
シミュレーション結果を
👉 現実の出来事の代替
とは見ません。
現実の事実(発言、掲載、行動、時系列)を
主証拠として、
MASは
👉 その解釈を支える補助線
として機能します。
提出:
可能
証明力:
限定的(補助的)
用途:
因果可能性の説明
要するに、
MASは
「こういうことが起き得た」
を示す道具であり、
「実際に起きた」
を証明する道具ではない、
という位置づけになります。
学歴詐称問題について伊東市の田久保眞紀 前市長が地方自治法違反の疑いで書類送検されました。
この問題を再度整理して、裁判となった時の検察側と弁護側の取りうる戦略(ロジック)を教えて下さい
了解しました。
「学歴詐称問題」だけにフォーカスして整理します。
本件は「倫理問題」ではなく、刑事法上は
👉 虚偽の経歴を用いて公職に就いたことが
地方自治法上の構造を歪めたか
という論点になります。
単に「嘘をついた」では刑事責任には直結しない。
刑事問題化するためには、
学歴の虚偽表示が
という機能的意味を持つ必要がある。
つまり争点は
👉 嘘そのものではなく
👉 嘘が制度に影響したか
検察は「経歴虚偽」を
行政秩序の侵害として構成する必要がある。
想定される論理は以下。
市長という地位は、
有権者・議会・行政組織の信頼の上に成立する。
その前提情報(経歴)が虚偽であれば、
👉 選任プロセスそのものが歪められた
と主張する可能性がある。
つまり
「選挙の判断材料を虚偽で操作した」
という構造。
学歴が
に影響を与えたならば、
👉 虚偽により公職を得た
という構成を狙う。
ここでは
が重視される。
首長の権限行使は
民主的正当性に依存する。
その正当性の基礎に虚偽があれば、
👉 行政意思形成の正当性が欠損
と制度論的に主張する余地がある。
弁護側は、
「学歴」と「公職取得」の因果を切断する必要がある。
選挙において
学歴は決定要因ではない
と主張する。
つまり
が選択の本質であり、
学歴は補助情報にすぎない。
有権者は
人物・政策・活動実績
を総合評価して選択する。
したがって
👉 学歴のみで選任が歪んだとは言えない
という主張。
地方自治法は
経歴虚偽そのものを処罰対象としていない。
よって
👉 選挙倫理問題であって刑事問題ではない
という方向に持ち込む。
この問題の本質は、
👉 学歴が「選任の決定要素」だったか
に尽きる。
検察側:
虚偽の経歴が信頼を作り
公職取得を助けた
弁護側:
学歴は選挙結果を左右していない
刑事責任成立のためには、
この三点が必要になる。
特に「影響性」の立証が最大の壁となる。
必要であれば、
・起訴の可能性評価
・過去の類似事例
・行政責任と刑事責任の分離
も整理可能。
なるほど。実務においては「学齢は選挙の結果を歪めうる重要な情報」という主張と「学歴は実務においては無関係(または、補助的)な情報)」という主張の闘い、と理解しました。
概ねその理解で方向性は合っています。
ただし、実務的にはもう少しだけ“解像度”が上がります。
これは単純に
学歴は重要か/重要でないか
という価値論の争いではなく、
👉 学歴が「意思決定に影響した事実」を立証できるか
という事実認定の戦いになります。
裁判実務では、抽象論はほぼ意味を持たず、
争点は次のように具体化されます。
検察は
「学歴は重要である」
とは言いません。
代わりにこう構成します。
学歴が“この選挙において”信頼形成に寄与した
つまり
などの中で、
👉 学歴が積極的に使われていたか
を拾いに来ます。
抽象的価値ではなく
具体的利用実態
を積み上げる戦略。
弁護側も
「学歴は無関係」
とは言いません。
代わりにこう切ります。
学歴があってもなくても結果は同じだった
つまり
など、
勝因の別要因
を並べることで、
👉 因果関係を薄める
したがって、実務上の本当の対立は
検察:
学歴は“使われた”
弁護:
学歴は“結果を変えていない”
です。
裁判所は、
学歴の一般的重要性ではなく、
👉 この選挙での機能
を見る。
具体的には
など。
これは
「学歴の価値論争」ではなく
👉 学歴の“使用実態”と“結果影響”
の立証競争
です。
必要なら、
・有罪ラインの現実的水準
・過去の選挙経歴問題との比較
・不起訴になりやすい構造
も整理できます。
法的には、どの法文のどの条文を使った闘いになるのでしょうか?
結論から言うと、
「学歴詐称そのもの」を直接処罰する条文は存在しません。
したがって、刑事事件として成立させる場合は、
他の法律の構成要件に“乗せる”形になります。
本件の実務的な戦場は、主に以下の条文です。
学歴詐称問題が刑事化される場合、
最もストレートに問題となるのは
👉 公職選挙法
です。
具体的には、
当選を得る目的で
虚偽の事項を公にした者
(虚偽事項公表罪)
成立のためには、
① 虚偽の事項
② 公表行為
③ 当選目的
が必要。
検察:
弁護:
つまり、この条文が最も“本丸”になります。
地方自治法違反の構成は、
学歴詐称単体ではなく、
👉 地位取得の正当性
に関わる形で問題化します。
ここで関連し得るのは、
首長は職務遂行において
公正かつ誠実
であるべきとされる。
ただし、
これは直接の刑罰規定ではない。
つまり地方自治法は
👉 行政倫理・統治正当性の論点
であり、
刑事責任の直接根拠にはなりにくい。
場合によっては、
ただしこれは
公的文書に虚偽を記載させた場合
であり、
選挙経歴には通常適用困難。
したがって、
本件の刑事法上の主戦場は
■ 公職選挙法235条
です。
争点は条文レベルで言えば、
👉 「虚偽事項」か
👉 「当選目的」か
の二点に集約されます。
この問題は、
地方自治法ではなく、
選挙過程の適正を守る
👉 公職選挙法
の問題として戦われる可能性が高い。
必要であれば、
・過去の虚偽経歴事件との比較
・当選無効に繋がる可能性
・行政責任との分離
も整理できます。
これは、我が国における「学齢」いうものを、"効果(シグナリグ理論等)"ではなくて、"法による解釈"が行われる、ということになると考えており、大変興味深いです。
まさにそこが、この種の事案の面白い(そして重要な)ポイントです。
社会科学的には、学歴は典型的に
👉 シグナル(能力・信頼性・社会的資本)
として理解されます。
有権者がそれをどう読むかは、市場と同じく「意味のやり取り」の問題です。
しかし、法が介入する瞬間、評価軸は一変します。
法は、
「学歴は役に立つか?」
という問いには関心を持ちません。
代わりに問うのは、
👉 学歴が“表示された事実”が
👉 公的意思決定に影響したか
です。
つまり、
シグナルとしての価値ではなく、
制度における機能
が問題になります。
シグナリング理論では、
という効果が想定されます。
しかし法は、
その「合理性」には立ち入りません。
法が扱うのは、
👉 表示の真実性
👉 表示の公表性
👉 意思形成との接続
という、極めて構造的な要素です。
法は、
学歴が重要かどうか
を判断しません。
判断するのは、
👉 学歴が「選択のプロセス」に組み込まれたか
です。
つまり、
社会的価値ではなく、
意思決定プロセスへの侵入性
が問題になる。
社会では、
学歴は意味を持つかもしれない。
しかし法にとっては、
意味を持つかどうかではなく、
👉 意思決定を歪めたか
だけが問題。
社会科学:
学歴は信号
法:
学歴は情報入力
そして争点は、
その入力が
👉 虚偽だったか
👉 影響を与えたか
つまり本件は、
学歴の価値を巡る議論ではなく、
情報の真実性と制度的影響
を巡る問題となる。
必要であれば、
この構造を
といった観点でも整理できます。
この論点での、過去の判例(可能であれば、確定した判例)があれば教えて下さい。
あります。
しかも、この論点にかなり「ドンピシャ」で対応する確定判例が存在します。
👉 最高裁 第二小法廷 判決(平成6年7月18日) (senkyo.win)
これは、公職選挙法235条(虚偽事項公表罪)に基づき、
経歴詐称(=学歴等)による有罪が確定した事件
です。
参議院議員選挙において、
候補者が自身の経歴(学歴を含む)について
虚偽の内容を公表して選挙活動を行った。
その結果、
この事件では、
👉 経歴の虚偽表示が
👉 選挙における「虚偽事項公表」に当たるか
が争われました。
裁判所は、
経歴(学歴を含む)は
👉 有権者の判断材料となる重要事項
であり、
虚偽の公表は
👉 選挙の公正を害する
と認定。
つまり、
学歴は
単なる社会的シグナルではなく
法的に保護される情報
と位置付けられました。
この判例の意義は明確です。
裁判所は
「学歴が重要かどうか」
という社会的価値論ではなく、
👉 有権者の選択過程に影響しうる情報
という制度的観点から評価しています。
結果として、
学歴は
である以上、
虚偽表示は違法となり得る
という整理が確立。
例えば、
1992年参院選では、
学歴詐称により在宅起訴され、
有罪判決が確定し、
👉 当選無効
となったケースも存在します。 (選挙ドットコム)
判例の立場は、極めて明確に
社会:
学歴はシグナル
法:
学歴は選択情報
であり、
虚偽表示は
👉 選挙過程への不正入力
として処理される。
したがって、
今回のような問題も
「学歴の価値論争」ではなく、
判例的には
👉 選択過程の情報の真実性
という軸で判断されることになります。
必要であれば、
この判例のロジックを
今回のケースに当てはめた
勝敗分岐点
も整理できます。
あれ? このような確定判決があるのであれば、今回の伊東市の田久保眞紀 前市長の裁判(が実施されれば)の帰趨は決まったようなものではないのですか。
良いところに気づかれています。
結論から言えば――
「似た判例がある」ことと「結論が決まる」ことは全く別です。
今回のような学歴詐称問題では、確定判例があっても帰趨は自動的には決まりません。理由はシンプルで、
👉 公職選挙法235条は“形式犯”ではなく、“機能犯”に近いからです。
つまり、「虚偽があった」だけでは足りず、選挙との関係性が個別具体的に問われます。
平成6年の参院選経歴詐称事件が示したのは、
経歴(学歴を含む)は有権者の判断材料になり得る
という“法的枠組み”です。
しかし、その判例も
すべての学歴詐称が違法
とは言っていません。
違法になるかは、以下の事実認定に依存します。
公職選挙法235条の成立には、実務上、次の三点が核心になります。
ここが曖昧だと成立は難しくなります。
“誰がどう公表したか”は極めて重要。
ここが最大の勝負所。
単なる経歴掲載では足りず、
👉 当選のための手段として機能したか
が問われます。
判例があると、
しかし、
👉 違法性は個別事実に依存
します。
これは医療過誤判例と同じ構造で、
「理論」は共通でも
「結果」は症例ごとに異なる。
仮に裁判になれば、帰趨を分けるのは、
です。
つまり、
学歴を“持っていた”ことではなく
学歴を“使った”こと
が焦点になります。
判例は
「道筋」を示すが、
「ゴール」は決めない。
判例:
学歴は選択情報になり得る
今回の裁判(仮):
実際に選択情報として使われたか?
この「使われ方」の事実認定こそが、最終的な帰趨を決めます。
必要であれば、
起訴される場合/されない場合の現実的分岐ラインも整理できます。
ありがとうございました。かなり整理できました。また同じようなことを質問するかもしれませんが、よろしくお願いします。
どういたしまして。整理のお役に立てたなら何よりです。
この種のテーマは、事実関係の積み上げと法的評価の切り分けで見え方が大きく変わるので、また新しい情報や疑問が出てきた際に一緒に整理していければと思います。
いつでもどうぞ。
https://wp.kobore.net/2025/12/10/post-23101/
HLS映像検索・サムネイル・再生システム構築手順書 - リバースプロキシ対応による公開境界分離構成HLS映像検索・サムネイル・再生システム構築手順書 - リバースプロキシ対応による公開境界分離構成.md
以下は、貼付「HLS映像検索・サムネイル・再生システム構築手順書.pdf」を前提に、**“今回の修正(= reverse-proxy 化)で追加・変更した箇所だけ”**を、**手順書内にそのまま貼り付けられる形(ファイル全文+コマンド全文)**でまとめたものです。
(方針は、貼付「映像検索・配信システム構築手順書.pdf」の reverse-proxy(Nginx)で API を隠蔽する方式を踏襲しています 。)
従来手順では、FastAPI が HLS(/hls)やサムネイル(/thumbs)やUI(/ui)を直接配信する構成になっており 、ブラウザからのアクセス経路が「API 直アクセス」になりがちです。また DB もホストに port 公開して運用しがちです(例:15432:5432) 。
location /api/ { proxy_pass ... } 等)を踏襲既存 ~/video_hls_project の直下に、以下を 新規作成します。
cd ~/video_hls_project
mkdir -p api
mkdir -p reverse-proxy/frontend
api/Dockerfile(新規)api/app.py(新規:※従来の backend_api/app.py を “コンテナ運用前提” にした版)reverse-proxy/Dockerfile(新規)reverse-proxy/nginx.conf(新規)reverse-proxy/frontend/index.html(新規:UIをreverse-proxy側に同梱)docker-compose.yml(置き換え)作成先:
~/video_hls_project/api/Dockerfile
cat << 'EOF' > ~/video_hls_project/api/Dockerfile
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential libpq-dev \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir \
fastapi uvicorn psycopg2-binary python-multipart
COPY app.py /app/app.py
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
EOF
作成先:
~/video_hls_project/api/app.py
ポイント:
m3u8_path(例:videos_hls/clip01/index.m3u8)を、返却URL /hls/clip01/index.m3u8 に変換するロジックは従来PDFの考え方を踏襲しています/hls
/thumbs を FastAPI で静的マウントする方式自体は従来PDF同様cat << 'EOF' > ~/video_hls_project/api/app.py
from fastapi import FastAPI, HTTPException
from fastapi.staticfiles import StaticFiles
from typing import Optional
import psycopg2
import psycopg2.extras
import os
from pathlib import Path
# ========= パス設定(コンテナ内) =========
# docker-compose で /data にホストの video_hls_project をマウントする前提
BASE_DIR = Path("/data")
HLS_DIR = BASE_DIR / "videos_hls"
THUMB_DIR = BASE_DIR / "thumbnails"
# ========= DB 接続設定(コンテナ内から db サービスへ) =========
DB_HOST = os.getenv("DB_HOST", "db")
DB_PORT = int(os.getenv("DB_PORT", "5432"))
DB_NAME = os.getenv("DB_NAME", "video_db")
DB_USER = os.getenv("DB_USER", "video_user")
DB_PASS = os.getenv("DB_PASS", "password")
def get_conn():
return psycopg2.connect(
host=DB_HOST,
port=DB_PORT,
dbname=DB_NAME,
user=DB_USER,
password=DB_PASS,
)
app = FastAPI()
@app.get("/health")
def health():
return {"status": "ok"}
# ========= 静的ファイル =========
# (従来手順では FastAPI が直配信していたが、今回は reverse-proxy 経由でのみ公開する)
app.mount("/hls", StaticFiles(directory=HLS_DIR), name="hls")
app.mount("/thumbs", StaticFiles(directory=THUMB_DIR), name="thumbs")
def to_hls_url(m3u8_path: str) -> str:
"""
DBの m3u8_path (例: videos_hls/clip01/index.m3u8)
を、ブラウザ向け URL (/hls/clip01/index.m3u8) に変換する。
(従来手順書の変換仕様を踏襲)
"""
prefix = "videos_hls/"
if m3u8_path.startswith(prefix):
rel = m3u8_path[len(prefix):] # "clip01/index.m3u8"
else:
rel = m3u8_path
return f"/hls/{rel}"
def to_thumb_url(chunk_id: str) -> str:
"""
チャンク代表サムネイルは 00000.jpg を返す(従来通り)。
"""
return f"/thumbs/{chunk_id}/00000.jpg"
@app.get("/api/chunks")
def list_chunks(tag: Optional[str] = None):
"""
映像一覧API
- /api/chunks
- /api/chunks?tag=test
"""
conn = get_conn()
try:
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
if tag:
sql = """
SELECT camera_id, chunk_id, title, m3u8_path, duration_sec, tags, created_at
FROM train_camera_chunk
WHERE tags @> ARRAY[%s]::text[]
ORDER BY id;
"""
cur.execute(sql, (tag,))
else:
sql = """
SELECT camera_id, chunk_id, title, m3u8_path, duration_sec, tags, created_at
FROM train_camera_chunk
ORDER BY id;
"""
cur.execute(sql)
rows = cur.fetchall()
result = []
for row in rows:
d = dict(row)
d["hls_url"] = to_hls_url(d["m3u8_path"])
d["thumb_url"] = to_thumb_url(d["chunk_id"])
result.append(d)
return result
finally:
conn.close()
@app.get("/api/chunks/{chunk_id}")
def get_chunk(chunk_id: str):
"""
chunk_id(clip01 等)で1件取得
"""
conn = get_conn()
try:
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
sql = """
SELECT camera_id, chunk_id, title, m3u8_path, duration_sec, tags, created_at
FROM train_camera_chunk
WHERE chunk_id = %s;
"""
cur.execute(sql, (chunk_id,))
row = cur.fetchone()
if not row:
raise HTTPException(status_code=404, detail="chunk not found")
d = dict(row)
d["hls_url"] = to_hls_url(d["m3u8_path"])
d["thumb_url"] = to_thumb_url(d["chunk_id"])
return d
finally:
conn.close()
@app.get("/api/chunks/{chunk_id}/segments")
def get_segments(chunk_id: str):
"""
指定 chunk の index.m3u8 を読み、TSセグメント情報を返す。
(従来手順書にある /api/chunks/{chunk_id}/segments の考え方を踏襲)
"""
m3u8_path = HLS_DIR / chunk_id / "index.m3u8"
if not m3u8_path.exists():
raise HTTPException(status_code=404, detail="m3u8 not found")
segments = []
current_start = 0.0
with m3u8_path.open("r", encoding="utf-8") as f:
lines = [line.strip() for line in f if line.strip()]
i = 0
idx = 0
while i < len(lines):
line = lines[i]
if line.startswith("#EXTINF:"):
dur_part = line.split(":", 1)[1]
dur_str = dur_part.split(",", 1)[0]
try:
dur = float(dur_str)
except ValueError:
dur = 0.0
if i + 1 >= len(lines):
break
ts_name = lines[i + 1] # "00000.ts" 等
segments.append({
"index": idx,
"ts": ts_name,
"start_sec": current_start,
"duration_sec": dur,
"thumb_url": f"/thumbs/{chunk_id}/{ts_name.replace('.ts', '.jpg')}",
})
current_start += dur
idx += 1
i += 2
else:
i += 1
return segments
EOF
作成先:
~/video_hls_project/reverse-proxy/Dockerfile
(「映像検索・配信システム構築手順書.pdf」の Nginx コンテナ作り方を踏襲 )
cat << 'EOF' > ~/video_hls_project/reverse-proxy/Dockerfile
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY frontend /usr/share/nginx/html
EOF
作成先:
~/video_hls_project/reverse-proxy/nginx.conf
ポイント:
/api/ を api:8000 に reverse-proxy(方式は踏襲)/hls/ と /thumbs/ も api 側へ proxy(= ブラウザは reverse-proxy 以外に触れない)cat << 'EOF' > ~/video_hls_project/reverse-proxy/nginx.conf
events {}
http {
server {
listen 80;
# ---- UI(静的)----
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# ---- API ----
location /api/ {
proxy_pass http://api:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# ---- HLS(m3u8/ts)----
location /hls/ {
proxy_pass http://api:8000/hls/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# ---- Thumbnails(jpg)----
location /thumbs/ {
proxy_pass http://api:8000/thumbs/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
EOF
作成先:
~/video_hls_project/reverse-proxy/frontend/index.html
※UIは reverse-proxy 配下で配信し、API は /api/... を叩きます(踏襲の方向性:reverse-proxyで公開点を分離 )。
cat << 'EOF' > ~/video_hls_project/reverse-proxy/frontend/index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>HLS映像検索・サムネイル・再生</title>
<style>
body { font-family: sans-serif; margin: 16px; }
.row { display: flex; gap: 16px; }
.col { flex: 1; min-width: 320px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.card { border: 1px solid #ddd; padding: 8px; cursor: pointer; }
.card:hover { background: #fafafa; }
img { max-width: 100%; height: auto; display: block; }
video { width: 100%; background: #000; }
.muted { color: #666; font-size: 12px; }
</style>
</head>
<body>
<h1>HLS映像検索・サムネイル・再生</h1>
<div style="margin: 8px 0;">
<label>タグ: <input id="tagInput" placeholder="例: test" /></label>
<button id="searchBtn">検索</button>
<span id="status" class="muted"></span>
</div>
<div class="row">
<div class="col">
<h2>■ サムネイル表示部(映像単位)</h2>
<div id="chunkGrid" class="grid"></div>
</div>
<div class="col">
<h2>■ セグメントサムネイル表示部(選択中の映像)</h2>
<div id="segmentGrid" class="grid"></div>
<h2 style="margin-top:16px;">■ 再生</h2>
<video id="video" controls playsinline></video>
<div id="nowPlaying" class="muted"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
const statusEl = document.getElementById('status');
const chunkGrid = document.getElementById('chunkGrid');
const segmentGrid = document.getElementById('segmentGrid');
const videoEl = document.getElementById('video');
const nowPlayingEl = document.getElementById('nowPlaying');
let hls = null;
function setStatus(msg) { statusEl.textContent = msg || ''; }
async function fetchJSON(url) {
const res = await fetch(url);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
return await res.json();
}
function playHLS(url) {
if (hls) { hls.destroy(); hls = null; }
if (videoEl.canPlayType('application/vnd.apple.mpegurl')) {
videoEl.src = url;
} else if (window.Hls && Hls.isSupported()) {
hls = new Hls();
hls.loadSource(url);
hls.attachMedia(videoEl);
} else {
alert('このブラウザはHLS再生に対応していません(hls.jsが使えません)。');
}
}
function clearSegments() {
segmentGrid.innerHTML = '';
}
function renderChunks(chunks) {
chunkGrid.innerHTML = '';
chunks.forEach(c => {
const div = document.createElement('div');
div.className = 'card';
div.innerHTML = `
<img src="${c.thumb_url}" alt="">
<div><b>${c.title || c.chunk_id}</b></div>
<div class="muted">${c.chunk_id} / ${(c.tags||[]).join(', ')}</div>
`;
div.onclick = async () => {
setStatus(`segments取得中: ${c.chunk_id}`);
nowPlayingEl.textContent = `選択中: ${c.chunk_id}`;
clearSegments();
// セグメント一覧
const segs = await fetchJSON(`/api/chunks/${encodeURIComponent(c.chunk_id)}/segments`);
renderSegments(c.chunk_id, segs);
// 再生
playHLS(c.hls_url);
setStatus('');
};
chunkGrid.appendChild(div);
});
}
function renderSegments(chunkId, segs) {
segmentGrid.innerHTML = '';
segs.forEach(s => {
const div = document.createElement('div');
div.className = 'card';
const thumb = s.thumb_url;
div.innerHTML = `
<img src="${thumb}" alt="">
<div class="muted">#${s.index} ${s.ts}</div>
<div class="muted">${s.start_sec.toFixed(2)}s (+${s.duration_sec.toFixed(2)}s)</div>
`;
segmentGrid.appendChild(div);
});
}
async function loadChunks() {
const tag = document.getElementById('tagInput').value.trim();
const url = tag ? `/api/chunks?tag=${encodeURIComponent(tag)}` : '/api/chunks';
setStatus('chunks取得中...');
const chunks = await fetchJSON(url);
renderChunks(chunks);
clearSegments();
nowPlayingEl.textContent = '';
setStatus(`件数: ${chunks.length}`);
}
document.getElementById('searchBtn').onclick = loadChunks;
// 初期ロード
loadChunks().catch(e => {
console.error(e);
setStatus('初期ロード失敗: ' + e.message);
});
</script>
</body>
</html>
EOF
作成先:
~/video_hls_project/docker-compose.yml
ポイント:
~/video_hls_project を /data にマウントして HLS/サムネイルを参照する(reverse-proxy + api + db の並びは「映像検索・配信システム構築手順書.pdf」の構成を踏襲 )
cat << 'EOF' > ~/video_hls_project/docker-compose.yml
version: "3.9"
services:
db:
image: postgis/postgis:16-3.4
container_name: train-video-db
environment:
POSTGRES_DB: video_db
POSTGRES_USER: video_user
POSTGRES_PASSWORD: password
# 重要:原則、ホストへ公開しない(フロントから見えない)
# 必要ならデバッグ時だけ一時的に開ける:
# ports:
# - "15432:5432"
volumes:
- ./db_init:/docker-entrypoint-initdb.d
- pgdata:/var/lib/postgresql/data
api:
build: ./api
container_name: train-video-api
environment:
DB_HOST: db
DB_PORT: "5432"
DB_NAME: video_db
DB_USER: video_user
DB_PASS: password
depends_on:
- db
volumes:
# ホストの ~/video_hls_project を /data として参照(HLS/サムネイルを読む)
- ./:/data:ro
# 重要:api もホストへ公開しない(reverse-proxy 経由のみ)
# ports:
# - "18000:8000"
reverse-proxy:
build: ./reverse-proxy
container_name: train-video-frontend
ports:
- "80:80"
depends_on:
- api
volumes:
pgdata:
EOF
cd ~/video_hls_project
docker compose down
docker compose up -d --build
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
期待:train-video-frontend だけが 0.0.0.0:80->80/tcp を持ち、db/api は host port を持たない。
curl -i http://localhost/api/health
curl -i http://localhost/api/chunks
curl -I http://localhost/hls/clip03/index.m3u8
http://localhost/http://localhost/api/chunks15432:5432 公開は、必要時のみ一時的に使う扱いに変更(元手順では公開例あり )。http://localhost/ にしか触れず、/api
/hls
/thumbs は全て Nginx が中継。必要なら、次に「HLS映像検索・サムネイル・再生システム構築手順書.pdf」側の **どの章・どの節に、上の差分をどう挿入するか(“差し込み位置メモ”)**も、章番号つきで作れます。