webrtc2-peer
Version:
WebRTC2 Peer - Low-level WebRTC peer connection management for cross-platform real-time communication with signaling, ICE handling, and media streaming
100 lines (80 loc) • 2.87 kB
text/typescript
/**
* PeerConnection - WebRTC peer connection management
*/
import { EventEmitter } from 'eventemitter3';
export interface PeerConnectionEvents {
'connection-state-change': (state: RTCPeerConnectionState) => void;
'ice-candidate': (candidate: RTCIceCandidate) => void;
'remote-stream': (stream: MediaStream) => void;
'data-channel': (channel: RTCDataChannel) => void;
}
export class PeerConnection extends EventEmitter<PeerConnectionEvents> {
private pc: RTCPeerConnection;
private localStream?: MediaStream;
private remoteStream?: MediaStream;
constructor(config?: RTCConfiguration) {
super();
this.pc = new RTCPeerConnection(config || {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' }
]
});
this.setupEventHandlers();
}
private setupEventHandlers(): void {
this.pc.onconnectionstatechange = () => {
this.emit('connection-state-change', this.pc.connectionState);
};
this.pc.onicecandidate = (event) => {
if (event.candidate) {
this.emit('ice-candidate', event.candidate);
}
};
this.pc.ontrack = (event) => {
const [stream] = event.streams;
this.remoteStream = stream;
this.emit('remote-stream', stream);
};
this.pc.ondatachannel = (event) => {
this.emit('data-channel', event.channel);
};
}
async createOffer(): Promise<RTCSessionDescriptionInit> {
const offer = await this.pc.createOffer();
await this.pc.setLocalDescription(offer);
return offer;
}
async createAnswer(): Promise<RTCSessionDescriptionInit> {
const answer = await this.pc.createAnswer();
await this.pc.setLocalDescription(answer);
return answer;
}
async setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void> {
await this.pc.setRemoteDescription(description);
}
async addIceCandidate(candidate: RTCIceCandidateInit): Promise<void> {
await this.pc.addIceCandidate(candidate);
}
addLocalStream(stream: MediaStream): void {
this.localStream = stream;
stream.getTracks().forEach(track => {
this.pc.addTrack(track, stream);
});
}
createDataChannel(label: string, options?: RTCDataChannelInit): RTCDataChannel {
return this.pc.createDataChannel(label, options);
}
getConnectionState(): RTCPeerConnectionState {
return this.pc.connectionState;
}
getLocalStream(): MediaStream | undefined {
return this.localStream;
}
getRemoteStream(): MediaStream | undefined {
return this.remoteStream;
}
close(): void {
this.pc.close();
this.removeAllListeners();
}
}