@QingQ77: Transferring files between two devices that can't access the internet is too troublesome, so just have the sender encode the file into a set of dynamic QR codes, and the receiver can scan the screen once to receive it. https://github.com/deedy/qr-data-transfer…
Summary
QRFerry is an open-source browser-based tool that transfers files between two offline devices by encoding data as a live animated QR stream, using RaptorQ fountain coding and WebAssembly.
View Cached Full Text
Cached at: 08/04/26, 12:08 PM
Transferring files between two devices that both cannot access the internet is too much hassle—so just have the sending side encode the file into a stream of dynamic QR codes, and the receiving side can capture it by scanning the screen.
https://t.co/43vzV8kHTC https://t.co/Fl1JXsRMAo
deedy/qr-data-transfer
Source: https://github.com/deedy/qr-data-transfer
QRFerry
QRFerry moves a file from one device to another as a live animated QR stream.
The sender and receiver run entirely in the browser; the file is never uploaded
to an application server.
Use it
- Open the root page on the sending screen and choose a file.
- Open
/scanon the receiving phone and allow rear-camera access. - Start the QR stream and keep the complete code inside the phone’s guide.
- Save the file when RaptorQ recovery and the whole-file checksum reach 100%.
Robust through Turbo 30 use one stable QR target. Turbo 60 uses two V30-L lanes, updating them alternately at 30 fps each so one remains stable during every display transition. The opt-in 1 Mbps laboratory profile uses the same dual-lane design with V40-L for a nominal 1.40 Mbps optical payload channel before camera loss. Dual modes require fullscreen sender playback, the receiver’s Dual lane option, and a landscape phone held close and steady.
Demo
QRFerry air-gapped data transfer demo
This inline preview is generated from the final privacy-redacted demo. The
full-resolution recording remains local at
videos/qrferrydemo_timed_redacted.mov and is intentionally excluded from Git.
Protocol
- Brotli quality 11 and gzip level 9 are both attempted; only the smallest representation is retained, and only when it saves optical bytes.
- QR frames use raw byte mode, avoiding the Base45 expansion of the previous protocol.
- Every frame carries a compact binary header, a RaptorQ symbol, and CRC-32.
- File metadata is inside the protected RaptorQ object instead of repeating in descriptor beacons.
- Source and repair symbols are interleaved. The receiver can join mid-cycle, discard blur, accept frames out of order, and reconstruct after receiving enough unique symbols.
- Turbo 15 uses one V30-L code held for four refreshes on a 60 Hz screen. Turbo 30 holds one code for two refreshes. Turbo 60 alternates updates across two V30-L lanes, so each lane remains stable for two refreshes while their combined stream carries 60 symbols per second. The 1 Mbps laboratory profile applies the same scheme to two denser V40-L lanes.
- Playback is synchronized to browser display refreshes. The sender reports its measured render rate; the receiver reports negotiated and delivered camera fps, completed scans per second, and decoder p50/p95 latency.
- Dual scanning acquires at most two codes per exposure and accepts either stable lane; it avoids the density and acquisition cost of a four-code grid.
- Rendering uses
fast_qrcompiled to WebAssembly. Scanning uses ZXing-C++ compiled to WebAssembly. Fountain encoding and decoding use the RFC 6330 RaptorQ implementation compiled to WebAssembly. - The receiver verifies the per-frame CRC, the complete RaptorQ object CRC, the transmitted compressed payload CRC, and the original file CRC before saving.
Development
Requires Node.js >=22.13.0.
bash npm install npm run dev
The project does not require a Python environment. If Python tooling is added,
use uv for its environment and dependencies.
Test harness
bash npm test
The harness checks:
- metadata, compression, and end-to-end checksum round trips;
- per-frame corruption rejection;
- RaptorQ reconstruction after unordered simulated camera-frame erasures;
- the actual V30-L WebAssembly renderer passed through the actual ZXing-C++ WebAssembly scanner with exposure noise;
- exact QR capacity for every profile;
- production builds and server rendering for both
/and/scan.
Run npm run lint and npx tsc --noEmit for the additional source checks.
Similar Articles
Decimen Optical Transfer: fountain-coded QR file transfer
Decimen Optical Transfer is an open-source web app that sends files between devices using animated QR codes and fountain codes, requiring only a screen and camera with no network connection. It supports files up to 64 MB, works offline as a PWA, and achieves around 130 KB/s transfer rates.
@QingQ77: Reliably transfer files between phone, computer, and browser—works even under restricted networks like NAT, hotel Wi-Fi, campus networks; large files support resume. https://github.com/shrimpsend/shrimpsend… ShrimpSend (虾传) is…
ShrimpSend (虾传) is an open-source cross-platform file transfer system that enables direct connections under restricted networks like NAT and hotel Wi-Fi, supports resumable transfers, and transfers files directly between devices without a server relay.
Show HN: ShadowCat – file transfer through QR Codes in a Browser
ShadowCat is an offline single-file HTML page for transferring data between devices via QR codes, intended for old phones with functional cameras and browsers but broken radios.
@geekbb: A multi-protocol downloader with a Rust engine and Flutter UI, supporting HTTP/FTP, BT magnet, eD2K, and HLS/DASH streaming media, positioned as a free and open-source IDM alternative. https://github.com/zerx-lab/Flu…
A multi-protocol downloader based on a Rust engine and Flutter UI, supporting HTTP/FTP, BT magnet, eD2K, and HLS/DASH streaming media, positioned as a free and open-source IDM alternative.
Streaming the IETF MoQ sessions with MoQ… kinda
Meetecho 博客文章描述了如何利用 MoQ (Media over QUIC) 协议来流式传输 IETF MoQ 会议,作为传统 WebRTC 方案的补充,实现了自动捕获并传输相同媒体的一种新型方式。