Permalink
Fetching contributors…
Cannot retrieve contributors at this time
executable file 494 lines (391 sloc) 19.9 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.webrtc-experiment.com/style.css">
<title>Switch+Cameras using RTCMultiConnection</title>
<meta name="description" content="Switch/Change Cameras in a live conference using RTCMultiConnection" />
<meta name="keywords" content="WebRTC,RTCMultiConnection,Demos,Experiments,Samples,Examples" />
<style>
video {
width: 100%;
}
button,
input,
select {
font-weight: normal;
padding: 2px 4px;
text-decoration: none;
display: inline-block;
text-shadow: none;
font-size: 16px;
outline: none;
}
.make-center {
text-align: center;
padding: 5px 10px;
}
.video-parent-container {
display: inline-block;
border: 2px solid black;
margin: 2px 5px;
border-radius: 5px;
object-fit: fill;
width: 42%;
background: black;
}
</style>
</head>
<body>
<article>
<header style="text-align: center;">
<h1>Switch+Cameras using RTCMultiConnection</h1>
<p>
<a href="https://rtcmulticonnection.herokuapp.com/">HOME</a>
<span> &copy; </span>
<a href="http://www.MuazKhan.com/" target="_blank">Muaz Khan</a> .
<a href="http://twitter.com/WebRTCWeb" target="_blank" title="Twitter profile for WebRTC Experiments">@WebRTCWeb</a> .
<a href="https://github.com/muaz-khan?tab=repositories" target="_blank" title="Github Profile">Github</a> .
<a href="https://github.com/muaz-khan/RTCMultiConnection/issues?state=open" target="_blank">Latest issues</a> .
<a href="https://github.com/muaz-khan/RTCMultiConnection/commits/master" target="_blank">What's New?</a>
</p>
</header>
<div class="github-stargazers"></div>
<section class="experiment">
<div class="make-center">
<input type="text" id="room-id" value="abcdef">
<button id="open-room">Open Room</button>
<button id="join-room">Join Room</button>
<button id="open-or-join-room">Auto Open Or Join Room</button>
<div id="room-urls" style="text-align: center;display: none;background: #F1EDED;margin: 15px -10px;border: 1px solid rgb(189, 189, 189);border-left: 0;border-right: 0;"></div>
<br><br>
<label for="audio-devices">Audio Devices:</label>
<select id="audio-devices" disabled></select>
<br>
<label for="video-devices">Video Devices:</label>
<select id="video-devices" disabled></select>
<br>
<button id="switch-camera" disabled>Switch Webcam</button>
<button id="switch-microphone" disabled>Switch Microphone</button>
</div>
<div id="videos-container"></div>
</section>
<script src="/dist/RTCMultiConnection.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
// ......................................................
// .......................UI Code........................
// ......................................................
document.getElementById('open-room').onclick = function() {
disableInputButtons();
connection.open(document.getElementById('room-id').value, function() {
showRoomURL(connection.sessionid);
});
};
document.getElementById('join-room').onclick = function() {
disableInputButtons();
connection.join(document.getElementById('room-id').value);
};
document.getElementById('open-or-join-room').onclick = function() {
disableInputButtons();
connection.openOrJoin(document.getElementById('room-id').value, function(isRoomExists, roomid) {
if(!isRoomExists) {
showRoomURL(roomid);
}
});
};
var chatContainer = document.querySelector('.chat-output');
function appendDIV(event) {
var div = document.createElement('div');
div.innerHTML = event.data || event;
chatContainer.insertBefore(div, chatContainer.firstChild);
div.tabIndex = 0;
div.focus();
document.getElementById('input-text-chat').focus();
}
// ......................................................
// ..................RTCMultiConnection Code.............
// ......................................................
var connection = new RTCMultiConnection();
// by default, socket.io server is assumed to be deployed on your own URL
connection.socketURL = '/';
// comment-out below line if you do not have your own socket.io server
// connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';
connection.socketMessageEvent = 'switch-cameras-demo';
connection.socketCustomEvent = connection.channel;
connection.session = {
audio: true,
video: true
};
connection.sdpConstraints.mandatory = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
};
function receiveCustomMessages() {
connection.connectSocket(function(socket) {
socket.on(connection.socketCustomEvent, function(message) {
if(message.remoteUserId !== connection.userid) return;
if(!message.reloadVideo) return;
var streamEvent = connection.streamEvents[message.streamid];
if(!streamEvent) return;
var videoParentNode = document.getElementById(message.userid);
if(!videoParentNode) return;
setTimeout(function() {
videoParentNode.querySelector('video').src = URL.createObjectURL(streamEvent.stream);
videoParentNode.querySelector('video').play();
}, 2000);
});
});
}
var videosContainer = document.getElementById('videos-container');
connection.onstream = function(event) {
event.mediaElement.id = '';
if(event.mediaElement) {
event.mediaElement.muted = true;
delete event.mediaElement;
}
if(event.stream.mediaElement) {
event.stream.mediaElement.muted = true;
delete event.stream.mediaElement;
}
var videoParentNode = document.getElementById(event.userid);
if(videoParentNode && event.type == 'local') {
var oldStream;
connection.attachStreams.forEach(function(stream) {
if(stream.streamid !== event.stream.streamid) {
oldStream = stream;
}
});
if(!oldStream) {
oldStream = connection.attachStreams[0];
if(!oldStream) return;
}
if(event.stream.getAudioTracks().length) {
oldStream.addTrack(event.stream.getAudioTracks()[0]);
}
if(event.stream.getVideoTracks().length) {
oldStream.addTrack(event.stream.getVideoTracks()[0]);
}
connection.attachStreams = [oldStream];
videoParentNode.querySelector('video').src = URL.createObjectURL(oldStream);
videoParentNode.querySelector('video').play();
connection.renegotiate();
connection.connectSocket(function(socket) {
connection.getAllParticipants().forEach(function(participantId) {
socket.emit(connection.socketCustomEvent, {
remoteUserId: participantId,
reloadVideo: true,
userid: connection.userid,
streamid: oldStream.streamid
});
});
});
return;
}
videoParentNode = document.createElement('div');
videoParentNode.id = event.userid;
videoParentNode.className = 'video-parent-container';
var video = document.createElement('video');
video.src = URL.createObjectURL(event.stream);
video.controls = true;
videoParentNode.appendChild(video);
video.play();
videosContainer.appendChild(videoParentNode);
if(event.type === 'remote' && !connection.alreadyHandlingRemoteMessages) {
connection.alreadyHandlingRemoteMessages = true;
receiveCustomMessages();
document.getElementById('switch-camera').disabled = false;
document.getElementById('switch-microphone').disabled = false;
videoDevices.disabled = false;
audioDevices.disabled = false;
}
};
connection.onSettingLocalDescription = function(event) {
var tries = 0;
(function looper() {
if(tries > 10) return; // try till 10 seconds
tries++;
connection.getAllParticipants().forEach(function(p) {
var div = document.getElementById(p);
if(!div) return;
var video = div.querySelector('video');
if(!video || !!video.currentTime) return;
video.src = URL.createObjectURL(connection.peers[p].peer.getRemoteStreams()[0]);
video.play();
});
setTimeout(looper, 1000);
})();
};
connection.onstreamended = function(event) {
var div = document.getElementById(event.userid);
if(div && div.parentNode) {
div.parentNode.removeChild(div);
}
};
var videoDevices = document.getElementById('video-devices');
var audioDevices = document.getElementById('audio-devices');
connection.DetectRTC.load(function() {
connection.DetectRTC.MediaDevices.forEach(function(device) {
if(document.getElementById(device.id)) {
return;
}
if(device.kind === 'audioinput') {
var option = document.createElement('option');
option.id = device.id;
option.innerHTML = device.label || device.id;
option.value = device.id;
audioDevices.appendChild(option);
if(connection.mediaConstraints.audio.optional.length && connection.mediaConstraints.audio.optional[0].sourceId === device.id) {
option.selected = true;
}
}
if(device.kind.indexOf('video') !== -1) {
var option = document.createElement('option');
option.id = device.id;
option.innerHTML = device.label || device.id;
option.value = device.id;
videoDevices.appendChild(option);
if(connection.mediaConstraints.video.optional.length && connection.mediaConstraints.video.optional[0].sourceId === device.id) {
option.selected = true;
}
}
});
});
document.getElementById('switch-camera').onclick = function() {
var videoSourceId = videoDevices.value;
if(connection.mediaConstraints.video.optional.length && connection.attachStreams.length) {
if(connection.mediaConstraints.video.optional[0].sourceId === videoSourceId) {
alert('Selected video device is already selected.');
return;
}
}
connection.attachStreams.forEach(function(stream) {
stream.getVideoTracks().forEach(function(track) {
stream.removeTrack(track);
if(track.stop) {
track.stop();
}
});
});
connection.mediaConstraints.video.optional = [{
sourceId: videoSourceId
}];
connection.captureUserMedia();
};
document.getElementById('switch-microphone').onclick = function() {
var audioSourceId = audioDevices.value;
if(connection.mediaConstraints.audio.optional.length && connection.attachStreams.length) {
if(connection.mediaConstraints.audio.optional[0].sourceId === audioSourceId) {
alert('Selected audio device is already selected.');
return;
}
}
connection.attachStreams.forEach(function(stream) {
stream.getAudioTracks().forEach(function(track) {
stream.removeTrack(track);
if(track.stop) {
track.stop();
}
});
});
connection.mediaConstraints.audio.optional = [{
sourceId: videoSourceId
}];
connection.captureUserMedia();
};
function disableInputButtons() {
document.getElementById('open-or-join-room').disabled = true;
document.getElementById('open-room').disabled = true;
document.getElementById('join-room').disabled = true;
document.getElementById('room-id').disabled = true;
}
// ......................................................
// ......................Handling Room-ID................
// ......................................................
function showRoomURL(roomid) {
var roomHashURL = '#' + roomid;
var roomQueryStringURL = '?roomid=' + roomid;
var html = '<h2>Unique URL for your room:</h2><br>';
html += 'Hash URL: <a href="' + roomHashURL + '" target="_blank">' + roomHashURL + '</a>';
html += '<br>';
html += 'QueryString URL: <a href="' + roomQueryStringURL + '" target="_blank">' + roomQueryStringURL + '</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;
})();
var roomid = '';
if (localStorage.getItem(connection.socketMessageEvent)) {
roomid = localStorage.getItem(connection.socketMessageEvent);
} else {
roomid = connection.token();
}
document.getElementById('room-id').value = roomid;
document.getElementById('room-id').onkeyup = function() {
localStorage.setItem(connection.socketMessageEvent, this.value);
};
var hashString = location.hash.replace('#', '');
if(hashString.length && hashString.indexOf('comment-') == 0) {
hashString = '';
}
var roomid = params.roomid;
if(!roomid && hashString.length) {
roomid = hashString;
}
if(roomid && roomid.length) {
document.getElementById('room-id').value = roomid;
localStorage.setItem(connection.socketMessageEvent, roomid);
// auto-join-room
(function reCheckRoomPresence() {
connection.checkPresence(roomid, function(isRoomExists) {
if(isRoomExists) {
connection.join(roomid);
return;
}
setTimeout(reCheckRoomPresence, 5000);
});
})();
disableInputButtons();
}
</script>
<section class="experiment own-widgets latest-commits">
<h2 class="header" id="updates" style="color: red;padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RTCMultiConnection/commits/master">Latest Updates</a></h2>
<div id="github-commits"></div>
</section>
<section class="experiment own-widgets">
<h2 class="header" id="updates" style="color: red;padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RTCMultiConnection/issues">Latest Issues</a></h2>
<div id="github-issues"></div>
</section>
<section class="experiment">
<h2 class="header" id="feedback">Feedback</h2>
<div>
<textarea id="message" style="height: 8em; margin: .2em; width: 98%; border: 1px solid rgb(189, 189, 189); outline: none; resize: vertical;" placeholder="Have any message? Suggestions or something went wrong?"></textarea>
</div>
<button id="send-message" style="font-size: 1em;">Send Message</button><small style="margin-left:1em;">Enter your email too; if you want "direct" reply!</small>
</section>
<a href="https://github.com/muaz-khan/RTCMultiConnection" class="fork-left"></a>
<script>
window.useThisGithubPath = 'muaz-khan/RTCMultiConnection';
</script>
<script src="https://cdn.webrtc-experiment.com/commits.js" async></script>
</article>
<footer>
<p>
<a href="https://www.webrtc-experiment.com">WebRTC Experiments</a> © <a href="https://plus.google.com/+MuazKhan" rel="author" target="_blank">Muaz Khan</a>
<a href="mailto:muazkh@gmail.com" target="_blank">muazkh@gmail.com</a>
<a href="https://github.com/muaz-khan" target="_blank">Github</a>
</p>
</footer>
</body>
</html>