2026年 02月 12日

モールスデコーダのストリームデコードテスト

チマチマ表示されると可愛い

2026年 02月 11日

モールスデコーダwpmによるSNRの悪化

まだいろいろいじってしまっていた。10-40wpm を学習するようにしたり (文字単位で学習頻度が一定になるような確率補正をいれている)、データジェネレータをリファクタリングしたり。

評価手段の1つとしてwpm(送信速度)ごとのSNRパフォーマンスを出すようにしてみた。今までは 15wpm 固定で評価していたので、学習の偏り (過学習) になっていないかちゃんと評価できていなかった。

理論的には速度が倍なら3dB分のディスアドバンテージがあるはずだけど、CER=10%の線を見ると、10wpmで-12dB、20wpmで-10dB、30wpmで-8dB、40wpmで-6dB程度となっている。

  • 10wpm → 20wpm は理論値より悪化がすくない (2dB)
  • 20wpm → 40wpm は理論値より悪化が多い (4dB)
2026年 02月 08日

NanoVNA-Web-Client の更新

https://github.com/cho45/NanoVNA-Web-Client

これまた Vue2 + Vuetify という構成だったのを Vue3 + Vanilla CSS に改修した。普通に大変だった。

Android App サポート (Capacitor) は完全に削除した。PWAでいいし…… しかしAndroidでWebSerialがうまくいかなかったりして案外つらい。WebUSBサポートは切れなかった。

テストがなかったのでこれを期にかなり書いたけど、LLMに書かせると本当にひどいしまともに mock できるまでに時間がかかる。ESMのimportの巻き上げとかを理解してない。まじカス

vite でビルドして成果物を github pages で公開するという形にかえた。もともと公開していたURLにはリダイレクトするだけのHTMLを置いた。こういうビルドシステム本当に嫌いだけどまぁもういいや…… メンテ不能になるのが嫌なわけだけど、きっと次メンテ不能になるころにはLLMがなんとかしてくれるでしょ……

まーーじでこんな1円にもならないことしててどうすんの

Hacking Reality with JavaScript: 7 Ways to Control the Physical World from the Browser

『JavaScriptから現実世界に干渉する7の方法: ブラウザでハードウェアをコントロールする技術』という本を書いた。これの英語版もKDPで出してみた。『Hacking Reality with JavaScript: 7 Ways to Control the Physical World from the Browser』とちょっとタイトルかえた。翻訳自体は Gemini CLI。まぁないよりはいいだろう…… どうせ日本語版も対象読者が狹すぎて売れないし、あってもなくても同じならあったほうがマシだろう

本文中の図は基本的に全部 matplotlib で書いてあるので、そこも全部翻訳して生成しなおしつつ、サンプルアプリは簡易的な i18n 対応をした。

2026年 02月 06日

Google Antigravity がシェル履歴を汚染する

Antigravity はなんか普通にインタラクティブなシェルを起動するのだが、シェルの履歴がめちゃくちゃ混ざってうざいので以下の設定をいれた

if [[ "$TERM_PROGRAM" == "vscode" ]]; then
    HISTFILE=~/.zsh_history_vscode
fi
2026年 02月 05日

ScreenToGifで最新のffmpegを使う

ScreenToGifはffmpeg同梱してるが、v4.4.1 とだいぶ古い。

PS C:\Users\cho45> C:\ProgramData\ScreenToGif\ffmpeg.exe
ffmpeg version 4.4.1-full_build-www.gyan.dev Copyright (c) 2000-2021 the FFmpeg developers

winget install ffmpeg

winget install ffmpeg

で簡単に入れられるので、フルパスしらべて

(base) PS C:\Users\cho45> Get-Command ffmpeg

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     ffmpeg.exe                                         0.0.0.0    C:\Users\cho45\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.0.1-full_build\bin\ffmpeg.exe

これを ScreenToGif の設定画面で指定してあげる。

animated avif

Animated AVIF の出力選択はあるのだけど、ffmpeg が古いせいか avif への出力に失敗したので新しくした。

animated avif と AV1 +webm って何がちがうのかという感じはするが (コンテナが違うというのはそうだけど)

hackrf-sweep-webusbの更新

盆栽。地味に自分でも定期的に使っており、自分で作ったやつの中では使用頻度が高い。ということで盆栽がて、いろいろ古かったのでなおした。

ひさしぶりに見たらHackRF One だいぶ高いね…… とおもった。

やったこと

Rust 環境アップデート・コードをまともに

  • edition 更新
  • テスト (rust レベル + node )
  • 実装修正
    • ゼロアロケーションに

JS側

  • Vue2 やめて Vue3 に
  • Vue Material やめて Vanilla CSS に
  • バンドプリセット
2026年 02月 03日

続 Conformer モールスデコーダ

-11dB(2500Hz BW) ぐらいまで90%、-15dB で50%デコードぐらいまではきたけどもういいかな……

モデル構造もちょっと変えた。Signal Head とかを Conformer の途中から出すようにして、2層分の Conformer をCTC Head だけに使うようにしてみた。ただあんまり意味があるのかは…… Conformerの層ごとの寄与度的なやつを出してみたけど、ほぼ Conv。Attn が意外に最初のほうで使われていてよくわからない。

あと内部の次元数も半分(256→128)にした。あんまり変わらないみたい。もっと減らして深くしたほうがいいのかも。わからない。

200ms 分の推論がスマフォ(Pixel7)で20ms前後。ちゃんと実用的に10バッチ同時にやるとかできたら格好いいかもだけどそこまでのモチベがなし……


人間だと -15dB (2500Hz BW) までは完コピできるみたいな論文?がでてくるんだけど、絶対盛ってるだろと思う。100Hz のフィルタ入れて 15wpm ならなんとか多少聞き覚えのある単語がわかるぐらい。CQはわかるけどコールは聞きとれない。https://cho45.github.io/morse-decoder-2026/demo.html で -15dB 設定して聞いてみてほしい。

2026年 02月 01日

builderscon::3DP #1

からくりすとさん来るぞというので、ビタビタのターゲティングを勝手に感じ取り絶対に行くぞと思い行ってきた。大変良かった。

カメラ付きでアラート出すプリンタとか、マルチカラーのプリンタとか羨ましいと思いつつ、まあそこまで今のプリンタに不満ないんだよなという……


Fusion の派生機能を知らなかったので試してみたい。エクスポートしたときどうなるのか不安に思ったけど個別に書かれるらしい。


転職ドラフトのビールスポンサーすごいなと思った。なんとなく世の中景気悪いイメージだったけど少人数(5人から)から支援しているとのこと。

会場のアンドパッド案内板がおしゃれだった。関係ないけどビルのエレベーターがうちのリビンクの広さぐらいあり、でかすぎて怖かった。


からくりすとさん、よく知らないCADを使ってるなと思ってたけど、 Rhinocerosらしい。ある程度シミュレーションしてるのかな?と思ってたけど、「動かせないCADなのでからくり作るには向かない」と言っていてびっくりした。なんとなく動くだろうい頭のなかでやってるらしい。天才すぎる。

動画にはなってない実用品の3Dプリントも格好良くて良かった。ますますファンになった。

あとよく軸に使っている虫ピンみたいなの、なんだろうなと思ってついに直接訊いてみたら、真鍮釘とのこと。釘で調べたことなかった


あと小さい3Dプリンタの話、3Dプリンタは「大は小を兼ねない」という感じの話もしていて良かった。完全に同意見です。自分もVoron0.1気に入ってる。

2026年 01月 31日

reload した後 h2oの古いプロセスが残り続ける場合

h2o は graceful restart をするのだが、稀に古いプロセスがずっと残ることがあって困ってた。(正確には start_server が restart させていて、h2o 自体は graceful shutdown しているだけ)

一例としてはこういう感じ (これは単に SIGHUP 直後なだけだけど、ときどき reload するとプロセスが残っていく)

 $  sudo systemctl status h2o
● h2o.service - H2O HTTP Server
     Loaded: loaded (/etc/systemd/system/h2o.service; enabled; preset: enabled)
     Active: active (running) since Sat 2026-01-10 17:36:22 JST; 2 weeks 4 days ago
    Process: 902234 ExecReload=/bin/kill -s HUP $MAINPID (code=exited, status=0/SUCCESS)
   Main PID: 1288 (perl)
      Tasks: 23 (limit: 2274)
     Memory: 53.0M (peak: 1015.0M swap: 12.2M swap peak: 95.1M)
        CPU: 1h 38min 58.048s
     CGroup: /system.slice/h2o.service
             ├─  1288 perl -x /usr/local/share/h2o/start_server --pid-file=/var/run/h2o.pid --port=0.0.0.0:80 "--port=[::]:80" --port=0.0.0.0:u443 "--port=[::]:u443" --port=0.0.0.0:443 "--port=[::]:443" -- /usr/local/bin/h2o -c /srv/www/h2o.conf.yaml
             ├─897714 /usr/local/bin/h2o -c /srv/www/h2o.conf.yaml
             ├─897716 neverbleed
             ├─897735 perl -x /usr/local/share/h2o/annotate-backtrace-symbols
             ├─902237 /usr/local/bin/h2o -c /srv/www/h2o.conf.yaml
             ├─902238 neverbleed
             └─902257 perl -x /usr/local/share/h2o/annotate-backtrace-symbols

結論: http*-graceful-shutdown-timeout を設定しよう

まず以下のような設定をし忘れないように。この例だと30秒で強制切断。デフォルトが0(無効)

http2-graceful-shutdown-timeout: 30
http3-graceful-shutdown-timeout: 30

メモ: タイムアウトの仕組み

HTTP/2 (lib/http2/connection):
  1. initiate_graceful_shutdown → 最初のGOAWAY送信
  2. 1000ms後 → graceful_shutdown_resend_goaway → 2回目のGOAWAY送信
  3. もし http2-graceful-shutdown-timeout > 0なら、その時間後に強制終了
HTTP/3 (lib/http3/server.c):
  1. 同様に1000ms後に2回目のGOAWAY
  2. もし http3-graceful-shutdown-timeout > 0なら、その時間後に強制終了
HTTP/1 (lib/http1.c):
  1. Keep-Alive をオフにしてレスポンス終了時 close

とにかくタイムアウトは全部設定しておこう!

調査

ただこの2つを設定していても接続が残るケースが発生して悩んだ

$  sudo ss -tapn | grep 902501                                                                                                                                                                                                              
ESTAB      0      0                              127.0.0.1:54080                                 127.0.0.1:5001  users:(("h2o",pid=902501,fd=66))                                                                                             
ESTAB      0      0                              127.0.0.1:46754                                 127.0.0.1:3000  users:(("h2o",pid=902501,fd=72))                                                                                             
CLOSE-WAIT 1      0                              127.0.0.1:52768                                 127.0.0.1:80    users:(("h2o",pid=902501,fd=74))                                                                                               

CLOSE-WAIT が残っている。

→ 最終的にこれは grafana の websocket への接続がずっと残っているというものだった。ブラウザの grafana タブを閉じたらプロセスが消えた。なんで CLOSE-WAIT?

websocket の proxy.timeout.io はデフォルト30秒らしいけど、通信が続くと一生切断されないのかも?