在无线电模块失效的老旧设备之间传输文件,浏览器纯前端方案提供了一条独特的光学通道。ShadowCat 项目通过单文件 HTML 实现了一套完整的 QR 码文件传输系统,无需服务器、无需安装,仅依赖摄像头和浏览器即可工作。本文从编码效率、分片策略与重传机制三个维度,剖析这类光学传输方案的工程化设计要点。
编码效率的权衡:为何选择 Base64
QR 码支持多种编码模式,效率差异显著。理论上,纯数字模式(Digit Mode)可将 3 位十进制数压缩至 10 比特,效率达 99.66%;字母数字模式(Alphanumeric Mode)以 45 进制编码,效率约 99.85%。然而 ShadowCat 选择了 Base64 编码,每个字符承载 6 比特信息却占用 8 比特存储空间,效率仅 75%。
这一选择的核心考量是兼容性优先。Base64 输出为可打印 ASCII 字符,避免了二进制数据在浏览器解码链中可能触发的编码歧义 —— 不同解码器对字节模式的解释存在差异(JIS X 0201 与 ISO-8859-1 的历史遗留问题),而 Base64 的字符集在 URL、剪贴板和 UI 展示中均无特殊含义。对于需要跨设备、跨浏览器运行的离线工具,这种 "浪费" 是必要的技术债。
若追求极限效率,可采用分块进制转换策略:将数据切分为 7 字节块,转换为 17 位十进制数字,效率可提升至 98.82%。但这需要自定义编解码逻辑,增加了实现复杂度。建议在受控环境(如内部工具)中采用优化方案,在开放环境(如公共网页)中保留 Base64 的保守策略。
分片大小的工程决策
ShadowCat 的协议设计简洁明了:头部帧 QRX1|H|<total>|<filename>|<sizeBytes>|<crc32hex> 携带元数据,数据帧 QRX1|D|<idx>|<base64chunk> 承载分片内容。分片大小直接决定传输效率与容错能力的平衡点。
分片过小(如 100 字符)会放大帧间开销:每个 QR 码的固定开销(定位图案、格式信息、版本信息)占比上升,且帧率受限(老旧设备摄像头解码速度有限)。分片过大(如 1000 字符)则增加单帧解码失败概率,一旦丢失需重传整个大块,且高密度 QR 码对拍摄距离、对焦精度要求更高。
项目给出的参考配置是 500 字符分片配合 3 FPS 帧率,理论吞吐约 1.1 KB/s(Base64)或 0.83 KB/s 原始数据。实际部署中,建议根据设备能力动态调整:
- 老旧设备:300 字符分片 + ECC Q 级(25% 纠错),降低 QR 密度
- 现代设备:700-800 字符分片 + ECC M 级(15% 纠错),提升吞吐
- 极限场景:ECC L 级(7% 纠错)配合稳定拍摄环境,最大化容量
分片索引采用 1-based 编号,接收端通过位图或集合跟踪已接收块,在 UI 中以网格形式展示缺失帧,用户可手动触发指定帧重发或等待下一轮循环。
循环播放与重传策略
ShadowCat 的发送端采用循环播放模式:按 [header, chunk1, chunk2, ..., chunkN] 顺序无限循环,接收端持续扫描直至所有分片收齐。这种设计规避了双向通信需求,但引入了重复接收与顺序错乱的处理逻辑。
接收端需实现以下机制:
- 头部去重:通过 CRC32 校验识别重复的头部帧,避免重复初始化
- 分片去重:基于索引号忽略已接收的分片,防止重复写入
- 缺失追踪:维护未接收索引的集合,驱动 UI 展示与完成判断
- 完整性校验:全部收齐后验证 CRC32,确保文件无损
发送端的控制功能(暂停、恢复、指定帧重发)为交互式修复提供可能。当接收端显示特定分片持续丢失时,可暂停循环并单独发送该帧,避免完整重传的开销。这种 "按需重传" 策略在光学通道不稳定时尤为重要。
光学通道的局限与 WebRTC 回退
纯 QR 传输的带宽受限于显示刷新率与摄像头解码速度,ShadowCat 的 0.83 KB/s 原始吞吐意味着 100 KB 文件需约 2 分钟完成传输。当设备具备网络能力时,应设计分层回退机制:
- 第一层:QR 码传输会话标识(短字符串),建立 WebRTC 数据通道
- 第二层:WebRTC 直连传输文件内容,带宽可达 Mbps 级
- 第三层:若 WebRTC 协商失败(防火墙、NAT 限制),回退至 QR 码完整传输
会话标识的 QR 传输仅需毫秒级,却能为具备网络能力的设备打开高速通道。这种 "光学握手 + 网络传输" 的混合模式,兼顾了离线兼容性与在线效率。
可落地参数清单
基于 ShadowCat 的实践,整理以下可直接应用的配置参数:
| 参数项 | 保守配置 | 平衡配置 | 激进配置 |
|---|---|---|---|
| 分片大小 | 300 字符 | 500 字符 | 800 字符 |
| ECC 级别 | Q (25%) | M (15%) | L (7%) |
| 帧率 | 2 FPS | 3 FPS | 5 FPS |
| 理论吞吐 | ~0.4 KB/s | ~0.8 KB/s | ~1.5 KB/s |
| 适用场景 | 老旧设备、远距离拍摄 | 通用场景 | 现代设备、近距离稳定拍摄 |
协议设计建议:
- 头部包含总块数、文件名、原始大小、CRC32 四项元数据
- 数据帧包含索引与 Base64 载荷,索引从 1 开始
- 分隔符选用管道符
|,避免 Base64 字符集冲突 - 接收端支持 "显示缺失块网格" 与 "单帧重发请求" 交互
总结
浏览器纯前端 QR 文件传输是特定场景下的务实方案 —— 当蓝牙、WiFi、NFC 全部失效时,摄像头与屏幕构成的光学通道成为最后的数据桥梁。ShadowCat 的设计展示了如何在编码效率与兼容性、分片大小与容错能力、循环传输与按需重传之间取得平衡。对于需要支持离线传输的 Web 应用,建议将 QR 传输作为降级方案纳入架构,配合 WebRTC 实现分层传输策略,在极端环境与高效传输之间灵活切换。
参考来源
- ShadowCat: https://github.com/unprovable/ShadowCat
- Efficient QR codes: https://www.imperialviolet.org/2021/08/26/qrencoding.html
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。