HTML5 QR スキャナー

動くスキャナーと、自分で作る人向けの API の話。

カメラはボタンを押したときだけ要求します。フレームは端末内で解読し、そのまま破棄します。

HTML5 のスキャナーは、3 つのブラウザ API を重ねたものです。getUserMedia でカメラのストリームを取り、canvas でフレームを標本化し、デコーダに渡します。デコーダは、あればネイティブの BarcodeDetector、なければ同梱の JavaScript デコーダです。プラグインもネイティブコードも登場しません。

このページが道具と解説を兼ねているのは、この検索で来る人の多くがこれから自分で作る人で、どこが要になる部分かを知りたいからです。

使い方

  1. コードを読むだけなら上のスキャナーを使ってください。
  2. 自分で実装するなら、下の API の順序を読んでください。
  3. 本番用のデコーダを選ぶ前に、互換性の注意を確認してください。

実装の順序

getUserMedia({ video: { facingMode: 'environment' } }) でストリームを取り、video 要素に繋ぎ、playsinline を付けます。これが無いと iOS Safari は動画を全画面にします。次に canvas へ 8〜10 fps 程度に間引いて描画し、canvas をデコーダへ渡します。成功したらトラックを止めます。

罠は解像度です。1080p のフレームを渡すと遅く、640 ピクセル幅のものより精度が上がるわけでもありません。先に縮小し、requestAnimationFrame ごとではなく一定間隔で解読してください。

確認日:2026-10-21。このツールはすべてブラウザ内で動作します。サーバーもアカウントもなく、生成した内容は保存されません。

よくある質問

html5-qrcode のようなライブラリは必要ですか?

必須ではありません。ライブラリはブラウザ間の差異と UI を引き受けます。多形式が必要なら価値がありますが、QR だけでよければ BarcodeDetector と jsQR のフォールバックで数十行、サイズもはるかに小さく済みます。

自分のサイトで getUserMedia が例外を投げるのは?

セキュアコンテキスト(HTTPS か localhost)が必要です。平文 HTTP では navigator.mediaDevices が undefined になり、これが最もよくある原因です。

終わった後にカメラを止めるには?

stream.getTracks().forEach(t => t.stop()) を呼びます。途中で離脱する場合に備えて pagehide も購読し、そこで解放してください。

関連ツール

QR コードのその他のツール。