Skip to content

Instantly share code, notes, and snippets.

@vitlage
Last active March 20, 2018 14:44
Show Gist options
  • Save vitlage/ea5f2c09a25714353ee92092a8de731b to your computer and use it in GitHub Desktop.
Save vitlage/ea5f2c09a25714353ee92092a8de731b to your computer and use it in GitHub Desktop.
<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