You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZXing-js/browser扫描任意二维码均返回ChecksumError求助

ZXing-js 扫描二维码抛出 ChecksumException 问题修复

以下是针对「能检测到二维码但一直返回ChecksumException」问题的排查和修复方案:

核心问题分析

ChecksumException 表示识别到的二维码数据校验不通过,通常是图像数据失真(比如拉伸、叠加UI元素干扰)或识别参数配置不当导致的。结合你的代码,主要问题集中在Canvas绘制顺序、视频与Canvas尺寸匹配、API使用这几个方面。


具体修复步骤

1. 调整Canvas绘制顺序:先扫描再绘制UI元素

当前代码先把视频画到Canvas,扫描后又绘制扫描框和扫描线,导致下一次扫描时Canvas残留的UI元素干扰识别。修改scan方法,先完成扫描再绘制UI:

scan: async function () {
    try {
        if (this.localMediaStream) {
            console.log("Scanning Video Feed.");

            const video = this.qrvideo;
            // 获取视频真实尺寸,避免拉伸变形
            const videoWidth = video.videoWidth;
            const videoHeight = video.videoHeight;
            // 同步Canvas尺寸与视频尺寸
            this.qrcanvas.width = videoWidth;
            this.qrcanvas.height = videoHeight;

            // 先清空Canvas
            this.context.clearRect(0, 0, videoWidth, videoHeight);
            // 按真实尺寸绘制视频帧到Canvas
            this.context.drawImage(video, 0, 0, videoWidth, videoHeight);

            // 优先执行扫描
            const code = await this.qr.decodeFromCanvas(this.qrcanvas);
            this.read(code);

            // 扫描成功后再绘制UI元素(不影响下一次扫描)
            this.transposeRect(videoWidth, videoHeight);
        }
    } catch(err) {
        if (err instanceof NotFoundException) {
            console.log('No QR code found.')
            // 未识别到二维码时也绘制UI,保持视觉反馈
            const video = this.qrvideo;
            const videoWidth = video.videoWidth;
            const videoHeight = video.videoHeight;
            this.transposeRect(videoWidth, videoHeight);
        }
        if (err instanceof ChecksumException) {
            console.log('A code was found, but it\'s read value was not valid.')
        }
        if (err instanceof FormatException) {
            console.log('A code was found, but it was in a invalid format.')
        }
    }
}

2. 替换过时的getUserMedia API

旧的navigator.getUserMedia已被废弃,改用标准的navigator.mediaDevices.getUserMedia提升兼容性:

修改selectSource方法:

selectSource: function (source) {
    this.selected_source = source;

    let constraints = {
        audio: false,
        video: {
            facingMode: "environment",
            deviceId: source // 注意参数名是deviceId,不是sourceId
        }
    };

    // 改用新API
    navigator.mediaDevices.getUserMedia(constraints)
        .then(this.startScan)
        .catch(this.scanError);
}

3. 调整识别参数(可选)

暂时关闭TRY_HARDER参数,测试是否是过度识别导致的校验错误:

修改mountQRReader里的hints配置:

// 注释或移除TRY_HARDER
// hints.set(DecodeHintType.TRY_HARDER, true);

如果关闭后正常,再根据实际场景决定是否开启,或调整扫描频率。

4. 优化扫描触发方式:避免重复扫描

把setInterval改为requestAnimationFrame,确保上一次扫描完成后再进行下一次:

修改startScan方法:

startScan: function (stream) {
    this.qrvideo.srcObject = stream;
    this.localMediaStream = stream;
    this.qrvideo.play();

    // 替换setInterval为requestAnimationFrame
    const scanLoop = async () => {
        await this.scan();
        if (this.localMediaStream) {
            this.polling = requestAnimationFrame(scanLoop);
        }
    };
    scanLoop();
}

修改stopScan方法:

stopScan: function () {
    if (this.polling) {
        cancelAnimationFrame(this.polling);
    }
    if (this.localMediaStream) {
        this.localMediaStream.getVideoTracks().forEach(track => track.stop());
    }
}

额外注意事项

  • 确保二维码清晰,无模糊、反光,扫描距离合适
  • 测试不同设备的摄像头,排查硬件兼容性问题
  • 更新@zxing/library和@zxing/browser到最新版本,修复已知bug

内容的提问来源于stack exchange,提问作者pneves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:18:25