JSでスマホのカメラからQRコード・バーコードを読み取ってみる
この記事は、よくあるスマホのカメラからQRコードやバーコードを読み取るやつをWebブラウザで実装したものです。
カメラの他、保存済の画像も対象にしてみました。
まずは今回作ったデモページを動かしてみる
以下のQRコードは今回作成したページのURLです。
スマートフォンで読み取って、デモページを開いてください。
PCなら、カメラ付きノートPCか、USBカメラを接続すると同様に動きます。

QRコードのURLはこちら
https://ykoba079.github.io/test_prj/smartphone-js/02-camera-code-reader/
画面上部の(QR/バーコード/両方)で、読み取る対象を選択します。
画面下部にある「カメラを起動」ボタンを押すと、カメラにアクセスして処理を開始します。以下のようにカメラの利用許可を求められるので、許可してください。
許可すると画面中央にカメラ画像が表示されるので、QRコードやバーコードをカメラに映してみてください。
検出するとコードの位置に枠と番号が付き、画面下部のリストにコードの種類と内容が表示されます。
1枚の画像に複数のコードが写っている場合は10件まで検出します。
以下は、QRとバーコード両方を映したところです。
「カメラを起動」ボタンの横にある「写真を選択」ボタンでは、保存しておいた画像ファイルを対象にコードを読み取ります。
イベントでアンケート入力のQRコードを投影されたとき、後でじっくりアンケートページを入力したい時など写真を残しておけばいいので、ちょっと便利かなと思います。
スマホなら写真ライブラリを選択すると、撮影した写真の一覧が表示されるのでそこから写真を選択すると同様にQRコード・バーコードの読み取りをします。

JavaScriptでカメラ映像と写真はブラウザ内で処理しています。
写真データをサーバなどへ送信は行いません。
JavaScriptからスマートフォンのカメラを使う
今回はWebブラウザでQRコードを読み取るために、JavaScriptからカメラへアクセスしました。
ブラウザからカメラを利用するには、navigator.mediaDevices.getUserMedia()を使用します。
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facingMode: { ideal: "environment" }
}
});
video.srcObject = stream;
await video.play();
navigator.mediaDevices.getUserMedia()は、Webブラウザから端末に接続されているカメラやマイクにアクセスして、映像や音声のストリームデータを取得するための機能です。
上記ではビデオを対象にし、facingMode: "environment"は、スマートフォンの背面カメラを優先する指定です。
なぜカメラの利用に許可が必要?
Webページを開いただけでカメラ映像を自由に取得できてしまうと、利用者が知らないうちに周囲の映像を取得されるなど、プライバシーやセキュリティ上の問題につながります。
そのため、ブラウザではカメラやマイクなどのデバイスを利用する際に、利用者へ明示的な許可を求める仕組みになっています。
カメラを停止するときは、以下のように取得したストリームのトラックを停止します。
stream.getTracks().forEach((track) => track.stop());
カメラ映像を画像として取り出す
カメラが返すのは連続した映像です。コードを解析するため、まずは映像の一場面をcanvasへ描画して画像データを取り出します。
context.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageData = context.getImageData(
0,
0,
canvas.width,
canvas.height
);
まず、drawImage()で、現在のカメラ映像をcanvas要素へ1フレーム分描画します。
第1引数には描画元のvideo要素を指定し、後ろの引数でcanvasの左上 (0, 0) から、canvas.width × canvas.height の大きさに合わせて描画しています。
context.drawImage(video, 0, 0, canvas.width, canvas.height);
続いてgetImageData()で、canvasに描画した画像をピクセルデータとして取得します。
const imageData = context.getImageData(
0,
0,
canvas.width,
canvas.height
);
ここではcanvas全体を対象にしているため、左上 (0, 0) から幅canvas.width、高さcanvas.heightの範囲を取得しています。
返されるImageDataは、画像の幅・高さと、各ピクセルのRGBA値になります。今回はこのImageDataを、そのままコード読み取りライブラリへ渡して解析しています。
デモではスマートフォンへの負荷を抑えるため、カメラの全フレームを解析するのではなく、一定間隔で画像を取り出しています。また、大きな画像は解析前に縮小しています。
ZXing-WASMでコードを読み取る
コードの解析にはzxing-wasmを使用しました。
zxing-wasmは、ZXing-C++というQRコード・バーコード解析ライブラリをWebブラウザから使えるようにしたもので、Webブラウザ内でQRコードや一次元バーコードを解析できます。
読み取り処理のコア部分は、以下のように記載しています。
readBarcodesに、処理する画像データと、QRコードやCode39などのバーコードの種類を指定しています。
const results = await ZXingWASM.readBarcodes(imageData, {
formats: [
"QRCode",
"EAN13",
"EAN8",
"Code128",
"Code39",
"ITF"
],
tryRotate: true,
tryInvert: true,
maxNumberOfSymbols: 10
});
読み取り結果は配列で返されます。
複数のコードを検出した場合は、それぞれの内容と位置を取得できます。
results.forEach((result) => {
console.log(result.format); // QRCode、Code39など
console.log(result.text); // 読み取った内容
console.log(result.position); // 画像内の位置
});
今回のデモでは、次のコード形式を対象にしています。
| 種類 | 主な用途例 |
|---|---|
| QRコード | URL、テキスト、各種案内 |
| EAN-13/EAN-8 | 日本の商品で使われるJANコード |
| Code 39/128 | 製造・物流の管理ラベル |
| ITF/ITF-14 | 段ボールなどの集合包装 |
使用ライブラリとライセンス
使用ライブラリのライセンスは次のとおりです。
| ソフトウェア | ライセンス | 再配布時の主な対応 |
|---|---|---|
| zxing-wasm | MIT License | 著作権表示とライセンス文を含める |
| ZXing-C++/ZXingWasm.cpp | Apache License 2.0 | ライセンス文を含める。NOTICEがある場合はその内容も確認する |
| Zint由来部分 | BSD 3-Clause License | 著作権表示・ライセンス条件・免責条項を含める |
今回は次のように、リポジトリのライセンス情報に記載しました。
カメラだけでなく写真からも読み取る
スマートフォンでも、ファイル選択用のinputから写真ライブラリを開けます。(スマホでの挙動を最近知りましたw)
<input type="file" accept="image/*">
イベントのアンケート入力用のQRコード等、その場で入力する時間が無い場合はコードの写真を撮っておいて、後から処理する、という事や、PDFやFAXで受け取った注文票にコードがある場合も利用できそうですね。
画像全体に対してコードが小さい(書類の下に小さくあるとか)と読み込みに失敗しやすくなるので、その場合は別途、ユーザーに読み取り範囲をタップして指定してもらったり、帳票のレイアウトが決まっているならコードのある範囲だけを切り出したりしてから、ライブラリへ渡すといった工夫が必要になります。
1件ずつしか読めないわけではない
スマートフォンの標準的なQRコード読み取り機能は、カメラに映した1つのコードを素早く読み取り、その場でURLを開くような用途に向いています。
一方で、1枚の書類や写真に複数のコードが含まれている場合もあります。
今回のデモでは画像全体を解析し、複数のQRコードやバーコードを一度に検出するようにしているので、検出した位置情報を使えば、帳票の並びに沿ったコード一覧を作ることもできそうですね。
例えば、以下のようなケースでしょうか。
製造・インフラ・設備点検
- 部品ラベルから部品番号を読み取る
- 作業指示書と対象部品の組み合わせを確認する
- 設備の管理番号から点検記録を呼び出す
物流
- 荷札や梱包箱のコードを読み取り、入出庫対象の確認に利用する
- 複数のラベルを写真に撮り、後からまとめて確認する
オフィス・金融
- 貸与端末や備品の資産番号を確認する
- 郵送物や帳票の仕分けを補助する
まとめ
今回は、スマートフォンのカメラと写真をJavaScriptから利用し、QRコードとバーコードを読み取ってみました。
専用のバーコードリーダーの方が速度や精度はよいですが、ちょっと確認してみたい時や、普段バーコードリーダーを持ち歩いていない場面にもすぐ対応できる点がやはり便利かと思います。
お試しを!



