WebRTC
Set up VidMeet video calling — ICE servers, and Cloudflare TURN for production.
VidMeet is GKSPHONE's video calling. Everything below is the Cfg.VidMeet block in gksphone/config/serverconfig.lua.
Cfg.VidMeet = {
Enabled = true,
IceServer = "manual", -- "manual" | "cloudflare"
Cloudflare = {
TokenID = "",
ApiToken = "",
TTL = 3600 -- credential lifetime in seconds
},
ManualIceServers = {
{ urls = "stun:stun.cloudflare.com:3478" },
{ urls = "stun:stun.l.google.com:19302" },
-- ...
}
}| Key | Default | Does |
|---|---|---|
Enabled | true | Turns video calling on or off entirely |
IceServer | "manual" | Which mode to use |
Cloudflare.TokenID | "" | Turn Token ID from the Cloudflare dashboard |
Cloudflare.ApiToken | "" | API token, needs Calls Edit permission |
Cloudflare.TTL | 3600 | How long generated credentials stay valid |
ManualIceServers | 5 STUN servers | RTCIceServer[] used in manual mode |
Which mode?
manual | cloudflare | |
|---|---|---|
| Setup | none | Cloudflare account + tokens |
| Relay | STUN only unless you add your own TURN | TURN on Cloudflare's global network |
| Cost | free | pay-as-you-go |
| Good for | development, small servers | production |
STUN alone fails for roughly one connection in five — mobile data (CGNAT), corporate firewalls and some VPNs all block direct peer-to-peer. A TURN relay fixes those. Add your own to ManualIceServers:
ManualIceServers = {
{ urls = "stun:stun.l.google.com:19302" },
{ urls = "turn:turn.yourdomain.com:3478", username = "user", credential = "secret" },
{ urls = "turns:turn.yourdomain.com:5349", username = "user", credential = "secret" },
}turns: is TLS on port 5349 and is required on HTTPS pages.
Cloudflare TURN
Create a TURN Server app
At dash.cloudflare.com, go to Media → Realtime → TURN Server and click Create a TURN Server app. Name it anything, e.g. gksphone-vidmeet.
Copy both values
The next page shows the Turn Token ID and a 64-character API Token.
The API token is shown once. Copy it before leaving the page — Cloudflare cannot show it again.
Fill in serverconfig.lua
Cfg.VidMeet = {
Enabled = true,
IceServer = "cloudflare",
Cloudflare = {
TokenID = "your-turn-token-id",
ApiToken = "your-api-token",
TTL = 3600
},
-- ManualIceServers is ignored in cloudflare mode
}Restart and test a call
Watch the server console for Cloudflare API errors.
TTL
Fresh credentials are generated per call, so the window only needs to outlast one session.
| Value | ||
|---|---|---|
3600 | 1 hour | Default. Comfortable for a ~30 minute call |
86400 | 24 hours | Longer than needed, wider exposure if intercepted |
604800 | 7 days | Debugging only |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Calls connect then drop | NAT traversal failing | Add TURN, or switch to cloudflare mode |
Cloudflare API error 403 | Wrong ApiToken, or it lacks permission | Recreate the token with Calls Edit |
Cloudflare API error 404 | Wrong TokenID | Recheck it under Media → Realtime → TURN Server |
| Works locally, not in production | Firewall blocking UDP | Open UDP 3478, or use turns: on TCP 5349 |
| High latency for some players | STUN only | Enable TURN |

