Simple one-to-one WebRTC video/voice and data channels
—
Access connection details, statistics, peer addressing information, and real-time connection state monitoring for WebRTC peer connections.
Access real-time connection state and buffering information.
/**
* Whether the peer connection and data channel are ready to use
*/
peer.connected: boolean;
/**
* Amount of data buffered in the data channel (bytes)
*/
peer.bufferSize: number;
/**
* Whether the peer has been destroyed and cleaned up
*/
peer.destroyed: boolean;Usage Examples:
const peer = new Peer({ initiator: true });
// Check connection state
if (peer.connected) {
peer.send('Hello!');
} else {
console.log('Peer not connected yet');
}
// Monitor buffer size
function checkBuffer() {
console.log('Buffer size:', peer.bufferSize, 'bytes');
if (peer.bufferSize > 32768) { // 32KB
console.warn('Buffer getting full - consider waiting');
}
}
setInterval(checkBuffer, 1000);
// Check if peer is destroyed
if (peer.destroyed) {
console.log('Peer has been destroyed');
} else {
// Safe to use peer
peer.send('Data');
}Access local and remote peer addressing details after connection establishment.
/**
* Local peer's IP address (available after connection)
*/
peer.localAddress: string;
/**
* Local peer's port number (available after connection)
*/
peer.localPort: number;
/**
* Local peer's IP family ('IPv4' or 'IPv6')
*/
peer.localFamily: string;
/**
* Remote peer's IP address (available after connection)
*/
peer.remoteAddress: string;
/**
* Remote peer's port number (available after connection)
*/
peer.remotePort: number;
/**
* Remote peer's IP family ('IPv4' or 'IPv6')
*/
peer.remoteFamily: string;
/**
* Get local address information as an object
* @returns Address information object
*/
peer.address(): AddressInfo;
interface AddressInfo {
address: string;
family: string;
port: number;
}Usage Examples:
const peer = new Peer({ initiator: true });
peer.on('connect', () => {
// Access address information
console.log('Local address:', peer.localAddress, ':', peer.localPort);
console.log('Local family:', peer.localFamily);
console.log('Remote address:', peer.remoteAddress, ':', peer.remotePort);
console.log('Remote family:', peer.remoteFamily);
// Get structured address info
const addressInfo = peer.address();
console.log('Address info:', addressInfo);
// { address: '192.168.1.100', family: 'IPv4', port: 54321 }
});
// Log connection details
function logConnectionInfo(peer) {
console.log('Connection Info:');
console.log(' Local:', `${peer.localFamily} ${peer.localAddress}:${peer.localPort}`);
console.log(' Remote:', `${peer.remoteFamily} ${peer.remoteAddress}:${peer.remotePort}`);
console.log(' Connected:', peer.connected);
console.log(' Buffer size:', peer.bufferSize, 'bytes');
}Retrieve detailed WebRTC connection statistics for monitoring and debugging.
/**
* Get connection statistics
* @param callback - Callback function receiving error and stats array
*/
peer.getStats(callback: (err: Error | null, stats: RTCStatsReport[]) => void): void;
interface RTCStatsReport {
id: string;
type: string;
timestamp: number;
[key: string]: any;
}Usage Examples:
const peer = new Peer({ initiator: true });
peer.on('connect', () => {
// Get basic stats
peer.getStats((err, reports) => {
if (err) {
console.error('Failed to get stats:', err);
return;
}
console.log('Stats reports:', reports.length);
reports.forEach(report => {
console.log('Report type:', report.type, 'ID:', report.id);
});
});
// Monitor stats periodically
setInterval(() => {
peer.getStats((err, reports) => {
if (err) return;
// Find candidate pair stats
const candidatePairs = reports.filter(r => r.type === 'candidate-pair');
candidatePairs.forEach(pair => {
if (pair.nominated) {
console.log('Active connection:');
console.log(' Bytes sent:', pair.bytesSent);
console.log(' Bytes received:', pair.bytesReceived);
console.log(' Round trip time:', pair.currentRoundTripTime, 'ms');
}
});
// Find data channel stats
const dataChannels = reports.filter(r => r.type === 'data-channel');
dataChannels.forEach(dc => {
console.log('Data channel:');
console.log(' Messages sent:', dc.messagesSent);
console.log(' Messages received:', dc.messagesReceived);
console.log(' Bytes sent:', dc.bytesSent);
console.log(' Bytes received:', dc.bytesReceived);
});
});
}, 5000);
});Monitor connection state changes and ICE gathering progress.
// ICE connection state changes
peer.on('iceStateChange', (iceConnectionState: string, iceGatheringState: string) => void);
// WebRTC signaling state changes
peer.on('signalingStateChange', (signalingState: string) => void);
// ICE gathering timeout
peer.on('iceTimeout', () => void);
// Negotiation completed
peer.on('negotiated', () => void);Usage Examples:
const peer = new Peer({ initiator: true });
// Monitor ICE state
peer.on('iceStateChange', (iceConnectionState, iceGatheringState) => {
console.log('ICE Connection State:', iceConnectionState);
console.log('ICE Gathering State:', iceGatheringState);
switch (iceConnectionState) {
case 'new':
console.log('ICE connection starting');
break;
case 'checking':
console.log('ICE connection checking connectivity');
break;
case 'connected':
console.log('ICE connection established');
break;
case 'completed':
console.log('ICE connection completed');
break;
case 'failed':
console.log('ICE connection failed - check network/firewall');
break;
case 'disconnected':
console.log('ICE connection temporarily disconnected');
break;
case 'closed':
console.log('ICE connection closed');
break;
}
});
// Monitor signaling state
peer.on('signalingStateChange', signalingState => {
console.log('Signaling State:', signalingState);
switch (signalingState) {
case 'stable':
console.log('No ongoing exchange - ready for new negotiation');
break;
case 'have-local-offer':
console.log('Local offer has been applied');
break;
case 'have-remote-offer':
console.log('Remote offer has been applied');
break;
case 'have-local-pranswer':
console.log('Local provisional answer applied');
break;
case 'have-remote-pranswer':
console.log('Remote provisional answer applied');
break;
case 'closed':
console.log('Connection closed');
break;
}
});
// Handle ICE timeout
peer.on('iceTimeout', () => {
console.warn('ICE gathering timed out - connection may be slower');
});
// Handle negotiation completion
peer.on('negotiated', () => {
console.log('Peer connection negotiation completed successfully');
});Utility functions for comprehensive connection monitoring and diagnostics.
Usage Examples:
// Comprehensive connection monitor
class PeerMonitor {
constructor(peer) {
this.peer = peer;
this.startTime = Date.now();
this.setupMonitoring();
}
setupMonitoring() {
// Log all state changes
this.peer.on('iceStateChange', (ice, gathering) => {
console.log(`[${this.getElapsed()}] ICE: ${ice}, Gathering: ${gathering}`);
});
this.peer.on('signalingStateChange', state => {
console.log(`[${this.getElapsed()}] Signaling: ${state}`);
});
this.peer.on('connect', () => {
console.log(`[${this.getElapsed()}] Connected!`);
this.logConnectionInfo();
this.startStatsMonitoring();
});
this.peer.on('error', err => {
console.error(`[${this.getElapsed()}] Error: ${err.code} - ${err.message}`);
});
}
getElapsed() {
return `${((Date.now() - this.startTime) / 1000).toFixed(1)}s`;
}
logConnectionInfo() {
const peer = this.peer;
console.log('Connection established:');
console.log(` Local: ${peer.localFamily} ${peer.localAddress}:${peer.localPort}`);
console.log(` Remote: ${peer.remoteFamily} ${peer.remoteAddress}:${peer.remotePort}`);
}
startStatsMonitoring() {
this.statsInterval = setInterval(() => {
this.peer.getStats((err, reports) => {
if (err) return;
const stats = this.extractKeyStats(reports);
console.log(`[${this.getElapsed()}] Stats:`, stats);
});
}, 10000); // Every 10 seconds
}
extractKeyStats(reports) {
const stats = {
bytesSent: 0,
bytesReceived: 0,
messagesSent: 0,
messagesReceived: 0,
rtt: null
};
reports.forEach(report => {
if (report.type === 'candidate-pair' && report.nominated) {
stats.bytesSent += report.bytesSent || 0;
stats.bytesReceived += report.bytesReceived || 0;
stats.rtt = report.currentRoundTripTime;
} else if (report.type === 'data-channel') {
stats.messagesSent += report.messagesSent || 0;
stats.messagesReceived += report.messagesReceived || 0;
}
});
return stats;
}
destroy() {
if (this.statsInterval) {
clearInterval(this.statsInterval);
}
}
}
// Usage
const peer = new Peer({ initiator: true });
const monitor = new PeerMonitor(peer);
// Clean up when done
peer.on('close', () => {
monitor.destroy();
});Check for WebRTC support before creating peer connections.
/**
* Static property indicating WebRTC support in current environment
*/
Peer.WEBRTC_SUPPORT: boolean;Usage Examples:
const Peer = require('simple-peer');
// Check support before creating peers
if (Peer.WEBRTC_SUPPORT) {
console.log('WebRTC supported - creating peer');
const peer = new Peer({ initiator: true });
} else {
console.error('WebRTC not supported in this environment');
// Fallback to alternative communication method
fallbackToWebSocket();
}
// Environment-specific checks
function checkWebRTCCapabilities() {
console.log('WebRTC Support:', Peer.WEBRTC_SUPPORT);
if (typeof window !== 'undefined') {
// Browser environment
console.log('Browser WebRTC APIs:');
console.log(' RTCPeerConnection:', !!window.RTCPeerConnection);
console.log(' getUserMedia:', !!navigator.mediaDevices?.getUserMedia);
console.log(' getDisplayMedia:', !!navigator.mediaDevices?.getDisplayMedia);
} else {
// Node.js environment
console.log('Node.js environment - wrtc package required');
}
}