Last active
January 12, 2020 10:39
-
-
Save sudoanand/c7b7eb0034cfb4f75c53e26dc6b7f942 to your computer and use it in GitHub Desktop.
WebRTC one to one video call demo, usage https://websocket.in as signalling server. Need help? Tweet to @hack4mer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=yes"> | |
<style> | |
body { | |
display: flex; | |
height: 100vh; | |
margin: 0; | |
align-items: center; | |
justify-content: center; | |
padding: 0 50px; | |
font-family: -apple-system, BlinkMacSystemFont, sans-serif; | |
} | |
video { | |
max-width: calc(50% - 100px); | |
margin: 0 50px; | |
box-sizing: border-box; | |
border-radius: 2px; | |
padding: 0; | |
box-shadow: rgba(156, 172, 172, 0.2) 0px 2px 2px, rgba(156, 172, 172, 0.2) 0px 4px 4px, rgba(156, 172, 172, 0.2) 0px 8px 8px, rgba(156, 172, 172, 0.2) 0px 16px 16px, rgba(156, 172, 172, 0.2) 0px 32px 32px, rgba(156, 172, 172, 0.2) 0px 64px 64px; | |
} | |
.copy { | |
position: fixed; | |
top: 10px; | |
left: 50%; | |
transform: translateX(-50%); | |
font-size: 16px; | |
color: rgba(0, 0, 0, 0.5); | |
} | |
</style> | |
</head> | |
<body> | |
<div class="copy">Open the same URL in another Tab/URL to start the video-call</div> | |
<video id="localVideo" autoplay muted></video> | |
<video id="remoteVideo" autoplay></video> | |
<script> | |
var peerConnectionConfig = { | |
'iceServers': [ | |
{ 'urls': 'stun:stun.stunprotocol.org:3478' }, | |
{ 'urls': 'stun:stun.l.google.com:19302' }, | |
] | |
}; | |
var localVideo = document.getElementById('localVideo'); | |
var remoteVideo = document.getElementById('remoteVideo'); | |
var serverConnection = new WebSocket("wss://connect.websocket.in/hack4mer?room_id=2"); | |
serverConnection.onmessage = function (message) { | |
var signal = JSON.parse(message.data); | |
console.log("M",signal); | |
if (signal.type == "callRequest") { | |
startVideoCall(true, signal); | |
console.log("Starting a call with: " + signal.from); | |
} | |
else if (signal.sdp) { | |
if (!peerConnection) startVideoCall(false, signal); | |
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(function () { | |
// Only create answers in response to offers | |
if (signal.sdp.type == 'offer') { | |
console.log("Got an offer from " + signal.from, signal) | |
peerConnection.createAnswer().then((description) => { | |
//The remove description | |
peerConnection.setLocalDescription(description).then(function () { | |
serverConnection.send(JSON.stringify({ | |
'peerInfo': "test", | |
'from': "test", | |
'to': signal.from, | |
'sdp': peerConnection.localDescription | |
})); | |
}).catch(errorHandler); | |
}).catch(errorHandler); | |
} else { | |
console.log("Got an asnwer from " + signal.from); | |
} | |
}).catch(errorHandler); | |
} else if (signal.ice) { | |
//Utilities.log("Adding ice.candidate : ",signal); | |
peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler); | |
} | |
} | |
serverConnection.onopen = function () { | |
console.log("Socket connected"); | |
requestVideo(); | |
} | |
serverConnection.onerror = function () { | |
console.error("Socket disconnected"); | |
} | |
var constraints = { | |
video: true, | |
audio: true | |
}; | |
var peerConnection = null; | |
var isNegotiating = false; | |
if (navigator.mediaDevices.getUserMedia) { | |
navigator.mediaDevices.getUserMedia(constraints).then(getUserMediaSuccess).catch(errorHandler); | |
} else { | |
alert('Your browser does not support getUserMedia API'); | |
} | |
function errorHandler(error) { | |
console.error(error); | |
} | |
function getUserMediaSuccess(stream) { | |
localVideo.srcObject = stream; | |
} | |
//New joiners make a video request | |
function requestVideo() { | |
console.log("Starting the video request"); | |
serverConnection.send(JSON.stringify({ | |
peerInfo: "test", | |
'from': "test", | |
'type': 'callRequest' | |
} | |
)); | |
} | |
//Already connected peers startVideoCall with the new joiner as response to his requestVideo | |
function startVideoCall(isCaller, requestSignal) { | |
console.log("making pc:", requestSignal.from); | |
peerConnection = new RTCPeerConnection(peerConnectionConfig); | |
var peerFrom = peerConnection; | |
peerFrom.onicecandidate = (event) => { | |
if (event.candidate != null) { | |
serverConnection.send(JSON.stringify({ | |
'peerInfo': "test", | |
'from': "test", | |
'to': requestSignal.from, | |
'ice': event.candidate | |
})); | |
} | |
} | |
peerFrom.ontrack = (event) => { | |
if (event.track.kind != "video") { | |
return; | |
} | |
console.log("Remote video found!!"); | |
remoteVideo.srcObject = event.streams[0]; | |
remoteVideo.style.height = "auto"; | |
} | |
peerFrom.onsignalingstatechange = (e) => { // Workaround for Chrome: skip nested negotiations | |
isNegotiating = (peerConnection.signalingState != "stable"); | |
} | |
//Add the track to be sent | |
var stream = localVideo.srcObject; | |
stream.getTracks().forEach((track) => { peerConnection.addTrack(track, stream); }); | |
//Create offer when needed | |
isNegotiating = false; | |
peerFrom.onnegotiationneeded = async () => { | |
if (!isCaller) { | |
return; | |
} | |
console.log("I need it", window.theRemoteDesc); | |
if (isNegotiating) { | |
console.log(requestSignal); | |
console.log("SKIP nested negotiations"); | |
return; | |
} | |
isNegotiating = true; | |
var description = await peerFrom.createOffer(); | |
console.log('got local description'); | |
console.log("a", isCaller, requestSignal); | |
await peerFrom.setLocalDescription(description); | |
console.log("b"); | |
//if(isCaller){ | |
console.log('Making offer'); | |
//Send a call offer | |
serverConnection.send(JSON.stringify({ | |
'peerInfo': "test", | |
'from': "test", | |
'to': requestSignal.from, | |
'sdp': peerConnection.localDescription | |
})); | |
//} | |
}; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment