809 lines
34 KiB
HTML
809 lines
34 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||
|
<title>Home - KEVIN</title>
|
||
|
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css?h=5d0606363cf6affbcda5495e4fefc96c">
|
||
|
<link rel="stylesheet" href="assets/fonts/Lato.css">
|
||
|
<link rel="stylesheet" href="assets/fonts/font-awesome.min.css?h=9db842b3dc3336737559eb4abc0f1b3d">
|
||
|
<link rel="stylesheet" href="assets/fonts/material-icons.min.css?h=9db842b3dc3336737559eb4abc0f1b3d">
|
||
|
<link rel="stylesheet" href="assets/fonts/simple-line-icons.min.css?h=9db842b3dc3336737559eb4abc0f1b3d">
|
||
|
<link rel="stylesheet" href="assets/css/animate.css">
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<nav id="nav" class="navbar navbar-light navbar-expand bg-light navigation-clean">
|
||
|
<div class="container"><a class="navbar-brand" href="/">KEVIN</a><button data-toggle="collapse" class="navbar-toggler" data-target="#navcol-1"></button>
|
||
|
<div class="collapse navbar-collapse" id="navcol-1"></div>
|
||
|
</div>
|
||
|
</nav>
|
||
|
<section class="features-icons bg-light text-center">
|
||
|
<div class="container">
|
||
|
<div class="row" id="header">
|
||
|
<div class="col-lg-4">
|
||
|
<div class="mx-auto features-icons-item mb-5 mb-lg-0 mb-lg-3">
|
||
|
<div class="d-flex features-icons-icon" id="open-room"><i class="material-icons m-auto text-primary" data-bs-hover-animate="pulse">group_add</i></div>
|
||
|
<h3>Group Chat</h3>
|
||
|
<p class="lead mb-0">Create a Group Chat with several people</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="col-lg-4">
|
||
|
<div class="mx-auto features-icons-item mb-5 mb-lg-0 mb-lg-3">
|
||
|
<div class="d-flex features-icons-icon"><i class="icon-camrecorder m-auto text-primary" data-toggle="modal" data-target="#preview-webcam" data-bs-hover-animate="pulse"></i></div>
|
||
|
<h3>Share Webcam</h3>
|
||
|
<p class="lead mb-0">Share your Webcam + Audio</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="col-lg-4">
|
||
|
<div class="mx-auto features-icons-item mb-5 mb-lg-0 mb-lg-3">
|
||
|
<div class="d-flex features-icons-icon" id="screen-share"><i class="icon-screen-desktop m-auto text-primary" data-bs-hover-animate="pulse"></i></div>
|
||
|
<h3>Share Screen</h3>
|
||
|
<p class="lead mb-0">Share your Screen</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="col-auto align-self-center mx-auto">
|
||
|
<div id="videos-container" style="margin: 20px 0;"></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="col-auto align-self-center mx-auto">
|
||
|
<div id="videos-container"></div>
|
||
|
<div id="room-urls" style="display: none;background: #F1EDED;border: 1px solid rgb(189, 189, 189);border-left: 0;border-right: 0;margin: 10px;"></div>
|
||
|
<input type="text" id="room-id" value="abcdef" autocorrect=off autocapitalize=off size=20 style="display: none;">
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="col-auto align-self-center mx-auto">
|
||
|
<label id="record"><input type="checkbox" id="record-entire-conference">Record?</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="col-lg-4 align-self-center mx-auto">
|
||
|
<span id="recording-status" style="display: none;"></span>
|
||
|
</div>
|
||
|
<div class="col-lg-4 align-self-center mx-auto">
|
||
|
<span id="recording-time" style="display: none;"></span>
|
||
|
</div>
|
||
|
<div class="col-lg-4 align-self-center mx-auto">
|
||
|
<button class="btn btn-primary" id="btn-stop-recording" style="display: none;" type="button">Stop Recording</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</section>
|
||
|
<div class="modal fade" id="preview-webcam" tabindex="-1" aria-labelledby="preview-webcam-label" aria-hidden="true">
|
||
|
<div class="modal-dialog modal-xl">
|
||
|
<div class="modal-content">
|
||
|
<div class="modal-header">
|
||
|
<h5 class="modal-title" id="preview-webcam-label">Preview</h5>
|
||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||
|
<span aria-hidden="true">×</span>
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="modal-body">
|
||
|
<div id="container-preview" style="margin: 0px auto;width: 100%;">
|
||
|
<div class="d-flex justify-content-center">
|
||
|
<video playsinline autoplay id="videoPreview" width="640"></video>
|
||
|
</div>
|
||
|
<div class="d-flex justify-content-center">
|
||
|
<label for="videoSource" style="margin-top: 5px;">Video source: </label><select id="videoSource"></select>
|
||
|
<label for="audioSource" style="margin-top: 5px;margin-left: 10px;">Audio source: </label><select id="audioSource"></select>
|
||
|
</div>
|
||
|
<div class="d-flex justify-content-center">
|
||
|
<canvas width="320px" height="30px" id="vumeter" style="background-color: black;"></canvas>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="modal-footer">
|
||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||
|
<button type="button" class="btn btn-primary" id="webcam-share">Start</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<footer class="footer bg-light">
|
||
|
<div class="container">
|
||
|
<div class="row" id="footer">
|
||
|
<div class="col-lg-6 my-auto h-100 text-center text-lg-left">
|
||
|
<ul class="list-inline mb-2"></ul>
|
||
|
<p class="text-muted small mb-4 mb-lg-0">rC3 Edition</p>
|
||
|
</div>
|
||
|
<div class="col-lg-6 my-auto h-100 text-center text-lg-right">
|
||
|
<ul class="list-inline mb-0">
|
||
|
<li class="list-inline-item"><a href="#"></a></li>
|
||
|
<li class="list-inline-item"><a href="#"></a></li>
|
||
|
<li class="list-inline-item"><a href="https://github.com/voc/kevin"><i class="fa fa-github fa-2x fa-fw"></i></a></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</footer>
|
||
|
<script src="assets/js/jquery.min.js?h=89312d34339dcd686309fe284b3f226f"></script>
|
||
|
<script src="assets/bootstrap/js/bootstrap.min.js?h=03ab36d1dde930b7d44a712f19075641"></script>
|
||
|
<script src="assets/js/script.min.js?h=84a111365b31658389bfd638cc1392eb"></script>
|
||
|
<script src="assets/js/RTCMultiConnection.js"></script>
|
||
|
<script src="assets/js/adapter.js"></script>
|
||
|
<script src="/socket.io/socket.io.js"></script>
|
||
|
<link rel="stylesheet" href="assets/css/getHTMLMediaElement.css">
|
||
|
<script src="assets/js/getHTMLMediaElement.js"></script>
|
||
|
<script src="assets/js/RecordRTC.js"></script>
|
||
|
<script>
|
||
|
// ......................................................
|
||
|
// .......................UI Code........................
|
||
|
// ......................................................
|
||
|
document.getElementById('open-room').onclick = function() {
|
||
|
window.addEventListener('beforeunload', function (e) {
|
||
|
e.preventDefault();
|
||
|
e.returnValue = '';
|
||
|
});
|
||
|
disableInputButtons();
|
||
|
connection.open(document.getElementById('room-id').value, function(isRoomExist, roomid, error) {
|
||
|
if(error) {
|
||
|
disableInputButtons(true);
|
||
|
alert(error);
|
||
|
}
|
||
|
else if (connection.isInitiator === true) {
|
||
|
showRoomURL(roomid);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
document.getElementById('webcam-share').onclick = function() {
|
||
|
window.addEventListener('beforeunload', function (e) {
|
||
|
e.preventDefault();
|
||
|
e.returnValue = '';
|
||
|
});
|
||
|
disableInputButtons();
|
||
|
connection.sdpConstraints.mandatory = {
|
||
|
OfferToReceiveAudio: true,
|
||
|
OfferToReceiveVideo: true
|
||
|
};
|
||
|
connection.session = {
|
||
|
audio: true,
|
||
|
video: true,
|
||
|
oneway: true
|
||
|
};
|
||
|
|
||
|
const audioInputSelect = document.querySelector('select#audioSource');
|
||
|
const videoSelect = document.querySelector('select#videoSource');
|
||
|
const audioSource = audioInputSelect.value;
|
||
|
const videoSource = videoSelect.value;
|
||
|
connection.mediaConstraints.audio = {
|
||
|
deviceId: audioSource
|
||
|
};
|
||
|
connection.mediaConstraints.video = {
|
||
|
deviceId: videoSource
|
||
|
};
|
||
|
|
||
|
connection.open(document.getElementById('room-id').value, function(isRoomExist, roomid, error) {
|
||
|
if(error) {
|
||
|
disableInputButtons(true);
|
||
|
alert(error);
|
||
|
}
|
||
|
else if (connection.isInitiator === true) {
|
||
|
showRoomURL(roomid);
|
||
|
}
|
||
|
});
|
||
|
params.source = 'webcam';
|
||
|
};
|
||
|
|
||
|
document.getElementById('screen-share').onclick = function() {
|
||
|
window.addEventListener('beforeunload', function (e) {
|
||
|
e.preventDefault();
|
||
|
e.returnValue = '';
|
||
|
});
|
||
|
disableInputButtons();
|
||
|
connection.sdpConstraints.mandatory = {
|
||
|
OfferToReceiveAudio: false,
|
||
|
OfferToReceiveVideo: false
|
||
|
};
|
||
|
connection.session = {
|
||
|
screen: true,
|
||
|
oneway: true
|
||
|
};
|
||
|
|
||
|
connection.open(document.getElementById('room-id').value, function(isRoomExist, roomid, error) {
|
||
|
if(error) {
|
||
|
disableInputButtons(true);
|
||
|
alert(error);
|
||
|
}
|
||
|
else if (connection.isInitiator === true) {
|
||
|
showRoomURL(roomid);
|
||
|
}
|
||
|
});
|
||
|
params.source = 'screen';
|
||
|
};
|
||
|
|
||
|
// ......................................................
|
||
|
// ..................RTCMultiConnection Code.............
|
||
|
// ......................................................
|
||
|
|
||
|
var connection = new RTCMultiConnection();
|
||
|
|
||
|
connection.socketURL = 'https://kevin.c3voc.de/';
|
||
|
|
||
|
connection.socketMessageEvent = 'rC3-VOCcast';
|
||
|
|
||
|
connection.session = {
|
||
|
audio: true,
|
||
|
video: true,
|
||
|
//oneway: true
|
||
|
};
|
||
|
|
||
|
connection.sdpConstraints.mandatory = {
|
||
|
OfferToReceiveAudio: true,
|
||
|
OfferToReceiveVideo: true
|
||
|
};
|
||
|
|
||
|
// STAR_FIX_VIDEO_AUTO_PAUSE_ISSUES
|
||
|
// via: https://github.com/muaz-khan/RTCMultiConnection/issues/778#issuecomment-524853468
|
||
|
var bitrates = 512;
|
||
|
var resolutions = 'Ultra-HD';
|
||
|
var videoConstraints = {};
|
||
|
|
||
|
if (resolutions == 'HD') {
|
||
|
videoConstraints = {
|
||
|
width: {
|
||
|
ideal: 1280
|
||
|
},
|
||
|
height: {
|
||
|
ideal: 720
|
||
|
},
|
||
|
frameRate: 30
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (resolutions == 'Ultra-HD') {
|
||
|
videoConstraints = {
|
||
|
width: {
|
||
|
ideal: 1920
|
||
|
},
|
||
|
height: {
|
||
|
ideal: 1080
|
||
|
},
|
||
|
frameRate: 30
|
||
|
};
|
||
|
}
|
||
|
|
||
|
connection.mediaConstraints = {
|
||
|
video: videoConstraints,
|
||
|
audio: true
|
||
|
};
|
||
|
|
||
|
var CodecsHandler = connection.CodecsHandler;
|
||
|
|
||
|
connection.processSdp = function(sdp) {
|
||
|
var codecs = 'vp8';
|
||
|
|
||
|
if (codecs.length) {
|
||
|
sdp = CodecsHandler.preferCodec(sdp, codecs.toLowerCase());
|
||
|
}
|
||
|
|
||
|
if (resolutions == 'HD') {
|
||
|
sdp = CodecsHandler.setApplicationSpecificBandwidth(sdp, {
|
||
|
audio: 128,
|
||
|
video: bitrates,
|
||
|
screen: bitrates
|
||
|
});
|
||
|
|
||
|
sdp = CodecsHandler.setVideoBitrates(sdp, {
|
||
|
min: bitrates * 8 * 1024,
|
||
|
max: bitrates * 8 * 1024,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (resolutions == 'Ultra-HD') {
|
||
|
sdp = CodecsHandler.setApplicationSpecificBandwidth(sdp, {
|
||
|
audio: 128,
|
||
|
video: bitrates,
|
||
|
screen: bitrates
|
||
|
});
|
||
|
|
||
|
sdp = CodecsHandler.setVideoBitrates(sdp, {
|
||
|
min: bitrates * 8 * 1024,
|
||
|
max: bitrates * 8 * 1024,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return sdp;
|
||
|
};
|
||
|
// END_FIX_VIDEO_AUTO_PAUSE_ISSUES
|
||
|
|
||
|
connection.iceServers = [];
|
||
|
connection.iceServers.push({
|
||
|
'urls': 'stun:stun.franconian.net:3478',
|
||
|
});
|
||
|
connection.iceServers.push({
|
||
|
'urls': 'turn:stun.franconian.net:3478',
|
||
|
'credential': 'ec0WlmT6lj0p4ou8XFAV66nTDopm9JPra3TnIIkxUM1VaqwAzTtoFqbXVeOoFsdU',
|
||
|
'username': 'turnuser',
|
||
|
});
|
||
|
|
||
|
connection.videosContainer = document.getElementById('videos-container');
|
||
|
connection.onstream = function(event) {
|
||
|
var existing = document.getElementById(event.streamid);
|
||
|
if(existing && existing.parentNode) {
|
||
|
existing.parentNode.removeChild(existing);
|
||
|
}
|
||
|
|
||
|
event.mediaElement.removeAttribute('src');
|
||
|
event.mediaElement.removeAttribute('srcObject');
|
||
|
event.mediaElement.muted = true;
|
||
|
event.mediaElement.volume = 0;
|
||
|
|
||
|
var video = document.createElement('video');
|
||
|
|
||
|
try {
|
||
|
video.setAttributeNode(document.createAttribute('autoplay'));
|
||
|
video.setAttributeNode(document.createAttribute('playsinline'));
|
||
|
} catch (e) {
|
||
|
video.setAttribute('autoplay', true);
|
||
|
video.setAttribute('playsinline', true);
|
||
|
}
|
||
|
|
||
|
if(event.type === 'local') {
|
||
|
video.volume = 0;
|
||
|
try {
|
||
|
video.setAttributeNode(document.createAttribute('muted'));
|
||
|
} catch (e) {
|
||
|
video.setAttribute('muted', true);
|
||
|
}
|
||
|
}
|
||
|
video.srcObject = event.stream;
|
||
|
|
||
|
if (params.action && params.action == 'view') {
|
||
|
var width = params.width;
|
||
|
var mediaElement = getHTMLMediaElement(video, {
|
||
|
buttons: [''],
|
||
|
width: width,
|
||
|
showOnMouseEnter: false
|
||
|
});
|
||
|
}
|
||
|
else if (params.source && params.source == 'webcam') {
|
||
|
try {
|
||
|
video.setAttributeNode(document.createAttribute('controls'));
|
||
|
} catch (e) {
|
||
|
video.setAttribute('controls', true);
|
||
|
}
|
||
|
var mediaElement = getHTMLMediaElement(video, {
|
||
|
buttons: ['full-screen'],
|
||
|
showOnMouseEnter: true
|
||
|
});
|
||
|
}
|
||
|
else if (params.source && params.source == 'screen') {
|
||
|
var mediaElement = getHTMLMediaElement(video, {
|
||
|
buttons: ['full-screen'],
|
||
|
showOnMouseEnter: true
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
var width = parseInt(connection.videosContainer.clientWidth / 3) - 20;
|
||
|
var mediaElement = getHTMLMediaElement(video, {
|
||
|
title: event.userid,
|
||
|
buttons: ['full-screen'],
|
||
|
width: width,
|
||
|
showOnMouseEnter: true
|
||
|
});
|
||
|
}
|
||
|
|
||
|
connection.videosContainer.appendChild(mediaElement);
|
||
|
|
||
|
setTimeout(function() {
|
||
|
mediaElement.media.play();
|
||
|
}, 5000);
|
||
|
|
||
|
mediaElement.id = event.streamid;
|
||
|
|
||
|
console.log('sessionid: ' + connection.sessionid);
|
||
|
// to keep room-id in cache
|
||
|
//localStorage.setItem(connection.socketMessageEvent, connection.sessionid);
|
||
|
|
||
|
|
||
|
function calculateTimeDuration(secs) {
|
||
|
var hr = Math.floor(secs / 3600);
|
||
|
var min = Math.floor((secs - (hr * 3600)) / 60);
|
||
|
var sec = Math.floor(secs - (hr * 3600) - (min * 60));
|
||
|
|
||
|
if (min < 10) {
|
||
|
min = "0" + min;
|
||
|
}
|
||
|
|
||
|
if (sec < 10) {
|
||
|
sec = "0" + sec;
|
||
|
}
|
||
|
|
||
|
if(hr <= 0) {
|
||
|
return min + ':' + sec;
|
||
|
}
|
||
|
|
||
|
return hr + ':' + min + ':' + sec;
|
||
|
}
|
||
|
|
||
|
|
||
|
chkRecordConference.parentNode.style.display = 'none';
|
||
|
|
||
|
if(chkRecordConference.checked === true) {
|
||
|
btnStopRecording.style.display = 'inline-block';
|
||
|
recordingStatus.style.display = 'inline-block';
|
||
|
recordingtime.style.display = 'inline-block';
|
||
|
|
||
|
var recorder = connection.recorder;
|
||
|
if(!recorder) {
|
||
|
recorder = RecordRTC([event.stream], {
|
||
|
type: 'video',
|
||
|
disableLogs: false,
|
||
|
video: {
|
||
|
width: 1920,
|
||
|
height: 1080
|
||
|
}
|
||
|
});
|
||
|
recorder.startRecording();
|
||
|
dateStarted = new Date().getTime();
|
||
|
connection.recorder = recorder;
|
||
|
}
|
||
|
else {
|
||
|
recorder.getInternalRecorder().addStreams([event.stream]);
|
||
|
}
|
||
|
|
||
|
if(!connection.recorder.streams) {
|
||
|
connection.recorder.streams = [];
|
||
|
}
|
||
|
|
||
|
connection.recorder.streams.push(event.stream);
|
||
|
recordingStatus.innerHTML = 'Recording ' + connection.recorder.streams.length + ' streams';
|
||
|
|
||
|
(function looper() {
|
||
|
if(!recorder) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
recordingtime.innerHTML = 'Recording Duration: ' + calculateTimeDuration((new Date().getTime() - dateStarted) / 1000);
|
||
|
|
||
|
setTimeout(looper, 1000);
|
||
|
})();
|
||
|
}
|
||
|
|
||
|
if(event.type === 'local') {
|
||
|
connection.socket.on('disconnect', function() {
|
||
|
if(!connection.getAllParticipants().length) {
|
||
|
location.reload();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var recordingtime = document.getElementById('recording-time');
|
||
|
var recordingStatus = document.getElementById('recording-status');
|
||
|
var chkRecordConference = document.getElementById('record-entire-conference');
|
||
|
var btnStopRecording = document.getElementById('btn-stop-recording');
|
||
|
btnStopRecording.onclick = function() {
|
||
|
var recorder = connection.recorder;
|
||
|
if(!recorder) return alert('No recorder found.');
|
||
|
recorder.stopRecording(function() {
|
||
|
var blob = recorder.getBlob();
|
||
|
invokeSaveAsDialog(blob);
|
||
|
|
||
|
connection.recorder = null;
|
||
|
btnStopRecording.style.display = 'none';
|
||
|
recordingStatus.style.display = 'none';
|
||
|
chkRecordConference.parentNode.style.display = 'none';
|
||
|
recordingtime.style.display = 'none';
|
||
|
});
|
||
|
};
|
||
|
|
||
|
connection.onstreamended = function(event) {
|
||
|
var mediaElement = document.getElementById(event.streamid);
|
||
|
if (mediaElement) {
|
||
|
mediaElement.parentNode.removeChild(mediaElement);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
connection.onMediaError = function(e) {
|
||
|
if (e.message === 'Concurrent mic process limit.') {
|
||
|
if (DetectRTC.audioInputDevices.length <= 1) {
|
||
|
alert('Please select external microphone. Check github issue number 483.');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var secondaryMic = DetectRTC.audioInputDevices[1].deviceId;
|
||
|
connection.mediaConstraints.audio = {
|
||
|
deviceId: secondaryMic
|
||
|
};
|
||
|
|
||
|
connection.join(connection.sessionid);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ..................................
|
||
|
// ALL below scripts are redundant!!!
|
||
|
// ..................................
|
||
|
|
||
|
function disableInputButtonsView() {
|
||
|
//document.getElementById('room-id').onkeyup();
|
||
|
|
||
|
document.getElementById('record-entire-conference').style.display = "none";
|
||
|
document.getElementById('record').style.display = "none";
|
||
|
document.getElementById('header').style.display = "none";
|
||
|
document.getElementById('nav').style.display = "none";
|
||
|
document.getElementById('footer').style.display = "none";
|
||
|
document.getElementById('open-room').disabled = true;
|
||
|
document.getElementById('webcam-share').disabled = true;
|
||
|
document.getElementById('screen-share').disabled = true;
|
||
|
document.getElementById('room-id').disabled = true;
|
||
|
}
|
||
|
|
||
|
function disableInputButtons(enable) {
|
||
|
//document.getElementById('room-id').onkeyup();
|
||
|
|
||
|
document.getElementById('record-entire-conference').style.display = "none";
|
||
|
document.getElementById('record').style.display = "none";
|
||
|
document.getElementById('header').style.display = "none";
|
||
|
document.getElementById('open-room').disabled = !enable;
|
||
|
document.getElementById('webcam-share').disabled = !enable;
|
||
|
document.getElementById('screen-share').disabled = !enable;
|
||
|
document.getElementById('room-id').disabled = !enable;
|
||
|
}
|
||
|
|
||
|
// ......................................................
|
||
|
// ......................Handling Room-ID................
|
||
|
// ......................................................
|
||
|
|
||
|
function showRoomURL(roomid, source, width) {
|
||
|
var roomHashURL = '#' + roomid;
|
||
|
var roomQueryStringURL = '?roomid=' + roomid;
|
||
|
var roomViewQueryStringURL = '?action=view&roomid=' + roomid;
|
||
|
|
||
|
var html = '<h3>Share URLs:</h3><br>';
|
||
|
|
||
|
//html += 'Hash URL: <a href="' + roomHashURL + '" target="_blank">' + roomHashURL + '</a>';
|
||
|
//html += '<br>';
|
||
|
if (source == 'group') {
|
||
|
html += 'Join URL: <a href="' + roomQueryStringURL + '" target="_blank">' + roomQueryStringURL + '</a>';
|
||
|
html += '<br />';
|
||
|
}
|
||
|
|
||
|
html += 'View URL: <a href="' + roomViewQueryStringURL + '" target="_blank">' + roomViewQueryStringURL + '</a>';
|
||
|
html += '<br />';
|
||
|
html += 'View URL OBS (360p): <a href="view.html' + roomViewQueryStringURL + '&width=640" target="_blank">view.html' + roomViewQueryStringURL + '&width=640</a>';
|
||
|
html += '<br />';
|
||
|
html += 'View URL OBS (720p): <a href="view.html' + roomViewQueryStringURL + '&width=1280" target="_blank">view.html' + roomViewQueryStringURL + '&width=1280</a>';
|
||
|
html += '<br />';
|
||
|
html += 'View URL OBS (1080p): <a href="view.html' + roomViewQueryStringURL + '&width=1920" target="_blank">view.html' + roomViewQueryStringURL + '&width=1920</a>';
|
||
|
|
||
|
|
||
|
var roomURLsDiv = document.getElementById('room-urls');
|
||
|
roomURLsDiv.innerHTML = html;
|
||
|
|
||
|
roomURLsDiv.style.display = 'block';
|
||
|
}
|
||
|
|
||
|
(function() {
|
||
|
var params = {},
|
||
|
r = /([^&=]+)=?([^&]*)/g;
|
||
|
|
||
|
function d(s) {
|
||
|
return decodeURIComponent(s.replace(/\+/g, ' '));
|
||
|
}
|
||
|
var match, search = window.location.search;
|
||
|
while (match = r.exec(search.substring(1)))
|
||
|
params[d(match[1])] = d(match[2]);
|
||
|
window.params = params;
|
||
|
console.log(params);
|
||
|
})();
|
||
|
|
||
|
function genID() {
|
||
|
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||
|
var idsize = 8;
|
||
|
var streamid = '';
|
||
|
for (var i = 0; i < idsize; i++) {
|
||
|
streamid += chars.charAt(Math.floor(Math.random() * chars.length));
|
||
|
}
|
||
|
return streamid;
|
||
|
}
|
||
|
|
||
|
var roomid = '';
|
||
|
//if (localStorage.getItem(connection.socketMessageEvent)) {
|
||
|
// roomid = localStorage.getItem(connection.socketMessageEvent);
|
||
|
//} else {
|
||
|
// roomid = genID();
|
||
|
// console.log('roomid gen: ' + roomid);
|
||
|
//}
|
||
|
roomid = genID();
|
||
|
console.log('roomid gen: ' + roomid);
|
||
|
|
||
|
var txtRoomId = document.getElementById('room-id');
|
||
|
txtRoomId.value = roomid;
|
||
|
//txtRoomId.onkeyup = txtRoomId.oninput = txtRoomId.onpaste = function() {
|
||
|
// localStorage.setItem(connection.socketMessageEvent, document.getElementById('room-id').value);
|
||
|
//};
|
||
|
|
||
|
var hashString = location.hash.replace('#', '');
|
||
|
if (hashString.length && hashString.indexOf('comment-') == 0) {
|
||
|
hashString = '';
|
||
|
}
|
||
|
|
||
|
var roomid = params.roomid;
|
||
|
if (!roomid && hashString.length) {
|
||
|
roomid = hashString;
|
||
|
}
|
||
|
|
||
|
var action = params.action
|
||
|
|
||
|
if (roomid && roomid.length) {
|
||
|
document.getElementById('room-id').value = roomid;
|
||
|
//localStorage.setItem(connection.socketMessageEvent, roomid);
|
||
|
|
||
|
if (action && action == 'join') {
|
||
|
connection.join(roomid);
|
||
|
}
|
||
|
// auto-join-room
|
||
|
(function reCheckRoomPresence() {
|
||
|
connection.checkPresence(roomid, function(isRoomExist) {
|
||
|
if (isRoomExist) {
|
||
|
if (action && action == 'view') {
|
||
|
connection.sdpConstraints.mandatory = {
|
||
|
OfferToReceiveAudio: true,
|
||
|
OfferToReceiveVideo: true
|
||
|
};
|
||
|
connection.session = {
|
||
|
audio: true,
|
||
|
video: true,
|
||
|
oneway: true
|
||
|
};
|
||
|
connection.join(roomid);
|
||
|
disableInputButtonsView();
|
||
|
return;
|
||
|
} else {
|
||
|
connection.openOrJoin(roomid);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
setTimeout(reCheckRoomPresence, 5000);
|
||
|
});
|
||
|
})();
|
||
|
disableInputButtons();
|
||
|
}
|
||
|
|
||
|
// detect 2G
|
||
|
if(navigator.connection &&
|
||
|
navigator.connection.type === 'cellular' &&
|
||
|
navigator.connection.downlinkMax <= 0.115) {
|
||
|
alert('2G is not supported. Please use a better internet service.');
|
||
|
}
|
||
|
|
||
|
$(document).ready(function(){
|
||
|
$('#preview-webcam').on('shown.bs.modal', function (e) {
|
||
|
console.log('starting preview');
|
||
|
|
||
|
const videoElement = document.querySelector('#videoPreview');
|
||
|
const audioInputSelect = document.querySelector('select#audioSource');
|
||
|
const videoSelect = document.querySelector('select#videoSource');
|
||
|
const selectors = [audioInputSelect, videoSelect];
|
||
|
|
||
|
function gotDevices(deviceInfos) {
|
||
|
const values = selectors.map(select => select.value);
|
||
|
selectors.forEach(select => {
|
||
|
while (select.firstChild) {
|
||
|
select.removeChild(select.firstChild);
|
||
|
}
|
||
|
});
|
||
|
for (let i = 0; i !== deviceInfos.length; ++i) {
|
||
|
const deviceInfo = deviceInfos[i];
|
||
|
const option = document.createElement('option');
|
||
|
option.value = deviceInfo.deviceId;
|
||
|
if (deviceInfo.kind === 'audioinput') {
|
||
|
option.text = deviceInfo.label || `microphone ${audioInputSelect.length + 1}`;
|
||
|
audioInputSelect.appendChild(option);
|
||
|
} else if (deviceInfo.kind === 'videoinput') {
|
||
|
option.text = deviceInfo.label || `camera ${videoSelect.length + 1}`;
|
||
|
videoSelect.appendChild(option);
|
||
|
} else {
|
||
|
console.log('Some other kind of source/device: ', deviceInfo);
|
||
|
}
|
||
|
}
|
||
|
selectors.forEach((select, selectorIndex) => {
|
||
|
if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
|
||
|
select.value = values[selectorIndex];
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var max_level_L = 0;
|
||
|
var old_level_L = 0;
|
||
|
var cnvs = document.getElementById("vumeter");
|
||
|
var cnvs_cntxt = cnvs.getContext("2d");
|
||
|
|
||
|
function gotStream(stream) {
|
||
|
window.stream = stream;
|
||
|
videoElement.srcObject = stream;
|
||
|
|
||
|
var audioContext = new AudioContext();
|
||
|
var microphone = audioContext.createMediaStreamSource(stream);
|
||
|
var javascriptNode = audioContext.createScriptProcessor(1024, 1, 1);
|
||
|
|
||
|
microphone.connect(javascriptNode);
|
||
|
javascriptNode.connect(audioContext.destination);
|
||
|
javascriptNode.onaudioprocess = function(event) {
|
||
|
|
||
|
var inpt_L = event.inputBuffer.getChannelData(0);
|
||
|
var instant_L = 0.0;
|
||
|
|
||
|
var sum_L = 0.0;
|
||
|
for(var i = 0; i < inpt_L.length; ++i) {
|
||
|
sum_L += inpt_L[i] * inpt_L[i];
|
||
|
}
|
||
|
instant_L = Math.sqrt(sum_L / inpt_L.length);
|
||
|
max_level_L = Math.max(max_level_L, instant_L);
|
||
|
instant_L = Math.max( instant_L, old_level_L -0.008 );
|
||
|
old_level_L = instant_L;
|
||
|
|
||
|
cnvs_cntxt.clearRect(0, 0, cnvs.width, cnvs.height);
|
||
|
cnvs_cntxt.fillStyle = '#00ff00';
|
||
|
cnvs_cntxt.fillRect(10,10,(cnvs.width-20)*(instant_L/max_level_L),(cnvs.height-20)); // x,y,w,h
|
||
|
}
|
||
|
|
||
|
return navigator.mediaDevices.enumerateDevices();
|
||
|
}
|
||
|
|
||
|
function handleError(error) {
|
||
|
console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
|
||
|
if (error.name == 'NotAllowedError') {
|
||
|
//document.getElementById('container-preview').style.display = "none";
|
||
|
//document.getElementById('webcam-share').style.display = "none";
|
||
|
alert("No devices found. Please check browser permissions for audio/video devices.");
|
||
|
window.location.href = "index.html";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function start() {
|
||
|
if (window.stream) {
|
||
|
window.stream.getTracks().forEach(track => {
|
||
|
track.stop();
|
||
|
});
|
||
|
}
|
||
|
const audioSource = audioInputSelect.value;
|
||
|
const videoSource = videoSelect.value;
|
||
|
const constraints = {
|
||
|
audio: {deviceId: audioSource ? {exact: audioSource} : undefined},
|
||
|
video: {deviceId: videoSource ? {exact: videoSource} : undefined}
|
||
|
};
|
||
|
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
|
||
|
}
|
||
|
|
||
|
navigator.mediaDevices.enumerateDevices().then(gotDevices);
|
||
|
audioInputSelect.onchange = start;
|
||
|
videoSelect.onchange = start;
|
||
|
start();
|
||
|
})
|
||
|
|
||
|
$('#preview-webcam').on('hide.bs.modal', function (e) {
|
||
|
console.log('stoping preview');
|
||
|
var preview = document.querySelector("#videoPreview");
|
||
|
|
||
|
if (preview.srcObject) {
|
||
|
var stream = preview.srcObject;
|
||
|
var tracks = stream.getTracks();
|
||
|
|
||
|
for (var i = 0; i < tracks.length; i++) {
|
||
|
var track = tracks[i];
|
||
|
track.stop();
|
||
|
}
|
||
|
|
||
|
preview.srcObject = null;
|
||
|
}
|
||
|
})
|
||
|
|
||
|
$('#webcam-share').click(function(){
|
||
|
console.log('starting share');
|
||
|
$('#preview-webcam').modal('hide');
|
||
|
})
|
||
|
});
|
||
|
|
||
|
</script>
|
||
|
</body>
|
||
|
|
||
|
</html>
|