WebRTC API
Peer-to-peer communication, video streaming, and real-time data channels for interactive gaming experiences
Quick Navigation
Real-time Streaming
High-quality video and audio streaming with adaptive bitrate control
Quality Management
Dynamic quality adjustment based on network conditions and preferences
Data Channels
Low-latency data transmission for game inputs and control messages
Quick Start
Get started with Playcast WebRTC peer connections:
Create a Client Peer
import {
PlaycastPeerClient,
MakeClientPeerConfig
} from '@playcastdotio/Peer';
const config: MakeClientPeerConfig = {
realtimeApiManager: {
send: (message) => websocket.send(JSON.stringify(message))
},
iceServers: {
urls: ['stun:stun.l.google.com:19302'],
username: 'your_username',
credential: 'your_credential'
},
forceTurn: false,
additionalMetadata: {
isAppleDevice: false,
browserType: 'chrome',
version: '1.0.0'
}
};
const clientPeer = createClientPeer(config);
// Connect to host
clientPeer.connect('host-peer-id-123');
Create a Host Peer
import {
PlaycastPeerHost,
MakeHostPeerConfig
} from '@playcastdotio/Peer';
const config: MakeHostPeerConfig = {
realtimeApiManager: {
send: (message) => websocket.send(JSON.stringify(message))
},
iceServers: {
urls: ['stun:stun.l.google.com:19302'],
username: 'your_username',
credential: 'your_credential'
},
forceTurn: false,
validatorFunction: async (localPeer, remotePeer) => {
// Validate connection request
return true;
}
};
const hostPeer = createHostPeer(config);
Peer Types
Playcast supports different types of peer connections for various use cases.
Client peer that connects to a host for receiving video streams and sending input events.
Key Methods
connect(targetHostId: string)- Connect to a host peersendMessage(message)- Send message to hostclose(kickReason?)- Close connectionchangeQualityProfile(profile)- Change stream quality
Host peer that accepts client connections and streams video while receiving input events.
Key Methods
broadcastMessage(message)- Send message to all clientsaddTracksForAll(tracks)- Add media tracks for all clientssetDefaultTracks(tracks)- Set default media tracksupdateConfig(newConfig)- Update peer configuration
Specialized client for remote control scenarios with enhanced input handling.
Host peer optimized for remote control applications with low-latency input processing.
Connection Management
Managing peer connections, signaling, and connection states.
Connection States
| State | Description | Available Actions |
|---|---|---|
| signalling | Establishing WebRTC connection | Wait for connection or handle signaling messages |
| validating | Validating connection request | Accept or reject connection |
| connected | Active peer connection | Send messages, manage tracks, adjust quality |
| closed | Connection closed | Reconnect or clean up resources |
| refused | Connection rejected | Handle rejection, possibly retry |
Handling Connection Events
// Monitor connection status
clientPeer.status.subscribe((status) => {
switch (status.connectionState) {
case 'signalling':
console.log('Establishing connection...');
break;
case 'connected':
console.log('Connected successfully');
// Start sending input events
break;
case 'closed':
console.log('Connection closed:', status.kickReason);
// Handle reconnection logic
break;
case 'refused':
console.log('Connection refused');
break;
}
});
// Handle incoming messages
clientPeer.onMessage((message) => {
console.log('Received message:', message);
// Process game state updates, etc.
});
Signaling with PeerMessages
// Handle peer messages for signaling
clientPeer.handlePeerMessage({
type: 'offer',
peerId: 'remote-peer-id',
sdp: {
type: 'offer',
sdp: 'v=0\r\no=- ...'
}
});
// Send ICE candidates
clientPeer.handlePeerMessage({
type: 'ice-candidate',
peerId: 'remote-peer-id',
candidate: {
candidate: 'candidate:...',
sdpMLineIndex: 0,
sdpMid: 'video'
}
});
Quality Management
Dynamic quality adjustment based on network conditions, device capabilities, and user preferences.
Quality Profiles
| Profile | Resolution | Bitrate | FPS | Use Case |
|---|---|---|---|---|
| ultra | 1920x1080 | 8-12 Mbps | 60 | High-end gaming, minimal compression |
| high | 1920x1080 | 4-6 Mbps | 60 | Good quality gaming |
| medium | 1280x720 | 2-3 Mbps | 30 | Balanced quality and bandwidth |
| low | 854x480 | 1-1.5 Mbps | 30 | Limited bandwidth scenarios |
| potato | 640x360 | 0.5-1 Mbps | 15 | Very poor network conditions |
Changing Quality Profiles
// Change quality profile for client
clientPeer.changeQualityProfile('high');
// Set custom quality preset for specific channel
clientPeer.setQualityPreset('video', {
maxBitrate: 3000000, // 3 Mbps
maxFramerate: 30,
scaleResolutionDownBy: 1.5
});
// Apply preset group for multiple channels
const presetGroup = {
video: {
maxBitrate: 4000000,
maxFramerate: 60,
scaleResolutionDownBy: 1.0
},
audio: {
maxBitrate: 128000
}
};
clientPeer.setQualityPresetGroup(presetGroup);
Quality Monitoring
// Monitor quality preset changes
clientPeer.qualityPresetStore.subscribe((presetGroup) => {
console.log('Quality presets updated:', presetGroup);
// Update UI indicators
updateQualityIndicator(presetGroup.video.maxBitrate);
});
// Get current statistics
clientPeer.statistics.subscribe((stats) => {
if (stats) {
console.log('Current bitrate:', stats.bitrate);
console.log('Packet loss:', stats.packetLoss);
console.log('RTT:', stats.roundTripTime);
}
});
Media Tracks
Managing video and audio tracks for streaming and communication.
Track Management for Hosts
// Set default tracks for new connections
const defaultTracks = {
video: videoTrack,
audio: audioTrack,
screen: screenShareTrack
};
hostPeer.setDefaultTracks(defaultTracks);
// Add tracks for all connected clients
hostPeer.addTracksForAll({
webcam: webcamTrack
});
// Remove specific tracks from all clients
hostPeer.removeTracksForAll({
screen: null // Remove screen share
});
// Set new track set (replaces existing)
hostPeer.setTracksForAll({
video: newVideoTrack,
audio: newAudioTrack
});
Track Management for Remote Clients
// Add tracks to specific remote client
const remotePeer = hostPeer.remotePeers.get('client-id');
if (remotePeer) {
remotePeer.addTracks({
personalVideo: personalVideoTrack
});
// Set tracks (replaces existing)
remotePeer.setTracks({
video: videoTrack,
audio: audioTrack
});
// Remove specific tracks
remotePeer.removeTracks({
personalVideo: null
});
}
Track Events and Monitoring
// Monitor outgoing tracks (client)
clientPeer.outgoingTracks.subscribe((tracks) => {
console.log('Outgoing tracks:', Object.keys(tracks));
// Handle track changes
Object.entries(tracks).forEach(([name, track]) => {
if (track) {
console.log(`Track ${name} is active`);
}
});
});
// Monitor incoming tracks (client)
clientPeer.incomingTracks.subscribe((tracks) => {
console.log('Incoming tracks:', Object.keys(tracks));
// Attach tracks to video elements
Object.entries(tracks).forEach(([name, track]) => {
if (track && name === 'video') {
const videoElement = document.getElementById('game-video');
if (videoElement) {
videoElement.srcObject = new MediaStream([track]);
}
}
});
});
WebRTC Statistics
Monitor connection quality, bandwidth usage, and performance metrics.
Available Statistics
Monitoring Statistics
// Subscribe to statistics updates
clientPeer.statistics.subscribe((stats) => {
if (stats) {
// Display connection quality
updateConnectionQuality({
bitrate: `${(stats.bitrate / 1000000).toFixed(1)} Mbps`,
packetLoss: `${(stats.packetLoss * 100).toFixed(2)}%`,
latency: `${stats.roundTripTime}ms`,
fps: stats.frameRate,
resolution: `${stats.resolution.width}x${stats.resolution.height}`,
codec: stats.codecName
});
// Auto-adjust quality based on performance
if (stats.packetLoss > 0.05) {
// High packet loss, reduce quality
clientPeer.changeQualityProfile('low');
} else if (stats.packetLoss < 0.01 && stats.bitrate < 2000000) {
// Good conditions, can increase quality
clientPeer.changeQualityProfile('medium');
}
}
});
// Disable statistics collection to save resources
clientPeer.disableStats();
Statistics for Remote Peers
// Monitor statistics for all remote peers (host)
hostPeer.remotePeers.subscribe((remotePeers) => {
Object.entries(remotePeers).forEach(([peerId, peer]) => {
peer.statistics.subscribe((stats) => {
if (stats) {
console.log(`Client ${peerId} stats:`, {
bitrate: stats.bitrate,
latency: stats.roundTripTime,
quality: stats.resolution
});
// Handle poor performance
if (stats.roundTripTime > 200) {
console.warn(`High latency for client ${peerId}`);
// Maybe reduce quality or show warning
}
}
});
});
});
disableStats() when detailed metrics aren't needed, or adjust collection intervals for better performance.
Error Handling
Handling connection failures, network issues, and recovery strategies.
Common Error Scenarios
// Handle connection failures
clientPeer.status.subscribe((status) => {
if (status.connectionState === 'closed' && status.kickReason) {
switch (status.kickReason) {
case 'network-error':
// Network connectivity issues
showNetworkErrorMessage();
attemptReconnect();
break;
case 'host-disconnected':
// Host ended the session
showHostDisconnectedMessage();
redirectToLobby();
break;
case 'validation-failed':
// Connection was rejected
showValidationFailedMessage();
break;
case 'peer-timeout':
// Connection timed out
showTimeoutMessage();
attemptReconnect();
break;
default:
showGenericErrorMessage(status.kickReason);
}
}
});
// Implement reconnection logic
async function attemptReconnect() {
const maxRetries = 3;
let retryCount = 0;
while (retryCount < maxRetries) {
try {
await clientPeer.connect(hostId);
console.log('Reconnection successful');
break;
} catch (error) {
retryCount++;
console.log(`Reconnection attempt ${retryCount} failed:`, error);
if (retryCount < maxRetries) {
// Wait before retrying
await new Promise(resolve => setTimeout(resolve, 2000 * retryCount));
}
}
}
if (retryCount === maxRetries) {
showReconnectionFailedMessage();
}
}