├── README.md ├── agora-rtm-sdk-1.4.4.js ├── index.html ├── main.css ├── main.js └── slide show visuals ├── High Level Overview (Gif).gif ├── How WebRTC Workds (Gif 2).gif └── WebSockets Vs WebRTC (2).jpg /README.md: -------------------------------------------------------------------------------- 1 | # WebRTC-Crash-Course 2 | 3 | Tutorial link: https://youtu.be/8I2axE6j204 4 | 5 | ## Cloning and starting project 6 | 1. git clone https://github.com/divanov11/WebRTC-Crash-Course 7 | 2. cd WebRTC-Crash-Course 8 | 3. Create an account on agora.io 9 | 4. Create agora apora app and copy app ID 10 | 5. Update APP_ID on line 1 in main.js 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebRTC 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | width:800px; 3 | margin:0 auto; 4 | } 5 | 6 | #videos{ 7 | display: grid; 8 | grid-template-columns: 1fr 1fr; 9 | column-gap: 1em; 10 | width: 100%; 11 | padding: 10px; 12 | } 13 | 14 | video{ 15 | width:100%; 16 | border:2px solid greenyellow; 17 | background-color: rgb(63,62,62); 18 | } 19 | 20 | textarea{ 21 | height: 50px; 22 | width: 100%; 23 | } 24 | 25 | @media screen and (max-width:800px) { 26 | body{ 27 | width:100%; 28 | } 29 | } -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | let APP_ID = "YOU'RE AGORA APP ID" 2 | 3 | 4 | let peerConnection; 5 | let localStream; 6 | let remoteStream; 7 | 8 | let uid = String(Math.floor(Math.random() * 10000)) 9 | let token = null; 10 | let client; 11 | 12 | let servers = { 13 | iceServers:[ 14 | { 15 | urls:['stun:stun1.1.google.com:19302', 'stun:stun2.1.google.com:19302'] 16 | } 17 | ] 18 | } 19 | 20 | 21 | let init = async () => { 22 | client = await AgoraRTM.createInstance(APP_ID) 23 | await client.login({uid, token}) 24 | 25 | const channel = client.createChannel('main') 26 | channel.join() 27 | 28 | channel.on('MemberJoined', handlePeerJoined) 29 | client.on('MessageFromPeer', handleMessageFromPeer) 30 | 31 | localStream = await navigator.mediaDevices.getUserMedia({video:true, audio:false}) 32 | document.getElementById('user-1').srcObject = localStream 33 | } 34 | 35 | let handlePeerJoined = async (MemberId) => { 36 | console.log('A new peer has joined this room:', MemberId) 37 | createOffer(MemberId) 38 | } 39 | 40 | let handleMessageFromPeer = async (message, MemberId) => { 41 | message = JSON.parse(message.text) 42 | console.log('Message:', message.type) 43 | 44 | if(message.type === 'offer'){ 45 | if(!localStream){ 46 | localStream = await navigator.mediaDevices.getUserMedia({video:true, audio:false}) 47 | document.getElementById('user-1').srcObject = localStream 48 | } 49 | 50 | document.getElementById('offer-sdp').value = JSON.stringify(message.offer) 51 | createAnswer(MemberId) 52 | } 53 | 54 | if(message.type === 'answer'){ 55 | document.getElementById('answer-sdp').value = JSON.stringify(message.answer) 56 | addAnswer() 57 | } 58 | 59 | if(message.type === 'candidate'){ 60 | if(peerConnection){ 61 | peerConnection.addIceCandidate(message.candidate) 62 | } 63 | } 64 | } 65 | 66 | let createPeerConnection = async (sdpType, MemberId) => { 67 | peerConnection = new RTCPeerConnection(servers) 68 | 69 | remoteStream = new MediaStream() 70 | document.getElementById('user-2').srcObject = remoteStream 71 | 72 | localStream.getTracks().forEach((track) => { 73 | peerConnection.addTrack(track, localStream) 74 | }) 75 | 76 | peerConnection.ontrack = async (event) => { 77 | event.streams[0].getTracks().forEach((track) => { 78 | remoteStream.addTrack(track) 79 | }) 80 | } 81 | 82 | peerConnection.onicecandidate = async (event) => { 83 | if(event.candidate){ 84 | document.getElementById(sdpType).value = JSON.stringify(peerConnection.localDescription) 85 | client.sendMessageToPeer({text:JSON.stringify({'type':'candidate', 'candidate':event.candidate})}, MemberId) 86 | } 87 | } 88 | } 89 | 90 | let createOffer = async (MemberId) => { 91 | 92 | createPeerConnection('offer-sdp', MemberId) 93 | 94 | let offer = await peerConnection.createOffer() 95 | await peerConnection.setLocalDescription(offer) 96 | 97 | document.getElementById('offer-sdp').value = JSON.stringify(offer) 98 | client.sendMessageToPeer({text:JSON.stringify({'type':'offer', 'offer':offer})}, MemberId) 99 | } 100 | 101 | let createAnswer = async (MemberId) => { 102 | createPeerConnection('answer-sdp', MemberId) 103 | 104 | let offer = document.getElementById('offer-sdp').value 105 | if(!offer) return alert('Retrieve offer from peer first...') 106 | 107 | offer = JSON.parse(offer) 108 | await peerConnection.setRemoteDescription(offer) 109 | 110 | let answer = await peerConnection.createAnswer() 111 | await peerConnection.setLocalDescription(answer) 112 | 113 | document.getElementById('answer-sdp').value = JSON.stringify(answer) 114 | client.sendMessageToPeer({text:JSON.stringify({'type':'answer', 'answer':answer})}, MemberId) 115 | } 116 | 117 | let addAnswer = async () => { 118 | let answer = document.getElementById('answer-sdp').value 119 | if(!answer) return alert('Retrieve answer from peer first...') 120 | 121 | answer = JSON.parse(answer) 122 | 123 | if(!peerConnection.currentRemoteDescription){ 124 | peerConnection.setRemoteDescription(answer) 125 | } 126 | 127 | } 128 | 129 | init() 130 | 131 | // document.getElementById('create-offer').addEventListener('click', createOffer) 132 | // document.getElementById('create-answer').addEventListener('click', createAnswer) 133 | // document.getElementById('add-answer').addEventListener('click', addAnswer) -------------------------------------------------------------------------------- /slide show visuals/High Level Overview (Gif).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/WebRTC-Crash-Course/b736efe28d2e9ef0d6feba6d221dd925b840adf9/slide show visuals/High Level Overview (Gif).gif -------------------------------------------------------------------------------- /slide show visuals/How WebRTC Workds (Gif 2).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/WebRTC-Crash-Course/b736efe28d2e9ef0d6feba6d221dd925b840adf9/slide show visuals/How WebRTC Workds (Gif 2).gif -------------------------------------------------------------------------------- /slide show visuals/WebSockets Vs WebRTC (2).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/WebRTC-Crash-Course/b736efe28d2e9ef0d6feba6d221dd925b840adf9/slide show visuals/WebSockets Vs WebRTC (2).jpg --------------------------------------------------------------------------------