HTML5 二维码扫描器
一个能用的扫描器,外加实现细节。
只有点击按钮时才会请求摄像头权限。每一帧都在本机解码后立即丢弃。
HTML5 扫描器是三个浏览器 API 叠起来的:getUserMedia 取摄像头流,canvas 抽帧,再加一个解码器,存在原生 BarcodeDetector 就用它,不存在就用内置的 JavaScript 解码器。全程没有插件,也没有原生代码。
这一页既是工具也是解释,因为搜到这里的人多数正准备自己写一个,想知道哪几块是承重的。
使用方法
- 只需要读码的话,直接用上面的扫描器。
- 想知道 API 调用顺序,读下面的实现说明。
- 要上生产之前,先看兼容性那几条再选解码器。
实现顺序
用 `getUserMedia({ video: { facingMode: 'environment' } })` 请求视频流,接到 video 元素上,并设置 `playsinline`,不设的话 iOS Safari 会把视频全屏接管。然后按限定的频率把画面画进 canvas,通常是每秒 8 到 10 帧,再把 canvas 交给解码器。解出结果后,停止所有轨道。
坑在分辨率。把 1080p 的帧直接交给解码器,既慢,也不比 640 像素宽的帧更准。先缩小,并且按固定间隔解码,而不是每个动画帧都解一次。
审校于 2026-10-21。这个工具完全在你的浏览器里运行——没有服务器、不需要账号,生成的内容也不会被保存。
常见问题
需要用 html5-qrcode 这类库吗?
不一定。这类库处理跨浏览器差异和界面,需要支持很多格式时值得用。只做二维码的话,BarcodeDetector 加一个 jsQR 兜底不过几十行,体积小得多。
为什么我的站点上 getUserMedia 会抛错?
它要求安全上下文,也就是 HTTPS 或 localhost。普通 HTTP 下 `navigator.mediaDevices` 是 undefined,这是最常见的原因。
用完怎么关掉摄像头?
调用 `stream.getTracks().forEach(t => t.stop())`。同时监听 `pagehide`,用户扫到一半离开时也能释放摄像头。
相关工具
更多二维码工具。