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
相关产品推荐
相关产品推荐

