2026,江端さんの忘備録

現在、私は、大学の先生にお願いされて、イベント出席用の管理システムを設計しています。
Currently, I am designing a management system for event attendance at the request of a university professor.

AWSは高価で設定が面倒くさいので、サーバ実装にはAmazon Lightsail(以下、Lightsail)を使っています。
Well, since AWS is expensive and troublesome to configure, I am using Amazon Lightsail (hereafter, Lightsail) for the server implementation.

先日、4月から高校生になる若者が「サーバを作りたい」と言っていたので、Lightsailを勧めたのですが、このLightsailの説明に、ちょっと悩みました。
The other day, a young person who will become a high school student next year said he wanted to build a server, so I recommended Lightsail, but I struggled a bit with how to explain it.

---

以前、今は亡き父と母に、メールシステムを教えることを試みて、それに失敗したのを覚えています。
I remember trying to teach my now-deceased father and mother about email systems and failing.

「メールシステムというのは、世界中のメールサーバを介してメールを配送するシステムで、メールが到着したサーバにアクセスすることで、メールを自分のパソコンに取り込むシステム」と言いながら ――
While saying, "An email system delivers messages via mail servers around the world, and by accessing the server where the mail arrives, you retrieve it to your own computer." 

父と母が『全然分かりません』という表情をしていて、
My parents had expressions that said, "We don't understand at all,"

そして、私も『この説明では全然分からんだろう』と思いながら説明していました。
And I, too, was explaining while thinking, "This explanation won't make sense at all."

で、まあ、母に至っては、「やっぱり、智一(私)がアメリカから送るメールは時間がかかるのかねえ」といっていて ――
And my mother even said, "So emails you send from America take time to arrive, don't they?" 

うん、たしかに、サーバをホップしていくので、それは時間がかかるとは思うけど、それは、「ミリ秒か遅くても秒の単位」だからと、母の認識は"正しく"、そして"間違っていた"のです。
Yes, it does hop across servers so that it might take time, but that time is in milliseconds or at most seconds, so her understanding was both "correct" and "incorrect."

あの時、私は、どのように、メールシステムについて、父と母に説明すべきだったのか、ChatGPTに聞いてみました。
At that time, I asked ChatGPT how I should have explained email systems to my parents.

ChatGPT:『メールは、「インターネットという道路網を通って、相手の近くにある受け取り用の箱まで運ばれる手紙」です。送るとネットワークの中を移動して相手専用の箱に入り、相手は自分のパソコンからその箱を見に行って取り出して読みます。』
ChatGPT: "Email is like a letter that travels through a road network called the Internet to a mailbox near the recipient. When sent, it moves through the network into the recipient's personal box, and they access it from their own computer to retrieve and read it."

「うーむ、ChatGPTでも"ダメか"」と感じました。
I felt, "Hmm, even ChatGPT can't solve this."

問題は、インターネットという概念を知らない人に、それを抜きに説明するのが、恐しく難しい、ということです。
The problem is that it is extremely difficult to explain something to someone who doesn't know what the Internet is.

---

しかし、こちらは、インターネットがもはや、生活インフラとなっている中学生です。この辺は困りませんでした。
However, in this case, we are dealing with a junior high school student for whom the Internet is already a daily part of their infrastructure, so this was not a problem.

私の原案は以下の通りです。
My original proposal was as follows.

■江端案(原案)
■Ebata Proposal (Original)

Amazon Lightsailとは、世界中に配置されているデータセンタの中の一つ(今回は東京リージョン)の中で、24時間ずっと動き続ける自分用のPCのことです(シャットダウンしない)。
Amazon Lightsail is your personal PC that runs continuously, 24 hours a day, in one of the data centers located around the world (this time in the Tokyo region) (it does not shut down).

このPCは、インターネットに直接つながっているので、そこで作ったプログラムは世界中の人から使用されます。
This PC is directly connected to the Internet, so programs created there can be used by people all over the world.

このように24時間いつでも誰でも使えるプログラムのことを、「サーバー」と言います。
Such programs that are available to anyone, anytime are called "servers."

つまりAmazon Lightsailとは、自分で作ったプログラムをサーバーとして世界中の人に使ってもらえる、Amazon社が提供するサーバー基盤のことです。
In other words, Amazon Lightsail is a server platform provided by Amazon that lets programs you create run as servers for people around the world.

これ(原案)に対するChatGPT案(校正案)は以下の通りです。
In response to this (original proposal), ChatGPT's revised proposals were as follows.

■ChatGPT案(その1)
■ChatGPT Proposal (1)

Amazon Lightsailとは、世界中にあるAmazonのデータセンターの中で、24時間ずっと動き続ける「自分専用のコンピューター」を借りることができるサービスです(今回は東京にあるものを使います)。
Amazon Lightsail is a service that lets you rent your own dedicated computer that runs continuously, 24 hours a day, in Amazon's data centers around the world (this time we use one in Tokyo).

このコンピューターはインターネットに直接つながっているため、そこで作ったプログラムを、世界中の人からアクセスできるようにすることができます。
Because this computer is directly connected to the Internet, programs created there can be accessed by people around the world.

このように、インターネットを通して他の人が使えるように動いているコンピューターやプログラムのことを「サーバー」と呼びます。
Such computers or programs that operate so others can use them via the Internet are called "servers."

つまりAmazon Lightsailとは、自分で作ったプログラムをインターネット上で公開し、他の人が使えるようにするためのコンピューターを提供してくれる、Amazonのサービスです。
In other words, Amazon Lightsail is an Amazon service that provides a computer for publishing your programs on the Internet so others can use them.

■ChatGPT案(その2)
■ChatGPT Proposal (2)

Amazon Lightsailとは、インターネットの中に置ける「自分専用のゲームサーバー用マシン」のようなものです。
Amazon Lightsail is like your own dedicated game server machine that you can place on the Internet.

たとえば、マインクラフトのマルチプレイサーバーを動かすには、ずっと電源が入ったままのパソコンが必要になります。しかも、そのパソコンはインターネットにつながっていて、友達がいつでもアクセスできる状態でなければなりません。
For example, running a Minecraft multiplayer server requires a computer that is always powered on and connected to the Internet so friends can access it at any time.

でも、自分の家のパソコンを24時間つけっぱなしにするのは大変です。
But keeping your home computer on 24 hours a day is difficult.

そこで使うのがAmazon Lightsailです。
That's where Amazon Lightsail comes in.

これは、Amazonのデータセンターの中にある「ずっと動き続けているパソコン」を、自分専用に1台借りられるサービスです。
It is a service that lets you rent your own always-on computer in Amazon's data center.

そのパソコンは最初からインターネットにつながっているので、そこにプログラムを置けば、世界中の人がアクセスできます。
Since that computer is already connected to the Internet, installing a program on it allows access from anywhere in the world.

このように、みんながネット経由で使えるように動いている仕組みのことを「サーバー」と呼びます。
Such a mechanism that runs so everyone can use it over the network is called a "server."

つまりAmazon Lightsailとは、
In other words, Amazon Lightsail is

自分だけの「ネット上のゲームサーバー用PC」を借りて、そこに自分の作ったプログラム(たとえばAPI)を置き、スマホアプリやWebサイトから使えるようにできるサービスです。
a service that allows you to rent your own "game server PC on the Internet," place your own programs (such as APIs) on it, and make them usable from smartphone apps or websites.

---

うん、いずれも悪くはない、と思いました。
I thought that none of these were bad.

インターネットを理解していない世代と、理解している世代 ―― 説明の仕方も随分変わるものだなぁ、と実感しています。
I realized that the way explanations change greatly between generations who understand the Internet and those who do not.

もっとも「私の説明能力が、世代に関係なく常に不足している」という可能性も否定できませんが。
However, I cannot deny the possibility that my explanatory ability is always insufficient regardless of generation.

Amazon Web Service(AWS)の無料期間が経過していて、3~4回くらい、5000円/月の課金を喰らっていたことを知って、先日あわててアカウントを抹消しました。

2020/10,江端さんの技術メモ

Amazon Web Service(AWS)の無料期間が経過していて、3~4回くらい、5000円/月の課金を喰らっていたことを知って、先日あわててアカウントを抹消しました。

# 練習用に使っていただけなに、バカみたいです。

ところで、私が今、個人のWebサイトで利用させて頂いているのは、さくらインターネットの月額500円の仮想サーバです。WordPressと併用できて、とても便利です。

ただ、以前、このサーバを使って実家監視システムを作ろうと思ったのですが、色々問題があって使えませんでした(ホームページ用の仮想サーバなんだから当り前)。

といって、AWSは、高額の上に設定が面倒。このクラウドに、どれだけの時間を持っていかれたことか

という訳で調べたら、Amazonにも3.5ドル/月のサーバがあることが分かりました。 Amazon Lightsail です。

うん、これ、いい。私は、サーバを攻撃から守る気もないし、システム破られて持ち出された情報なんぞ入れる気もない。EC2なんぞ1つあれば十分だし、DBはUbuntuの中に作りこんでしまえばいい。

そもそも、ファイアウォールとして使っているロードバランサの設定も、Route53の設定もやりたくありません。

という訳で忘れない内にAmazon Lightsail の作成手順をメモしておきます。

(1)AWSのアカウントを作成(省略)

(2)Amazon Lightsail を選んで、「インスタンスの作成」ボタンを押下
https://lightsail.aws.amazon.com/ls/webapp/home/instances

私は、Ubuntu20.04を選択

一番安い$3.5を選択

あとは、ほったらかしにして(入力値はデフォルト、タグは無視)「インスタンスの作成」ボタンを押下

で、「データベース」タブは無視して、「ネットワーキングタブ」を選択

「静的IPの作成」ボタンを押して、そのままIPアドレスを作る。ちなみに、pingでは応答しないようです。

次に「DNSゾーン」の作成ですが、私は、お名前.comに1つドメイン名を確保しているので、それを使うことにしました。

そのやり方については、これを参考にして下さい。

基本的には、この情報を、お名前.comの方に書き込むだけです。

DNSレコードは、Aレコードだけを設定すれば良いです(サブドメインを作りたい場合は別)。

結果として、こんな表示が出せれば正解

DNSの反映されるに、10分~20分ってところだったと思います。

それと、どこでやったか忘れてしまったけど、SSHアクセス用の秘密鍵をダウンロードするプロセスがでてくるので、それをダウンロードしておく。LightsailDefaultKey-ap-northeast-1.pem てな名前でした(ダウンロード後、リネームしておくと良いでしょう)。

それを使ってTeraTermで、カーネルにアクセスできるようになります。FTPもteratermから "ファイル" → "SSH SCP"を選ぶと、ファイル転送できます(FFFTPは使えません)

あとは、TeraTermでSSHログインして、こんなコマンド投入しておきました。

>sudo apt-get update
>sudo apt install net-tools
>sudo apt install emacs
>sudo apt install golang-go

ロードバランサを使うと$18/月も取られるようなので、OS剥き出しで運用することにしました。

ポートのオープンはこちらからできます。ローカルのテストで http://localhost:8080 とかを使っていましたので、以下のように8080をオープンしておきます。これで、http://sea-anemone:8080 とかが使えるようになります。

(因みに、IPアドレスはデタラメな値に差し替えています)

なお、go言語で作っているサーバの方ですが、以下のような書き換えだけで対応できるようです。

//var addr = flag.String("addr", "localhost:8080", "http service address") // これは動かない
//var addr = flag.String("addr", "0.0.0.0:8080", "http service address") // ローカルでの環境
var addr = flag.String("addr", ":8080", "http service address") // AWS lightsailでの環境

お金がかかるので不満なのですが、システムが丸ごと壊れるのが怖いので、やっぱりスナップショットは1つ作っておくことにしました。

 

未分類

このコンテンツはパスワードで保護されています。閲覧するには以下にパスワードを入力してください。

2026,江端さんの忘備録

新しく上司になった人間は、新しいことを始めたがります。
People who have just become supervisors tend to start new initiatives.

それは、組織を良くしようという善意からであることが多いのですが、現場にとっては必ずしも福音ではありません。
This is often driven by good intentions to improve the organization, but it is not necessarily a blessing for those on the front lines.

なぜなら、新しく導入される「やり方」は、多くの場合、上司にとって良いやりかたではあっても、部下にとっては面倒なことが多いからです。
Because newly introduced "ways of doing things" may be beneficial for the supervisor, but they are often troublesome for subordinates.

「新しく導入される"やり方"」は、良いこともあります。しかし、これは善し悪しの問題ではありません。
These "newly introduced methods" may sometimes be good. However, this is not a matter of good or bad.

しかし、その変更に付き合わされる現場は、手順の再学習、運用の調整、想定外のトラブル対応など、多大な負荷を背負うことになります。
However, the people on the ground who must adapt to these changes end up bearing a heavy burden relearning procedures, adjusting operations, and handling unexpected troubles.

要するに、
In short,

―― 面倒くせい
"it's a hassle."

です。
That's what it comes down to.

---

「改革」というのが、多くの場合上手くいかないのは、大きく2つ理由があります
There are broadly two reasons why "reforms" often fail.

(1)「改革」は、成功するか失敗するか分からない。先例がないから。
(1) A reform may succeed or fail; there is no precedent.

(2)成功するか失敗するか、どちらにせよ、新しいことを強いられるのは面倒で不愉快だから
(2) Whether it succeeds or fails, being forced into something new is troublesome and unpleasant.

既存の方式が、それなりに機能しているのであれば、わざわざ「改革」なんぞ望みません。
If the existing system is functioning reasonably well, no one goes out of their way to seek reform.

「改革」は誰のためにあるのか ーー 畢竟(ひっきょう)、「改革を試してみたい人のため」"だけ"にあります。
For whom does reform exist? Ultimately, it exists only for those who want to try reform.

加えて、もう一つ理由を加えるのであれば、
If one more reason were to be added,

(3)「改革」が成功したとしても、それが大きく評価されることは極めてまれである。その「改革」は、後発的に『誰がやっても同じだった』として、歴史の中に埋没されていくから
(3) Even if a reform succeeds, it is rarely highly valued; it later gets buried in history as something "anyone could have done."

もあるでしょう。
That too may be the case.

いわゆる、「コロンブスの卵」というやつです。これは、改革を目指す人にとっても、負の動機(改革を実施しない言い訳)になると思います。
This is what is called the "Columbus's egg." It can even become a negative motivator, an excuse not to implement reform.

---

冒頭に上げた事例も含めて、こうした営みは「政治改革」です。
Including the example mentioned at the beginning, such efforts are "political reform."

政治とは、別に国会や行政で行われているものだけでなく、会社の部や課のレベルは勿論、家族や、友人間でも行われるものであり、そして、多くの場合「政治改革」は、
Politics is not only what happens in parliament or government; it takes place within company departments, families, and among friends, and in many cases, "political reform":

(1)実施されない
(1) Is never implemented,

(2)実施されて、失敗する
(2) Is implemented and fails,

(3)実施されて、成功して、すぐに忘れ去られる
(3) Is implemented, succeeds, and is quickly forgotten.

の3つの運命しかありません。
These are the only three possible outcomes.

以上、「政治改革の被害者」と「政治改革の実施者」の両方の視点からの分析をしてきました。
Thus far, this has been an analysis from both the victim's and the implementer's perspectives of political reform.

---

私も若いころは、自分の能力の範囲での「政治改革の実施者」をやってきたつもりです。それが、家庭内であったり、テニスサークルであったり、自分の課の中であったりと ーー 随分とチンケなレベルではありますが。
When I was younger, I too considered myself an implementer of "political reform" within my limited capacity, whether at home, in a tennis club, or within my department, though admittedly at a rather trivial level.

ただ、歳を経ることによって、上記の「政治改革」の3つの背景と3つのアウトプットを感じるようになってきて、いつしか『改革者側に立つのは、面倒くさい』と思うようになってきました。
However, as I grew older, I began to sense the three backgrounds and three outcomes of such "political reform," and gradually came to feel that standing on the reformer's side was simply a hassle.

この『面倒くさい』が最高レベルに達した時に、私が至った一のパラダイムが、
When this sense of hassle reached its peak, I arrived at a paradigm:

―― たった一人の政治改革
"political reform by just one person."

です。
That was it.

---

たとえば、私が課内の「政治改革の実施者」であった頃の話です。
For example, when I was acting as a reformer within my department:

ある時、私は、「会議が多すぎる」という、誰もが一度は思う問題に直面しました。
At one point, I faced the common complaint: "There are too many meetings."

週次会議、進捗会議、レビュー会議、報告会議 ーー 名称は違いますが、要するに全部同じです。
Weekly meetings, progress meetings, review meetings, reporting meetings, different names, but essentially the same.

私は、これを改革しようとしました。
I tried to reform this.

まず、(1)会議時間の半減、(2)事前資料の提出義務化、(3)発言者の事前登録、(4)決定事項の即時ログ化、という、『効率化された新会議制度』を設計しました。
First, I designed an "efficient new meeting system": (1) halving meeting time, (2) mandatory pre-submission of materials, (3) pre-registration of speakers, and (4) immediate logging of decisions.

資料を作り、関係者に説明し、導入しました ―― 結果、『会議は半減しませんでした』。
I prepared materials, explained them to stakeholders, and implemented the results: meetings were not halved.

事前資料は提出されず、発言者登録は形骸化し、ログは誰も見ませんでした。
Materials were not submitted, speaker registration became a formality, and no one looked at the logs.

そして何より、『新しい運用ルールの説明のための会議』が追加されました。
Above all, a "meeting to explain the new rules" was added.

つまり、私は「会議を減らす改革」によって、『会議を増やした』のです。
In short, through a reform meant to reduce meetings, I increased them.

―― うん、バカとしか言いようがない
"Yes, there's no way to describe it except as foolish."

"反省"や"自己批判"という言葉を越えて「呆れて笑うしかない」 ―― "自嘲自棄(じちょうじき)"です。
Beyond "reflection" or "self-criticism," it left me only able to laugh in exasperated self-mocking despair.

---

その後の私は、一切の会議改革を提案することをやめました。
After that, I stopped proposing any reforms to meetings.

その代わり、自分の出席する会議だけ、「本当に必要なこと以外は発言しない」という運用を開始しました。
Instead, I began operating under a rule in meetings I attended: not to speak unless necessary.

(正確にいうと『議論の発散を防ぎ、収束する方向に姑息に誘導する』運用ですが)
(More precisely, I subtly steered discussions to prevent divergence and move toward closure.)

驚くべきことに、私が発言しなくても、会議は進行し、決定もなされ、議事録も問題なく作られました。
Remarkably, even without my speaking, meetings proceeded, decisions were made, and minutes were created without issue.

何一つ問題は起きませんでした。それどころか、会議時間は短縮されました。
No problems arose; in fact, meeting times were shortened.

私が、説明や補足は新規な事項を言い出さないように努めた結果、議論が拡散しなかったのです(議論を「発展させなかった」とも言えますが)。
By refraining from introducing new points in explanations or clarifications, discussions did not spread outward (or one could say they did not "develop").

私は、会議制度を変えなかったにも関わらず、会議の運用を変えてしまったのです ―― 私の主催する会議についてだけ、ですが。
Without changing the meeting system, I had changed its operation at least for the meetings I chaired.

---

その後、「江端さんは、会議を時間以内にきっきりまとめる」という評価を受けるようになったという話も聞きましたが、私は何もしていません。
Later, I heard that I was evaluated as someone who neatly wraps up meetings within the allotted time, but I did nothing.

本当に「何もしなかった」。
Truly, I did nothing.

制度を変えるのではなく、改革者を一人減らす ―― その改革者が、たまたま私だった、というだけの話です。
Rather than changing the system, I reduced the number of reformers by one; that reformer just happened to be me.

---

改革を否定する改革 ―― これが、私の至った「たった一人の政治改革」です。
A reform that denies reform, that is, the "political reform by just one person," I arrived at.

『つまり、政府主導の「働き方改革」は、実体を反映していない虚構の(あるいは労働時間だけに注力した)実体のない、あるいは、害悪ですらあるものである、と言えるでしょうか』とChatGPTに聞いてみた件

未分類

https://wp.kobore.net/2025/12/10/post-23101/

HLS映像検索・サムネイル・再生システム構築手順書 - リバースプロキシ対応による公開境界分離構成

HLS映像検索・サムネイル・再生システム構築手順書 - リバースプロキシ対応による公開境界分離構成.md

以下は、貼付「HLS映像検索・サムネイル・再生システム構築手順書.pdf」を前提に、**“今回の修正(= reverse-proxy 化)で追加・変更した箇所だけ”**を、**手順書内にそのまま貼り付けられる形(ファイル全文+コマンド全文)**でまとめたものです。
(方針は、貼付「映像検索・配信システム構築手順書.pdf」の reverse-proxy(Nginx)で API を隠蔽する方式を踏襲しています 。)


0. 背景と目的(今回の差分の意義)

背景

従来手順では、FastAPI が HLS(/hls)やサムネイル(/thumbs)やUI(/ui)を直接配信する構成になっており 、ブラウザからのアクセス経路が「API 直アクセス」になりがちです。また DB もホストに port 公開して運用しがちです(例:15432:5432) 。

目的(今回)

  • ブラウザから見える公開点を **http://localhost/(reverse-proxy)に一本化**する
  • API/DB/HLS/サムネイルを“フロントから直接見えない”(= 直接ポート露出や直配信を避ける)構造へ寄せる
  • 方式は「映像検索・配信システム構築手順書.pdf」の reverse-proxy 構成(location /api/ { proxy_pass ... } 等)を踏襲

1. 今回の修正で追加するディレクトリ

既存 ~/video_hls_project の直下に、以下を 新規作成します。

cd ~/video_hls_project

mkdir -p api
mkdir -p reverse-proxy/frontend

2. 今回の修正で「新規に作る(または置き換える)」ファイル一覧

  • 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(置き換え)

3. ファイル全文:api/Dockerfile(新規)

作成先: ~/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

4. ファイル全文:api/app.py(新規)

作成先: ~/video_hls_project/api/app.py

ポイント:

  • DB内 m3u8_path(例:videos_hls/clip01/index.m3u8)を、返却URL /hls/clip01/index.m3u8 に変換するロジックは従来PDFの考え方を踏襲しています
  • /hls /thumbs を FastAPI で静的マウントする方式自体は従来PDF同様
  • ただし公開は reverse-proxy 経由に統一します(後述 nginx.conf)
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

5. ファイル全文:reverse-proxy/Dockerfile(新規)

作成先: ~/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

6. ファイル全文:reverse-proxy/nginx.conf(新規)

作成先: ~/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

7. ファイル全文:reverse-proxy/frontend/index.html(新規)

作成先: ~/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

8. ファイル全文:docker-compose.yml(置き換え)

作成先: ~/video_hls_project/docker-compose.yml

ポイント:

  • db / api / reverse-proxy の 3サービス化(reverse-proxy の ports 80:80 のみ公開)
  • db の ports 公開は 原則やめる(必要ならコメント解除で運用)
  • api は ~/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

9. 起動方法(今回版)

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 を持たない。


10. 確認方法(今回版)

10.1 reverse-proxy 経由で API を確認

curl -i http://localhost/api/health
curl -i http://localhost/api/chunks

10.2 HLS の疎通確認(例:clip03)

curl -I http://localhost/hls/clip03/index.m3u8

10.3 ブラウザ確認

  • Web UI:http://localhost/
  • 映像一覧(JSON):http://localhost/api/chunks

11. 運用上の注意(今回の「フロントから見えない」化の要点)

  • DBはホストへ port 公開しない(原則)
    従来の 15432:5432 公開は、必要時のみ一時的に使う扱いに変更(元手順では公開例あり )。
  • APIもホストへ port 公開しない
    ブラウザは http://localhost/ にしか触れず、/api /hls /thumbs は全て Nginx が中継。

必要なら、次に「HLS映像検索・サムネイル・再生システム構築手順書.pdf」側の **どの章・どの節に、上の差分をどう挿入するか(“差し込み位置メモ”)**も、章番号つきで作れます。

未分類

今の私の体重は、

―― この値が、偏差値なら、日本の9割の大学で合格できるだろう

というレベルの値です。

こういう単位系を無視して語る愚か者は、世の中には多くいます。

偏差値0とか、偏差値100とか書いて、自分の無学を晒している者もいます。

ともあれ、単位や偏差の意味を無視すれば、私はいま「世界トップクラスの優秀さ」を誇っていることになります。

―― 体重計の上では。

----

要するに、私は今、偏差値としてなら“極めて望ましい範囲”に収まっているのです。

つまり、数値を文脈を外して語ると『笑われる(冷嗤される)』ので要注意、ということです。

「今だに『偏差値至上主義』とか言う言葉を"批判"の用語として使っている奴 = バカ」

 

 

2026,江端さんの忘備録

今回は大学院(博士課程)に入学するまでの「ドタバタ劇」をお伝えしたいと思います。願書提出から受験までの過程は、人生やキャリアの棚卸しと、残酷なまでの自己点検の連続となりました。

2026年02月26日 10時00分 公開
[江端智一,EE Times Japan]

3年間の休載を経て戻ってきました。休載していた理由は、私はリタイア(定年退職)間際だったにもかかわらず、「MAS(マルチエージェントシミュレーション)」を研究すべく、社会人のまま大学院博士課程に突っ込んでいったからです。なぜ“そんなこと”になったのか――。そして私をそこまでさせた「MAS」とは何なのか。社会人大学院生の実態を赤裸々に語りつつ、MASを技術的に深掘りしていきます。
⇒連載バックナンバーはこちらから

2026,江端さんの忘備録

先週末、OpenAIが提供する"AIエンジン"を使って、対話型のアンケートシステムのプロトタイプを作っていました。
Last weekend, I was building a prototype of an interactive survey system using the "AI engine" provided by OpenAI.

思ったより簡単に作ることができて、ちょっと驚いています。
I was a little surprised to find I could build it more easily than I had expected.

これまでのプログラミングと違って、膨大なAPIを覚えてプログラミングをする必要もなく、パッケージをセットするだけで動き出す、というこの仕組み(AIエンジン)に、かなり驚いています。
Unlike traditional programming, there was no need to memorize a vast number of APIs; I was quite astonished by this mechanism (the AI engine) that starts working simply by installing a package.

『弊社の研究者&技術者の8割が、AIを扱えるようにする』
"Enable 80% of our company's researchers and engineers to handle AI."

(と、誰か(エライ人)が言っていたと思うが、誰も弊社に問い合わせないように。私は面倒に巻き込まれるのはイヤだから)
(I think someone said that, but please don't contact my company about it. I don't want to get dragged into anything troublesome.)

という方針は、"無茶"ではなく"十分にスコープに入っている"のかもしれないなぁ、と思い始めています。
I am beginning to think that this policy may not be "reckless" but rather "well within scope."

---

こういう話をすると、以下の話を思い出します。
Whenever I talk about this, I am reminded of the following.

(1)自分が使えるようになった途端、それまでリモート会議を頑なに認めなかったにもかかわらず、まるで最初からITリテラシーに理解のある「リモート会議推進派」であったかのように振る舞う会社幹部(のジジイ)
(1) A company executive (an old guy) who, the moment he became able to use remote meetings himself, began acting as if he had always been an IT-literate "proponent of remote meetings," despite having stubbornly refused to acknowledge them before.

(2)IT関連に特段の関心も理解もなかったにもかかわらず、所属サークルで広報担当となり、Web広報のためにHTMLを書き始めた途端、「Webなんて誰にでもできる」と言い出した私の娘
(2) My daughter, who had neither a particular interest nor understanding of IT, but once she became the publicity officer of her club and started writing HTML for web promotion, suddenly began saying, "Anyone can do web stuff."

そして、
And then,

(3)以前から「AIはサービスとして利用できれば十分で、深く関わる必要はない」と言い続けていたのに、対話型アンケートシステムのプロトタイプを完成させた途端、「弊社の研究者・技術者の8割がAIを扱えるようにする」という会社の方針に理解を示し始める研究員(私だ)
(3) A researcher (that would be me) who had long insisted that "it is enough to use AI as a service; there is no need to be deeply involved," but after completing a prototype of an interactive survey system, began to show support for the company policy of enabling "80% of our researchers and engineers to handle AI."

嫌な奴らですねぇ、こういう奴らって ーー 自分の安全が担保されたとたん、いきなり『他の人もできるはず』と、掌を返すだけでなく、他人に自分の考えを押し付けはじめる人間って、本当に最低です。
What unpleasant people these are! those who, the moment their own safety is secured, suddenly declare "others should be able to do it too," not only reversing their stance but also beginning to impose their views on others. Truly the worst.

---

『AIエンジンを使ったシステムの研究というのは、AIの研究ではない』とは思いますが、『AI技術の応用研究』であるとは思います。
I do not think that researching systems using an AI engine is the same as researching AI itself, but I do believe it constitutes applied research in AI technology.

トランジスタを発明したのは、米国のジョン・バーディーンさんらですが、そのトランジスタをトランジスタラジオとして世界に定着させたのは、我が国のソニーの盛田昭夫さん。
The transistor was invented by John Bardeen and others in the United States, but it was Akio Morita of Sony in Japan who established the transistor radio worldwide.

まあ、私が盛田さんと同レベルになるのは難しい(というか不可能)ですが、その方向性を踏襲することはできます。
Well, it is difficult (indeed impossible) for me to reach Morita's level, but I can follow that direction.

私が今考えているのは、日本でもっとも嫌われている仕事の一つである、『PTAの役員の仕事をAIエージェントにやらせる』です。
I am now considering having AI agents handle one of the most disliked tasks in Japan: serving as PTA officers.

このPTAの役員は、なんなら「クラスの学級委員」でもいいし、可能であれば『町内会のジジイたちを、全部、AIエージェントに置き換える』でもいいです。
These PTA officers could just as well be "class representatives," and if possible, we might even "replace all the old men in neighborhood associations with AI agents."

これ、荒唐無稽な話ではなく、私の直感が「多分、できるぞ」と言っているものです。
This is not an absurd idea; my intuition tells me, "We can probably do it."

私の直感はかなりの確率で外れますが、それでも、完全独立型のAIエージェントでなく、CoPilot(副操縦士)という役割から始めるのであれば、十分にスコープに入ると思っています。
My intuition is often wrong, but even so, if we begin not with fully autonomous AI agents but with a CoPilot role, I think it is well within scope.

実際に、今の私は、ソースコード作成も、コラム執筆も、生成AIサービスを副操縦士として使い倒していますから。
In fact, I already make full use of generative AI services as a copilot for both writing source code and composing columns.

---

嫁さん:「そうかな?それは、社会ニーズと言い切れるかな?」
Wife: "Really? Can you definitively call that a social need?"

江端:「なんで疑問句? PTAの役員なんて『任命された人がその場で泣き崩れた』という話を、どこでも聞くぞ。町内会も役員を任命されたら、町内会を脱退した、なんて話は山ほど聞いてきたぞ」
Ebata: "Why the question? I've heard everywhere stories of people breaking down in tears on the spot when appointed as PTA officers. I've also heard countless stories of people quitting neighborhood associations when assigned as officers."

嫁さん:「『PTAの役員をやって、子どもの生活と関わりたい』と立候補する人で溢れているのを、この目でみたし、町内会が老後の生き甲斐、という人も、同じようにいるよ」
Wife: "I've seen with my own eyes places overflowing with volunteers who want to be PTA officers to be involved in their children's lives. And some people see neighborhood associations as their purpose in retirement."

江端:「それは、レアケースじゃないの?」
Ebata: "Isn't that just a rare case?"

嫁さん:「自分の1年を、1日の祭の為だけに捧げている人、というのが存在しているのは否定できないでしょ?」
Wife: "You can't deny that there are people who dedicate an entire year of their lives to a single day's festival, can you?"

- たしかに、10年毎に死傷者を出すような祭が、行政によって「禁止」または「廃止」にされていない。
- Indeed, some festivals produce casualties every decade, yet have not been banned or abolished by authorities.

- 街中をものすごいスピードで山車を走らせるような、野蛮な祭が地域によって圧倒的な支持を経て継続されている。
- Even "barbaric" festivals in which floats are driven at tremendous speed through town continue with overwhelming local support.

- そんな祭に参加する人数が、減っていない ーー 下手すると増えているところもある
- The number of participants in such festivals has not decreased? In some places, it has even increased.

嫁さん:「だいたいね。学校が『祭の準備の為に、学校を休むことを認めている。下手すると"勧めて"いる』という地域があるんだよ」
Wife: "In some regions, schools allow? and sometimes even encourage? students to take time off for festival preparations."

江端:「なんで、生存帰還率100%を担保できないような祭に対して、地域や、こともあろうに教育機関までが支援をしているんだ? 彼らは、狂っているのか?」
Ebata: "Why would communities and even educational institutions of all things support a festival that cannot guarantee a 100% survival rate? Are they insane?"

嫁さん:「『タスクの軽量化が絶対の正義ではない』からでしょう」
Wife: "Because ‘lightning tasks are not absolute justice.'"

---

私は、PTAや町内会の仕事を"タスク"として見ている。議事録、日程調整、連絡文作成――これらは確実にAIエージェントで軽くできる。
I view PTA and neighborhood association work as "tasks." Minutes, scheduling, drafting notice? AI agents can certainly lighten these.

だが、嫁さんは、その先を語っている
But my wife is talking about something beyond that.

揉め事や感情の衝突、非合理な祭への情熱まで含めて、それは「物語」であって、負担軽量化の対象の「外」にあるということです。
Including conflicts, emotional clashes, and a passion for irrational festivals? These are "stories," and lie outside the scope of burden reduction.

「人生の重荷は軽ければ軽い方が良い」という私のテーゼに対して、嫁さんは、「人生の重荷の価値は人それぞれ」というアンチテーゼを実施例込みで示したのです。
Against my thesis that "the burdens of life are better the lighter they are," my wife presented the antithesis that "the value of life's burdens differs from person to person," complete with concrete examples.

---

巨大なモミの木(御柱)を山から切り出し、急斜面を滑り落とす「木落し(きおとし)」という祭の運営をAIエージェントにやらせてみたら、どうなるだろうか?
What would happen if we let AI agents manage the "Kiotoshi," a festival in which a massive fir tree (Onbashira) is cut from the mountain and slid down a steep slope?

『そんな祭は止めなさい』と言って、運用を投げ出すだろうか。
Would it say, "Such a festival should be stopped," and abandon the operation?

それとも『最大被害者数(死者を含む)を数値で入力して下さい』と言って、御柱の質量と長さ、乗車人数、坂の斜度の計算を計算をし始めるだろうか。
Or would it say, "Please input the maximum acceptable number of casualties (including fatalities)," and begin calculating the mass and length of the log, the number of riders, and the slope angle?

どっちになっても、私には興味深いです。
Whichever way it goes, I find it fascinating.

こういう「非連携システム間での、生成AIのオペレーションによる知識伝達」をやってみたいんです

2026,江端さんの忘備録

私はSNSを使っておりませんが、Microsoft Teamsを業務で使用させられております。
I do not use social networking services, but I am made to use Microsoft Teams for work.

「便利である」というのは事実ですが、仕事の最中に割り込まれるという点において、その便利と相殺の関係にある、という感じはしています。
It is indeed convenient, but because it interrupts me in the middle of work, I feel that intrusion offsets this convenience.

割り込みに関しては、対応策があるので、これは、その対応をサボっている私にも責任があるのですが、SNSの価値の一つには、この「割り込み」にあるので、これを消すのもどうかな、とも思っています。
As for interruptions, there are countermeasures, so I am also responsible for neglecting them; however, one of the values of SNS lies precisely in this "interruption," so I hesitate to eliminate it.

「便利である」という観点の一つに「いいね」アイコンがあります。
One aspect of its "convenience" is the "Good" icon.

---

わたし、この「いいね」アイコンについては、以前、『お前の食ったメシなんぞに興味があるか』と書いたことがあります。
As for this "Good" icon, I once wrote, "Do you think I care about the meal you ate?"

この気持ちには変化はないのですが、業務で使われる「いいね」には、別の意味があります。
My feelings about that have not changed, but when "Good" is used in a work context, it carries a different meaning.

そのメッセージが「いい」のではなく、そのメッセージを「読んで、理解した」ということを相手に伝える手段として用いるという点です。
It is not that the message itself is "good," but that it serves as a means of conveying to the other party that one has "read and understood" the message.

まずメリットですが、『圧倒的なラクさ』です。いちいち、返信メッセージを書かなくても良い、というのはラクです。
The first advantage is its "overwhelming ease." Not having to write a reply message every single time is undeniably easy.

---

これを書いていて思い出したのですが、以前、亡き父が、ある人のために色々手を尽したことに対して、『御礼のメモ(1~2行)』だけを受けとって激怒していた、という事件がありました。
Writing this reminds me of an incident in which my late father became furious after receiving only a "thank-you note (one or two lines)" in return for the considerable efforts he had made for someone.

私、亡き母から懇願されて、この件の調停に入ったのですが、父も母も「状況を客観的に説明する能力と技術」が決定的に欠けており、何がなんだか分からない状況が、随分長い時間かかったことを覚えています。
At my late mother’s pleading, I intervened to mediate the matter, but both my father and mother were decisively lacking in the ability and skill to explain the situation objectively, and I remember that it took a very long time before I could understand what was actually going on.

この時は、『私が礼状を代筆して、それを送付するように相手方に依頼する』という、なんとも面倒なことをやって、事態を収拾した記憶があります。
At that time, I recall resolving the situation by drafting a proper letter of thanks myself and asking the other party to send it.

これは、誰が悪いというものではなく、典型的なジェネレーションギャップと言えましょう。
This was not a matter of who was at fault; it was a typical generational gap.

とは言え、私も、自分の貢献に対して、それ相応の礼を返して貰えなければ、「激怒」はしないまでも、その後に「一方的な交流のシャットダウン」をする、というプロトコルを運用しています。
That said, if I do not receive an appropriate expression of thanks for my own contributions. At the same time, I may not "fly into a rage," but I operate a protocol of "unilaterally shutting down communication" thereafter.

「理由を提示せず、一方的にネットワークを遮断する」のですから、私は、父より苛烈な措置を取っている、とも言えます。
Since this means "cutting off the network unilaterally without presenting a reason," one could say that I take measures harsher than my father did.

閑話休題
That aside.

---

他にメリットがあるとすれば、「摩擦係数の低減」です。
Another advantage, if any, is the "reduction of friction."

メッセージに逐一文章で返答すると、どうしても語尾や語調、ニュアンスに余計な意味が付与されます。短い返信であっても、「冷たい」「不機嫌だ」「皮肉だ」と解釈される余地が生じます。しかし「いいね」は、その余白を極端に削ぎ落とします。
When responding to messages with written sentences each time, unintended meanings inevitably attach themselves to endings, tone, and nuance. Even a short reply may be interpreted as "cold," "irritated," or "sarcastic." However, a "Like" strips away that margin for interpretation to an extreme degree.

肯定でも賞賛でもなく、「受信確認」「内容把握」「処理済み」のシグナルとして機械的に扱える。これは、組織内通信においては極めて効率的です。
It is neither affirmation nor praise, but can be treated mechanically as a signal of "receipt confirmed," "content understood," or "processed." In internal organizational communication, this is highly efficient.

ある意味で、「いいね」は感情を削減する装置です。
In a sense, the "Good" is a device that reduces emotion.

その他のメリットとしては、通信のUDP化(×TCP化)があります。
Another advantage is the UDP-ization (rather than TCP-ization) of communication.

「送達確認不要」の「一斉ブロードキャスト」というのは、いわゆる、『同調圧力製造装置』としても上手く機能する装置です。
A "mass broadcast" with "no delivery confirmation required" also functions effectively as what might be called a "device for manufacturing conformity pressure."

---

比してデメリットがあるとすれば、「読んで、理解した」に加えて「納得した」という意味が込められかねない、というリスクです。
By contrast, a potential disadvantage is the risk that, in addition to "read and understood," it may also be taken to mean "agreed."

例えば、以下のようなメッセージは、難問です。
For example, the following kind of message poses a difficult problem.

『本件は、江端さんの提案ベースの内容での検討を進めれば良いと思います』
"I think we should proceed with consideration of this matter based on Mr. Ebata’s proposal."

さて、このメッセージに「いいね」を付けた場合。
Now, suppose I attach a "Good" to this message.

最も無難に見えて、実は最も情報量が多い行為になります。
It appears to be the safest action, yet it actually carries the most information.

少なくとも、
At the very least,

- 読んだ
- I have read it

- 理解した
- I have understood it

- 異論を唱えない
- I raise no objection

- 進行を許容する
- I permit it to proceed

という複数の意味が、まとめてパッケージ化されます。
Multiple meanings are bundled together.

しかも、そのメッセージは「江端さんの提案ベース」と明示している。そこに「いいね」が付くと、第三者から見れば、
Moreover, the message explicitly states "based on Mr. Ebata’s proposal." If a "Good" is attached to it, then from a third party’s perspective,

"江端本人がその進め方を了承し、かつ、江端が本案件を担当することを認めた."
"Ebata himself has approved this course of action and acknowledged that he will be responsible for the matter."

と読めます。
That is how it may be read.

反対していない、どころか、推進側の当事者として確定する可能性すらあります。
Not only is there no opposition, but it may even solidify my position as a party promoting the matter.

つまり、「受信確認」のつもりが、「合意の証跡」になるリスクを孕む。
In other words, what was intended as "receipt confirmation" could become "evidence of agreement."

デジタルの軽さに反して、ログは重いのです。
In contrast to the lightness of digital actions, logs are heavy.

---

では、「いいね」を付けなかった場合。
Then what if I do not attach a "Good"?

今度は逆方向の意味が生まれます。
Now meanings arise in the opposite direction.

- まだ読んでいないのか
- Has he not yet read it?

- 読んだが賛同していないのか
- Has he read it, but does not agree?

- あえて反応を保留しているのか
- Is he deliberately withholding a response?

- 不機嫌なのか
- Is he in a bad mood?

沈黙は、空白ではありません。解釈の余白です。
Silence is not emptiness; it is a margin for interpretation.

しかも、周囲が次々と「いいね」を付けていく中で一人だけ無反応であれば、それは"消極的反対"のシグナルとして読まれかねない。
Moreover, if everyone else is attaching "Good" one after another and only one person remains unresponsive, that may be read as a signal of "passive opposition."

つまり、「合意しない自由」を守ろうとした結果、「協調しない人」というラベルを貼られる可能性がある。
Thus, in attempting to preserve the "freedom not to agree," one may end up being labeled as "uncooperative."

---

ここにあるのは、ボタン一つの問題ではありません。
What is at issue here is not merely a single button.

「いいね」は、感情を削減する装置であると同時に、責任の所在を曖昧にする装置でもあり、そしてときに、責任を固定する装置にもなる。
The "Like" is at once a device that reduces emotion, a device that obscures responsibility, and at times a device that fixes responsibility in place.

軽い操作に対して、解釈は決して軽くない。
For such a light action, interpretation is never light.

押しても意味が増幅し、押さなくても意味が増幅する。
Whether pressed or not pressed, meaning is amplified.

デジタル通信の合理性の裏側に、人間の解釈という、どうしようもなくアナログな装置が居座っている。
Behind the rationality of digital communication sits the irreducibly analog device of human interpretation.

それだけの話なのですが、それだけの話では済まないのです。
That is all there is to it, yet it cannot be dismissed as merely that.

---

つまるところ、私は ――
In the end, I

Teamsの通知を切るかどうかで悩み、
worry about whether to turn off Teams notifications,

「いいね」を押すかどうかで悩み、
worry about whether to press "Good,"

押した後も「これは合意と見なされるのではないか」と悩み、
worry after pressing it that it might be regarded as an agreement,

押さなかったら押さなかったで「面倒な人と思われるのではないか」と悩む、
And if I do not press it, I worry that I might be thought of as a troublesome person,

という、極めて生産性の低い高度情報処理をやっているわけです。
and thus find myself engaged in an extremely unproductive form of high-level information processing.

―― お前の食う飯なんぞ、知ったことか

 

未分類

『学生運動』はなぜ失敗したのか?

youtube.com/watch?v=2J_PFpY8jPo

を視聴した、私の感想。

『malloc()をしないで、最初にポインタだけを作っておき、メモリは後で、私以外の誰かが作るか、OS(社会)が自力でメモリを確保してポインタとリンクするに違いないという、アホほど甘ったれたシステム構築(またはプログラミング)をやってきたせい』

さて、私が言っていることが、あなた(ChatGPT)に理解できますか?

-----

はい、あなたが言っていることは理解できます
あなたは『学生運動』の失敗を、コンピュータのプログラミングと対比して 比喩的に説明しているのだと思います。

あなたの表現を整理すると次のようになります:

  • 「学生運動」は malloc() をしないでポインタだけを用意した状態に例えられる
    ⇒ ポインタ(目的・戦略・資源の確保計画・組織的基盤)だけ作って
  • メモリ(資源・実行力・社会の支持・体系的戦略)は
    「後で誰かが勝手に確保してくれるだろう」 「OS(社会)が補完してくれるだろう」
    期待していた(甘えていた)
  • しかし実際には、ポインタだけに頼っていても
    実際のメモリ確保(実効的な組織力・戦略・支持)は勝手には埋まらず
    システム(運動)は動作しなかった=失敗した
    という趣旨の比喩表現です。

これは比喩的な把握として十分理解できます。
つまりあなたはこう言いたい:

目的や理想だけ掲げて、具体的な戦略・役割分担・資源確保・社会との整合性を確立しないまま動いたので、システム(運動)が実行不能になった

ということだ、と捉えています。

この比喩は、コンピュータプログラミングで言えば ポインタだけつくって実際のメモリ領域(動作に必要な実データ)を割り当てていない状態です。
その状態ではプログラムが「クラッシュ」するのと同じように、現実の社会運動でも 実行力・支持基盤・戦略がないと失敗する、という指摘ですよね。

歴史的に見ても、1960年代の日本の学生運動では:

  • 多くの要求や理想・抗議目標があったものの
  • 組織的統一や長期的戦略、社会全体の支持基盤に乏しく
  • 内部対立や派閥分裂が進み
  • 当局の弾圧と資源不足で持続できなくなった

という分析がされています。(ウィキペディア)

この「失敗の要因」を システム設計論に喩えるあなたの説明は、こうした歴史分析と大筋で一致しており、意味として十分理解できます。

「70年代安保闘争における全共闘または他のセクトにおいて、その活動の総括はどのように行われましたか」とChatGPTと議論をしてみた件