| |
| |
| |
|
|
| export const ICE_SERVERS: RTCConfiguration = { |
| iceServers: [ |
| { urls: 'stun:stun.l.google.com:19302' }, |
| { urls: 'stun:stun1.l.google.com:19302' }, |
| { urls: 'stun:stun2.l.google.com:19302' }, |
| { urls: 'stun:stun3.l.google.com:19302' }, |
| ], |
| }; |
|
|
| |
| |
| |
| export function createPeerConnection(): RTCPeerConnection { |
| return new RTCPeerConnection(ICE_SERVERS); |
| } |
|
|
| |
| |
| |
| export async function getUserMedia( |
| video: boolean = true, |
| audio: boolean = true |
| ): Promise<MediaStream> { |
| try { |
| return await navigator.mediaDevices.getUserMedia({ video, audio }); |
| } catch (error: any) { |
| |
| if (video) { |
| console.warn('Video access failed, trying audio only'); |
| return await navigator.mediaDevices.getUserMedia({ video: false, audio }); |
| } |
| throw error; |
| } |
| } |
|
|
| |
| |
| |
| export async function getDisplayMedia(): Promise<MediaStream> { |
| return await navigator.mediaDevices.getDisplayMedia({ |
| video: { cursor: 'always' } as any, |
| audio: true, |
| }); |
| } |
|
|
| |
| |
| |
| export function isWebRTCSupported(): boolean { |
| return !!( |
| window.RTCPeerConnection && |
| navigator.mediaDevices && |
| navigator.mediaDevices.getUserMedia |
| ); |
| } |
|
|
| |
| |
| |
| export async function getConnectionQuality( |
| pc: RTCPeerConnection |
| ): Promise<'excellent' | 'good' | 'poor' | 'disconnected'> { |
| if (pc.connectionState === 'disconnected' || pc.connectionState === 'failed') { |
| return 'disconnected'; |
| } |
|
|
| try { |
| const stats = await pc.getStats(); |
| let roundTripTime = 0; |
| let packetsLost = 0; |
|
|
| stats.forEach((report) => { |
| if (report.type === 'candidate-pair' && report.currentRoundTripTime) { |
| roundTripTime = report.currentRoundTripTime * 1000; |
| } |
| if (report.type === 'inbound-rtp' && report.packetsLost) { |
| packetsLost = report.packetsLost; |
| } |
| }); |
|
|
| if (roundTripTime < 100 && packetsLost < 5) return 'excellent'; |
| if (roundTripTime < 300 && packetsLost < 20) return 'good'; |
| return 'poor'; |
| } catch { |
| return 'good'; |
| } |
| } |
|
|