Last active
March 20, 2018 14:44
-
-
Save vitlage/ea5f2c09a25714353ee92092a8de731b to your computer and use it in GitHub Desktop.
This file contains 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
<html lang="en"> | |
<head> | |
<title>Janus connection</title> | |
<meta charset="utf8"> | |
</head> | |
<body> | |
<style> | |
.remoteVideo { | |
width: 320px; | |
height: 240px; | |
margin: 0; | |
} | |
</style> | |
<h2>Janus WebRTC gateway</h2> | |
<video id="localVideo" playsinline autoplay muted></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<video class="remoteVideo" playsinline autoplay></video> | |
<!--<script src="adapter.js"></script>--> | |
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script> | |
<script> | |
var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; | |
var socket = new WebSocket("wss://janus_located_url:8989/", 'janus-protocol'); | |
var mainStream; | |
var stunServer = { | |
iceServers: [ | |
{urls: "stun:23.21.150.121"}, | |
{urls: "stun:stun.l.google.com:19302"}, | |
{urls: "stun:stun.lawsroom.com:3478"}, | |
{urls: "turn:stun.lawsroom.com:3478", credential: "tianyahechumizhiyin", username: "yiquganchangduan"}, | |
{urls: "turn:stun.lawsroom.com:3478?transport=tcp", credential: "tianyahechumizhiyin", username: "yiquganchangduan"}, | |
{urls: "turn:stun.lawsroom.com:3478?transport=udp", credential: "tianyahechumizhiyin", username: "yiquganchangduan"}, | |
{urls: "turn:numb.viagenie.ca", credential: "muazkh", username: "webrtc@live.com"} | |
] | |
}; | |
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; | |
var mediaConstraints; | |
var peerConnections = []; | |
var numberOfJoinBack = 0; | |
var jseps = []; | |
var answers = []; | |
window.users = []; | |
if (isFirefox) { | |
mediaConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true }; | |
} else { | |
mediaConstraints = { | |
mandatory: { OfferToReceiveAudio: true, OfferToReceiveVideo: true }, | |
optional: [ | |
{DtlsSrtpKeyAgreement: true}, | |
{RtpDataChannels: true} | |
] | |
}; | |
} | |
var pc = new RTCPeerConnection(stunServer); | |
var newHandleIDs = []; | |
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); | |
navigator.getUserMedia( | |
{ audio: true, video: true }, | |
function (stream) { | |
mainStream = stream; | |
pc.addStream(mainStream); | |
if(isSafari) { | |
document.getElementById("localVideo").srcObject = stream; | |
} else { | |
document.getElementById("localVideo").src = window.URL.createObjectURL(stream); | |
} | |
pc.onaddstream = function(evt) { | |
console.log("on local add stream"); | |
}; | |
}, | |
function(error) { console.log("error for this Peer Connection", error) } | |
); | |
socket.onerror = function(error) { | |
alert("Connection to server not established. Please contact you system administrator " + error.message); | |
}; | |
socket.onopen = function(e) { | |
// Creating session with Janus server | |
socket.send(JSON.stringify({"janus": "create", "transaction": "test"})); | |
}; | |
pc.onicecandidate = function (event) { | |
if (event.candidate) { | |
socket.send(JSON.stringify( | |
{ | |
"janus" : "trickle", | |
"transaction" : "trickletransaction", | |
"candidate": event.candidate, | |
"session_id": window.sessionId, | |
"handle_id": pluginId | |
} | |
)); | |
} | |
}; | |
socket.onmessage = function(event) { | |
var connectionData = JSON.parse(event.data); | |
if(!window.sessionId) { | |
window.sessionId = connectionData.data.id; | |
socket.send(JSON.stringify({ | |
"janus": "attach", | |
"plugin": "janus.plugin.videoroom", | |
"session_id": window.sessionId, | |
"transaction": "testattachtoroom", | |
"force-bundle" : true, | |
"force-rtcp-mux" : true, | |
})); | |
} | |
if(!window.pluginId && connectionData["session_id"]) { | |
window.pluginId = connectionData.data.id; | |
socket.send(JSON.stringify({ | |
"janus": "message", | |
"session_id": window.sessionId, | |
"handle_id": window.pluginId, | |
"transaction": "testlistrequest", | |
"body": { | |
"request" : "list", | |
} | |
})); | |
} | |
// Creating offer | |
if (connectionData.transaction == "testlistrequest") { | |
// Connect with video room | |
socket.send(JSON.stringify({ | |
"janus": "message", | |
"session_id": window.sessionId, | |
"handle_id": window.pluginId, | |
"transaction": "testjoinroom", | |
"body": { | |
"request" : "join", | |
"room" : 5678, | |
"ptype" : "publisher", | |
"display" : "Zirka_Vasyl_:D", | |
} | |
})); | |
// Keep session alive, every minute send keepalive message to Janus | |
setInterval(function(){ | |
socket.send(JSON.stringify({ | |
"janus" : "keepalive", | |
"session_id" : window.sessionId, | |
"transaction" : "keepalivestransaction" | |
})); | |
}, 60000); | |
createOffer(pc, window.pluginId); | |
} | |
// On answer on our offer we setting remote description of another peer | |
if(connectionData.jsep && connectionData.jsep.type == "answer") { | |
pc.setRemoteDescription(new SessionDescription(connectionData.jsep), function() { | |
}, function (e) { | |
console.log("Error setting remote desk! Ha!", e); | |
}); | |
} | |
if(connectionData.plugindata && connectionData.plugindata.plugin == "janus.plugin.videoroom") { | |
// Attach event for each publisher in video room | |
if(connectionData.plugindata.data && connectionData.plugindata.data.publishers) { | |
var isItNewUserCame = false; | |
// If new user come after some time | |
if(window.users.length > 0) { | |
var newPublisherCame = connectionData.plugindata.data.publishers; | |
// If only one user came at the same time | |
if(newPublisherCame.length == 1) { | |
for(var i = 0; i < window.users.length; i++){ | |
if(newPublisherCame[0].id != window.users[i].id) { | |
isItNewUserCame = true; | |
console.log("after some time new user came with id", newPublisherCame[0].id); | |
break; | |
} | |
} | |
} | |
// If few users came at the same time | |
else { | |
// TODO: write this case to check 2 arrays | |
console.log("2 users came at the same time! Check scenario"); | |
} | |
window.users.push(newPublisherCame); | |
createPeerConnections(newPublisherCame, "new_user_come_to_us"); | |
} else { | |
window.users = connectionData.plugindata.data.publishers; | |
createPeerConnections(connectionData.plugindata.data.publishers, null); | |
} | |
} | |
} | |
// We create join on each user | |
if(connectionData.janus == "success" && connectionData.transaction == "attach_on_publisher") { | |
newHandleIDs.push(connectionData.data.id); | |
window.newHandleIDs = newHandleIDs; | |
if(window.users.length == window.newHandleIDs.length) { | |
for (let i = 0; i < window.users.length; i++) { | |
socket.send(JSON.stringify({ | |
"janus": "message", | |
"plugin": "janus.plugin.videoroom", | |
"session_id": window.sessionId, | |
"handle_id": newHandleIDs[i], | |
"transaction": "join_on_each_publisher_be", | |
"opaque_id": "test_bebebe", | |
"body": { | |
"request": "join", | |
"ptype": "listener", | |
"display": "Zirka_Vasyl_xD", | |
"room": 5678, | |
"feed": window.users[i].id // id of user | |
} | |
})); | |
} | |
} | |
} | |
// When user come after some time | |
if(connectionData.janus == "success" && connectionData.transaction == "attach_new_user_after_some_time") { | |
newHandleIDs.push(connectionData.data.id); | |
socket.send(JSON.stringify({ | |
"janus": "message", | |
"plugin": "janus.plugin.videoroom", | |
"session_id": window.sessionId, | |
"handle_id": newHandleIDs[newHandleIDs.length - 1], | |
"transaction": "new_user_came_join", | |
"opaque_id": "test_bebebe", | |
"body": { | |
"request": "join", | |
"ptype": "listener", | |
"display": "Zirka_Vasyl_xD", | |
"room": 5678, | |
"feed": window.users[window.users.length - 1][0].id // id of last user just came | |
} | |
})); | |
} | |
// Creating answer on offer (when offer from any user come) | |
if(connectionData.transaction == "join_on_each_publisher_be" && connectionData.jsep) { | |
numberOfJoinBack++; | |
jseps.push(connectionData.jsep); | |
if(numberOfJoinBack == newHandleIDs.length) { | |
for(let i = 0; i < newHandleIDs.length; i++) { | |
peerConnections[i].setRemoteDescription(jseps[i], function () { | |
peerConnections[i].createAnswer().then(function (answer) { | |
answers.push(answer); | |
var tmp = peerConnections[i].setLocalDescription(answers[i]); | |
return tmp; | |
}, | |
function () { | |
console.log("in first then error"); | |
}, mediaConstraints) | |
.then(function () { | |
socket.send(JSON.stringify( | |
{ | |
"janus": "message", | |
"transaction": "answer_for_new_peer_connection", | |
"session_id": window.sessionId, | |
"handle_id": newHandleIDs[i], | |
"body": { | |
"request": "start", | |
"room": 5678 | |
}, | |
"jsep": answers[i] | |
} | |
)); | |
}, | |
function () { | |
console.log("in second then error"); | |
}) | |
.catch(function (e) { | |
console.log("my error here is", e); | |
}); | |
}, function (e) { | |
console.log("Error setting remote description", e); | |
}); | |
} | |
} | |
} | |
// Creating answer on offer for new user which came after some time | |
if(connectionData.transaction == "new_user_came_join" && connectionData.jsep) { | |
jseps.push(connectionData.jsep); | |
peerConnections[peerConnections.length - 1].setRemoteDescription(jseps[jseps.length - 1], function () { | |
peerConnections[peerConnections.length - 1].createAnswer().then(function (answer) { | |
console.log("inside create answer", answer); | |
answers.push(answer); | |
var tmp = peerConnections[peerConnections.length - 1].setLocalDescription(answers[answers.length - 1]); | |
return tmp; | |
}, | |
function () { | |
console.log("in first then error"); | |
}, mediaConstraints) | |
.then(function () { | |
socket.send(JSON.stringify( | |
{ | |
"janus": "message", | |
"transaction": "answer_for_new_peer_connection_new_user", | |
"session_id": window.sessionId, | |
"handle_id": newHandleIDs[newHandleIDs.length - 1], | |
"body": { | |
"request": "start", | |
"room": 5678 | |
}, | |
"jsep": answers[answers.length - 1] | |
} | |
)); | |
}, | |
function (e) { | |
console.log("error ", e); | |
}) | |
.catch(function (e) { | |
console.log("error ", e); | |
}); | |
}, function (e) { | |
console.log("Error setting remote description", e); | |
}); | |
} | |
if(connectionData.janus == "hangup") { | |
var userLeft = document.getElementById(connectionData.sender); | |
if(userLeft) { | |
setTimeout(function() { | |
userLeft.pause(); | |
userLeft.setAttribute('src', ''); | |
userLeft.removeAttribute('src'); | |
userLeft.removeAttribute("id"); | |
}, 0); | |
userLeft.removeChild(userLeft.firstChild); | |
} | |
} | |
}; | |
function createPeerConnections(publishers, transactionName) { | |
console.log("publishers", publishers); | |
if(!transactionName){ | |
for(let i = 0; i < publishers.length; i++) { | |
peerConnections.push(new RTCPeerConnection(stunServer)); | |
socket.send(JSON.stringify({ | |
"janus": "attach", | |
"plugin": "janus.plugin.videoroom", | |
"session_id": window.sessionId, | |
"opaque_id": "test_opaque_id", | |
"transaction": "attach_on_publisher", | |
"force-bundle": true, | |
"force-rtcp-mux": true | |
})); | |
peerConnections[i].onaddstream = function (evt) { | |
console.log('inside new on add stream', evt); | |
var secondStream = evt.stream; | |
console.log("stream is", secondStream); | |
attachVideoSrcToElement(secondStream, newHandleIDs[i]); | |
}; | |
peerConnections[i].onicecandidate = function (event) { | |
console.log("newHandleIDs[0] to check", newHandleIDs); | |
if (event.candidate) { | |
socket.send(JSON.stringify( | |
{ | |
"janus": "trickle", | |
"transaction": "trickletransaction_for_new_peer_connection", | |
"candidate": event.candidate, | |
"session_id": window.sessionId, | |
"handle_id": newHandleIDs[i] | |
} | |
)); | |
} | |
}; | |
} | |
} | |
// When new user come after some time | |
else { | |
peerConnections.push(new RTCPeerConnection(stunServer)); | |
socket.send(JSON.stringify({ | |
"janus": "attach", | |
"plugin": "janus.plugin.videoroom", | |
"session_id": window.sessionId, | |
"opaque_id": "test_opaque_id", | |
"transaction": "attach_new_user_after_some_time", | |
"force-bundle": true, | |
"force-rtcp-mux": true | |
})); | |
peerConnections[peerConnections.length - 1].onaddstream = function(evt) { | |
var secondStream = evt.stream; | |
attachVideoSrcToElement(secondStream, newHandleIDs[newHandleIDs.length - 1]); | |
}; | |
peerConnections[peerConnections.length - 1].onicecandidate = function(event) { | |
if(event.candidate) { | |
socket.send(JSON.stringify( | |
{ | |
"janus": "trickle", | |
"transaction": "trickle_new_user_after_some_time", | |
"candidate": event.candidate, | |
"session_id": window.sessionId, | |
"handle_id": newHandleIDs[newHandleIDs.length - 1] | |
} | |
)); | |
} | |
}; | |
} | |
} | |
function createOffer(incomePC, handleId) { | |
if(isSafari) { | |
incomePC.addTransceiver('audio'); | |
incomePC.addTransceiver('video'); | |
} | |
incomePC.createOffer( | |
function(description){ | |
window.desc = description.sdp; | |
incomePC.setLocalDescription(description, function () { | |
console.log("happy set local desk"); | |
}, | |
function () { | |
console.log("error to set local desk"); | |
}); | |
socket.send(JSON.stringify( | |
{ | |
"janus" : "message", | |
"transaction" : "test_create_offer1", | |
"session_id": sessionId, | |
"handle_id": handleId, | |
"body" : { | |
"request": "configure", | |
"audio" : true, | |
"video" : true | |
}, | |
"jsep" : description | |
} | |
)); | |
}, | |
function(error) { console.log(error) }, | |
mediaConstraints | |
); | |
} | |
function attachVideoSrcToElement(stream, userId) { | |
var videoContainer = document.querySelectorAll('.remoteVideo'); | |
var url = URL.createObjectURL(stream); | |
for(var i = 0; i < videoContainer.length; i++) { | |
if(!videoContainer[i].src) { | |
videoContainer[i].src = url; | |
videoContainer[i].id = userId; | |
break; | |
} | |
} | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment