Initial commit of Twilio Server Starter for Python

This commit is contained in:
Jeffrey Linwood
2016-11-14 10:41:18 -06:00
parent 5430cce36c
commit 49b3c6d012
20 changed files with 1259 additions and 2 deletions

29
static/video/index.html Executable file
View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Twilio Video - Video Quickstart</title>
<link rel="stylesheet" href="site.css">
</head>
<body>
<div id="remote-media"></div>
<div id="controls">
<div id="preview">
<p class="instructions">Hello Beautiful</p>
<div id="local-media"></div>
<button id="button-preview">Preview My Camera</button>
</div>
<div id="room-controls">
<p class="instructions">Room Name:</p>
<input id="room-name" type="text" placeholder="Enter a room name" />
<button id="button-join">Join Room</button>
<button id="button-leave">Leave Room</button>
</div>
<div id="log"></div>
</div>
<script src="//media.twiliocdn.com/sdk/js/common/v0.1/twilio-common.min.js"></script>
<script src="//media.twiliocdn.com/sdk/js/video/releases/1.0.0-beta2/twilio-video.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="quickstart.js"></script>
</body>
</html>

120
static/video/quickstart.js Executable file
View File

@@ -0,0 +1,120 @@
var videoClient;
var activeRoom;
var previewMedia;
var identity;
var roomName;
// Check for WebRTC
if (!navigator.webkitGetUserMedia && !navigator.mozGetUserMedia) {
alert('WebRTC is not available in your browser.');
}
// When we are about to transition away from this page, disconnect
// from the room, if joined.
window.addEventListener('beforeunload', leaveRoomIfJoined);
$.getJSON('/token', function (data) {
identity = data.identity;
// Create a Conversations Client and connect to Twilio
videoClient = new Twilio.Video.Client(data.token);
document.getElementById('room-controls').style.display = 'block';
// Bind button to join room
document.getElementById('button-join').onclick = function () {
roomName = document.getElementById('room-name').value;
if (roomName) {
log("Joining room '" + roomName + "'...");
videoClient.connect({ to: roomName}).then(roomJoined,
function(error) {
log('Could not connect to Twilio: ' + error.message);
});
} else {
alert('Please enter a room name.');
}
};
// Bind button to leave room
document.getElementById('button-leave').onclick = function () {
log('Leaving room...');
activeRoom.disconnect();
};
});
// Successfully connected!
function roomJoined(room) {
activeRoom = room;
log("Joined as '" + identity + "'");
document.getElementById('button-join').style.display = 'none';
document.getElementById('button-leave').style.display = 'inline';
// Draw local video, if not already previewing
if (!previewMedia) {
room.localParticipant.media.attach('#local-media');
}
room.participants.forEach(function(participant) {
log("Already in Room: '" + participant.identity + "'");
participant.media.attach('#remote-media');
});
// When a participant joins, draw their video on screen
room.on('participantConnected', function (participant) {
log("Joining: '" + participant.identity + "'");
participant.media.attach('#remote-media');
participant.on('disconnected', function (participant) {
log("Participant '" + participant.identity + "' left the room");
});
});
// When a participant disconnects, note in log
room.on('participantDisconnected', function (participant) {
log("Participant '" + participant.identity + "' left the room");
participant.media.detach();
});
// When the conversation ends, stop capturing local video
// Also remove media for all remote participants
room.on('disconnected', function () {
log('Left');
room.localParticipant.media.detach();
room.participants.forEach(function(participant) {
participant.media.detach();
});
activeRoom = null;
document.getElementById('button-join').style.display = 'inline';
document.getElementById('button-leave').style.display = 'none';
});
}
// Local video preview
document.getElementById('button-preview').onclick = function () {
if (!previewMedia) {
previewMedia = new Twilio.Video.LocalMedia();
Twilio.Video.getUserMedia().then(
function (mediaStream) {
previewMedia.addStream(mediaStream);
previewMedia.attach('#local-media');
},
function (error) {
console.error('Unable to access local media', error);
log('Unable to access Camera and Microphone');
});
};
};
// Activity log
function log(message) {
var logDiv = document.getElementById('log');
logDiv.innerHTML += '<p>&gt;&nbsp;' + message + '</p>';
logDiv.scrollTop = logDiv.scrollHeight;
}
function leaveRoomIfJoined() {
if (activeRoom) {
activeRoom.disconnect();
}
}

144
static/video/site.css Executable file
View File

@@ -0,0 +1,144 @@
@import url(https://fonts.googleapis.com/css?family=Share+Tech+Mono);
body,
p {
padding: 0;
margin: 0;
}
body {
background: #272726;
}
div#remote-media {
height: 43%;
width: 100%;
background-color: #fff;
text-align: center;
margin: auto;
}
div#remote-media video {
border: 1px solid #272726;
margin: 3em 2em;
height: 70%;
max-width: 27% !important;
background-color: #272726;
background-repeat: no-repeat;
}
div#controls {
padding: 3em;
max-width: 1200px;
margin: 0 auto;
}
div#controls div {
float: left;
}
div#controls div#room-controls,
div#controls div#preview {
width: 16em;
margin: 0 1.5em;
text-align: center;
}
div#controls p.instructions {
text-align: left;
margin-bottom: 1em;
font-family: Helvetica-LightOblique, Helvetica, sans-serif;
font-style: oblique;
font-size: 1.25em;
color: #777776;
}
div#controls button {
width: 15em;
height: 2.5em;
margin-top: 1.75em;
border-radius: 1em;
font-family: "Helvetica Light", Helvetica, sans-serif;
font-size: .8em;
font-weight: lighter;
outline: 0;
}
div#controls div#room-controls input {
font-family: Helvetica-LightOblique, Helvetica, sans-serif;
font-style: oblique;
font-size: 1em;
}
div#controls button:active {
position: relative;
top: 1px;
}
div#controls div#preview div#local-media {
width: 270px;
height: 202px;
border: 1px solid #cececc;
box-sizing: border-box;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjgwcHgiIGhlaWdodD0iODBweCIgdmlld0JveD0iMCAwIDgwIDgwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOnNrZXRjaD0iaHR0cDovL3d3dy5ib2hlbWlhbmNvZGluZy5jb20vc2tldGNoL25zIj4KICAgIDwhLS0gR2VuZXJhdG9yOiBTa2V0Y2ggMy4zLjEgKDEyMDAyKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5GaWxsIDUxICsgRmlsbCA1MjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJjdW1tYWNrIiBza2V0Y2g6dHlwZT0iTVNMYXllckdyb3VwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTU5LjAwMDAwMCwgLTE3NDYuMDAwMDAwKSIgZmlsbD0iI0ZGRkZGRiI+CiAgICAgICAgICAgIDxnIGlkPSJGaWxsLTUxLSstRmlsbC01MiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU5LjAwMDAwMCwgMTc0Ni4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zOS42ODYsMC43MyBDMTcuODUsMC43MyAwLjA4NSwxOC41IDAuMDg1LDQwLjMzIEMwLjA4NSw2Mi4xNyAxNy44NSw3OS45MyAzOS42ODYsNzkuOTMgQzYxLjUyMiw3OS45MyA3OS4yODcsNjIuMTcgNzkuMjg3LDQwLjMzIEM3OS4yODcsMTguNSA2MS41MjIsMC43MyAzOS42ODYsMC43MyBMMzkuNjg2LDAuNzMgWiBNMzkuNjg2LDEuNzMgQzYxLjAwNSwxLjczIDc4LjI4NywxOS4wMiA3OC4yODcsNDAuMzMgQzc4LjI4Nyw2MS42NSA2MS4wMDUsNzguOTMgMzkuNjg2LDc4LjkzIEMxOC4zNjcsNzguOTMgMS4wODUsNjEuNjUgMS4wODUsNDAuMzMgQzEuMDg1LDE5LjAyIDE4LjM2NywxLjczIDM5LjY4NiwxLjczIEwzOS42ODYsMS43MyBaIiBpZD0iRmlsbC01MSI+PC9wYXRoPgogICAgICAgICAgICAgICAgPHBhdGggZD0iTTQ3Ljk2LDUzLjMzNSBMNDcuOTYsNTIuODM1IEwyMC4wOTMsNTIuODM1IEwyMC4wOTMsMjcuODI1IEw0Ny40NiwyNy44MjUgTDQ3LjQ2LDM4LjI1NSBMNTkuMjc5LDMwLjgwNSBMNTkuMjc5LDQ5Ljg1NSBMNDcuNDYsNDIuNDA1IEw0Ny40Niw1My4zMzUgTDQ3Ljk2LDUzLjMzNSBMNDcuOTYsNTIuODM1IEw0Ny45Niw1My4zMzUgTDQ4LjQ2LDUzLjMzNSBMNDguNDYsNDQuMjE1IEw2MC4yNzksNTEuNjY1IEw2MC4yNzksMjguOTk1IEw0OC40NiwzNi40NDUgTDQ4LjQ2LDI2LjgyNSBMMTkuMDkzLDI2LjgyNSBMMTkuMDkzLDUzLjgzNSBMNDguNDYsNTMuODM1IEw0OC40Niw1My4zMzUgTDQ3Ljk2LDUzLjMzNSIgaWQ9IkZpbGwtNTIiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+);
background-position: center;
background-repeat: no-repeat;
margin: 0 auto;
}
div#controls div#preview div#local-media video {
max-width: 100%;
max-height: 100%;
border: none;
}
div#controls div#preview button#button-preview {
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE3cHgiIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDE3IDEyIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOnNrZXRjaD0iaHR0cDovL3d3dy5ib2hlbWlhbmNvZGluZy5jb20vc2tldGNoL25zIj4KICAgIDwhLS0gR2VuZXJhdG9yOiBTa2V0Y2ggMy4zLjEgKDEyMDAyKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5GaWxsIDM0PC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGRlZnM+PC9kZWZzPgogICAgPGcgaWQ9IlBhZ2UtMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc2tldGNoOnR5cGU9Ik1TUGFnZSI+CiAgICAgICAgPGcgaWQ9ImN1bW1hY2siIHNrZXRjaDp0eXBlPSJNU0xheWVyR3JvdXAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xMjUuMDAwMDAwLCAtMTkwOS4wMDAwMDApIiBmaWxsPSIjMEEwQjA5Ij4KICAgICAgICAgICAgPHBhdGggZD0iTTEzNi40NzEsMTkxOS44NyBMMTM2LjQ3MSwxOTE5LjYyIEwxMjUuNzY3LDE5MTkuNjIgTDEyNS43NjcsMTkxMC4wOCBMMTM2LjIyMSwxOTEwLjA4IEwxMzYuMjIxLDE5MTQuMTUgTDE0MC43ODUsMTkxMS4yNyBMMTQwLjc4NSwxOTE4LjQyIEwxMzYuMjIxLDE5MTUuNTUgTDEzNi4yMjEsMTkxOS44NyBMMTM2LjQ3MSwxOTE5Ljg3IEwxMzYuNDcxLDE5MTkuNjIgTDEzNi40NzEsMTkxOS44NyBMMTM2LjcyMSwxOTE5Ljg3IEwxMzYuNzIxLDE5MTYuNDUgTDE0MS4yODUsMTkxOS4zMyBMMTQxLjI4NSwxOTEwLjM3IEwxMzYuNzIxLDE5MTMuMjQgTDEzNi43MjEsMTkwOS41OCBMMTI1LjI2NywxOTA5LjU4IEwxMjUuMjY3LDE5MjAuMTIgTDEzNi43MjEsMTkyMC4xMiBMMTM2LjcyMSwxOTE5Ljg3IEwxMzYuNDcxLDE5MTkuODciIGlkPSJGaWxsLTM0IiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj48L3BhdGg+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=)1em center no-repeat #fff;
border: none;
padding-left: 1.5em;
}
div#controls div#log {
border: 1px solid #686865;
}
div#controls div#room-controls {
display: none;
}
div#controls div#room-controls input {
width: 100%;
height: 2.5em;
padding: .5em;
display: block;
}
div#controls div#room-controls button {
color: #fff;
background: 0 0;
border: 1px solid #686865;
}
div#controls div#room-controls button#button-leave {
display: none;
}
div#controls div#log {
width: 35%;
height: 9.5em;
margin-top: 2.75em;
text-align: left;
padding: 1.5em;
float: right;
overflow-y: scroll;
}
div#controls div#log p {
color: #686865;
font-family: 'Share Tech Mono', 'Courier New', Courier, fixed-width;
font-size: 1.25em;
line-height: 1.25em;
margin-left: 1em;
text-indent: -1.25em;
width: 90%;
}