要約
QuaggaJSは、JavaScriptでバーコード読み取り機能を実装できるオープンソースライブラリである。PCやスマートフォンのカメラを利用して、EAN、UPC、Code128など、多様なバーコード形式を読み取ることができる。本記事では、QuaggaJSの基本的な使い方と実装手順を紹介する。
対象読者: JavaScript初心者〜中級者、バーコード読み取り機能の実装を検討している開発者
検証環境: QuaggaJS(2025年1月時点の最新版)
この記事を読むことで得られるメリット
この記事を読むことで以下のことが分かる:
- QuaggaJSの導入方法(npm/CDN)
- ブラウザのカメラからバーコードを読み取る実装方法
- QuaggaJSが対応している11種類のバーコード形式
- 実際に動作するサンプルコードと詳細な実装例
- よくあるエラーとトラブルシューティング方法
- 実践的なカスタマイズ方法
この記事を読むのにかかる時間
約10分
環境
- MacOS Apple M4 Max Sequoia 15.1
- Node.js v14.17.4
- npm 6.14.14
- Visual Studio Code
- Git Bash 2.32.0.1
QuaggaJSの動作イメージ
※ブラウザのカメラ使用許可が必要である。
PCのカメラからバーコードを読み取るための領域が画面に表示され、バーコードをカメラに向けると自動的に読み取りが行われる。読み取ったバーコード情報は、JavaScriptで受け取って任意の処理に活用できる。
QuaggaJSの導入方法
npmでのインストール
Node.js環境を使用している場合は、以下のコマンドでインストールする。
npm install quagga
CDNでの読み込み
HTMLファイルに直接読み込む場合は、以下のscriptタグを追加する。
<script type="text/javascript" src="https://serratus.github.io/quaggaJS/examples/js/quagga.min.js"></script>
実装コード
基本的な実装例
以下は、QuaggaJSを使用してバーコードを読み取る基本的な実装例である。
<body>
<div id="interactive" class="viewport"></div>
<script src="./js/quaggaJS/dist/quagga.js"></script>
<script>
Quagga.init({
inputStream: { type : 'LiveStream' },
decoder: {
readers: [{
format: 'ean_reader',
config: {}
}]
}
}, (err) => {
if(!err) {
Quagga.start();
}
});
Quagga.onDetected((result) => {
var code = result.codeResult.code;
// ここでコードを受け取って、何かしらの処理(例えば、楽天市場APIを使用して商品検索等)を実行
});
</script>
</body>
実装のポイント
- #interactive.viewport: このID要素内にカメラの映像が表示される
- Quagga.init(): QuaggaJSを初期化し、バーコードリーダーの設定を行う
- Quagga.start(): カメラの起動とバーコード検知を開始する
- Quagga.onDetected(): バーコードが検知されたときに実行されるコールバック関数
対応しているバーコード形式
QuaggaJSは、以下の11種類のバーコード形式に対応している。
デコーダー名 | 説明 |
|---|---|
code_128_reader | Code128形式(デフォルト) |
ean_reader | EAN-13形式(JANコード) |
ean_8_reader | EAN-8形式 |
code_39_reader | Code39形式 |
code_39_vin_reader | Code39 VIN形式 |
codabar_reader | Codabar形式 |
upc_reader | UPC形式 |
upc_e_reader | UPC-E形式 |
i2of5_reader | Interleaved 2 of 5形式 |
2of5_reader | Standard 2 of 5形式 |
code_93_reader | Code93形式 |
詳細な仕様は、QuaggaJS公式ドキュメントを参照されたい。
詳細な実装例
複数のバーコード形式を同時に読み取る
実際のアプリケーションでは、複数のバーコード形式に対応する必要がある場合が多い。以下は、EAN、UPC、Code128を同時にサポートする例である。
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#interactive'),
constraints: {
width: 640,
height: 480,
facingMode: "environment" // スマートフォンの背面カメラを使用
}
},
decoder: {
readers: [
"ean_reader",
"ean_8_reader",
"upc_reader",
"upc_e_reader",
"code_128_reader"
]
},
locate: true // バーコードの位置を自動検出
}, function(err) {
if (err) {
console.error("初期化エラー:", err);
return;
}
console.log("QuaggaJS初期化完了");
Quagga.start();
});
読み取り結果を画面に表示する
バーコードの読み取り結果をユーザーに表示する実装例である。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>QuaggaJS バーコードリーダー</title>
<style>
#interactive {
width: 640px;
height: 480px;
border: 2px solid #333;
}
#result {
margin-top: 20px;
font-size: 24px;
font-weight: bold;
color: #2ecc71;
}
</style>
</head>
<body>
<h1>バーコードリーダー</h1>
<div id="interactive" class="viewport"></div>
<div id="result">バーコードをカメラに向けてください...</div>
<script src="https://serratus.github.io/quaggaJS/examples/js/quagga.min.js"></script>
<script>
Quagga.init({
inputStream: {
type: "LiveStream",
target: document.querySelector('#interactive')
},
decoder: {
readers: ["ean_reader", "code_128_reader"]
}
}, function(err) {
if (err) {
document.getElementById('result').innerText = "エラー: " + err;
return;
}
Quagga.start();
});
Quagga.onDetected(function(result) {
const code = result.codeResult.code;
const format = result.codeResult.format;
document.getElementById('result').innerText =
`検出: ${code} (形式: ${format})`;
// 読み取り成功時の音を鳴らす(オプション)
const audio = new Audio('beep.mp3');
audio.play();
// APIを呼び出して商品情報を取得する例
fetchProductInfo(code);
});
function fetchProductInfo(barcode) {
// 商品情報APIの呼び出し例
fetch(`https://api.example.com/products/${barcode}`)
.then(response => response.json())
.then(data => {
console.log("商品情報:", data);
// 商品情報を表示する処理
})
.catch(error => {
console.error("商品情報の取得エラー:", error);
});
}
</script>
</body>
</html>
エラーハンドリングを含む実装例
本番環境では、適切なエラーハンドリングが必要である。以下は、エラー処理を含む実装例である。
function initQuagga() {
Quagga.init({
inputStream: {
type: "LiveStream",
target: document.querySelector('#interactive'),
constraints: {
width: { min: 640 },
height: { min: 480 }
}
},
decoder: {
readers: ["ean_reader"]
}
}, function(err) {
if (err) {
handleInitError(err);
return;
}
console.log("QuaggaJS初期化成功");
Quagga.start();
// 読み取り開始
Quagga.onDetected(onBarcodeDetected);
// 処理中のフレームを監視(デバッグ用)
Quagga.onProcessed(onFrameProcessed);
});
}
function handleInitError(err) {
console.error("初期化エラー:", err);
if (err.name === 'NotAllowedError') {
alert('カメラの使用が許可されていません。ブラウザの設定を確認してください。');
} else if (err.name === 'NotFoundError') {
alert('カメラが見つかりません。デバイスにカメラが接続されているか確認してください。');
} else {
alert('エラーが発生しました: ' + err.message);
}
}
function onBarcodeDetected(result) {
const code = result.codeResult.code;
// 信頼度チェック(誤検出を防ぐ)
if (result.codeResult.decodedCodes.length > 0) {
const errors = result.codeResult.decodedCodes
.filter(x => x.error !== undefined)
.map(x => x.error);
const avgError = errors.reduce((a, b) => a + b, 0) / errors.length;
// エラー率が10%以下の場合のみ受け入れる
if (avgError < 0.1) {
console.log("バーコード検出:", code);
processBarcode(code);
} else {
console.warn("信頼度が低いため無視:", avgError);
}
}
}
function onFrameProcessed(result) {
// デバッグ用: 処理中のフレームを可視化
const drawingCtx = Quagga.canvas.ctx.overlay;
const drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0,
parseInt(drawingCanvas.getAttribute("width")),
parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(box => box !== result.box).forEach(box => {
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {
color: "green",
lineWidth: 2
});
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {
color: "blue",
lineWidth: 2
});
}
}
}
function processBarcode(code) {
// バーコードの処理ロジック
console.log("処理するバーコード:", code);
}
// 停止処理
function stopQuagga() {
Quagga.stop();
console.log("QuaggaJS停止");
}
// ページ読み込み時に初期化
document.addEventListener('DOMContentLoaded', initQuagga);
// ページを離れる時に停止
window.addEventListener('beforeunload', stopQuagga);
カスタム設定でパフォーマンスを最適化
バーコード読み取りの精度とパフォーマンスを調整する設定例である。
Quagga.init({
inputStream: {
type: "LiveStream",
target: document.querySelector('#interactive'),
constraints: {
width: 1280,
height: 720,
facingMode: "environment"
},
area: { // 読み取り領域を制限してパフォーマンス向上
top: "25%",
right: "25%",
left: "25%",
bottom: "25%"
}
},
locator: {
patchSize: "medium", // x-small, small, medium, large, x-large
halfSample: true // パフォーマンス向上のため解像度を半分に
},
numOfWorkers: 4, // Web Workerの数(CPUコア数に応じて調整)
frequency: 10, // フレーム処理頻度(低くするとCPU負荷軽減)
decoder: {
readers: ["ean_reader"],
multiple: false // 複数のバーコードを同時に読み取らない
},
locate: true
}, function(err) {
if (err) {
console.error(err);
return;
}
Quagga.start();
});
トラブルシューティング
カメラが起動しない
症状: カメラの映像が表示されない、エラーメッセージが出る
原因と対処法:
- カメラの許可がない
- ブラウザがカメラへのアクセスを拒否している
- 対処法: ブラウザの設定からカメラの許可を有効にする
- Chrome: 設定 → プライバシーとセキュリティ → サイトの設定 → カメラ
- Safari: 環境設定 → Webサイト → カメラ
- HTTPSでない
- QuaggaJSはセキュリティ上の理由でHTTPS環境が必要
- 対処法: HTTPS環境で実行する(localhostは例外)
- 開発環境では
localhostを使用する
- カメラが他のアプリケーションで使用中
- 他のアプリがカメラを占有している
- 対処法: 他のカメラアプリを終了する
- ブラウザの互換性問題
- 古いブラウザではカメラAPIが未対応
- 対処法: 最新版のChrome、Firefox、Safariを使用する
バーコードが読み取れない
症状: カメラは起動するが、バーコードを認識しない
原因と対処法:
- 照明が不十分
- バーコードが暗すぎて認識できない
- 対処法: 明るい場所で使用する、照明を追加する
- バーコードとカメラの距離が不適切
- 近すぎる、または遠すぎる
- 対処法: バーコードがカメラの中央に収まるよう調整する(10-30cm程度)
- バーコードの形式が未対応
- 指定したデコーダーがバーコード形式に対応していない
- 対処法: 複数のデコーダーを設定する(上記の詳細な実装例を参照)
- バーコードの品質が悪い
- 印刷が薄い、破損している
- 対処法: 鮮明なバーコードを使用する
- カメラの解像度が低い
- 解像度が低すぎてバーコードが認識できない
- 対処法: 解像度を上げる(width: 1280, height: 720など)
パフォーマンスが悪い
症状: 動作が重い、CPUファンが回る、バッテリーが急激に減る
原因と対処法:
- 解像度が高すぎる
- 高解像度でCPU負荷が高い
- 対処法: 解像度を下げる(640x480から試す)
- フレーム処理頻度が高すぎる
- 毎フレーム処理でCPUを消費している
- 対処法:
frequencyを下げる(10以下に設定)
- Web Workerの数が多すぎる
- CPUコア数以上のWorkerを設定している
- 対処法:
numOfWorkersを2-4に設定
- 読み取り領域が広すぎる
- 画面全体を処理している
- 対処法:
areaで読み取り領域を制限する(上記のカスタム設定例を参照)
誤検出が多い
症状: バーコードでないものを認識する、間違ったコードを読み取る
原因と対処法:
- 信頼度チェックが甘い
- エラー率が高い結果も受け入れている
- 対処法: エラーハンドリング実装例のように信頼度チェックを追加
- 複数のデコーダーが競合
- 複数の形式で誤認識
- 対処法: 必要な形式のみに絞る
- 環境が複雑
- 背景に文字やパターンが多い
- 対処法: シンプルな背景を使用する、読み取り領域を制限する
よくある質問(FAQ)
Q1: QuaggaJSは無料で使えるか?
A: はい、QuaggaJSはMITライセンスのオープンソースライブラリであり、商用・非商用を問わず無料で使用できる。
Q2: スマートフォンでも動作するか?
A: はい、モバイルブラウザ(Chrome、Safari)でも動作する。facingMode: "environment"を設定することで、スマートフォンの背面カメラを使用できる。
constraints: {
facingMode: "environment" // 背面カメラ
// facingMode: "user" // 前面カメラ
}
Q3: オフラインでも使えるか?
A: はい、npmでインストールすればオフライン環境でも動作する。CDN版を使用する場合は、インターネット接続が必要である。
Q4: QRコードも読み取れるか?
A: いいえ、QuaggaJSは1次元バーコード専用である。QRコード(2次元コード)を読み取る場合は、jsQRやZXingなどの別のライブラリを使用する必要がある。
Q5: ReactやVue.jsで使えるか?
A: はい、ReactやVue.jsでも使用できる。コンポーネントのマウント時にQuagga.init()、アンマウント時にQuagga.stop()を呼び出す必要がある。
React の例:
import { useEffect } from 'react';
import Quagga from 'quagga';
function BarcodeScanner() {
useEffect(() => {
Quagga.init({
inputStream: {
type: "LiveStream",
target: document.querySelector('#interactive')
},
decoder: {
readers: ["ean_reader"]
}
}, (err) => {
if (!err) {
Quagga.start();
}
});
Quagga.onDetected((result) => {
console.log("検出:", result.codeResult.code);
});
return () => {
Quagga.stop();
};
}, []);
return <div id="interactive" className="viewport" />;
}
Q6: 読み取り速度を上げるには?
A: 以下の方法で読み取り速度を向上できる:
- デコーダーを必要な形式のみに絞る
halfSample: trueで解像度を下げるfrequencyを上げる(ただしCPU負荷も増加)- 照明を明るくする
- 読み取り領域を制限する
Q7: 商用利用時の注意点は?
A: QuaggaJSはMITライセンスなので、ライセンス表示をすれば商用利用可能である。ただし、以下の点に注意が必要である:
- HTTPS環境が必須(本番環境ではSSL証明書が必要)
- カメラの許可をユーザーに求める必要がある
- プライバシーポリシーにカメラ使用を明記する
- ブラウザの互換性を事前にテストする
Q8: TypeScriptで使用できるか?
A: はい、型定義ファイルをインストールすることでTypeScriptでも使用できる。
npm install --save-dev @types/quagga
Q9: バーコードの読み取り音を鳴らすには?
A: Quagga.onDetected()内でAudio APIを使用する。
Quagga.onDetected((result) => {
const audio = new Audio('beep.mp3');
audio.play();
});
Q10: 複数のバーコードを同時に読み取れるか?
A: QuaggaJSは基本的に1つずつバーコードを読み取る設計である。複数のバーコードを同時に読み取る場合は、multiple: trueを設定するが、パフォーマンスへの影響が大きいため推奨されない。
動作デモ
実際に動作するデモを試すことで、QuaggaJSの使い方をより深く理解できる。
公式デモページ
QuaggaJSの公式デモページでは、ブラウザ上で直接バーコード読み取りを試すことができる。
デモURL: https://serratus.github.io/quaggaJS/examples/
CodePenでのデモ
CodePenで動作するサンプルコードを確認・編集できる。自分のアカウントでフォークして、カスタマイズも可能である。
おすすめのCodePenデモ:
- QuaggaJS Basic Example: https://codepen.io/search/pens?q=quaggajs
自分でデモを作成する
以下のHTMLファイルを作成し、HTTPS環境(またはlocalhost)で実行することで、簡単にデモを試すことができる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QuaggaJS デモ</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
h1 {
text-align: center;
color: #333;
}
#interactive {
width: 100%;
max-width: 640px;
height: 480px;
margin: 20px auto;
border: 3px solid #2ecc71;
border-radius: 8px;
overflow: hidden;
}
#result {
text-align: center;
margin-top: 20px;
padding: 15px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.code {
font-size: 32px;
font-weight: bold;
color: #2ecc71;
margin: 10px 0;
}
.format {
font-size: 16px;
color: #666;
}
button {
display: block;
margin: 20px auto;
padding: 10px 30px;
font-size: 16px;
background-color: #3498db;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #2980b9;
}
</style>
</head>
<body>
<h1>📱 QuaggaJS バーコードリーダー デモ</h1>
<div id="interactive" class="viewport"></div>
<div id="result">
<p>バーコードをカメラに向けてください...</p>
</div>
<button onclick="location.reload()">リセット</button>
<script src="https://serratus.github.io/quaggaJS/examples/js/quagga.min.js"></script>
<script>
Quagga.init({
inputStream: {
type: "LiveStream",
target: document.querySelector('#interactive'),
constraints: {
width: 640,
height: 480,
facingMode: "environment"
}
},
decoder: {
readers: [
"ean_reader",
"ean_8_reader",
"code_128_reader",
"upc_reader"
]
}
}, function(err) {
if (err) {
document.getElementById('result').innerHTML =
'<p style="color: red;">エラー: ' + err.message + '</p>';
return;
}
console.log("QuaggaJS初期化成功");
Quagga.start();
});
Quagga.onDetected(function(result) {
const code = result.codeResult.code;
const format = result.codeResult.format;
document.getElementById('result').innerHTML =
'<div class="code">' + code + '</div>' +
'<div class="format">形式: ' + format + '</div>';
// ビープ音(オプション)
try {
const audio = new Audio('data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBiJ+zO3akT8MGV203vK5Zx4EJHzL8N2UQQwWYrfr6qpYFApHouHxt2ohBiJ+zO3akT8MGV203vK5Zx4EJHzL8N2UQQwWYrfr6qpYFApHouHxt2ohBiJ+zO3akT8MGV203vK5Zx4EJHzL8N2UQQwWYrfr6qpYFApHouHxt2ohBiJ+zO3akT8MGV203vK5Zx4EJHzL8N2UQQwWYrfr6qpYFApHouHxt2ohBiJ+zO3akT8MGV203vK5Zx4EJHzL8N2UQQwWYrfr6qpYFA==');
audio.play();
} catch (e) {
console.log("音声再生エラー:", e);
}
});
</script>
</body>
</html>
デモの使い方
- 上記のHTMLを
demo.htmlとして保存 - ローカルサーバーを起動(例:
python3 -m http.server 8000) - ブラウザで
http://localhost:8000/demo.htmlにアクセス - カメラの許可を求められたら「許可」をクリック
- バーコードをカメラに向けて読み取りを試す
デモのカスタマイズ
デモコードを以下のようにカスタマイズできる:
- デザイン変更: CSSを編集してUIをカスタマイズ
- 対応形式の変更:
readers配列を編集 - 解像度調整:
widthとheightを変更 - カメラ選択:
facingModeをuser(前面)またはenvironment(背面)に変更 - 読み取り後の処理:
Quagga.onDetected()内の処理を追加
まとめ
本記事では、JavaScriptでバーコード読み取り機能を実装できるQuaggaJSライブラリについて、導入方法から実践的な活用法まで包括的に解説した。
主なポイント
導入の容易さ:
- npmまたはCDNで簡単に導入可能
- わずか数行のコードでバーコード読み取り機能を実装
- MITライセンスで商用・非商用問わず無料で使用可能
豊富な機能:
- EAN、UPC、Code128など11種類のバーコード形式に対応
- 複数の形式を同時にサポート可能
- パフォーマンス調整のための詳細な設定オプション
実践的な実装:
- エラーハンドリングを含む本番環境向けの実装例
- 信頼度チェックによる誤検出の防止
- React、Vue.jsなどのフレームワークとの統合
トラブルシューティング:
- カメラが起動しない場合の対処法(HTTPS環境、カメラ許可など)
- バーコードが読み取れない場合の解決策(照明、距離、解像度調整)
- パフォーマンス問題の解決(解像度、フレーム処理頻度、読み取り領域の最適化)
実用的な活用例:
- ECサイトの商品検索機能
- 在庫管理システム
- 図書館の蔵書管理
- イベントのチケット管理
- 物流・配送管理
QuaggaJSは、ブラウザのカメラを活用したバーコード読み取り機能を手軽に実装できる強力なライブラリである。本記事で紹介した実装例やトラブルシューティング方法を参考に、ぜひ自分のプロジェクトに導入してみてほしい。公式デモやCodePenのサンプルも活用することで、より深い理解が得られるだろう。