github.com/pion/webrtc/v4@v4.0.1/examples/swap-tracks/jsfiddle/demo.js (about) 1 /* eslint-env browser */ 2 3 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 4 // SPDX-License-Identifier: MIT 5 6 // Create peer conn 7 const pc = new RTCPeerConnection({ 8 iceServers: [ 9 { 10 urls: 'stun:stun.l.google.com:19302' 11 } 12 ] 13 }) 14 15 pc.oniceconnectionstatechange = e => { 16 console.debug('connection state change', pc.iceConnectionState) 17 } 18 pc.onicecandidate = event => { 19 if (event.candidate === null) { 20 document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) 21 } 22 } 23 24 pc.onnegotiationneeded = e => 25 pc.createOffer().then(d => pc.setLocalDescription(d)).catch(console.error) 26 27 pc.ontrack = event => { 28 console.log('Got track event', event) 29 document.getElementById('serverVideo').srcObject = new MediaStream([event.track]) 30 } 31 32 const canvases = [ 33 document.getElementById('canvasOne'), 34 document.getElementById('canvasTwo'), 35 document.getElementById('canvasThree') 36 ] 37 38 // Firefox requires getContext to be invoked on an HTML Canvas Element 39 // prior to captureStream 40 const canvasContexts = canvases.map(c => c.getContext('2d')) 41 42 // Capture canvas streams and add to peer conn 43 const streams = canvases.map(c => c.captureStream()) 44 streams.forEach(stream => stream.getVideoTracks().forEach(track => pc.addTrack(track, stream))) 45 46 // Start circles 47 requestAnimationFrame(() => drawCircle(canvasContexts[0], '#006699', 0)) 48 requestAnimationFrame(() => drawCircle(canvasContexts[1], '#cf635f', 0)) 49 requestAnimationFrame(() => drawCircle(canvasContexts[2], '#46c240', 0)) 50 51 function drawCircle (ctx, color, angle) { 52 // Background 53 ctx.clearRect(0, 0, 200, 200) 54 ctx.fillStyle = '#eeeeee' 55 ctx.fillRect(0, 0, 200, 200) 56 // Draw and fill in circle 57 ctx.beginPath() 58 const radius = 25 + 50 * Math.abs(Math.cos(angle)) 59 ctx.arc(100, 100, radius, 0, Math.PI * 2, false) 60 ctx.closePath() 61 ctx.fillStyle = color 62 ctx.fill() 63 // Call again 64 requestAnimationFrame(() => drawCircle(ctx, color, angle + (Math.PI / 64))) 65 } 66 67 window.startSession = () => { 68 const sd = document.getElementById('remoteSessionDescription').value 69 if (sd === '') { 70 return alert('Session Description must not be empty') 71 } 72 73 try { 74 pc.setRemoteDescription(JSON.parse(atob(sd))) 75 } catch (e) { 76 alert(e) 77 } 78 } 79 80 window.copySDP = () => { 81 const browserSDP = document.getElementById('localSessionDescription') 82 83 browserSDP.focus() 84 browserSDP.select() 85 86 try { 87 const successful = document.execCommand('copy') 88 const msg = successful ? 'successful' : 'unsuccessful' 89 console.log('Copying SDP was ' + msg) 90 } catch (err) { 91 console.log('Unable to copy SDP ' + err) 92 } 93 }