2025,江端さんの技術メモ

今で言う投稿サイトに"fj"というものがありました。

There was a posting site called “fj” back then.

かつて、そこでは、『「ナンバーディスプレイ通知」の是非』について、熱い議論が交されていました。

In the past, there were heated debates about the pros and cons of “number display notification.”

「ナンバーディスプレイ通知」とは、相手先の電話番号がスマホに表示されることです。

'Number display notification' is when the other party's phone number is displayed on your smartphone.

今となっては、『何のために、そんな議論をしていたんだろう』と思われるかもしれません。

Now, you may be thinking, 'What was the point of all that discussion?

ですので、当時のことを思い出しながら書いてみます。

So, I'll try to write about it while remembering what happened back then.

-----

(1)プライバシー保護: 発信者の番号通知がプライバシー侵害につながる可能性が懸念された。

(1) Privacy protection: There were concerns that caller ID could violate privacy.

(2)受信者の権利: 受信者の利便性と発信者の匿名性の対立が議論された。

(2) Recipient's rights: The conflict between the recipient's convenience and the sender's anonymity was discussed.

(3)迷惑電話対策: 迷惑電話抑止の利点と偽装番号などの新たな問題が指摘された。

(3) Measures against nuisance calls: The benefits of discouraging nuisance calls and new problems, such as spoofed numbers, were pointed out.

(4)法的・技術的課題: 技術や料金、法整備が利用者の選択肢に影響を与えるとされた。

(4) Legal and technical issues: Technology, fees, and legal developments are said to affect users' choices.

(5)社会的影響: ナンバーディスプレイ普及によるコミュニケーションの変化が懸念された。

(5) Social impact: There were concerns about changes in communication due to the spread of number display.

-----

今となっては、「相手先の電話番号が表示されない」ということ自体、意味が分からないと思うのですが、当時は、『発信者のプライバシーを保護する』という、考え方があったのです。

Nowadays, I find it incomprehensible that the other party's phone number is not displayed, but at the time, there was a concept of 'protecting the privacy of the caller.'

この議論は、「ナンバーディスプレイ通知サービス = 是」とする側が優位だったように記憶しております。

I remember that the side that said “Number Display Notification Service = Good” was in the majority.

理屈はシンプルでして「ナンバーディスプレイ通知 = 非」とする人は、ナンバーディスプレイ通知サービスを使わなければ、それで足るだろう、という理由でした。

The logic is simple: if you don't use the number display notification service, it should be sufficient to set “number display notification = bad.”

ただ、これを個人の自由選択の問題に矮小化してしまえば、『発信者のプライバシーを保護する』という考え方そもののが消滅することが公共の利益に反する、という主張もあり、私は、それはそれで一理あったと思います。

However, suppose this is reduced to personal freedom of choice. In that case, there is also the argument that the idea of 'protecting the privacy of the sender' itself will disappear, which is contrary to the public interest, and I think that has a point.

この問題は「SNSの匿名性」の問題と形を変えて、引き継がれているように思います。

This problem has been passed on differently as the “anonymity of SNS” problem.

今は、(1)完全キャッシュレス決済、(2)現金決済との併存、という意見の論争があるようです。

There seems to be a debate between the opinions of (1) utterly cashless payment and (2) coexistence with cash payment.

これについては、調べて頂ければ、双方、説得力のある論が展開されていますので、興味のある人は調べて下さい。

If you investigate this, you will find that both sides have developed persuasive arguments. Please do so if you are interested.

-----

私が思い出すのは「地上デジタル放送」への切替の時の話です。

I remember the story of the switch to terrestrial digital broadcasting.

政府は10年も前から、切替を宣言していました(地上デジタル放送への完全移行を2011年7月24日に実施しましたが、この切替計画については約10年前の 2001年 から公知し、その10年間を移行期間としていました)。

The government had been announcing the switchover for 10 years (the complete switchover to terrestrial digital broadcasting was carried out on July 24th, 2011, but the switchover plan had been publicized about 10 years ago in 2001, and the 10 years was set aside as a transition period).

で、いざ「地上デジタル放送」への切替を行う1月前くらいから、マスコミは「高齢者や貧困者」を盾にした「地上デジタル放送反対キャンペーン」を実施はじめました。

So, about a month before the switch to terrestrial digital broadcasting, the media began to run a campaign against terrestrial digital broadcasting, using older people and people with low incomes as a shield.

当然、政府はそれに応じませんでした。

Naturally, the government did not respond.

さすがに、この件に関しては、私は『政府は悪くない』と思いましたよ。

As expected, I thought the government was not to blame.

だって、10年間も移行期間があったんですよ。こればかりは『いざとなったらゴネればなんとかなる』は、通用しないと思いました。

After all, there was a 10-year transition period. In this case, the saying “if push comes to shove, you can make do by complaining” wouldn't work.

私が覚えている限り、この騒ぎは、切替から1~2週間後にはニュースにも出てこなくなりました。

As far as I can remember, this commotion stopped appearing in the news after the switchover, which took place a week or two ago.

大した手間ではなかったからでしょう(あるいは、テレビがなくても何とかなることが、分かったのかもしれません)。

It probably wasn't much trouble (or maybe they realized they could manage without a TV).

-----

今年は「マイナンバーカード」で、一悶着おきそうな感じがしますが、多分、これも「地上デジタル放送」と同じような結末になるだろうと予想しています。

This year, there has been much fuss about the My Number Card, but I think it will probably be like terrestrial digital broadcasting.

2025,江端さんの技術メモ

以下は現在TCをインストールして設定したラズパイのifconfigです。

pi@raspberrypi:~$ ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.88 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::ba27:ebff:fe69:5b65 prefixlen 64 scopeid 0x20<link>
inet6 240f:30:a9ce:1:ba27:ebff:fe69:5b65 prefixlen 64 scopeid 0x0<global>
ether b8:27:eb:69:5b:65 txqueuelen 1000 (Ethernet)
RX packets 10040 bytes 750155 (732.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1326 bytes 166549 (162.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether b8:27:eb:69:5b:65 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether f4:4d:ad:04:49:d5 txqueuelen 1000 (Ethernet)
RX packets 11626 bytes 1414469 (1.3 MiB)
RX errors 0 dropped 4 overruns 0 frame 0
TX packets 1326 bytes 166549 (162.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 6 bytes 234 (234.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6 bytes 234 (234.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::ba27:ebff:fe3c:e30 prefixlen 64 scopeid 0x20<link>
ether b8:27:eb:3c:0e:30 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 23 bytes 3164 (3.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eth0 → eth1 の方向に bitrateを500
eht1 → eth0の方向にbitrateを300
で設定したい時、入力するコマンドを、 既存の設定をクリアにするところから教えて下さい

以下の手順で、既存の設定をクリアし、eth0からeth1の方向にビットレート500kbps、eth1からeth0の方向にビットレート300kbpsを設定できます。


1. 既存のtc設定をクリアする

まず、eth0eth1tc設定を削除します。

sudo tc qdisc del dev eth0 root 2>/dev/null
sudo tc qdisc del dev eth1 root 2>/dev/null

2. eth0 → eth1 のビットレートを500kbpsに制限する

eth0tcを設定します。

sudo tc qdisc add dev eth0 root handle 1: htb default 1
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 500kbit ceil 500kbit

3. eth1 → eth0 のビットレートを300kbpsに制限する

eth1tcを設定します。

sudo tc qdisc add dev eth1 root handle 1: htb default 1
sudo tc class add dev eth1 parent 1: classid 1:1 htb rate 300kbit ceil 300kbit

4. 設定確認

以下のコマンドで設定を確認できます。

sudo tc -s qdisc show dev eth0
sudo tc -s qdisc show dev eth1

5. オプション: 遅延やパケットロスを追加する場合

例えば、遅延やパケットロスを追加したい場合は、以下のように設定します。

eth0 → eth1 に遅延を追加(例: 50ms)

sudo tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 50ms

eth1 → eth0 にパケットロスを追加(例: 10%)

sudo tc qdisc add dev eth1 parent 1:1 handle 10: netem loss 10%

この設定により、双方向の帯域制御が行われます。必要に応じて、burstlatencyのオプションを追加してください。

2025,江端さんの技術メモ

先日、昨年末に放送された、「NHKスペシャル 量子もつれ アインシュタイン 最後の謎」について、その番組と無関係な日記をしました。

The other day, I wrote a diary entry about the “NHK Special: Quantum Entanglement - Einstein's Last Mystery” broadcast at the end of last year, but the diary had nothing to do with the program.

サッカー、野球、バレー、ありとあらゆるスポーツも"AI+センサ(カメラ等)+コンピュータ"で片付けていいんじゃないですか?

私、以前、「量子コンピュータ」の連載を担当していたとき、この番組に登場した人物を一人(デビット・ボームさん)を除いて全部調べ挙げました。

When I was in charge of the serialization of “Quantum Computers” before, I looked up all the people who appeared in the program except for one (David Bohm).

デビット・ボームさんは、新しい量子力学の理論の解釈を提唱し、その後、アカデミズムから冷や飯をくらい続けた方です。

David Bohm proposed a new interpretation of quantum mechanics but was shunned by academia.

その後、デビット・ボームさんは、超能力やカルトに傾倒していったようです。量子力学とは、そういう性質があるようです ―― まさか、研究者自身がハマるとは思いませんでしたが。

After that, David Bohm seems devoted to psychic powers and cults. Quantum mechanics seems to have that kind of property - I never thought that the researcher himself would become involved.

(↑クリックするとコラムに飛びます)

(Click to go to the column)

要するに、学会の主流でない研究の主張しつづけることは、研究者としてはリスクがある、ということです(ちなみに、デビット・ボームさんのこの理論は、現在も見直しされていないようです(一応、調べました))。

In short, there is a risk for researchers to continue to advocate research that is not mainstream in academic circles (incidentally, it seems that David Bohm's theory has not been revised to date (I checked)).

ただ、この「精神」は次の世代に引き継がれました。

However, this “spirit” was passed on to the next generation.

『どんな複雑で難関な理論であろうとも、実験で検証しなればならない』ということです。

"Regardless of a theory's complexity or challenge, it requires validation through experimentation.'

私、ジョン・スチュワート・ベルさんの「ベルの不等式」を理解した時に、凄いショックを受けました。

I was shocked when I understood John Stewart Bell's “Bell's Inequality.”

で、それを本当に実験したのが、ジョン・クラウザーさんです。

And the person who experimented was John Crowther.

私が尊敬している科学者の一人です。

He is one of the scientists I admire.

なにしろ、この人、「アインシュタインさんの大ファン」で、「量子力学の内容が難解で、理解できないから、全否定したい」という、おおよそ、量子力学の歴史の中で、登場できる人物ではないのです。

After all, this person is “a big fan of Einstein” and “wants to completely deny quantum mechanics because it is too difficult to understand” and is not a character who could appear in the history of quantum mechanics.

ところが、自分の願いに反して、実験によって量子力学の正当性を証明してしまった、という、稀有な人物なのです。

However, he is a rare person who, against his wishes, proved the validity of quantum mechanics through his experiments.

彼は、その実験設備を、スクラッチから「全部手作り」で完成させました。

He completed the experimental equipment “all by hand” from scratch.

実験予算ゼロの中で、大学の中の研究室の実験設備の残骸を拾ってきては、スクラッチから研究装置を作り上げた、という話は、私を魅了してやみません。

The story of how, with zero budget for experiments, he built up research equipment from scratch by picking up the remnants of experimental equipment from university laboratories never fascinates me.

さらに、他の研究者から、実験装置の不備を指摘されて、最終的にその実験を最終的に中止するに至ってしまった、という話は、『研究者という立場の弱さ」を示す顕著な例になります。

Furthermore, the story of how the experiment was eventually canceled after being pointed out by another researcher as being flawed in the experimental equipment is a striking example of “the weakness of the researcher's position.”

-----

で、まあ、私が言いたいのは、私も、今、従来にはなかった新しい手法をつかって、かなり無茶な方向で研究を暴走させている最中なのですが、デビット・ボームさんや、ジョン・クラウザーさんが喰らった「冷や飯」の話を聞くと―― なんか、力づけられるのです。

So, I'm also in the middle of letting my research run wild in a rather absurd direction, using new methods that have never been used before. Hearing about the “cold rice” that David Bohm and John Crowther had to eat gives me strength.

まあ、私の場合、ずっと「冷や飯」という公算が高いのですが ―― もうキャリアとか考える必要もないシニアとなっていることは、逆に「強み」と言えるかもしれません。

Well, in my case, I'll likely be “cold rice” for the rest of my life, but I'm already a senior citizen who doesn't have to think about my career anymore, which might be considered an advantage.

とは言え、晩年に、カルト宗教に嵌って、家族に迷惑をかけるシニアになるよりは、シミュレーションのコーディングで一人で狂っている老人の方が、まだマシだ、と思うのです。

I think that it is better to be a crazy older man alone, coding simulations, than to be a senior who gets caught up in a cult religion and causes trouble for his family in his later years.

2024,江端さんの技術メモ

頻繁に忘れれるので、メモ(バージョンによってコロコロ替わるので、これは一例)

sudo nano /etc/dhcpcd.conf
interface eth0
static ip_address=192.168.0.200/24
static routers=192.168.0.1
static domain_name_servers=8.8.8.8 8.8.4.4

======
別のケースとしては、
sudo nano /etc/netplan/99_config.yaml

 

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: false
      addresses:
        - 192.168.101.30/24
      routes:
        - { to: default, via: 192.168.101.1 }
      nameservers:
        addresses:
          - 8.8.8.8
          - 8.8.4.4
    enx207bd2222d29:
      dhcp4: false
      addresses:
        - 192.168.0.15/24

 

2024,江端さんの技術メモ

古いラズパイの再活用方法

 

1. 背景と目的

実験システム用にTCが2台必要となったので、2019年の実証実験で使っていたラズパイを改造してTCにすることにした。

2. 今回のターゲットとしたラズパイとその構成

ディストリビューションはRaspbianである。

Linux raspberrypi 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux

ラズパイにはイーサポートが1つしかないので、2つ目のポートは、USB-Ethを使う。

Cable Matters USB LAN変換アダプター 有線LANアダプター USB イーサネットアダプタ USB2.0 to RJ45

ディストリビューションはRaspbianである。

3. 古いラズパイの再構築

3.1. 状況の把握

古いラズパイを再利用するために、sudo apt-get updateをすると、

E: Failed to fetch http://raspbian.raspberrypi.org/raspbian/pool/main/c/cyrus-sasl2/libsasl2-modules_2.1.27~101-g0780600+dfsg-3+deb9u1_armhf.deb 404 Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]

E: Failed to fetch http://raspbian.raspberrypi.org/raspbian/pool/main/libv/libvpx/libvpx4_1.6.1-3+deb9u2_armhf.deb 404 Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]

という表示がでてくる。

3.2 リポジトリの更新更新

この場合リポジトリのURLが古い可能性があるので。/etc/apt/sources.listまたは/etc/apt/sources.list.d/raspi.listを編集し、最新のリポジトリURLを使用していることを確認する。

sudo nano /etc/apt/sources.list.d/raspi.list

deb行を以下のように変更する:

deb http://archive.raspbian.org/raspbian/ buster main contrib non-free rpi

3.3 パッケージリストを更新更新

リポジトリURLを変更した後、以下のコマンドを実行してパッケージリストを更新する。

アップグレード手順の例:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
sudo apt-get autoremove

必要に応じて、リリースをアップグレード:

sudo sed -i 's/stretch/buster/g' /etc/apt/sources.list
sudo sed -i 's/stretch/buster/g' /etc/apt/sources.list.d/raspi.list
sudo apt-get update
sudo apt-get upgrade

以上

2024,江端さんの技術メモ

これまで、動画の一部を切り取る、という作業をしてきましたが、有償ソフトであり、他の人には紹介できない状況でした。

しかし、先日、「OBS Studio」というフリーのソフトを教えてもらい、使ってみました。

ちょっとハマったところがあったので、自分の為にメモを残しておきます(私が分かりそうな部分は、ザックリ省略します)

Step 1 OBS起動

Step 2 「ウインドウキャプチャ」

で、ここからハマった

画面の切出しが分からない。ChatGPTに聞いたところ、『Altキーを押しながらドラッグで切り出せる』と言われたんだけど、
「Altキーを押しながらドラッグ」すると、画面全体を動かし、サイズも変えることはできますが、画面の部分を指定することができません。

で、なんどか質問を繰り返して

プレビュー画面の赤枠の「端」Altキーを押した状態でドラッグすると、その部分を切り取れます。

で分かりました。

Step 3 で、この後は、「録画開始」で切りとった部分だけが録画できるようになります。

今回は、比較的軽い「ハマり」で助かりました。

重要なのは「端」です。この一語がないだけで、ハマってしまうのが、この(IT)界隈の面倒くささです。

2024,江端さんの技術メモ

Windowsのmsys2でもmsys64でもUbuntu22.04でもdockerでも、VMAF機能尽きのffmpegが上手くいかなくて困っています。

g:\home\ebata\vmafに

FROM ubuntu:22.04

# 必要なパッケージのインストール
RUN apt-get update && apt-get install -y \
    wget build-essential yasm pkg-config libtool autoconf automake cmake git \
    libx264-dev libx265-dev meson ninja-build nasm python3-pip && \
    apt-get clean

# VMAFのビルドとインストール
RUN git clone https://github.com/Netflix/vmaf.git /vmaf && \
    cd /vmaf/libvmaf && \
    meson setup build --buildtype release && \
    ninja -C build && \
    ninja -C build install && \
    ldconfig

# FFmpegのビルドとインストール
RUN git clone https://git.ffmpeg.org/ffmpeg.git /ffmpeg && \
    cd /ffmpeg && \
    ./configure --enable-gpl --enable-libx264 --enable-libx265 --enable-libvmaf && \
    make && make install

# 実行用のディレクトリを作成
RUN mkdir /workspace
WORKDIR /workspace

で、

docker build -t custom-ffmpeg-vmaf .

をやっても、かならず、こんなエラーが出てきて、これが、どうしても消せない。

G:\home\ebata\vmaf>docker run --rm -it -v G:\download:/workspace ffmpeg-vmaf ffmpeg -i /workspace/104014_1280x720.mp4 -i /workspace/104014_1280x720.mp4 -lavfi libvmaf="model=/workspace/vmaf_v0.6.1.json" -f null -
ffmpeg version N-118070-g17e4746687 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 11 (Ubuntu 11.4.0-1ubuntu1~22.04)
configuration: --enable-gpl --enable-libx264 --enable-libx265 --enable-libvmaf
libavutil 59. 51.100 / 59. 51.100
libavcodec 61. 27.101 / 61. 27.101
libavformat 61. 9.101 / 61. 9.101
libavdevice 61. 4.100 / 61. 4.100
libavfilter 10. 6.101 / 10. 6.101
libswscale 8. 12.100 / 8. 12.100
libswresample 5. 4.100 / 5. 4.100
libpostproc 58. 4.100 / 58. 4.100
[Parsed_libvmaf_0 @ 0x55f5cc0b97c0] could not parse model config: /workspace/vmaf_v0.6.1.json
[AVFilterGraph @ 0x55f5cc0b91c0] Error initializing filters
Error : Invalid argument


2日間かけたのですが、疲れ果てたので、闘うのを止めました。

で、代替手段です。

■ブラウザのサービスを使う方法

VMAF on Browser

■VMAFを組み込んだffmpegのバイナリダウンロード
https://www.gyan.dev/ffmpeg/builds/
https://www.gyan.dev/ffmpeg/builds/#git-master-builds

ダウンロードして展開した場所の内部で(パスが通っていない)ffmpegを実行

G:\download\ffmpeg-2024-12-11-git-a518b5540d-full_build\bin>ffmpeg -i input.mp4 -i reference.mp4 -lavfi libvmaf -f null -

実行結果は以下の通り(欲しいのは以下の赤字のところだけ) # 今回は同じファイルを使って比較しただけ

G:\download\ffmpeg-2024-12-11-git-a518b5540d-full_build\bin>ffmpeg -i input.mp4 -i reference.mp4 -lavfi libvmaf -f null -
ffmpeg version 2024-12-11-git-a518b5540d-full_build-www.gyan.dev Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14.2.0 (Rev1, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libopenjpeg --enable-libquirc --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-libqrencode --enable-librav1e --enable-libsvtav1 --enable-libvvenc --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-liblc3 --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
libavutil 59. 49.100 / 59. 49.100
libavcodec 61. 26.100 / 61. 26.100
libavformat 61. 9.100 / 61. 9.100
libavdevice 61. 4.100 / 61. 4.100
libavfilter 10. 6.101 / 10. 6.101
libswscale 8. 12.100 / 8. 12.100
libswresample 5. 4.100 / 5. 4.100
libpostproc 58. 4.100 / 58. 4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp41isom
creation_time : 2024-02-14T12:54:44.000000Z
Duration: 00:00:30.46, start: 0.000000, bitrate: 2228 kb/s
Stream #0:0[0x1](und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(progressive), 722x444 [SAR 1:1 DAR 361:222], 2032 kb/s, 29.97 fps, 29.97 tbr, 29970 tbn (default)
Metadata:
creation_time : 2024-02-14T12:54:44.000000Z
handler_name : VideoHandler
vendor_id : [0][0][0][0]
encoder : AVC Coding
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s (default)
Metadata:
creation_time : 2024-02-14T12:54:44.000000Z
handler_name : SoundHandler
vendor_id : [0][0][0][0]
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'reference.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp41isom
creation_time : 2024-02-14T12:54:44.000000Z
Duration: 00:00:30.46, start: 0.000000, bitrate: 2228 kb/s
Stream #1:0[0x1](und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(progressive), 722x444 [SAR 1:1 DAR 361:222], 2032 kb/s, 29.97 fps, 29.97 tbr, 29970 tbn (default)
Metadata:
creation_time : 2024-02-14T12:54:44.000000Z
handler_name : VideoHandler
vendor_id : [0][0][0][0]
encoder : AVC Coding
Stream #1:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 195 kb/s (default)
Metadata:
creation_time : 2024-02-14T12:54:44.000000Z
handler_name : SoundHandler
vendor_id : [0][0][0][0]
Stream mapping:
Stream #0:0 (h264) -> libvmaf
Stream #1:0 (h264) -> libvmaf
libvmaf:default -> Stream #0:0 (wrapped_avframe)
Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to 'pipe:':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp41isom
encoder : Lavf61.9.100
Stream #0:0: Video: wrapped_avframe, yuv420p(progressive), 722x444 [SAR 1:1 DAR 361:222], q=2-31, 200 kb/s, 29.97 fps, 29.97 tbn
Metadata:
encoder : Lavc61.26.100 wrapped_avframe
Stream #0:1(und): Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s (default)
Metadata:
encoder : Lavc61.26.100 pcm_s16le
creation_time : 2024-02-14T12:54:44.000000Z
handler_name : SoundHandler
vendor_id : [0][0][0][0]
[Parsed_libvmaf_0 @ 00000226c63e6640] VMAF score: 99.992967e=N/A speed=1.57x
[out#0/null @ 00000226c61d1ac0] video:392KiB audio:5616KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown
frame= 913 fps= 47 q=-0.0 Lsize=N/A time=00:00:29.95 bitrate=N/A speed=1.55x

で、この評価の見方は以下の通りです。


1. [Parsed_libvmaf_0 @ 000001f6e343da40] VMAF score: 97.465053

  • [Parsed_libvmaf_0 @ ...]
    libvmafフィルタが処理を行ったことを示しています。
  • VMAF score: 97.465053
    最終的なVMAFスコアが97.465です。この値は、評価対象の動画(input.mp4)と参照動画(reference.mp4)の視覚的な品質の差異を数値化したものです。スコアは通常 0〜100 の範囲で表され、高いスコア(90以上)は非常に高品質であることを意味します。

2. e=N/A speed=0.299x

  • e=N/A
    現在のところ特定のエンコードステータスがありません(通常は気にしなくて大丈夫です)。
  • speed=0.299x
    処理速度を示しています。speed=0.299xは、処理がリアルタイムの29.9%の速度で進行したことを意味します。この低速さは、VMAF計算が非常に計算集約的であるためです。

3. [out#0/null @ 000001f6e1dc98c0] video:754KiB ... muxing overhead: unknown

  • video:754KiB
    出力された動画データの合計サイズが754KiBであることを示します。
  • audio:0KiB subtitle:0KiB other streams:0KiB
    音声、字幕、その他のストリームが含まれていないことを示します(VMAF評価ではこれらは不要)。
  • global headers:0KiB
    グローバルヘッダーのデータサイズも0KiBであることを示します。
  • muxing overhead: unknown
    出力ファイルのオーバーヘッド(余分なデータ量)が計算されていないことを示しています。nullフォーマットを使用しているため、通常は無視して問題ありません。

4. frame= 1755 fps= 18 q=-0.0 Lsize=N/A time=00:00:29.27 bitrate=N/A speed=0.299x

  • frame=1755
    VMAF計算の対象となったフレーム数です。1755フレームが処理されました。
  • fps=18
    平均で1秒間に18フレームが処理されたことを示します。
  • q=-0.0
    映像の品質パラメータで、VMAF評価では特に重要ではありません。
  • Lsize=N/A
    出力ファイルの総サイズ(nullフォーマットなので未計算)。
  • time=00:00:29.27
    処理された動画の総時間が29.27秒であることを示します。
  • bitrate=N/A
    ビットレートが計算されていないことを示します(評価中なので未計算)。
  • speed=0.299x
    処理速度がリアルタイムの約30%であることを再度示しています。

 

■VMAFについての評価方法や読み方については、以下が詳しいです。

【Netflixでも使ってる!】 映像品質評価ライブラリVMAFを使ったエンコードパラメータの決定方法の紹介

2024,江端さんの技術メモ

注意点は、通信プロトコルのメトリクスが2以上あろうとも、
main()の開始近くで

GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
を1回、

main()の終了近くで

// 共有のイベントループを実行
g_main_loop_run(main_loop);

// メインループをクリーンアップ
g_main_loop_unref(main_loop);

を、それぞれ1回だけ発行すること。

g_main_loop_run(main_loop)でプログラムは無限ループに入ってロックするので、その下のプログラムは実行されないことにも注意。

(以下はイメージ。コンパイルしても稼動しません)

#include <glib.h>
#include <gst/gst.h>
#include <pthread.h>

typedef struct {
    GstElement *pipeline;
    GMainLoop *main_loop;  // 共有のイベントループ
} ArgsRtspRTSP;

typedef struct {
    GstElement *srtserversink;
    GMainLoop *main_loop;  // 共有のイベントループ
} Args;

void *print_rtsp_metrics_thread(void *arg) {
    ArgsRtspRTSP *args = (ArgsRtspRTSP *)arg;
    // RTSPメトリクス計測のロジック
    while (1) {
        g_usleep(1000000); // 1秒ごとに計測
        g_print("RTSP Metrics: Calculating...\n");
    }
    return NULL;
}

void *print_srt_metrics_thread(void *arg) {
    Args *args = (Args *)arg;
    // SRTメトリクス計測のロジック
    while (1) {
        g_usleep(1000000); // 1秒ごとに計測
        g_print("SRT Metrics: Calculating...\n");
    }
    return NULL;
}

void initialize_rtsp_pipeline(ArgsRtspRTSP *args) {
    // パイプラインの初期化
    args->pipeline = gst_pipeline_new("rtsp-pipeline");
    GstBus *bus = gst_element_get_bus(args->pipeline);
    gst_bus_add_watch(bus, (GstBusFunc)gst_bus_async_signal_func, args->main_loop);
    gst_object_unref(bus);
}

void initialize_srt_pipeline(Args *args) {
    // パイプラインの初期化
    args->srtserversink = gst_element_factory_make("srtserversink", "srt-sink");
    GstBus *bus = gst_element_get_bus(args->srtserversink);
    gst_bus_add_watch(bus, (GstBusFunc)gst_bus_async_signal_func, args->main_loop);
    gst_object_unref(bus);
}

int main(int argc, char *argv[]) {
    gst_init(&argc, &argv);

    // 共有のイベントループを作成
    GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);

    // RTSP引数の初期化
    ArgsRtspRTSP rtsp_args;
    rtsp_args.main_loop = main_loop;
    initialize_rtsp_pipeline(&rtsp_args);

    // SRT引数の初期化
    Args srt_args;
    srt_args.main_loop = main_loop;
    initialize_srt_pipeline(&srt_args);

    // スレッドの作成
    pthread_t rtsp_thread, srt_thread;

    pthread_create(&rtsp_thread, NULL, print_rtsp_metrics_thread, &rtsp_args);
    pthread_create(&srt_thread, NULL, print_srt_metrics_thread, &srt_args);

    // 共有のイベントループを実行
    g_main_loop_run(main_loop);

    // メインループをクリーンアップ
    g_main_loop_unref(main_loop);
    return 0;
}

ようするに、開始と終了は、1回のみ宣言する、ということ。

g_main_loop_run(main_loop) の後は、プログラムがそこでロックされて、その後のプログラムコードに進まないことに注意。

2024,江端さんの技術メモ

改めてGeoEntityDBの作り方の手順を示して下さい。

 

以下に、GeoEntityDB を作成する手順を改めて示します。


GeoEntityDBの作成手順

1. GeoEntityDBの作成

  1. PostgreSQLに接続します。
    psql -U postgres

     

  2. 新しいデータベースを作成し、PostGISを有効化します。
    CREATE DATABASE GeoEntityDB; \c GeoEntityDB CREATE EXTENSION postgis; CREATE EXTENSION pgrouting; -- 必要に応じて有効化

     


2. 地物テーブルの作成

地物データを格納するためのテーブルを作成します。

  1. テーブルスキーマを定義します。以下はカテゴリ付きの地物データ用のスキーマです。
    CREATE TABLE geo_entities ( id SERIAL PRIMARY KEY, -- 自動生成の一意識別子 category VARCHAR(10), -- カテゴリ (例: A1, B1, D2) stay_time INTEGER, -- 滞在時間 (分) geom GEOMETRY(POINT, 4326) -- 座標データ (EPSG:4326の緯度経度) );

    # id SERIAL PRIMARY KEY の部分は自動的にインポートされるので、csvの先頭の番号は行削除しておくこと

  2. インデックスを作成して検索性能を向上させます。
    CREATE INDEX geo_entities_geom_idx ON geo_entities USING GIST (geom);

     


3. CSVデータのインポート

CSVファイルから地物データをインポートします。

  1. 一時テーブルを作成(緯度・経度データを変換するために使用)。
    CREATE TEMP TABLE temp_geo_entities ( category VARCHAR(10), stay_time INTEGER, latitude DOUBLE PRECISION, longitude DOUBLE PRECISION );

     

  2. CSVをインポート(ファイルのパスは実際のCSVファイルの場所を指定してください)。
    COPY temp_geo_entities (category, stay_time, latitude, longitude) FROM '/path/to/geo_entities.csv' DELIMITER ',' CSV HEADER;

    # 実は、'/path/to/geo_entities.csv'の部分で酷く転けた記憶があるが、結果的にインポートできてしまったので、忘れた。

  3. 本テーブルに挿入(緯度・経度を POINT 型に変換して挿入)。
    INSERT INTO geo_entities (category, stay_time, geom) SELECT category, stay_time, ST_SetSRID(ST_MakePoint(longitude, latitude), 4326) FROM temp_geo_entities;

     

  4. データが正しくインポートされたか確認します。
    SELECT * FROM geo_entities LIMIT 10;

    #ここから先は試していないが、メモに残しておく。


4. 既存DBとの連携設定

方法 1: postgres_fdw を使った連携

hakata_ex_cost_db(道路ネットワークDB)と GeoEntityDB を連携させます。

  1. postgres_fdw を有効化(GeoEntityDBで実行)。
    CREATE EXTENSION postgres_fdw;

     

  2. 外部サーバーを登録
    CREATE SERVER hakata_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (dbname 'hakata_ex_cost_db', host 'localhost');

     

  3. 外部DBへのユーザーマッピングを作成
    CREATE USER MAPPING FOR current_user SERVER hakata_server OPTIONS (user 'postgres', password 'your_password');

     

  4. 必要なテーブルをインポート(例: 道路ネットワークテーブル)。
    IMPORT FOREIGN SCHEMA public FROM SERVER hakata_server INTO public;

     

  5. テーブルが使用可能か確認
    SELECT * FROM ways LIMIT 10;

     


5. 経路計算の設定

最短経路計算の基本例

エージェントの現在地から目的地(地物)までの経路を計算します。

  1. エージェントの現在地に最も近いノードを取得
    SELECT id FROM ways_vertices_pgr ORDER BY geom <-> ST_SetSRID(ST_MakePoint(130.3980676, 33.59543503), 4326) LIMIT 1;

     

  2. 地物の位置に最も近いノードを取得
    SELECT id FROM ways_vertices_pgr ORDER BY geom <-> (SELECT geom FROM geo_entities WHERE id = 1) LIMIT 1;

     

  3. Dijkstraアルゴリズムで経路計算
    SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra( 'SELECT id, source, target, cost FROM ways', start_node_id, end_node_id, directed := false );

     


6. 地物データと経路計算の組み合わせ

以下のようなクエリで、地物データの位置と経路計算を連携させます。

  1. エージェントの現在地から15メートル以内の地物を検索(これ、上手く稼動しません。下の方は使って下さい)
    SELECT id, category, stay_time, ST_Distance(geom, ST_SetSRID(ST_MakePoint(130.3980676, 33.59543503), 4326)) AS distance FROM geo_entities WHERE ST_DWithin(geom, ST_SetSRID(ST_MakePoint(130.3980676, 33.59543503), 4326), 15);

     

  2. 発見した地物への最短経路を計算
    SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra( 'SELECT id, source, target, cost FROM ways', start_node_id, (SELECT id FROM ways_vertices_pgr ORDER BY geom <-> (SELECT geom FROM geo_entities WHERE id = found_geo_id) LIMIT 1), directed := false );

     


まとめ

  1. GeoEntityDBの作成とデータインポート:
    • PostGISとpgRoutingを有効化し、CSVデータを地物テーブルに格納。
  2. 既存DBとの連携:
    • postgres_fdw を使用して、hakata_ex_cost_db の道路ネットワークを参照。
  3. 経路計算の実装:
    • エージェントの現在地と地物データを連携させ、道路ネットワーク上で最短経路を計算。

これにより、エージェントが嗜好に応じて地物に向かう動きをリアルにシミュレーションする仕組みを構築できます。

ーーーーー
こういうミスもやったので、以下のメモに残しておく。

SELECT * FROM geo_entities WHERE category = 'B1'; としたらエントリーがでてきませんが、
SELECT * FROM geo_entities WHERE category = ' B1'; としたらエントリーがでてきました。
categoryの要素でえ最初に空白が入っているものを修正したいのですが、どうしたら良いでしょうか

 

category の要素の先頭に空白が含まれている場合、それを修正するには TRIM 関数を使用して先頭と末尾の空白を取り除く必要があります。以下に、データを修正する方法を説明します。


手順

1. データの確認

まず、空白が含まれているデータを確認します。

SELECT * FROM geo_entities WHERE category LIKE ' %' OR category LIKE '% ';

 

  • LIKE ' %' は先頭に空白があるデータを検索します。
  • LIKE '% ' は末尾に空白があるデータを検索します。

2. 空白を修正

TRIM 関数を使用して、category カラムから空白を取り除きます。

すべてのエントリを修正する場合

以下のクエリで、空白を削除した値に更新します。

UPDATE geo_entities SET category = TRIM(category) WHERE category LIKE ' %' OR category LIKE '% ';

 


3. 修正結果の確認

修正後に、データが正しく更新されたか確認します。

SELECT * FROM geo_entities WHERE category LIKE ' %' OR category LIKE '% ';

 

  • クエリの結果が空であれば、すべての空白が正常に削除されたことを意味します。

4. 再度クエリを実行

修正後、以下のようにクエリを実行して正しいデータが取得できるか確認します。

SELECT * FROM geo_entities WHERE category = 'B1';

 


補足

  • TRIM の動作: TRIM 関数は、先頭と末尾の両方から空白を削除します(不要なスペースも含む)。
  • データの一時バックアップ: データ更新は破壊的変更となるため、念のため更新前にバックアップを取得しておくことをおすすめします。

これで問題が解決するはずです!もしさらなるサポートが必要であればお知らせください。


ざっくりとした使い方

 

geoentitydb=# \l
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | ICU Locale | ICU Rules | Access privileges
--------------------+----------+----------+-----------------+------------+------------+------------+-----------+-----------------------
geoentitydb | postgres | UTF8 | libc | en_US.utf8 | en_US.utf8 | | |
hakata_db | postgres | UTF8 | libc | en_US.utf8 | en_US.utf8 | | |
hakata_ex_cost_db | postgres | UTF8 | libc | en_US.utf8 | en_US.utf8 | | |

geoentitydb=# SELECT id, category, stay_time, geom FROM geo_entities where id = 29;
id | category | stay_time | geom
----+----------+-----------+----------------------------------------------------
29 | B1 | 20 | 0101000020E610000006802A6E9C4C6040099FB5F44BCB4040

 

geoentitydb=# SELECT id, category, stay_time, ST_X(geom) AS longitude, ST_Y(geom) AS latitude FROM geo_entities where id = 29;
id | category | stay_time | longitude | latitude
----+----------+-----------+-------------+-------------
29 | B1 | 20 | 130.3940955 | 33.58825549

こんな感じででてくる。

以下は、130.4064827799044, 33.591348965846656 から 100メートル以内のジオエンティティを抽出するSQLです。(こっちが正しい)

geoentitydb=# SELECT id, category, stay_time, ST_Distance(geom::geography, ST_SetSRID(ST_MakePoint(130.4064827799044, 33.591348965846656), 4326)::geography) AS distance FROM geo_entities WHERE ST_DWithin(geom::geography, ST_SetSRID(ST_MakePoint(130.4064827799044, 33.591348965846656), 4326)::geography, 100);

id | category | stay_time | distance
------+----------+-----------+-------------
304 | A2 | 60 | 68.03775787
357 | A3 | 120 | 75.80618279
366 | A3 | 120 | 76.48825161
414 | D2 | 180 | 80.65210758
415 | D2 | 180 | 79.93815148
429 | D2 | 180 | 61.23626794
435 | D2 | 180 | 62.50441807
546 | E1 | 480 | 77.36793898
550 | E1 | 480 | 90.09868468
813 | E2 | 300 | 54.40053345
1174 | F2 | 10 | 92.85196166
1217 | F2 | 10 | 89.44133931
1933 | H2 | 30 | 64.5772006
1942 | H2 | 30 | 84.70916514
(14 rows)