Masayan tech blog .

QuaggaJS完全ガイド|JSでバーコード読み取り実装【11形式対応】

公開日
最終更新日

要約

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();
});

トラブルシューティング

カメラが起動しない

症状: カメラの映像が表示されない、エラーメッセージが出る

原因と対処法:

  1. カメラの許可がない
    • ブラウザがカメラへのアクセスを拒否している
    • 対処法: ブラウザの設定からカメラの許可を有効にする
    • Chrome: 設定 → プライバシーとセキュリティ → サイトの設定 → カメラ
    • Safari: 環境設定 → Webサイト → カメラ
  2. HTTPSでない
    • QuaggaJSはセキュリティ上の理由でHTTPS環境が必要
    • 対処法: HTTPS環境で実行する(localhostは例外)
    • 開発環境ではlocalhostを使用する
  3. カメラが他のアプリケーションで使用中
    • 他のアプリがカメラを占有している
    • 対処法: 他のカメラアプリを終了する
  4. ブラウザの互換性問題
    • 古いブラウザではカメラAPIが未対応
    • 対処法: 最新版のChrome、Firefox、Safariを使用する

バーコードが読み取れない

症状: カメラは起動するが、バーコードを認識しない

原因と対処法:

  1. 照明が不十分
    • バーコードが暗すぎて認識できない
    • 対処法: 明るい場所で使用する、照明を追加する
  2. バーコードとカメラの距離が不適切
    • 近すぎる、または遠すぎる
    • 対処法: バーコードがカメラの中央に収まるよう調整する(10-30cm程度)
  3. バーコードの形式が未対応
    • 指定したデコーダーがバーコード形式に対応していない
    • 対処法: 複数のデコーダーを設定する(上記の詳細な実装例を参照)
  4. バーコードの品質が悪い
    • 印刷が薄い、破損している
    • 対処法: 鮮明なバーコードを使用する
  5. カメラの解像度が低い
    • 解像度が低すぎてバーコードが認識できない
    • 対処法: 解像度を上げる(width: 1280, height: 720など)

パフォーマンスが悪い

症状: 動作が重い、CPUファンが回る、バッテリーが急激に減る

原因と対処法:

  1. 解像度が高すぎる
    • 高解像度でCPU負荷が高い
    • 対処法: 解像度を下げる(640x480から試す)
  2. フレーム処理頻度が高すぎる
    • 毎フレーム処理でCPUを消費している
    • 対処法: frequencyを下げる(10以下に設定)
  3. Web Workerの数が多すぎる
    • CPUコア数以上のWorkerを設定している
    • 対処法: numOfWorkersを2-4に設定
  4. 読み取り領域が広すぎる
    • 画面全体を処理している
    • 対処法: areaで読み取り領域を制限する(上記のカスタム設定例を参照)

誤検出が多い

症状: バーコードでないものを認識する、間違ったコードを読み取る

原因と対処法:

  1. 信頼度チェックが甘い
    • エラー率が高い結果も受け入れている
    • 対処法: エラーハンドリング実装例のように信頼度チェックを追加
  2. 複数のデコーダーが競合
    • 複数の形式で誤認識
    • 対処法: 必要な形式のみに絞る
  3. 環境が複雑
    • 背景に文字やパターンが多い
    • 対処法: シンプルな背景を使用する、読み取り領域を制限する

よくある質問(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次元コード)を読み取る場合は、jsQRZXingなどの別のライブラリを使用する必要がある。

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デモ:

自分でデモを作成する

以下の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>

デモの使い方

  1. 上記のHTMLをdemo.htmlとして保存
  2. ローカルサーバーを起動(例: python3 -m http.server 8000
  3. ブラウザでhttp://localhost:8000/demo.htmlにアクセス
  4. カメラの許可を求められたら「許可」をクリック
  5. バーコードをカメラに向けて読み取りを試す

デモのカスタマイズ

デモコードを以下のようにカスタマイズできる:

  • デザイン変更: CSSを編集してUIをカスタマイズ
  • 対応形式の変更: readers配列を編集
  • 解像度調整: widthheightを変更
  • カメラ選択: facingModeuser(前面)またはenvironment(背面)に変更
  • 読み取り後の処理: Quagga.onDetected()内の処理を追加

まとめ

本記事では、JavaScriptでバーコード読み取り機能を実装できるQuaggaJSライブラリについて、導入方法から実践的な活用法まで包括的に解説した。

主なポイント

導入の容易さ:

  • npmまたはCDNで簡単に導入可能
  • わずか数行のコードでバーコード読み取り機能を実装
  • MITライセンスで商用・非商用問わず無料で使用可能

豊富な機能:

  • EAN、UPC、Code128など11種類のバーコード形式に対応
  • 複数の形式を同時にサポート可能
  • パフォーマンス調整のための詳細な設定オプション

実践的な実装:

  • エラーハンドリングを含む本番環境向けの実装例
  • 信頼度チェックによる誤検出の防止
  • React、Vue.jsなどのフレームワークとの統合

トラブルシューティング:

  • カメラが起動しない場合の対処法(HTTPS環境、カメラ許可など)
  • バーコードが読み取れない場合の解決策(照明、距離、解像度調整)
  • パフォーマンス問題の解決(解像度、フレーム処理頻度、読み取り領域の最適化)

実用的な活用例:

  • ECサイトの商品検索機能
  • 在庫管理システム
  • 図書館の蔵書管理
  • イベントのチケット管理
  • 物流・配送管理

QuaggaJSは、ブラウザのカメラを活用したバーコード読み取り機能を手軽に実装できる強力なライブラリである。本記事で紹介した実装例やトラブルシューティング方法を参考に、ぜひ自分のプロジェクトに導入してみてほしい。公式デモやCodePenのサンプルも活用することで、より深い理解が得られるだろう。