皆様こんにちは。初見の方は、初めまして。普段はマネジメントや別事業をしつつ、インフラからアプリまで何でもこなす現場のIT何でも屋です。
本シリーズは、新言語「Hike」 の圧倒的なフットプリント削減能力と低レイヤ制御力を活かして、Webフロントエンドの重量級処理を「軽量化」かつ「高速化」する【Hike軽速化(けいそくか)】をテーマにした実践記録です。今回はその第1弾2章として「バーコード・QRコード読取」をテーマにお届けします。
本題に入る前に、マルチプラットフォーム対応や拡張機能の充実を経てコア機能のマイルストーンを達成し、言語本体として「一応の完成」を迎えたHike言語に、心からお祝いを申し上げます!
基盤が整った今、現場からの発信でHikeの輪を大きく盛り上げ、エコシステムの発展に微力ながら貢献できれば幸いです!
はじめに:QR生成の快進撃と「次なる野望」
前回の記事(【Hike軽速化:バーコード_1】新言語「Hike」で定番 qrcode.js をWasm化したら、サイズ65%削減・秒間40万回生成になった話)では、QRコード生成エンジンを極小Wasm化(約20KB・生成2.5µs)し、既存JSコード無修正で置き換える実装例をご紹介しました。
生成がいけたなら、次はフロントエンドの難所である 『スマートフォンのカメラによるQRコード読取(スキャナー)』の軽量高速化だと思い計画が始まりました。
背景と課題:html5-qrcodeが抱える「三重苦」
Webでカメラ読取を実装する際のデファクトスタンダードは html5-qrcode です。
しかし、このライブラリは裏で巨大なJava移植コード(ZXing-js)を使用しており、以下のような三重苦を抱えていました。
- ファイルサイズが 350KB 〜 850KB と超重量級
- 毎フレーム大量のオブジェクトを生成・破棄するため、頻繁なGC(ガベージコレクション)による画面のカクつき(フレームドロップ)が発生
- スマホのCPUを常時酷使するため、現場の端末が急速に発熱しバッテリーが激減する
そこで私は、新言語「Hike」を用いて、QRコード専用の超軽量・ゼロGC読取モジュール(scan_qr:Wasm約22KB)を開発しました。
テスト環境での動作を確認し、「よし、カメラ読取の軽量高速化も見えたぞ」と検証を進めました。
検証:驚異的なパフォーマンスと優位性
性能ベンチマーク対比(Ryzen 5 3500U / Chrome V8実測)
検証環境(Ryzen 5 3500U / Chrome V8)にて、カメラ映像フレーム(640×480 VGA, RGBA)からのQRコード読取処理における従来ライブラリ(html5-qrcode + @zxing/library)と、今回Hikeで試作開発したQR読取特化モジュール(scan_qr)の性能対比データを計測・整理しました。
1. ライブラリフットプリント & 初期化コスト比較
| 比較項目 | 従来デファクトhtml5-qrcode + @zxing/library
|
HIKE WASM QR読取特化エンジン ( scan_qr) |
改善効果 / 優位性 |
|---|---|---|---|
| ライブラリ転送サイズ (Raw) | 約 350.0 KB 〜 850.0 KB | 約 22.0 KB | 約 94% 削減 |
| Gzip 転送サイズ (概算) | 約 110.0 KB 〜 240.0 KB | 約 8.5 KB | 約 92% 削減 |
| 初期スクリプトパース・コンパイル | 120 〜 380 ms (Long Task発生) | 3 〜 8 ms (Wasm Compile) | 約 30〜45 倍高速 |
| 静的メモリフットプリント | 約 35.0 MB 〜 65.0 MB | 約 2.2 MB 〜 3.5 MB | 約 93% 削減 |
2. 1フレームのデコード速度 & スループット (VGA)
| 処理ステージ | 従来ライブラリ (html5-qrcode) |
HIKE WASM (scan_qr) |
速度・性能差 |
|---|---|---|---|
| ① 画像前処理(グレースケール・二値化) | 12.50 ms | 1.85 ms | 約 6.7 倍高速 |
| ② ファインダパターン・位置検出 | 8.20 ms | 1.40 ms | 約 5.8 倍高速 |
| ③ Reed-Solomon誤り訂正・データ復号 | 5.30 ms | 0.95 ms | 約 5.5 倍高速 |
| 1フレーム総合処理時間 | 約 26.00 ms (理論上限 ~38 fps) | 約 4.20 ms (理論上限 ~238 fps) | 約 6.2 倍高速 |
| 画面描画レート (実効FPS) | 22 〜 35 fps (カクつき多発) | 60 fps 張り付き (完全滑らか) | フレームドロップ 0 |
【1フレーム読取時間比較 (ms)】※数値が低いほど高速
HIKE scan_qr : [██] 4.20 ms
html5-qrcode : [█████████████████████████] 26.00 ms
3. メモリ割り当て・ガベージコレクション (GC) & 端末負荷の比較
| 測定指標 | 従来ライブラリ (html5-qrcode) |
HIKE WASM (scan_qr) |
備考・メカニズム |
|---|---|---|---|
| 1フレームあたりの動的メモリ確保 | 約 320 KB 〜 580 KB | 0 バイト | WASMリニアメモリ固定バッファによるゼロアロケーション |
| 1分間連続スキャン時のGC発生回数 | 45 〜 80 回 (Minor/Major GC) | 0 回 | スキャン中のメインスレッド停止(Stall)が完全にゼロ |
| 連続稼働時のCPU占有率 | 45% 〜 75% (高負荷持続) | 8% 〜 14% | リソース消費を最小限に抑制 |
| 連続動作時の端末負荷 | 高負荷 (サーマルスロットル懸念) | 低負荷 (安定動作) | モバイル環境でのバッテリー消耗を軽減 |
誤算:検証で直面した、3つの巨大な落とし穴
①:「QRコードだけ」で動いているシステムなど現実にはほとんどない
私が作ったのは「QRコード専用」の超軽量スキャナーでした。
しかし、実際の物流・倉庫・店舗などの業務を想定すると、現場で使われるコードはQRだけではありません。
- 商品パッケージの JANコード(EAN-13 / EAN-8)
- 段ボールや出荷伝票の Code 128 / ITF(Interleaved 2 of 5)
- 部品や基板に小さく印字された Data Matrix
といった、多種多様な「1Dバーコード(一次元バーコード)」が日常的に飛び交っています。
多くのWebアプリは、「1つのカメラ画面でQRコードもJANコードも自動判別して読む」という仕様が求められます。そこにQRしか読めないWasmエンジンをそのまま導入しても、1Dバーコードが映った瞬間に当然デコードできず、実用上成り立たないことに気づきました。
②:既存ライブラリとのグローバル名前空間・ラッパー衝突
フロントエンドの既存システムには、歴史的経緯により複数のライブラリが同居しています。
- カメラ読取:
html5-qrcode - 伝票・ラベル描画(1D生成):
JsBarcode - 画面表示(QR生成):
qrcode.js
これらを部分的にHike製Wasmで置き換えようとした場合、
-
グローバル名前空間の汚染と競合:
window.QRCodeやwindow.Html5Qrcodeを誰が上書き・初期化するかの順序問題 - 非同期初期化のタイミングバグ: Wasmのフェッチ・コンパイルが完了する前に既存の同期的JSコードがAPIを叩いてしまう問題
- コールバック・戻り値の不一致: 既存のラッパーが期待するオブジェクト構造と、Wasmラッパーが返すレスポンスのプロパティの微妙な違い
という、「ラッパーの継ぎ足しによるスパゲッティ地獄」に陥るリスクがクリアに見えてきました。
③:現場の過酷な撮影環境(曲面・影・斜めかざし)
さらに、実際のスマートフォンの撮影環境を想定して検証を重ねると、想定外の悪条件が立ちはだかりました。
- ペットボトルや缶の円筒曲面: バーコードの両端が圧縮・湾曲して直線として認識できない
- 作業者の手やスマホの濃い影: 画面半分が暗くなり、単純な2値化アルゴリズムが破綻
- 斜めかざし(30°〜45°): 水平スキャンラインしか通さない簡易アルゴリズムではバーを横断できない
「QRコードが綺麗に読めたからといって、そのまま実業務で使えるわけではない……」
軽花(軽量化)の数字ばかりに囚われていた私のWasm化検証は、ここで一度立ち止まざるを得なくなりました。
悩みに悩んだ私は、こう考えました。
結論:統合エンジンへ…もう全部Hikeで統一してやらぁ!!
あかん、このままライブラリごとにパッチワークのようなラッパーを被せて辻褄を合わせるのはもう限界や……。
動的型付き言語の泥沼で消耗するくらいなら、QRも1Dバーコードも、生成も読取も、画像補正も、全部まとめてHikeで1つの超軽量エンジンとして作り直してやる!!
……と、現場で頭を抱えながらも腹をくくった私は、半ばやけくそ技術者としての執念を胸に、「Webにおけるあらゆるコード処理(読取&生成・1D/2D全19規格)を完全制覇する単一エンジン」のフルスクラッチ開発を決意しました。
目標
- 全19規格(QR/MicroQR/rMQR/DataMatrix/JAN/Code128/Code39/ITF等)の生成・読取を完全内装
- 2次元積分画像を用いた整数演算による超高速画像補正(影平坦化・ボケ強調・缶曲面アンローリング)
html5-qrcode/JsBarcode/qrcode.jsの3大ライブラリAPIを完全エミュレートする統合ドロップインラッパー- 用途に応じて必要なバイナリだけを十数KB〜百数十KBで切り出せるターゲット分離アーキテクチャ
おわりに
検証の段階でこれらの壁に気づけたことは、結果として幸いでした。
泥沼の衝突と現実の壁を乗り越え、ついに完成した究極のコード処理エンジン。
巨大なJSスタックを削減し、ゼロGC・超低発熱で過酷な現場をねじ伏せるアーキテクチャ(予定)の全貌は、次回の記事でたっぷりとお届けします。どうぞお楽しみに!
Hike軽速化 シリーズ一覧・まとめ
本シリーズの過去記事や今後の続編一覧は、以下のストックリストで一括管理しています。ぜひご活用ください!
👉 Hikeで軽速化シリーズ(Qiitaストック)
- 前回:【Hike軽速化:バーコード_1】新言語「Hike」で定番 qrcode.js をWasm化したら、サイズ68%削減・秒間40万回生成になった話
- 今回:【Hike軽速化:バーコード_2】新言語「Hike」でhtml5-qrcode比サイズ94%削減&45倍高速化!Wasmでカメラ読取を激変した話
- 次回:『【Hike軽速化:バーコード_3】新言語「Hike」でマルチ規格コード処理エンジンを統合したら、~~した話(仮)』近日公開予定
謝辞
本ツールの開発にあたり、多くのWebプロジェクトのカメラ読取を支えてこられた既存の強力なライブラリ html5-qrcode(mebjas氏)の開発者様に対し、心より深く敬意と感謝を申し上げます。偉大な先達の仕様やエコシステムがあるからこそ、こうした挑戦的な軽量・高速化の検証を行うことができました。
また、前回の番外編の記事にいただいたコメントにて、Hike言語の開発者である kanryu さんから「Hike言語のエヴァンジェリストとして現場からフィードバックを届けてほしい」という身に余るほど光栄なお言葉を頂戴いたしました。いただいた期待の大きさに身が引き思いですが、現場のリアルな活用事例や面白いネタを今後も積極的に発信し、エコシステムの発展に少しでも貢献できるよう全力で取り組んでいきたいと思います!
本記事の構成案の壁打ちや技術検証のサポートには生成AI(Gemini)を活用しました。AIの強力なアシストを受けながら、スムーズに検証から執筆までをやり切ることができました。
軽量なWasm環境やエッジな開発、AIを活用した開発に興味がある方は、ぜひ Hike を触ってみてください!
※「QRコード」は株式会社デンソーウェーブの登録商標です。
※本実装のAPIインターフェースは、既存の html5-qrcode (mebjas氏)、JsBarcode (lindell氏)、qrcode.js (Kazuhiko Arase氏) の仕様を参考に互換性を担保しています。