WebRTC/WHEP replaces the JPEG-over-WebSocket frame streaming from ARCADE2.
| ARCADE2 | ARCADE3-WHEP | |
|---|---|---|
| Video path | page.screenshot() JPEG → base64 → WS → <m-image> swap |
ffmpeg rawvideo → wrtc RTCVideoSource → WebRTC → <m-video> |
| Audio path | ffmpeg Opus chunks → base64 → WS → MediaSource JS buffer | ffmpeg PCM → RTCAudioSource → WebRTC (same peer connection) |
| Transport | TCP WebSocket | UDP WebRTC |
| Latency | ~200–500ms | ~30–80ms |
| Screen flicker | Yes (image element swap per frame) | No (native video texture) |
| Input path | WS → server → Puppeteer (unchanged) | Same |
Player presses E
→ cabinet opens WebSocket to /input?rom=...&session=SESSION_ID
→ server spawns Puppeteer + ffmpeg video + ffmpeg audio
→ server replies { type: "session_ready", whepUrl: "whep://server/stream/SESSION_ID" }
→ cabinet sets <m-video src="whep://...">
→ MML client POSTs SDP offer to https://server/stream/SESSION_ID
→ server feeds offer into RTCPeerConnection, returns SDP answer (201)
→ WebRTC handshake completes over UDP
→ video+audio stream appears on cabinet screen in ~1-2s
→ gamepad inputs flow: Gamepad API → WS → Puppeteer keyboard (unchanged)
| File | Purpose |
|---|---|
server-whep.js |
Main server — Puppeteer + ffmpeg + wrtc + WHEP endpoint + MML doc server |
arcade-wario-whep.html |
MML cabinet — <m-video> instead of <m-image> swap |
Dockerfile |
Chromium + ffmpeg + PulseAudio + wrtc deps |
start.sh |
Boots Xvfb + PulseAudio + Node |
default.pa |
PulseAudio virtual sink config |
package.json |
Adds @roamhq/wrtc to deps |
Dockerfile → builds automaticallyarcade3-production.up.railway.app)arcade-wario-whep.html update:
var SNES_SERVER_WS = "wss://arcade3-production.up.railway.app";
MML uses whep:// protocol which it converts to https:// for the SDP POST:
<m-video src="whep://arcade3-production.up.railway.app/stream/SESSION_ID">
becomes:
POST https://arcade3-production.up.railway.app/stream/SESSION_ID
Content-Type: application/sdp
Body: [SDP offer]
Response: 201 Created + SDP answer → WebRTC connected.
@roamhq/wrtc ships prebuilt binaries for Linux x64 — Railway’s default environment.
No compilation needed. It just works with npm install.
Each player who presses E gets their own:
This is the same model as ARCADE2. Railway’s free tier handles ~2-3 concurrent sessions. Upgrade to a paid Railway plan for more concurrent players.