qrcode-transmitter
v1.1.0
Published
A lightweight browser library for transmitting binary data across multi-frame QR codes.
Readme
qrcode-transmitter
A lightweight browser-oriented library for splitting arbitrary binary data into multiple QR frames and reassembling it on scan.
Features
- Splits
Uint8Arraypayloads into protocol frames and encodes each frame as QR SVG - Frame 0 includes SHA-256 of the full payload for integrity verification
- Scans QR codes from camera input and reassembles payloads automatically
- Handles duplicate frames and out-of-order frame delivery (
msgId + frameIndexaggregation) - Includes a runnable example app for local testing and demos
Installation
pnpm add qrcode-transmitterYou can also install it with npm or yarn.
Quick Start
import { encodeBytesToQRCodes, startVideoQRReceiver } from "qrcode-transmitter";
// 1) Sender: encode data into multiple QR frames (async, computes SHA-256)
const bytes = new TextEncoder().encode("Hello QR");
const frames = await encodeBytesToQRCodes(bytes);
// frames[i].svg can be injected into the DOM directly
// 2) Receiver: scan with a video element and reassemble (SHA-256 verified)
const video = document.querySelector("video") as HTMLVideoElement;
const receiver = startVideoQRReceiver(video, {
onFrame: (progress) => {
console.log(progress.frameIndex + 1, "/", progress.totalFrames);
},
onComplete: (data) => {
console.log(new TextDecoder().decode(data));
},
onVerifyFailed: (info) => {
console.error("SHA-256 mismatch", info.expectedSha256Base64, info.actualSha256Base64);
},
});
// Stop scanning when needed
receiver.stop();API
encodeBytesToQRCodes(bytes: Uint8Array): Promise<EncodedFrame[]>
Encodes a raw byte array and returns QR frame objects. Frame 0 includes SHA-256 (base64) of the full payload:
frameIndex: frame index (starting from 0)totalFrames: total number of framessvg: QR code SVG string for this framepayload: base64 payload of this frame
Encoding settings are fixed to:
- QR
TypeNumber = 15 - error correction level
L Bytemode for writing payload data
startVideoQRReceiver(video, options): { stop(): void }
Starts scanning and reassembles data by protocol:
video:HTMLVideoElementoptions.onFrame: called when each new (non-duplicate) frame is parsedoptions.onComplete: called when all frames are received and SHA-256 verification passesoptions.onVerifyFailed: called when SHA-256 verification fails after reassembly
Returns an object with stop() to stop and destroy the scanner.
Protocol
Frame 0: msgId|0/total|sha256Base64|payloadBase64
Frame i>0: msgId|idx/total|payloadBase64
msgId: 8-character random hexadecimal stringidx: current chunk indextotal: total chunk countsha256Base64: (frame 0 only) SHA-256 of full payload, base64-encodedpayloadBase64: base64 payload of the chunk
Local Development
pnpm install
pnpm build
pnpm test
pnpm exampleCommon scripts:
pnpm build: build todist/withtsuppnpm dev: watch buildpnpm typecheck: run TypeScript type checkspnpm test: run Vitestpnpm example: start the example app (Vite)
Run the Example
Live demo: https://haruamamiya.github.io/qrcode-transmitter/
After running pnpm example:
- In the "Encode" section, enter text or select a file to render QR frames at 5fps
- In the "Decode" section, allow camera permission and scan to see reconstructed output
