Skip to content

Punch

Fast Link Access Gate — SRT session brokerage for broadcast.

License: MIT Built on Cloudflare Workers TypeScript Tests


Punch landing page

Punch is a free, open-source signalling service that lets SRT endpoints find each other and connect — without manual port forwarding or static IP coordination, on networks that allow UDP rendezvous. It runs on Cloudflare Workers and costs nothing to operate.

The problem

Every SRT connection today requires manual coordination:

  1. Someone opens a UDP port on a public IP
  2. Both sides agree on IP, port, passphrase, and latency — via phone, Signal, email, or spreadsheet
  3. Someone configures caller vs listener mode (and gets it wrong half the time)
  4. Repeat for every camera, every show, every venue

For a 4-camera ISO shoot, that’s 4 separate coordination conversations. On a hotel WiFi with double NAT, it’s impossible without a relay server.

Commercial solutions exist (Haivision Hub, LiveU, Teradek Sharelink) — starting at hundreds of dollars per month, locked to proprietary hardware, closed ecosystems.

Between free CLI tools and enterprise SaaS, there is nothing.

Punch fills that gap.

How it works

WebSocket

WebSocket

SRT rendezvous (direct P2P)

Encoder

punch.thåst.se

Session

peer discovery,

NAT coordinates

Decoder

  1. Producer creates a session → gets a URL and QR code
  2. Encoder scans the QR → registers with Punch, reports its public IP:port
  3. Decoder does the same → Punch sends each peer the other’s coordinates
  4. Both start SRT in rendezvous mode → direct peer-to-peer, NAT hole-punched
  5. Punch stays connected → monitors health, carries tally, shows dashboard

The signalling server never touches the media. It brokers the introduction, then gets out of the way.

Quick start

  1. Open punch.thåst.se, enter a session name, and create the session. You will be taken to the operator dashboard at punch.thåst.se/s/<name>?t=<token>.
  2. Show the QR code on screen, or send the operator URL to the camera operator. They register their SRT endpoint with one tap.
  3. When both peers register, Punch reveals the auto-generated connection strings — ffmpeg, OBS, vMix, GStreamer and srt-live-transmit, ready to paste.

Session dashboard with QR, multi-stream view, and Join controls

A 60-second walkthrough lives in docs/quick-start.md.

Programmatic / self-hosted

The HTTP API works the same way against any Punch deployment. The hosted service punch.thåst.se enforces Cloudflare Turnstile on POST /api/session, so curl-only callers must use a self-hosted instance (no Turnstile secret set), or supply a turnstileToken from a Turnstile-enabled client.

Terminal window
# Self-hosted instance — no Turnstile secret configured
curl -X POST http://localhost:8787/api/session \
-H 'Content-Type: application/json' \
-d '{"name": "nab-floor-cam1"}'

Response:

{
"session": "nab-floor-cam1",
"token": "p_abc123...",
"url": "http://localhost:8787/s/nab-floor-cam1",
"qr": "http://localhost:8787/s/nab-floor-cam1/qr",
"streams": ["default"],
"latency": 200,
"ttl": 1800,
"state": "WAITING",
"created": "2026-05-03T11:49:15.620Z"
}

After both peers register, fetch the connection strings:

Terminal window
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8787/api/session/nab-floor-cam1/connect

The response contains parallel for_peer_a and for_peer_b format maps. See docs/protocol.md for the full shape.

Features

Session brokerage

  • Peer discovery — no manual IP exchange
  • NAT traversal — UDP hole punching via SRT rendezvous mode
  • Passphrase distribution — auto-generated AES keys, never texted
  • Auto-generated commands — exact FFmpeg, OBS, vMix, and GStreamer strings

Multi-camera sessions

  • Session bundles — group multiple SRT streams under one production
  • Per-stream metadata — camera role, audio config, labels
  • One QR per camera — operators scan and stream, nothing else

Real-time monitoring

  • Stream health dashboard — RTT, retransmit ratio, bitrate, buffer levels
  • Colour-coded status — green/amber/red, visible at arm’s length
  • Latency recommendation — measured RTT → suggested setting

Production control plane

  • Tally signalling — on-air/preview/off state via WebSocket
  • Camera labels — human-readable names on the dashboard
  • Session state machine — WAITING → READY → CONNECTED → CLOSED

Architecture

Punch runs entirely on Cloudflare Workers with Durable Objects:

  • Edge Worker — handles HTTP/WebSocket routing, JWT validation
  • Session Durable Object — one instance per session, strong consistency
  • Hibernatable WebSockets — idle connections cost nothing
  • Alarm API — automatic session cleanup after 30 minutes of inactivity

No servers to maintain. No databases to manage. Free tier handles ~3,000 sessions/day.

Client

Cloudflare Edge

anycast, nearest PoP

Worker

JWT validation, routing

Durable Object

session state, WebSocket hub

Alarm

TTL cleanup

Why Durable Objects, not KV

Workers KV has eventual consistency — up to 60 seconds propagation delay. For signalling, that means peer B might not see peer A’s registration for a full minute. Fatal.

Durable Objects provide single-threaded strong consistency per session. One object per session. No race conditions. No stale state.

The Punch protocol

PUNCH — Peer Unification via NAT Crossing Handshake

A minimal signalling protocol for SRT session brokerage. Designed to be what WHIP is for WebRTC — a simple, standardised way to negotiate SRT connections over HTTP and WebSocket.

Session lifecycle

WAITING Both peers not yet registered
READY Coordinates exchanged, rendezvous can begin
CONNECTED SRT connection established (reported by peers)
RELAYING Hole punch failed, relay path active (future)
CLOSED Session terminated or TTL expired

WebSocket messages

// Peer → Punch
{ type: 'register', port: 9000, meta: { label: 'CAM-1', audio: 'stereo' } }
{ type: 'health', rtt: 45, retransmit: 0.2, bitrate: 8500000 }
{ type: 'status', srt: 'connected' }
// Punch → Peer
{ type: 'peer', ip: '198.51.100.3', port: 9000, passphrase: '...' }
{ type: 'tally', state: 'preview' }
{ type: 'session', streams: [...], connected: 3, total: 4 }

Full protocol specification: docs/protocol.md

Comparison

SolutionCostSignallingMulti-camMonitoringOpen source
FFmpeg CLIFreeManualNoNoYes
srt-live-transmitFreeManualNoNoYes
SRT Mini Server$30/moBasicNoBasicNo
PunchFreeAutomaticYesYesYes
LiveU Solo$450/yr + hwProprietaryLimitedYesNo
Haivision HubEnterpriseProprietaryYesYesNo

Documentation

DocumentDescription
docs/why.mdWhy Punch exists — design philosophy and origin essay
docs/architecture.mdTechnical architecture, Durable Objects, state machine
docs/protocol.mdProtocol overview — narrative reference
docs/spec/punch-protocol-rfc.mdFormal protocol specification (RFC-style, normative)
docs/spec/openapi.yamlOpenAPI 3.1 description of the HTTP API
docs/spec/punch-messages.schema.jsonJSON Schema 2020-12 for WebSocket messages
docs/nat-traversal.mdNAT types, hole punching, relay fallback
docs/srt-primer.mdSRT fundamentals for context
docs/integration.mdFFmpeg, OBS, vMix, CasparCG, hardware encoders
docs/security.mdTokens, passphrases, access control
docs/deployment.mdCloudflare Workers setup and configuration
docs/roadmap.mdPhased feature roadmap

Known limitations

Punch is honest about what it does and does not do.

  • Signalling only, no media. Punch never touches video or audio. The signalling server brokers the introduction; once peers exchange coordinates, SRT runs direct peer-to-peer between them.
  • NAT traversal is signalling-assisted, not guaranteed. Punch coordinates the rendezvous, but it does not run STUN, TURN, or any UDP probing. The connection succeeds whenever the encoder’s NAT preserves a usable UDP mapping for the duration of the SRT handshake. In practice this covers the bulk of fixed-line and broadcast-venue deployments (port-preserving / cone NATs) and most prosumer home routers. It does not cover symmetric NAT, carrier-grade NAT, or networks that aggressively rewrite UDP source ports between packets — those need a TURN-style relay (Phase 3 roadmap). Field-validation matrix in progress; please file an issue with your environment if rendezvous fails.
  • Cloudflare-locked. Punch is built on Cloudflare-specific primitives — Workers, Durable Objects, hibernatable WebSockets, the alarm API. Running it elsewhere would be a rewrite. This is a deliberate trade-off: it makes the service free and globally distributed, but not portable.
  • IPv4 first. SRT rendezvous and the underlying UDP hole-punching mechanics are exercised on IPv4. IPv6 paths work but have less field validation in v1.0.
  • Free-tier scaling. The free Cloudflare Workers tier covers roughly 3,000 sessions per day. Sustained higher volumes need a paid Workers plan or a self-hosted deployment.
  • Operator URL = session-scoped admin token. The producer URL (/s/<session>?t=<token>) embeds the admin token. Anyone holding it can observe peer_match events and close the session. The token is bound to the single session and expires with its TTL — treat it like the SRT passphrase itself: send it through a private channel, do not paste it into shared chats. Per-peer scoped tokens with a separate join UI are on the roadmap (Phase 2/3); v1.0 ships with admin-scoped operator URLs and per-stream peer tokens via the API.

If any of these matter for your use case, open an issue — several are roadmap items waiting on a real-world driver.

Roadmap

Phase 1 — MVP

  • Session creation and peer discovery
  • WebSocket signalling with Durable Objects
  • Auto-generated FFmpeg/OBS/vMix commands
  • Web UI with QR code
  • Passphrase distribution

Phase 2 — Production grade

  • Multi-stream session bundles
  • Real-time health dashboard
  • Tally signalling
  • Latency recommendation engine

Phase 3 — Ecosystem

  • Formal protocol specification — see docs/spec/
  • Relay (TURN) fallback for symmetric NAT
  • CLI companion tool
  • Pre-flight network analysis

See docs/roadmap.md for the detailed phased plan.

Testing

Terminal window
npm test # Vitest under @cloudflare/vitest-pool-workers
npm run check # TypeScript type-check (no emit)

113 tests cover the HTTP and WebSocket surface end-to-end, session lifecycle, authentication, per-token stream-scope enforcement, rate limiting, CSP headers, and Turnstile verification.

Contributing

Punch is built by broadcast engineers, for broadcast engineers. Contributions welcome.

Licence

MIT — © 2026 The Thåst Collective