WebRTC Quick Start
Without signaling
We can use signaling or not, signaling is just a way for us to store the answer
and offer
. If the client can exchange this information manually, we don't really need signaling.
Example
Consider the following code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="createOffer">Create offer</button>
<input type="text" placeholder="offer" class="offerInput">
<button class="acceptOffer">accept offer</button>
<input type="text" placeholder="answer" class="answerInput">
<button class="acceptAnswer">accept answer</button>
<p>Status: <span class="status"></span></p>
<input type="text" placeholder="chat" class="chatInput">
<button class="sendChat">send chat</button>
<script src="app.js"></script>
</body>
</html>
const createOffer = document.querySelector(".createOffer")
const offerInput = document.querySelector(".offerInput")
const acceptOffer = document.querySelector(".acceptOffer")
const answerInput = document.querySelector(".answerInput")
const acceptAnswer = document.querySelector(".acceptAnswer")
const status = document.querySelector(".status")
const chatInput = document.querySelector(".chatInput")
const sendChat = document.querySelector(".sendChat")
let channel = null;
const connection = new RTCPeerConnection({ iceServers: [
{ urls: 'stun:stun.l.google.com:19302' }]
})
connection.ondatachannel = (event) => {
// the receiver will get this as it contains the information from the channel
const receivedChannel = event.channel;
channel = receivedChannel;
receivedChannel.onmessage = (event) => console.log("message:", event.data)
}
connection.onconnectionstatechange = (event) => {
status.innerText = connection.connectionState
}
createOffer.addEventListener("click", async () => {
channel = connection.createDataChannel("channel1")
channel.onmessage = (event) => {
console.log("message: ", event.data)
}
const offer = await connection.createOffer()
await connection.setLocalDescription(offer)
connection.onicecandidate = (event) => {
if (!event.candidate) {
// when candidate is null, ICE is finished gathering.
// We will then display in the offer
prompt("Copy the following offer", JSON.stringify(connection.localDescription))
}
}
})
acceptOffer.addEventListener("click", async () => {
const offer = JSON.parse(offerInput.value)
await connection.setRemoteDescription(offer)
connection.onicecandidate = (event) => {
if (!event.candidate) {
prompt("Copy the following answer", JSON.stringify(connection.localDescription))
}
}
const answer = await connection.createAnswer()
connection.setLocalDescription(answer)
})
acceptAnswer.addEventListener("click", async () => {
const answer = JSON.parse(answerInput.value)
connection.setRemoteDescription(answer)
})
sendChat.addEventListener("click", async() => {
channel.send(chatInput.value)
})
How to use:
- Browser 1, click
Create Offer
and send it to Browser 2 - Browser 2, paste the code in the
offerInput
and pressAccept Offer
. Then send theanswer
to Browser 1 - Browser 1 click on
Accept Answer
. That's it, the connection is established
[!note]
In this example, we disable ICE Trickling