cloudflare
references/realtime-sfu/configuration.md
.md 138 lines
Content
# Configuration & Deployment
## Dashboard Setup
1. Navigate to https://dash.cloudflare.com/?to=/:account/calls
2. Click "Create Application" (or use existing app)
3. Copy `CALLS_APP_ID` from dashboard
4. Generate and copy `CALLS_APP_SECRET` (treat as sensitive credential)
5. Use credentials in Wrangler config or environment variables below
## Dependencies
**Backend (Workers):** Built-in fetch API, no additional packages required
**Client (PartyTracks):**
```bash
npm install partytracks @cloudflare/calls
```
**Client (React + PartyTracks):**
```bash
npm install partytracks @cloudflare/calls observable-hooks
# Observable hooks: useObservableAsValue, useValueAsObservable
```
**Client (Raw API):** Native browser WebRTC API only
## Wrangler Setup
```jsonc
{
"name": "my-calls-app",
"main": "src/index.ts",
"compatibility_date": "2025-01-01", // Use current date for new projects
"vars": {
"CALLS_APP_ID": "your-app-id",
"MAX_WEBCAM_BITRATE": "1200000",
"MAX_WEBCAM_FRAMERATE": "24",
"MAX_WEBCAM_QUALITY_LEVEL": "1080"
},
// Set secret: wrangler secret put CALLS_APP_SECRET
"durable_objects": {
"bindings": [
{
"name": "ROOM",
"class_name": "Room"
}
]
}
}
```
## Deploy
```bash
wrangler login
wrangler secret put CALLS_APP_SECRET
wrangler deploy
```
## Environment Variables
**Required:**
- `CALLS_APP_ID`: From dashboard
- `CALLS_APP_SECRET`: From dashboard (secret)
**Optional:**
- `MAX_WEBCAM_BITRATE` (default: 1200000)
- `MAX_WEBCAM_FRAMERATE` (default: 24)
- `MAX_WEBCAM_QUALITY_LEVEL` (default: 1080)
- `TURN_SERVICE_ID`: TURN service
- `TURN_SERVICE_TOKEN`: TURN auth (secret)
## TURN Configuration
```javascript
const pc = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.cloudflare.com:3478' },
{
urls: [
'turn:turn.cloudflare.com:3478?transport=udp',
'turn:turn.cloudflare.com:3478?transport=tcp',
'turns:turn.cloudflare.com:5349?transport=tcp'
],
username: turnUsername,
credential: turnCredential
}
],
bundlePolicy: 'max-bundle', // Recommended: reduces overhead
iceTransportPolicy: 'all' // Use 'relay' to force TURN (testing only)
});
```
**Ports:** 3478 (UDP/TCP), 53 (UDP), 80 (TCP), 443 (TLS), 5349 (TLS)
**When to use TURN:** Required for restrictive corporate firewalls/networks that block UDP. ~5-10% of connections fallback to TURN. STUN works for most users.
**ICE candidate filtering:** Cloudflare handles candidate filtering automatically. No need to manually filter candidates.
## Durable Object Boilerplate
Minimal presence system:
```typescript
export class Room {
private sessions = new Map<string, {userId: string, tracks: string[]}>();
async fetch(req: Request) {
const {pathname} = new URL(req.url);
const body = await req.json();
if (pathname === '/join') {
this.sessions.set(body.sessionId, {userId: body.userId, tracks: []});
return Response.json({participants: this.sessions.size});
}
if (pathname === '/publish') {
this.sessions.get(body.sessionId)?.tracks.push(...body.tracks);
// Broadcast to others via WebSocket (not shown)
return new Response('OK');
}
return new Response('Not found', {status: 404});
}
}
```
## Environment Validation
Check credentials before first API call:
```typescript
if (!env.CALLS_APP_ID || !env.CALLS_APP_SECRET) {
throw new Error('CALLS_APP_ID and CALLS_APP_SECRET required');
}
```