🌐 WAN Live Session
Same realtime co-editing as LAN Live, but across the internet. WebRTC carries the data with DTLS encryption. A tiny Cloudflare Worker handles the introduction (rendezvous), then the peers talk directly - the Worker never sees your MIDI traffic. Up to 8 joiners per session.
Two screen captures from a real WAN session over the internet. Same ~200 ms tick rate as LAN, plus the round-trip latency of your link.
The Cloudflare Worker is just a 5-minute-TTL mailbox - it sees the SDPs but never your MIDI traffic. Want full quota / a custom domain / your own logs? Self-host the Cloudflare rendezvous →
When to use it
WAN Live is for everyone not on the same LAN: remote bandmate, friend in another city, classroom-from-home. Up to 8 joiners per session (host + 7 others). The same diff/apply pipeline as LAN, so the editing experience is identical - just routed through a Cloudflare Worker for the initial handshake and then peer-to-peer over DTLS-encrypted WebRTC.
For users on the same network, prefer LAN Live Session - same UX, no internet involved, lowest possible latency.
Quick start
- Host opens a MIDI file, picks Collab → Start WAN Live Session….
- A 4-character code appears. Click Copy invite to grab a paste-ready message.
- Each joiner picks Collab → Join WAN Live Session… and types the code.
- ~5-10 s of ICE / DTLS handshake, then everyone is
connected. Status bar shows
LIVE [Online] · N peer(s).
Connection Test
Open Settings → Collaboration → Test connection before starting a real session. The test runs in three stages:
- Pre-flight ping -
GET /healthagainst your configured rendezvous URL. 5-second timeout. Surfaces unreachable servers / firewall blocks within seconds. - Rendezvous round-trip - posts a session, receives a code, the in-process "peer" verifies the code, posts an offer, the "host" reads it.
- WebRTC loopback - both transports run inside this same process, do an ICE / DTLS handshake against each other via local host candidates, then send a single ping/pong frame.
The result is one of four buckets:
Connection looks great
Rendezvous fast, handshake clean. Real WAN sessions will work.
Connection works, slower than expected
Successful but rendezvous or handshake took longer than 3 s. Real sessions still work; consider raising ICE timeout if your network is consistently slow.
Test inconclusive
Rendezvous worked but the WebRTC loopback didn't. Most often this is NAT hairpinning - some routers don't loop their own public IP back to themselves. Real two-PC sessions usually still work. Verify by hosting on one PC and joining from another.
Connection failed
Either the rendezvous is unreachable (URL wrong, firewall block, DNS) or the WebRTC stack couldn't bind locally. The dialog includes a specific failure stage and reason - usually the firewall, see below.
The test is non-destructive and can be re-run any time you change network settings. With Collab disabled, the button stays clickable so you can verify your setup before opting in.
ICE, STUN, gathering timeout
WebRTC needs to discover candidate IP/port pairs that two peers can use to reach each other. That's ICE (Interactive Connectivity Establishment), and it relies on a STUN server to learn each peer's public IP. MidiEditor ships with a default list of free public STUN endpoints (Google's). For 95% of home / office connections that's all you need.
The ICE timeout setting (default 8 s) caps how long gathering can take before MidiEditor publishes the SDP with whichever candidates it has. Slow / blocked STUN endpoints can stall gathering otherwise; raising this to 12-15 s may help on flaky connections.
TURN servers (which actually relay traffic when peer-to-peer fails) are not in the bundled list. They cost real bandwidth and we don't pay for one by default. Symmetric NATs (rare on home networks, common on some mobile carriers and VPNs) require a TURN; you can run your own (e.g. Coturn) and add the URL to the rendezvous configuration. See Adding a TURN server.
Auto-reconnect
When enabled (off by default), a transport failure during a Live Session triggers an automatic re-handshake on the same code, up to Max retry attempts times. Useful for transient flaps - Wi-Fi roam, brief ISP hiccup. Doesn't help when the host restarts and gets a new code; in that case the joiner has to re-enter the new code manually.
A dropped peer never affects the others - reconnection is per-peer. A failed retry on one joiner doesn't kick everyone else.
Rendezvous
The Cloudflare Worker is a tiny key-value mailbox. Each session is one short-lived record (5-minute TTL). Joiners post their offer SDPs to the Worker; the host polls a list of pending offers and replies with an answer SDP per joiner. Once both sides have each other's SDP, ICE finds a path between them and DTLS handshakes peer-to-peer - the Worker isn't in the path anymore.
The default URL ships with the build and is shared across all users. For heavier use, custom domains, or full uptime control, deploy your own - see Self-host the Cloudflare rendezvous. Setup takes about five minutes and the free tier covers ~100k sessions/day.
Recovery scenarios
- Code expired (5-minute TTL) - the rendezvous returns 404 and the join dialog reports "code not found". Host generates a fresh one.
- Host restarted - the new code is different from the old. Joiner's auto-reconnect tries the old code (because we can't re-prompt the user), fails, and the user has to re-enter the new code manually. A documented asymmetry; the alternative was promiscuous code reuse and we picked safety over convenience.
- NAT changed mid-session (e.g. router rebooted, VPN toggled) - ICE re-gathers candidates and tries to recover. May drop briefly. Auto-reconnect catches this if enabled.
- 16 MiB-frame edit - a single sync hunk exceeded the WebRTC max-message-size cap (e.g. inserting hundreds of measures into a dense file in one action). The status bar shows "Live sync paused - last edit was too large to send". Save and split the change into smaller steps; the status clears on the next normal sync tick.
Troubleshooting
"Connection works in browser but not in MidiEditor"
The classic silent firewall block: the rendezvous URL opens fine in a
browser (or returns JSON via PowerShell Invoke-WebRequest), but the
Connection Test inside MidiEditor times out after 5 s with no specific error.
On Windows this almost always means the OS firewall is silently dropping
outbound HTTPS from the app without showing the usual "allow this app to
access network" prompt.
Fix on Windows:
- Windows Security → Firewall & network protection → "Allow an app through firewall"
- Click Change settings, then Allow another app…
- Browse to
MidiEditorAI.exe(where you installed the app) - Add it, then check both Private and Public boxes
Fix when third-party antivirus is involved (Bitdefender, Norton,
Kaspersky, McAfee, ESET, etc.): each AV has its own "Application Control" or
firewall list. Add an exception for MidiEditorAI.exe there as
well. AV-side blocks often happen without any visible prompt because
the AV's "trusted apps" filter only allows signed / well-known executables by
default.
Future MidiEditor releases may be code-signed, which usually eliminates the silent-block behaviour on Windows. For unsigned development builds, the firewall exception is a one-time setup.
Other common errors
"Couldn't reach rendezvous" / Connection Test reports health failed:
- Open the URL in a browser. JSON response = rendezvous works → likely the firewall block above.
- 404 / 5xx in the browser = rendezvous URL is wrong or Worker isn't deployed. Check Settings → Collaboration → Rendezvous URL and re-deploy your Worker if you self-host.
- DNS not resolving = corporate / hotel network DNS filter. Try a phone hotspot to confirm.
"ICE failed" / handshake never completes:
- Both sides on symmetric NAT (rare on home networks, common on some mobile carriers / corporate VPNs). Solution: configure a TURN server - see Adding a TURN server.
- One side blocks UDP entirely. Test with phone hotspot to verify.
- Try Connection Test on both ends - if both report "Inconclusive", NAT hairpinning is the issue, real two-PC sessions usually still work.
"Connected but no edits flow":
- Check the review-mode toggle in the Collab menu - if on, incoming hunks queue for manual approval instead of applying.
- The two peers might be on different files / different sessionIds. Open Collab History tab on both and confirm the head hash matches.
- Status bar shows "Live sync paused - last edit was too large"? Save and split the change - one frame can't exceed 16 MiB.
"This code has already been used" / 409 from rendezvous:
- Security feature - the worker refuses to overwrite an existing joiner-offer slot. This blocks MITM scanners that would race to claim a code's answer slot ahead of a legitimate joiner. The collision is also caught when two joiners pick the same random ID by accident, which is astronomically rare. Solution: the joiner re-runs Join WAN Live Session - a fresh joinerId is generated each time.
"Session is full" / 503 from rendezvous:
- Soft cap of 8 peers per session (Phase 9.8). Wait for an existing peer to leave, or start a new session.
Connection Test "Inconclusive":
- The in-process WebRTC loopback failed but rendezvous worked. Most common cause: NAT hairpinning - some routers don't loopback their own public IP. Real WAN sessions take a different network path so they usually still work. Verify by hosting on one PC and joining from another.