子どもがデカくなってきており集中して勉強できる「子ども部屋」が必要なのではないかという話になった。引っ越しも検討したけど、学区や家賃の問題があり、なんとか高校入学まではこのままでいけないかということに。

ということで自宅内のリレイアウト(模様替え)だけで「子ども部屋」を捻出することに。

基本要件

  • 子どもが寝るベッドを分ける
  • 勉強できるスペースをつくる

基本方針 (スペースの捻出)

  • ダイニングテーブルをなくし、リビングと食事スペースを統合する
  • その分のスペースを活用できるようにすべての要素を再配置する


事前に家具と間取りを Fusion (3Dモデリングソフト) でモデリングし、なんとか良い配置にならないか机上で試行錯誤してから着手した。だいたい1~2ヶ月ぐらいかけてマイグレーションしていった

フェーズ0

作業前

  • ダイニング: 部屋A
  • 仕事部屋: 部屋B
  • リビング: 部屋B
  • 寝室(子ども): 部屋C
  • 寝室(親): 部屋C

フェーズ1

ダイニングテーブルの廃棄とリビングの再配置

  • ダイニングテーブルの廃棄・椅子の廃棄
    • でかすぎるものは粗大。椅子はちょっと破壊して普通ごみ
  • リビングスペースの移設
    • テレビ台など
      • 放送設備は壊れていて見れない(見ない)ので配線を削除

一時的にローテーブルとアイロン台で食事をとるということに (のちに折り畳み式のローテーブルを買う)

  • リビング: 部屋A (ダイニング統合消滅)
  • 仕事部屋: 部屋B
  • 空きスペース: 部屋B
  • 寝室(子ども+親): 部屋C

フェーズ2

ベッドの移動。シングルベッド+セミダブルベッドを並べて3人で寝ていたのを、独立させる。(シングルベッドに子どもを寝かす予定だが、一旦自分がシングルに寝る)

  • リビング: 部屋A
  • 仕事部屋: 部屋B
  • 寝室(自分): 部屋B
  • 寝室(子ども+母親): 部屋C

フェーズ3

寝室にあった子どもの机と棚の移動。一旦リビングに移動

寝室にスペースができる。

  • リビング: 部屋A
  • 仕事部屋: 部屋B
  • 寝室(自分): 部屋B
  • 寝室(子ども+母親): 部屋C
  • 空きスペース: 部屋C

フェーズ4

寝室へ自分の作業机などをすべて移動

  • 寝室が仕事部屋になる
  • 壁柱などの移動があるのでかなり大変
  • リビング: 部屋A
  • 寝室(自分): 部屋B
  • 空きスペース: 部屋B
  • 寝室(子ども+母親): 部屋C
  • 仕事部屋: 部屋C

フェーズ5

「子ども部屋」の構築

3Dプリンタなどの移設。これはもともとあった部屋に残すのですこし位置をずらすだけ、、だけどベッドなどの兼ね合いで割と大変

子ども机を新たに買って、今までのものは棚として再配置し、勉強スペースを作る

  • リビング: 部屋A
  • 寝室(自分): 部屋B
  • 勉強机: 部屋B
  • 寝室(子ども+母親): 部屋C
  • 仕事部屋: 部屋C

部屋Bの半分ぐらいが「子ども部屋」として機能するように。ただまだ自分が「子ども部屋」のベッドで寝ている状態。タイミングをみて寝る場所を入れ替える。

2021年から使っているNASのHDDの音が気になるようになってしまった。作業部屋を移動したからかもしれないがなんとかすることに。

玄関に追い出す

箱に入れるとかも考えたが、同じ部屋に置いておくのは無理という結論にいたり、玄関に置き場所を確保した。

そのうえで 10Gbps の LAN をどうするかという問題に対処することに。

10Gbps 接続の選択肢

今までは 1m の DAC (ダイレクトアタッチケーブル) を使っていたが、玄関まで配線しようとすると 7m ぐらい必要。あんまり長い DAC よくなさそうだし高いので、この時点で排除して2択

  • AOC (Active Optical Cable)
    • 両端 SFP+ でケーブルは光ファイバ。光コネクタがなくて直結している。DACみたいに使える
    • 若干安い
  • 10GBASE-SR トランシーバ×2 + 光ファイバーケーブル
    • 一番汎用性が高い。光コネクタとかを理解する必要がある

一応 10GBASE-T のトランシーバ×2 + CAT6 LAN ケーブルという選択肢もあるかもだけど、消費電力は高いしコストも高いし信頼性も低いので新規導入では選択肢に入らないと思う。

結論としては 10GBASE-SR にした。

10GBASE-SR と光コネクタと光ファイバー

10GBASE-SR の SR は Short Range の略。MMF(マルチモードファイバー)というコアが比較的太くて機械的精度要求が低い光ファイバーを使い、300mぐらいまでの通信に使えるものらしい。意外とコスト低め。家庭内では十分

SFP+ の場合、光コネクタは LC を使うのがデファクトスタンダードらしい。

光ファイバーは OM3、OM4、OM5 などがマルチモードファイバーの規格名のようだ。数字が大きいほど性能が良いが、OM3でも十分なので一番安いのを選べばよい。つまり LC/LC OM3 となっている光ファイバーを買えばいい。

光ファイバーケーブルの接続

送受信で別々のファイバーを使うので、2本必要。duplex と書かれたものを買う。両端でペアになるように部品がついている。そしてペアのどっちがどっちのケーブルかわかるようになっている。そしてこれらはクロス接続する必要がある。

ただ今回買った光ファイバーは最初からクロス接続になるように配線されていた。買ってそのまま挿せばいいだけだった。

問題なくおわった

何もハマることなくすんなり接続できた。SFP+ はベンダーロックとかがあったりするので不安要素が多いのだけど、今回は大丈夫だった。

光ファイバーは最小曲げ半径が 7.5mm らしく意外を曲げられるようだ? しかしなんとなく銅線よりも取り回しに気をつかってしまう。

これで電気的に絶縁されて接続されてると思うと気分が良い

  1. トップ
  2. tech
  3. NASの10Gbps接続を10GBASE-SR(光ファイバー)に

経済的独立 (FIREのFIの部分)の文脈では「月1万円の支出削減は資産400万円を増やすのと同じ効果」があるといえる。

これは いわゆる「25倍ルール」 ないし 「33倍ルール」 から考えられる。

25倍ルール・33倍ルールとは

25倍ルールは、年間支出の 25倍の資産 があれば、資産の4%を毎年取り崩しても一生暮らせるという目安。「4%ルール」に基づくもの。

より安全に見積もりたい場合、資産の3%しか取り崩さないとすると、必要資産は 年間支出の33倍。国内だと税制やらなんやらで3%で計算しろとかなんとか。

たとえば年間400万円の支出 (税金や社会保険料なども含む) がかかるとすると

  • 25倍ルール → 1億円(400万 × 25)
  • 33倍ルール → 1.32億円(400万 × 33)

で無収入でも破綻しなくなる (破綻するかどうかは実際は確率の問題だが)

月1万円削減が資産400万円に相当する、とは

月1万円の支出を減らすと

  • 月1万円の支出削減 → 年間で12万円の削減
    • 1万円 × 12ヶ月 = 12万円
  • 25倍ルールを適用すると、必要な資産は:
    • 12万円 × 25 = 300万円
  • 33倍ルールを適用すると:
    • 12万円 × 33 = 396万円(約400万円)

月額1万円を得るのために400万円の資産が必要、ということは、逆に見れば「月1万円の支出を減らすと、300〜400万円の資産を持っているのと同じ効果」といえる。

なぜこの考え方が重要なのか?

資産を300〜400万円増やすのは自明に大変だが、月1万円の削減なら比較的簡単である。見方を変え、月あたりの1万円には資産換算で400万円という価値があると感じることができれば浪費により強いブレーキをかけることができる。

逆に月1万円の収入には400万円の資産と同等の効果があるともいえる。キャッシュフローの重要さが身に染みる。

  1. トップ
  2. tech
  3. 月1万円の支出削減は資産400万円に相当する

ファイナンシャルプランナーって信用できないじゃないですか。信用できるかどうか判断するためには相手と同等以上の金融知識が必要になる。人間には利害関係があり、不動産屋と金融屋は特に倫理観がないので、利害関係がない分、たとえハルシネーションがあったとしてもLLMのほうがマシだと考える。

ということでMoneyForward ME の家計簿データをLLMに診断してもらうということを考える。

MoneyForward ME の家計簿データを一括でダウンロードするブックマークレット

https://gist.github.com/cho45/e0ed3e408f87ab9a5c29e2d612db82ab

過去1年分の取引履歴CSVデータを結合したものと、資産推移を以下のような形式で一括でダウンロードする。transactions 以下は構造化されていないCSVがそのまま入っている。

これ自体も Claude Code に指示しつつ書いたのでほぼ手は入れてない。

### JSON構造

```json
{
  "exportDate": "2024-08-29",
  "period": {
    "from": "2023-09",
    "to": "2024-08"
  },
  "monthlyAssets": [...],
  "transactions": {...}
}
```

### フィールド詳細

#### `exportDate`
- データを取得した日付(YYYY-MM-DD形式)

#### `period`
- `from`: 取得期間の開始月(YYYY-MM形式)
- `to`: 取得期間の終了月(YYYY-MM形式)

#### `monthlyAssets`
月末時点の資産データの配列。各要素の構造:
```json
{
  "date": "2024-08-31",
  "assets": {
    "現金・預金": 1000000,
    "投資信託": 500000,
    "株式": 300000,
    "その他": 50000
  }
}
```

#### `transactions`
取引履歴データ:
```json
{
  "format": "csv",
  "encoding": "utf-8",
  "successCount": 12,
  "failedMonths": [],
  "rowCount": 365,
  "data": "\"計算対象\",\"日付\",\"内容\",\"金額(円)\",\"保有金融機関\",\"大項目\",\"中項目\",\"メモ\",\"振替\",\"ID\"\n\"1\",\"2024/08/25\",\"給与 ABC株式会社\",\"300000\",\"△△銀行\",\"収入\",\"給与\",\"\",\"0\",\"abc123def456ghi789\"\n..."
}
```

- `successCount`: 正常に取得できた月数
- `failedMonths`: 取得に失敗した月のリスト
- `rowCount`: 取引データの行数(ヘッダー除く)
- `data`: 実際のCSVデータ(Shift-JISからUTF-8に変換済み、ダブルクォート付き)

### CSVデータフォーマット詳細

`transactions.data` に含まれるCSVは以下の構造です:

#### ヘッダー行
```
"計算対象","日付","内容","金額(円)","保有金融機関","大項目","中項目","メモ","振替","ID"
```

#### データ行の例
```
"1","2024/08/29","コンビニA店","-500","△△銀行","食費","食料品","","0","abc123def456"
"1","2024/08/28","給与 ABC株式会社","250000","△△銀行","収入","給与","","0","def456ghi789"
"1","2024/08/27","電力会社","-8500","○○カード","水道・光熱費","電気代","","0","ghi789jkl012"
"0","2024/08/26","証券会社 積立","30000","△△銀行","未分類","未分類","","1","jkl012mno345"
```

#### 各列の詳細

1. **計算対象**: 家計簿の計算に含めるかの判定(1=計算対象、0=計算対象外)
2. **日付**: YYYY/MM/DD形式の取引日
3. **内容**: 取引の説明文(店舗名、サービス名など)
4. **金額(円)**: 取引金額(収入は正数、支出は負数)
5. **保有金融機関**: 連携している金融機関名
6. **大項目**: MoneyForwardの大分類カテゴリ
   - 例:収入、食費、住宅、水道・光熱費、通信費、交通費、税・社会保障、日用品、健康・医療、教養・教育、趣味・娯楽、衣服・美容、その他、未分類
7. **中項目**: 大項目の下位分類
   - 例:給与、食料品、家賃・地代、電気代、ガス・灯油代、インターネット、電車、所得税・住民税など
8. **メモ**: ユーザーが手動で入力したメモ(空白の場合が多い)
9. **振替**: 振替取引の場合は1、通常取引は0
10. **ID**: MoneyForward内部のユニークな取引ID

LLMへ指示をするプロンプト

家庭状況によって必要な診断が異なるので、ここに関しては↑のフォーマット情報を利用してプロンプトを生成するコードをLLMに書かせるのがよいと思う。

例えば最終的なプロンプトが以下のようになるようなコード自体をLLMに書かせる。

あなたは家計の浪費防止に特化したファイナンシャルアドバイザーです。以下のデータを基に「無駄な支出の特定」と「浪費防止策」を重点的に分析してください。

【家庭状況】
- 世帯主: 38歳
- 家族構成: 配偶者(38歳)・子供1人 (11歳)
- 住居: 首都圏、賃貸マンション(家賃月xx万円)
- 投資方針: 積極的
- 交通: 電車中心

妻と自分とで完全に財布が別で、厳密ではないが支出種別ごとに支払い者が違います。
食費や服飾費が妻、それ以外は自分という分類です。

<以下フォーマットされた分析データ>
【資産推移分析】
...

【月別収支推移】
...

【カテゴリ別年間支出】
...

【異常値・変動分析】
...

**統計的外れ値(大口支出上位10件)**
...

**カテゴリ別支出分布統計**
...

【浪費防止分析を実施してください】
1. **異常値に基づく浪費特定**: 統計的外れ値や前月比異常値から無駄な大口支出を特定。重複パターンから習慣的な無駄を抽出
2. **変動性からのリスク分析**: 月別変動係数の高いカテゴリから予算コントロールが困難な項目を特定し、安定化策を提案
...

これを ChatGPT なり Gemini なり Claude にコピペする。データからわからない前提はしっかり書いておかないと適切にならない。

  1. トップ
  2. tech
  3. 人間のファイナンシャルプランナーよりLLMのほうがマシだよね

VALETON GP-5 というマルチエフェクタを買ってみた。小さいながら凝っていて、アンプシミュレータも内蔵しているのでヘッドフォン直結やスピーカーシステム直結で使える。

これは USB 5V のバスパワーで動くので、スマホに繋げば電源供給をスマホ側でできる。
なので、最小構成では GP-5 + スマホだけでそこそこ良い運用ができる。

WebMIDI Switcher

https://github.com/cho45/webmidi-switcher

GP-5 本体のボタンは「長押し」にチューナー機能が割り当ててある関係で、エフェクトが切り替わるタイミングがボタンを離したときになってしまう。これが嫌なので、別途スイッチを用意したい。

GP-5 は USB MIDI コントロールができ、スマホ側は WebMIDI API から GP-5 に MIDI 信号をおくれる。

スマホから電源供給もしつつ、スマホ自体をフットスイッチにできると嬉しいので、そういうウェブアプリを作った。

PicoMIDI Switch

https://github.com/cho45/picomidi

しかしながら、スマホを足で踏むのは割とむずかしいし抵抗があるので、市販のフットスイッチを流用する方法を考えた。

TRSプラグを利用するただのモーメンタリなフットスイッチが売っているので、これを利用する。

Raspberry Pi Pico で USB MIDI デバイスを作って、TRS → USB MIDI 変換を行っている。スイッチへの MIDI 信号の割当も WebMIDI API でできるようなウェブアプリを作ってある。余計なアプリはいらない。

スマホ側の WebMIDI Switcher には MIDI メッセージを中継する機能をつけてある。これでハブを経由してそれぞれ接続すればコントロールできるようになっている。

かなり装備が軽く、かつフットスイッチありなので、いいんじゃないか

  1. トップ
  2. tech
  3. VALETON GP-5 + 自作MIDIデバイスたち

「MIDI フットコントローラ」とかで検索するとよくでてくる M-VAVE Chocolate Plus というのがある。4スイッチで USB Host にもなれ、BLE でも接続可能で 3000円代と安い。amazon.co.jp でも売ってるので(リンクは出さないが)、気にはなっていた。

改造したらなんとかならんかなと重い、Aliexpressで買ってみて、改造を試みてみた。

「技適未取得機器を用いた実験等の特例制度」を申請して自己責任で期間限定で合法となる、はず。

微弱無線局未満を目指してみたけど、設備がないと微弱無線局の基準を満たしているかは釈然とせず、結局安心して使えるようにはならないという結果だったので、やっぱ簡単な改造では使えないなというお気持ちになった。


なお FCC ID は 2ARCP-CHOCOLATEPLUS のよう (https://www.fcc.gov/oet/ea/fccid )。

  1. トップ
  2. tech
  3. M-VAVE Chocolate Plus は国内では使えません……

家族の予定は基本的に共有カレンダーで管理しているが「みんなが見れる用」として食卓近くに卓上アナログカレンダーが置いてあり、何年もの間、二重管理になっていた。ずっと気になってはいつつも、まぁ運用できてるし、単にカレンダー表示するだけでもまぁまぁ面倒なのでそのままだったが、この度 Raspberry Pi でサイネージを作ることにした。

構成はシンプルで、15インチの 1080p モニタと、余っていた Raspberry Pi 3 B (WiFi付き)

CUIUIC モバイルモニター 15.6インチ ポータブルモニター モバイルディスプレイ 1920x1080FHD IPS液晶パネル 400Nits 100%広色域 Tpye-C/mini HDMI/スピーカー内蔵 PS4/PS5/XBOX/Switch/PC/Macなど対応 保護カバー付き - CUIUIC

CUIUIC

4.0 / 5.0

できること

  • Google Calendar の表示 (ほぼ Google Calendar互換の表示をする。複数日とかも)
  • 天気予報 (気象庁のXMLから取得している)
  • 時計 (西暦・和暦・日付曜日時間)

10分ごとに内容を更新する。

https://github.com/cho45/my-sinage

モニタ解像度

Raspberry Pi のほとんどは 1080p までしかスムーズに出力できないので、あまり高精細なディスプレイを買ってはいけない。1920x1280 のモバイイルディスプレイをいくつか持っているけど、モニタとの相性もあるのか、まともに表示させることができなかった。素直になってください。1080pのモニタを買えばいいです。(2日ぐらい無駄にした)

15インチのモニタは微妙にデカいけど、カレンダーをフルで表示させるならこのぐらい大きくてもいいかなという印象。捨てるときのこと考えるとあんまり大きいもの買いたくないのよね……

モニタの固定

「モバイルモニタ」カテゴリのものは固定方法が考えられてない。VESAマウント? そんなものはない。ただのスレートです。

ということで3Dプリンタでスタンドを作り、棚板にビス止めすることにした。安定。

ウェブアプリ

認証情報を保持してカレンダーの画面を出すウェブサーバを立てている。これは Raspberry Pi 上ではなく、QNAP 上の Container Station で docker image を動かしている。QNAP はうちだとIP アドレス固定で使っているので管理しやすい。

ディスプレイが繋がっているサイネージ用の Raspberry Pi はブラウザでURLを開くだけ。

スマフォとかから管理画面を開いて強制リロードのシグナルを送ったりできるようにしてある。ウェブアプリ側を更新したときに呼ぶ用。

開発

ほぼほぼ Claude Code にやらせた。ウェブアプリ、ちょいちょいクソコードは書くものの、特にクライアントサイドを書かせるのは割とすんなりやってくれる。

サーバサイドはなんか結構ガイドしないとちゃんとやってくれない。

夜中は消灯

cron で 02:00 に画面を消灯、06:00 に点灯という制御を入れてある。

最近の Raspberry Pi OS (bookworm) は labwc というWayland コンポジタ実装が使われているが、あんまりこれの情報がないのでめんどくさい。

XDG_RUNTIME_DIR=/run/user/1000
 
 # 02:00 にオフ
 0 2 * * * /usr/bin/wlr-randr --output HDMI-A-1 --off
 # 06:00 にオン
 0 6 * * * /usr/bin/wlr-randr --output HDMI-A-1 --on --mode 1920x1080

この手のものはいかに運用を楽にするかというのが問題。「うまく動かない」場合にメンテできるのが自分しかいないからだ。

  1. トップ
  2. tech
  3. おうちサイネージ (食卓カレンダー)

昨今の QNAP には Container Station というコンテナイメージを実行するためのオフィシャルなアプリケーションが提供されている。これを使えば特にQNAP用というわけではないコンテナイメージも自由に動かせて嬉しい。

例えば VOICEVOX のAPIを自宅内で自由に使えたらな~ と思うと、サーバとして常時動いていて、CPU的にも比較的遊びのある QNAP で動かせると嬉しい。HTTP リクエストさえできれば自宅内の Raspberry PI だろうがなんだろうが低スペPCからも音声合成ができる。

https://hub.docker.com/r/voicevox/voicevox_engine

Docker Hub にオフィシャルなイメージがあるので、これを pull する

Create Container で Publish New Port して 50021 を指定する。これで 192.168.5.250:50021 でアクセス可能になる。これだけ

 curl -X 'GET' \
   'http://192.168.0.177:50021/speakers' \
   -H 'accept: application/json'
   
   [
     {
       "name": "四国めたん",
       "speaker_uuid": "7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff",
       "styles": [
         {
           "name": "ノーマル",
           "id": 2,
           "type": "talk"
         },
         {
           "name": "あまあま",
           "id": 0,
           "type": "talk"
         },
         {
           "name": "ツンツン",
           "id": 6,
           "type": "talk"
         },
         {
           "name": "セクシー",
           "id": 4,
           "type": "talk"
         },
         {
           "name": "ささやき",
           "id": 36,
           "type": "talk"
         },
         {
           "name": "ヒソヒソ",
           "id": 37,
           "type": "talk"
         }
       ],
       "version": "0.15.9",
       "supported_features": {
         "permitted_synthesis_morphing": "SELF_ONLY"
       }
     },
     {
         "name": "ずんだもん",
         "speaker_uuid": "388f246b-8c41-4ac1-8e2d-5d79f3ff56d9",
         "styles": [
           {
             "name": "ノーマル",
             "id": 3,
             "type": "talk"
           },
           {
             "name": "あまあま",
             "id": 1,
             "type": "talk"
           },
           {
             "name": "ツンツン",
             "id": 7,
             "type": "talk"
           },
           {
             "name": "セクシー",
             "id": 5,
             "type": "talk"
           },
           {
             "name": "ささやき",
             "id": 22,
             "type": "talk"
           },
           {
             "name": "ヒソヒソ",
             "id": 38,
             "type": "talk"
           },
           {
             "name": "ヘロヘロ",
             "id": 75,
             "type": "talk"
           },
           {
             "name": "なみだめ",
             "id": 76,
             "type": "talk"
           }
         ],
         "version": "0.15.9",
         "supported_features": {
           "permitted_synthesis_morphing": "SELF_ONLY"
         }
       },
  1. トップ
  2. tech
  3. QNAP を VOICEVOX 音声合成サーバにする

こういうのが500円で売っている。なんとなく買ってみた。

設定ツール (MINI KeyBoard.exe) が Google Drive で共有されて、そのQRコードがマニュアルにはってある。どう考えても実行するのは怖いので、まずは解析して設定ツールを自分で書くところからはじめる。

まぁそもそも、信頼できないデバイスをUSBで繋ぐなというのが正論だと思うが……

ILSpyで解析

MINI KeyBoard.exe は .NET アプリのようなので、ILSpy でデコンパイルできる。変なコードはとりあえず含まれていない。たぶん HID Report でなんかしてるだろうから、デコンパイルしたやつを Claude Code に読ませてプロトコルを解析してもらった。といってもそんなに精度高く解析はしてくれないので、結局自分でかなり勘を働かせて指示してやる必要があったけど……

WebHIDで再実装

ソフトは複数のミニキーボードに対応するものっぽいが、自分が持ってるのだけ設定できるツールを WebHID を使って作ってみた。というか Claude Code に作ってもらった。これに関しては完全に指示しかしてないはず。

https://github.com/cho45/webhid-mini-keyboard-configurator

WebHIDのセキュリティ……

Windows の Chrome / Edge で WebHID つかって動くことは確認済みなのだが、残念なことに動かないことがある。Chrome は WebHID に制限をかけていて、汎用キーボードっぽいものとかに対してはレポートの送受信ができないようになっている。この制限にひっかかったりひっかからなかったりする。

開発しはじめて動くまではまったくひっかからなかったのだが、できてからいろいろ試しはじめたらエラーが出たり出なかったりするように。Edge だと動いたり、しばらくたつと動かなかったり。かなりおかしな挙動をする。わけわかんない。

WebHID で作れば変なソフトインストールしないですむやん、というのが嬉しいポイントだけど、こんな挙動だと使えない。こまったねえ

関係ありそうなgithub project

カスタムファームウェア

そもそもファームから変えちゃおうってやつ

  1. トップ
  2. tech
  3. Aliexpress で買ったミニキーボードを WebHID で設定する

UHS-II 対応で USB 3.2 Gen1 接続し、最大 200MB/s ぐらいの読み込み速度が出るはずなのに、速度が出ないときの原因

40MB/s ぐらいで止まる

USB2.0 が 480Mbps(60MB/s)なので、実効速度40MB/s程度ぐらいで止まりうる。

原因

  • USB Type-A をゆっくりさしこむと USB2.0 で接続されてしまうことがある
    • 3.0 用の接点が奥にあるため
  • ケーブルが USB3.0 に対応していない (無結線)
    • 充電用ケーブルはダメです。柔らかいケーブルはだいたいダメです
  • ケーブルのコネクタとデバイスの相性が悪い (接触不良)
    • デバイス側コネクタが劣化してたりするとありうる
  • ケーブルの品質が低い
    • ケーブル品質が低すぎてUSB3.0のネゴシエーションに失敗すると USB2.0 にフォールバックします。

試してみること

  • Type-A なら一気に刺しこむ
  • Type-C で接続する
  • ケーブルをいろいろ変える
  • デバイスを変えてみる

90MB/s ぐらいで止まる

SD カードが UHS-I動作(104MB/s理論値)している可能性がある

原因

  • カードリーダーが非対応
  • カードリーダーの接触不良
  • カードの接点不良

試してみること

  • カードリーダーを変える
  • 接点復活剤をかけてみる
  1. トップ
  2. tech
  3. SDカードリーダーの速度が出ないときの挙動チェックリスト

5Gbps / 10Gbps 対応の通信用ケーブルは購入したら必ずベンチをとるべき。

というのも粗悪品であっても再送制御などで実行速度が下がるだけで通信できることが多いため、気付きにくいから。

1GB/s で読める SSD なのに、400MB/s でしか読めないということが起こりうる (10Gbps でリンクできず、5Gbpsにフォールバックしている)。一見動いてしまうので気付きにくいが実行速度が半分以下なのは相当信号状態が悪い。まずできるだけ短くて信頼できるメーカーの通信ケーブルを買うべき。

ケーブルやコネクタの見た目がよくても騙されてはいけない。うちでいろいろ検証した結果、エレコムの見た目しょぼいケーブルのほうが一番まともだった。

エレコム USBケーブル Type C (USB A to USB C) 1.0m USB3.1認証品 3A出力 最大10Gbps ブラック USB3-AC10NBK - エレコム(ELECOM)

エレコム(ELECOM)

5.0 / 5.0

スループットの目安

  • USB 2.0 480Mbps ~35-40MB/s
  • USB 3.2 Gen1 5Gbps ~400-450MB/s
  • USB 3.2 Gen2 10Gbps ~800-1000MB/s
  • USB 3.2 Gen2x2 20Gbps ~1600-1700MB/s

USB3はLTSSM(Link Training and Status State Machine)のトレーニングプロセスでリンクスピードを決めている。ここで10Gbpsでリンクできる品質にないと判断されると下の規格にフォールバックする。

10Gbps 以上は特に物理的に厳しい

1m以上で 10Gbps を謳っているものはまず嘘なので買うべきではない。10Gbps のパッシブな「延長ケーブル」もありえない。

  1. トップ
  2. tech
  3. 粗悪品のUSBケーブルが多いので買ったら必ずベンチをとるべき

https://www.uwe-sieber.de/usbtreeview_e.html USB Device Tree Viewer を使うのが早い。Windows 標準機能ではわからない。クソ (macOS のあなたは「システム情報」→「ハードウェア」→「USB」でわかります。良かったですね)

USB Device Tree Viewer の表示もそれほど分かりやすいとはいえない。以下が頭に入ってないといけない。

  • Low Speed = 1.5 Mbps (USB 1.0+)
  • Full Speed = 12 Mbps (USB 1.1+)
  • High Speed = 480 Mbps (USB 2.0)
  • SuperSpeed = 5 Gbps (USB 3.0 = USB 3.1 Gen1 = USB 3.2 Gen1)
  • SuperSpeed+ = 10 Gbps (USB 3.1 Gen2 = USB 3.2 Gen2)

アイコンにSがついてればSuperSpeed以上、HはHigh Speed、F は Full Speed

そして USB3系と USB2系は完全に別レイヤーで二重になっているという点を理解している必要がある。例えば USB3 のハブを繋いだら、必ず USB3 のハブと USB2 のハブが2つ表示され、ポートもそれぞれ別々に表示される。


3.2 Gen 2 (10Gbps) のハブ

       ========================== Summary =========================
 Vendor ID                : 0x05E3 (Genesys Logic, Inc.)
 Product ID               : 0x0625
 USB Version              : 3.2 Gen 2
 Port maximum Speed       : SuperSpeedPlus or higher
 Device maximum Speed     : SuperSpeedPlus or higher
 Device Connection Speed  : SuperSpeedPlus or higher
 Self powered             : yes
 Demanded Current         : 0 mA
 Used Endpoints           : 2

USB 2.0 のハブ (ただし USB3.0 のハブと物理的にポートを共有している)

       ========================== Summary =========================
 Vendor ID                : 0x1397 (Behringer Spezielle Studiotechnik GmbH)
 Product ID               : 0x0507
 USB Version              : 2.0
 Port maximum Speed       : High-Speed (Companion Port 1-20-4 is doing the SuperSpeed and SuperSpeedPlus or higher)
 Device maximum Speed     : High-Speed
 Device Connection Speed  : High-Speed
 Self powered             : no
 Demanded Current         : 500 mA
 Used Endpoints           : 1

USB 2.0 でポートスピードと接続スピードが違う場合

USB 3系と USB 2系は完全に分離しているので、Port maximum Speed が SuperSpeed で Device Connection Speed が Full-Speed ということは起こらない。

       ========================== Summary =========================
 Vendor ID                : 0x045E (Microsoft Corporation)
 Product ID               : 0x07A5
 USB Version              : 2.0 -> but Device is Full-Speed only
 Port maximum Speed       : High-Speed
 Device maximum Speed     : Full-Speed
 Device Connection Speed  : Full-Speed
 Self powered             : no
 Demanded Current         : 100 mA
 Used Endpoints           : 4
  1. トップ
  2. tech
  3. WindowsでのUSBリンクスピード

文字スクロール動画ジェネレーターというのを作った。

別のプロジェクトでffmpeg.wasmを使ってて面白かったので、もうちょっとわかりやすい応用を作ってみようという感じ。

Twitter はほぼそのまま再生されるけど、 Bluesky だとフレームレートが低くなっちゃうっぽい?

MediaRecorder vs ffmpeg.wasm

このジェネレータでは使ってないが、MediaRecorderというブラウザでcanvasを録画する標準機能がある。面白い機能なんだけどいくつか問題がある

  • 出力フォーマットがブラウザ依存かつ限られる
    • Chrome だと vp9+webm とか
    • ダウンロードして編集ソフトに持っていくと読みこめなかったりする
  • フレームレート可変になる
    • これもブラウザ依存だけど、canvas の dirty さを監視してて dirty なフレームしか記録しないようだ
    • ダウンロードして編集ソフトに持っていくと読みこめなかったりする
  • リアルタイムでしか収録できない
    • n秒録画するためにはn秒レンダリングして待つ必要がある
  • 尻切れ
    • なんかよくわからないが stop() したタイミングでうまく canvas を読んでくれない? みたい

ということで面白いけど使いにくい機能になっている。

「ダウンロードして編集ソフトに持っていくと読みこめなかったりする」を解決するために、MediaRecorder で録画したファイルを ffmpeg.wasm に読みこませてトランスコードする、という方針をとったりしていたけど、だったら直接 ffmpeg.wasm にフレーム画像全部渡せばいいとなり、MediaRecorder を使うのをやめてしまった。

MediaRecorder の使い道はストリーミングとかなんだろう。

  1. トップ
  2. tech
  3. 文字スクロール動画ジェネレーター

ただの時報

https://play-morse.lowreal.net/jiho.html

むかーーし作った時報のコードを発掘した。今なら Voicevox つけたらちゃんと喋る時報にできるぞと思ったのでガっとやった。正午だけ特殊なのでレアです。

短波JJYの再現

https://play-morse.lowreal.net/vhf-jjy.html

VHF JJYの再現スクリプトのほうも時報音声を入れるようにした。こっちは10分ごとにしか喋らないのでレアです。