├── 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
--------------------------------------------------------------------------------