Camera access required
Grant camera permission to capture frames for GIF encoding.
Waiting for camera…
postal MessagePort transport demo
Camera access required
Grant camera permission to capture frames for GIF encoding.
Waiting for camera…
Gif Stitch runs in two JavaScript execution contexts — the main thread and a Web Worker.
postal bridges them with its MessagePort transport,
turning what would be raw postMessage plumbing
into clean pub/sub and RPC.
The main thread calls connectToWorker(worker) and the
worker calls connectToHost(). They perform a SYN/ACK
handshake over a MessageChannel, then
addTransport() wires the result into postal's
outbound hook — from that point on, every publish and request flows across the boundary automatically.
When you hit Start, the main thread calls
channel.request("encode.start", payload)
for each GIF slot. The worker's
channel.handle("encode.start", ...)
does the encoding and returns the finished GIF bytes. The main thread gets a
resolved Promise — no manual correlation IDs, no reply listeners, no ceremony.
While the worker encodes each frame, it calls
channel.publish("encode.progress", {"{ index, percent }"}).
The main thread subscribed to that topic before sending the request — so the
progress bar updates live, mid-RPC, as a fire-and-forget stream alongside the
pending Promise. That's two postal patterns running in parallel on the same channel.
Webcam frames are RGBA data — roughly 1.2 MB per frame at 640×480.
Ten frames per GIF means ~12 MB per encoding request. Instead of structured-cloning
all that memory, we call
markTransferable(payload, buffers)
before the request. The transport passes the
ArrayBuffers directly to
postMessage's transfer list — zero-copy,
instant, no serialization cost.