
2026/04/08 1:33
WebUSB を通じて USB/IP にブリッジしたブラウザ内 Linux VM で、古いプリンターを救出する
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
著者は、3Dプリンターと交換して古いCanon SELPHY写真プリンターを入手し、その紙やインクの価値よりも低価格で購入しました。macOS と Windows がデバイスのサポートを終了したため、彼はブラウザ上で Alpine Linux エミュレーター(v86)を実行し、WebUSB/USB‑IP を使用して CUPS/Gutenprint コマンドを物理プリンターに転送するウェブアプリを構築しました。初期の試作ではカスタム CUPS バックエンドが必要でしたが、後続バージョンでは tcpip.js(WebAssembly にコンパイルされた lwIP)を使用して双方向ブリッジを作成し、印刷および SANE を介したスキャンの両方向通信を可能にしました。
画像は JPEG を 6 × 4 インチ用紙サイズに合わせた PDF にラップし、EXIF の向きと ICC プロファイルを保持するように処理されます。HEIC 写真は libheif-js と wasm‑mozjpeg を使用して変換されます。基本的なテレメトリ(プリンターの詳細、印刷ジョブ)は、アフィリエイトリンク経由で Neon Postgres データベースへ送信されます。
アプリは printerface.app および printervention.app でホストされ、スキャンプロトタイプは yes‑we‑scan.app にあります。著者は他の Gutenprint 対応モデルもサポートする予定ですが、コードをオープンソース化せず、消耗品ベンダーとのホワイトラベル取引を好みます。レガシーハードウェアを復活させることで、プロジェクトは電子廃棄物の削減を目指し、SELPHY プリンターの転売価格に影響を与える可能性があります。
このバージョンではすべての主要なポイントが保持され、未検証の推測を避け、明確で簡潔な物語を提示しています。
本文
ホーム
私が手に入れた古い写真プリンター
物語は、思わぬ形でカノン SELPHY 写真プリンターを手にしたことから始まります。
私は新しい3Dプリンターを購入し、友人マークに古いものを渡さないかと尋ねました。彼は喜んで受け取ってくれ、代わりにこの写真プリンターを差し出しました。実際には eBay で余剰品を拾い、紙とインク付きで紙・インクだけの価値以下で手に入れていたのでした。
私は新しいガジェットにワクワクして「家族全員が喜べるだろう」と思い、同意しました。すると、なぜこの古いプリンターはこんなにも安く売れるのか分かった―Mac も Windows も長らくサポートを止めていたからです。マークは Linux を使っているので、その問題に直面したことがありませんでした。
幸運なことに、デスクには既にテスト用として使用している小型の Lenovo ThinkCentre(Manjaro が動いています)があります。実際、このような機種も eBay で安価で手に入ります。
Linux なら AirPrint 経由で共有できる
Manjaro マシンに CUPS と Gutenprint をインストールし、SELPHY に美しく印刷しました。Avahi を設定して AirPrint で共有すれば、家族全員が Mac や iPhone から印刷できます。
1999 年のように写真をプリントしていた気分です――触れられる本物の写真!ただし、1999 年とは違い、簡単・即時・必要な部分だけを切り取って露出調整後に印刷できるという利点があります。CMY 印刷の魔法も目の前で体験できます。プリンターは紙を三回通過させます――黄→マゼンタ→シアンです。
ハッピーエンド!しかし、これは物語の途中にすぎません。次に考えたのは「親御さんにも一台欲しい」と思い、孫の写真を印刷できるよう Raspberry Pi をプリントサーバーとして設置する案でした。しかし、それだと余計な配線が増えてしまうので、やめました。
すべての人が Linux を使っているわけではない
私は「ソフトウェアだけで非エンジニア向けにできるはず」と考え、思い切って Claude Code に £18 を投資してコーディングを始めました。現代の LLM は驚くべきものです――コンピュータが心の自転車なら、Claude Code はプライベートジェットに相当します。
Claude と私はネイティブ Mac アプリを作ることにしました。このアプリは「Linux VM をさりげなく起動し、Virtualization.framework で USB 通信を転送し、mDNS でプリンターを宣言する」仕組みです。しかし、App Store に許可されない可能性が高く、Mac ユーザーしか恩恵を受けられません。
ほぼすべての人が使える Web アプリ
そこで思い出しました――Chrome は WebUSB をサポートしています。もしこれを Web アプリにすれば、インストール不要でどこでも動くはずです。さらに JavaScript でクールなことができるので楽しみました。
Xcode の代わりに VS Code に切り替えて再挑戦。数時間後、これが実現可能だと確信し、printerface.app と printervention.app を登録しました(Claude が前者を、妻が後者を好み、最終的には妻の選択が採用されました)。
仕組みは?
アプリの核
驚くべきことに v86 はブラウザ上で x86 CPU と周辺機器全体をエミュレートします。実行時にマシンコードを WebAssembly モジュールへコンパイルし、十分高速に動作させています。この v86 マシンには Alpine Linux を稼働させ、CUPS・Gutenprint などの必要パッケージをインストールしています。
- ブラウザが WebUSB 経由でプリンターに接続し、メーカーとモデル情報を取得します。
- trigrams(3文字列)で最も近い Gutenprint ドライバ名を検索し、エミュレートしたキーボード経由で
コマンドを送信してインストールします。lpadmin - ファイルをアップロードし、
コマンドで印刷指示を出します。エミュレーション環境内で生成される生のバイナリ印刷データがプリンターへ届きます。lp
CUPS と WebUSB の橋渡し
初回実装:
カスタム CUPS バックエンド(シェルスクリプト)を作り、受け取った生データを v86 TTY 経由でブラウザにバイト単位で送信。ブラウザ側は再構築し、USB の
transferOut 呼び出しでプリンターへ渡します。これで印刷が可能になりました――ワンウェイのデータストリームを送るだけです。
二回目実装:
より効率的に v86 の 9p ファイルシステムを利用して大きなチャンクで転送しました。ただし、最初の写真は「縞模様」に見える奇妙な歪みが生じました。教訓として、JavaScript 側から Linux 側へ読み戻す前に必ずファイルを書き込み完了させる必要があります。
主な欠点: 両方ともワンウェイであり、紙詰まりやインク切れなどのエラーを即座に検知できませんでした。
双方向通信へ
印刷とスキャン双方で双方向データフローが欲しかったので Claude が提案した方法:
- USB/IP(Linux 側): USB データを TCP パケットにパッキングし、逆に受信時には TCP から USB にアンパック。
- tcpip.js(JavaScript 側): lwIP を WebAssembly 化し、v86 の仮想ネットカードが送る生 Ethernet フレームを L4 TCP/IP トラフィックへ変換。
これで Claude は約 400 行の USB/IP → WebUSB ブリッジを構築。印刷はスムーズに機能し、CUPS が各段階で何が起きているか把握できるようになりました。また SANE を使ったスキャンアプリもプロトタイプ化し、小さな tcpip.js の修正で動作させました(yes-we-scan.app 近日公開予定)。
さらに調整
- 紙サイズ問題: CUPS が SELPHY の 6×4" ポストカード用紙に合うよう画像を縮小していました。現在は任意の JPEG を手作り PDF に埋め込み、プリンター用紙サイズと向きを保ちつつ ICC プロファイルも渡します。
- HEIC 対応: 多くの写真は HEIC 形式(Apple Photos, AirDrop)です。
とlibheif-js
を組み合わせた変換パイプラインを作り、ICC プロファイルを保持しつつメモリに全データを読み込まないようにしました。wasm-mozjpeg
さらに、消耗品へのアフィリエイトリンクと基本的なテレメトリー(セッション・プリンター・印刷ジョブ情報)を Neon PostgreSQL データベースへ送信する機能も追加しています。
今後の展望
現在は数台の写真プリンターでしかテストしていませんが、Gutenprint 対応モデルなら幅広く動作すると期待しています。ただし、大きすぎる一度に印刷した場合は非対応になる可能性があります。もしプリンターが機能しないときは教えてください。
brlaser や splix などの PPD パッケージを追加することで改善できます。
公開コードの一部はオープンソース化していません。これは、印刷消耗品企業にとって魅力的な Web プロパティとして活用できるためです。リポジトリをフォークせず、ホワイトラベルで使用していただく方から報酬を頂ければと思います。
— George MacKerron
2026 年 4 月