Skip to content

roman01la/ripley

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shitalks

A Riverside-style video calling app with local high-quality recording, cloud upload, and server-side demuxing into playable MKV files.

Live demo: https://shitalks-worker.roman01la.workers.dev

What it does

  • Live video calls between two participants via Cloudflare Realtime SFU
  • High-quality local recording using WebCodecs (VP9/H.264 + Opus) — independent of the live stream
  • Reliable upload with crash recovery — pending epochs survive page reload via OPFS + localStorage manifest
  • Server-side demux in Cloudflare Containers (Rust + ffmpeg) → playable MKV per participant
  • Multi-cam timeline generated as Final Cut Pro XML for editing

Stack

Layer Tech
Frontend Vue 3, Vite, TypeScript
Backend Cloudflare Workers + Durable Objects
WebRTC Cloudflare Realtime SFU
Recording WebCodecs (VideoEncoder/AudioEncoder) → OPFS
Storage Cloudflare R2
Demux Cloudflare Containers (Rust + ffmpeg)
Auth HMAC-SHA256 short-lived tokens

How it works

Browser                                  Cloudflare
┌─────────────────────────────┐         ┌──────────────────────┐
│ Camera/Mic                  │         │  Realtime SFU        │
│   ↓                         │  WebRTC │                      │
│ Capture → LiveScaler ───────┼────────▶│  Forwards tracks     │
│                             │         │                      │
│   ↓                         │   WS    │  RoomDO              │
│ ABR (1080p reactive)        │◀────────│  - Signaling         │
│                             │         │  - Token issuance    │
│                             │         │  - Demux orchestration│
│ Recorder (WebCodecs)        │         │                      │
│   ↓                         │         │  R2 Bucket           │
│ OPFS epochs (every 2s) ─────┼─PUT────▶│  recordings/         │
│   ↓                         │         │    {room}/{p}/{src}/ │
│ Upload manifest             │         │      epoch-NNNN.bin  │
│  (localStorage)             │         │                      │
│                             │         │  DemuxContainer      │
│                             │         │  (Rust + ffmpeg)     │
│                             │         │   ↓                  │
│                             │         │  demuxed/*.mkv       │
│                             │         │  + timeline.fcpxml   │
└─────────────────────────────┘         └──────────────────────┘

Key behaviors

  • ABR is reactive, not proactive — starts at 1080p and lets WebRTC's congestion controller handle bitrate. Only drops resolution after sustained congestion. Mirrors how Google Meet/Zoom work.
  • Recording is independent of live stream — captures at full camera resolution regardless of ABR rung.
  • Crash recovery — every epoch is recorded to a localStorage manifest before upload. On reload, orphaned epochs in OPFS are re-enqueued.
  • Token refresh on 401 — auth tokens auto-refresh when they expire mid-upload.
  • Server validates epoch completeness — demux only triggers when all expected epochs exist in R2.

Run locally

npm install

You need:

  • Node 20.19+ or 22.12+
  • Docker Desktop running (for the demux container)
  • A .dev.vars file with CALLS_APP_ID, CALLS_APP_SECRET, and optionally TURN_SERVICE_ID / TURN_SERVICE_TOKEN

Start the dev servers (two terminals):

# Terminal 1 — Vite frontend (port 5173)
npm run dev

# Terminal 2 — Wrangler backend (port 8787)
npx wrangler dev

Open http://localhost:8787 — the backend serves the frontend assets and proxies API/WS routes to the Durable Object.

For testing without Docker:

npx wrangler dev --enable-containers=false

(Uploads work, demux is disabled — use node demux-recording.mjs for local demuxing.)

Test

npm test              # 177 unit tests
npm run type-check    # vue-tsc

End-to-end test procedure: tests/e2e-call-test.md

Local demux from R2:

node demux-recording.mjs <dir>           # demux a directory of epoch-*.bin files
node demux-recording.mjs --opfs          # pull from browser OPFS via CDP

Deploy

npm run deploy

Builds the frontend, deploys the worker, and pushes the demux container image to Cloudflare's registry.

Project layout

src/
  app/                 Vue 3 frontend
    views/             LobbyView, CallStageView, DownloadView
    components/        VideoTile, CallControls, DebugPanel
    composables/       useRoom, useCapture, useDebugStats
  lib/                 Core controllers (framework-agnostic)
    room/              RoomController — WebRTC + signaling
    capture/           CaptureController — camera/mic/screen
    live/              AbrController — adaptive bitrate
    recorder/          WebCodecs recording, OPFS, crash recovery
    uploader/          UploaderController, TokenBucket, manifest
    sync/              SyncController — NTP-style clock alignment
    audio/             AudioProcessor
  worker/              Cloudflare Worker backend
    index.ts           HTTP router, CORS, auth gate
    room.ts            RoomDO Durable Object
    sfu.ts             Cloudflare Realtime SFU client
    upload.ts          Epoch upload handlers
    download.ts        MKV/FCPXML download
    mux.ts             Server-side demux handlers
    fcpxml.ts          Final Cut Pro XML builder
    auth.ts            HMAC token signing/verification
    demux-container.ts DemuxContainer config
  worker/container/    Rust demux server (Dockerfile + Cargo)
demux-recording.mjs    Local demux CLI (Node)
tests/                 E2E test docs

Notes

  • Recording duration is limited only by browser OPFS quota (~half of free disk space).
  • Demux runs in a Cloudflare Container with 15-minute idle timeout.
  • Recordings auto-delete after 7 days.
  • Max participants per room: 20.
  • Max upload payload: 50 MB per epoch.
  • WebSocket message size limit: 64 KB.

About

Riverside-style video calling app with local high-quality recording, cloud upload, and server-side demuxing into playable MKV files

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors