@colyseus/webrtc
v1.0.0
Published
WebRTC Signaling Server for Colyseus and Client Tools
Readme
@colyseus/webrtc
A signaling server utility for establishing WebRTC peer-to-peer connections through Colyseus rooms. Use it to add audio/video communication between clients.
This package handles signaling only — the exchange of SDP offers/answers and ICE candidates needed to establish WebRTC connections. It does not provide state synchronization over peer-to-peer; Colyseus state sync continues to work through the server as usual.
This package provides two entry points:
| Import | Environment | Purpose |
|---|---|---|
| @colyseus/webrtc | Server | Room message handlers for WebRTC signaling |
| @colyseus/webrtc/client | Browser | WebRTCClient that consumes signaling and manages peer connections |
Installation
npm install @colyseus/webrtcServer-side usage
Spread the signaling object into your room's messages to add all the WebRTC signaling handlers. Call onPeerDisconnected from onLeave so peers are notified when someone disconnects.
import { Room, Client } from "colyseus";
import { signaling, onPeerDisconnected } from "@colyseus/webrtc";
class VideoRoom extends Room {
messages = { ...signaling };
onLeave(client: Client) {
onPeerDisconnected(this, client);
}
}You can mix your own message handlers alongside signaling:
class VideoRoom extends Room {
messages = {
...signaling,
chat(client: Client, message: string) {
this.broadcast("chat", `${client.sessionId}: ${message}`);
},
};
}Signaling messages handled
| Message | Direction | Description |
|---|---|---|
| webrtc:join | client -> server | Client signals readiness; server replies with peer list and broadcasts to others |
| webrtc:offer | client -> server -> client | Relay SDP offer to the target peer |
| webrtc:answer | client -> server -> client | Relay SDP answer to the target peer |
| webrtc:ice-candidate | client -> server -> client | Relay ICE candidate to the target peer |
| webrtc:peers | server -> client | List of existing peer session IDs (sent on join) |
| webrtc:peer-joined | server -> client | A new peer has joined |
| webrtc:peer-left | server -> client | A peer has left |
Client-side usage
import { Client } from "@colyseus/sdk";
import { WebRTCClient } from "@colyseus/webrtc/client";
const client = new Client("ws://localhost:2567");
const room = await client.joinOrCreate("video");
const webrtc = new WebRTCClient(room);
webrtc.onLocalStream = (stream) => {
// Attach to a <video> element for self-preview
localVideo.srcObject = stream;
};
webrtc.onPeerConnected = (peerId, stream) => {
// Attach remote stream to a <video> element
};
webrtc.onPeerDisconnected = (peerId) => {
// Remove the peer's video element
};
// Request camera/mic and start signaling
await webrtc.join({ audio: true, video: true });
// Later, to stop and clean up:
webrtc.leave();
room.leave();WebRTCClient API
Constructor
new WebRTCClient(room, options?)room— Any object withsend(type, message)andonMessage(type, callback)(e.g. a ColyseusRoominstance).options.iceServers— Custom ICE servers. Defaults to Google STUN servers.
Methods
| Method | Description |
|---|---|
| join(constraints?) | Request user media with the given MediaStreamConstraints and start signaling. Defaults to { audio: true, video: true }. |
| leave() | Close all peer connections, stop local tracks, and unbind signaling listeners. |
Callbacks
| Callback | Signature | Description |
|---|---|---|
| onLocalStream | (stream: MediaStream) => void | Fired after getUserMedia succeeds |
| onPeerConnected | (peerId: string, stream: MediaStream) => void | Fired when a remote peer's media stream is received |
| onPeerDisconnected | (peerId: string) => void | Fired when a peer connection closes |
Properties
| Property | Type | Description |
|---|---|---|
| localStream | MediaStream \| null | The local media stream |
| peers | Map<string, RTCPeerConnection> | Active peer connections keyed by session ID |
| streams | Map<string, MediaStream> | Remote media streams keyed by session ID |
Running the example
The example/ directory contains a full working demo with a Colyseus server and a React client.
cd example
npm install
npm run devThis starts two processes concurrently:
- Server on
ws://localhost:2567(Colyseus + WebSocket transport) - Client on
http://localhost:3000(Vite + React)
Open http://localhost:3000 in two browser tabs (or two devices on the same network) to test video calling. The browser will ask for camera/microphone permissions.
How it works
Client A Server Client B
| | |
|--- webrtc:join ---------->| |
|<-- webrtc:peers [] | |
| | |
| |<-------- webrtc:join ------|
| |--------- webrtc:peers [A]->|
|<-- webrtc:peer-joined B --| |
| | |
| |<------ webrtc:offer (A) ---|
|<-- webrtc:offer (B) ------| |
| | |
|--- webrtc:answer (B) ---->| |
| |------- webrtc:answer (A)-->|
| | |
|<-------- ICE candidates exchanged via server --------->|
| | |
|<=============== peer-to-peer audio/video ==============>|License
MIT
