ESC
开源 更新于 2026-08-01 00:00 1 分钟阅读

decimen-光学传输:

decimen光学传输: Decimen Optical Transfer:基于喷泉编码的 QR 文件传输方案 仅使用 屏幕与摄像头 即可在两台设备间传输文件。 一方设备将文件显示为动态 QR 码构成的无尽流;另一方设备用摄像头对准屏幕,即可重建文件。无需网络连接、无需安装应用、无需配对,除了摄像头权限外无需任何额外授

来源:GitHub

decimen-光学传输:

Decimen Optical Transfer:基于喷泉编码的 QR 文件传输方案


仅使用 屏幕与摄像头 即可在两台设备间传输文件。
一方设备将文件显示为动态 QR 码构成的无尽流;另一方设备用摄像头对准屏幕,即可重建文件。无需网络连接、无需安装应用、无需配对,除了摄像头权限外无需任何额外授权。 文件以光信号形式传输。

这是一个从更大实验中提取的最小化概念验证,该实验曾通过更密集的帧结构、多码网格及带纠错的颜色通道实现 手机间 128 KB/s 的传输速率。本概念验证仅保留核心机制,可稳定传输 512 KB 图片(或通过发送端设置选择传输 2 MB 图片)。

手机通过光信号接收 2 MB 图片:有效吞吐 129.2 KB/s,解码发送端

传输进行中:手机正以 129 KB/s 的速率从空中捕获 2 MB 图片。

尝试使用


npm install
npm run dev
  • 发送设备(推荐使用笔记本电脑)上:打开 https://localhost:5173/send/ 即可立即开始流式传输。建议调高屏幕亮度。
  • 接收设备(手机)上:打开 Vite 显示的局域网地址(https://<局域网IP>:5173/receive/),接受一次证书警告后点击 Start camera,将摄像头对准屏幕上的二维码。
  • 数秒后:显示 传输完成!,并通过哈希值验证接收的图片。

为何开发服务器仅支持 HTTPS: 接收端需使用 getUserMedia API,而浏览器会完全禁用非安全源上的该功能:手机通过普通 HTTP 访问开发服务器时将无法调用摄像头(localhost 例外,但你的手机并非 localhost)。这是 Web 平台的强制规范。因此开发服务器默认携带自签名证书(@vitejs/plugin-basic-ssl);首次访问时浏览器会显示警告。点击"显示详情"后选择"访问此网站"(iOS)或点击"高级"后选择"继续访问"(Android/桌面端),此时页面仍处于安全上下文,摄像头即可正常使用。Vite 显示的奇怪域名 lvh.me 是解析至 127.0.0.1 的公共便利域名(指向本机,无需额外运行服务)。

请保持手机稳定,或最好将其倚靠支撑。因手部抖动导致的摄像头自动对焦搜索是吞吐量下降的首要原因。

工作原理


单向通道问题。 屏幕到摄像头的链路没有反向通道:接收端无法请求重传,且难免出现丢帧(模糊、刷新时序错位、自动对焦)。采用循环播放帧的方式体验很差:一旦丢失某一帧,需等待完整周期才能再次获取。

喷泉码彻底解决了该问题。 发送端不直接传输文件的数据块。每一帧都是伪随机选取的部分数据块进行异或运算的结果;子集根据帧序号确定性生成,其大小遵循健壮孤子分布(Luby 变换编码)。接收端只需按任意顺序收集任意约 K·1.15 个不同帧,即可从中解码文件。丢帧仅略微增加耗时,不影响正确性。发送与接收端的帧率无需匹配。

每帧均自带描述信息。 20 字节头部包含会话 ID、序列号、数据块数量/大小、文件长度及哈希值。无需握手:接收端可在传输中途锁定数据流,重启发送端(新会话 ID)会自动重置接收端。

解码机制。 Safari 从未内置 BarcodeDetector(WebKit Bug 281848),因此采用 zxing-cpp 编译为 WASM 并在 Web Worker 中运行,通过 requestVideoFrameCallback 驱动。繁忙的 Worker 会导致丢帧,但喷泉码能高效吸收此类损耗。

概念验证中内置的艰难摸索出的细节


  • JS 引擎对 Math.log 的实现存在差异(为近似实现)。发送端与接收端必须生成完全一致的孤子分布,因此 fountain.ts 包含基于精确 IEEE-754 运算构建的确定性对数计算。V8 与 JavaScriptCore 的不同步会导致完全无声的失败。
  • iOS 系统会虚假报告摄像头帧率。设置 frameRate: {ideal: 60} 时实际仅提供 30fps;必须强制指定 {exact: 60}(在 1280px 宽度捕获时有效)并设置回退方案。务必通过 getSettings() 读取实际参数。
  • requestVideoFrameCallback 链会跨越流存活并在新流上恢复执行;若无世代计数器,每次停止/启动都会泄漏僵尸捕获循环。
  • 进度条需跟踪已收集帧数而非已解块数。LT 解码的级联特性会导致进度在传输大部分时间内停滞,最后瞬间跳至 100%。
  • QR 纠错级别设为最低(L级)。帧内纠错与喷泉层解决不同问题(数据损坏与