Skip to content

Commit f737dd5

Browse files
JSDK-2353 Adding an example for capturing screen using getDisplayMedia(). (#71)
1 parent b27dd7c commit f737dd5

File tree

9 files changed

+341
-2
lines changed

9 files changed

+341
-2
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,12 @@ examples/codecpreferences/public/index.js
5353
examples/localvideofilter/public/index.js
5454
examples/localvideosnapshot/public/index.js
5555
examples/mediadevices/public/index.js
56+
examples/screenshare/public/index.js
5657

5758
# The generated helpers.js
5859
examples/bandwidthconstraints/public/helpers.js
5960
examples/codecpreferences/public/helpers.js
6061
examples/localvideofilter/public/helpers.js
6162
examples/localvideosnapshot/public/helpers.js
6263
examples/mediadevices/public/helpers.js
64+
examples/screenshare/public/helpers.js

examples/index.html

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ <h4 class="card-header">
6767
</a>
6868
</div>
6969
</div>
70-
<div class="col-sm-6">
70+
<div class="col-sm-12">
7171
<div class="card-deck">
7272
<a class="card" href="/codecpreferences" style="text-decoration: none">
7373
<h4 class="card-header">
@@ -80,6 +80,17 @@ <h4 class="card-header">
8080
</p>
8181
</div>
8282
</a>
83+
<a class="card" href="/screenshare" style="text-decoration: none">
84+
<h4 class="card-header">
85+
Share Your Screen
86+
</h4>
87+
<div class="card-block">
88+
<p class="card-text">
89+
This app demonstrates how to capture your screen so that you can share it with other Participants
90+
in the Room.
91+
</p>
92+
</div>
93+
</a>
8394
</div>
8495
</div>
8596
</div>

examples/screenshare/public/index.css

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono:300');
2+
3+
html {
4+
height: 100%;
5+
}
6+
7+
body {
8+
height: 100%;
9+
}
10+
11+
div.container-fluid {
12+
height: 100%;
13+
}
14+
15+
div.row {
16+
height: 100%;
17+
}
18+
19+
div.row.thin-gutters {
20+
margin: 0 2px 0 2px;
21+
}
22+
23+
div.row.thin-gutters > .col,
24+
div.row.thin-gutters > [class*="col-"] {
25+
padding: 0 2px;
26+
}
27+
28+
div.col-sm-8, div.col-sm-4 {
29+
height: 100%;
30+
}
31+
32+
pre.language-javascript {
33+
font-family: 'Roboto Mono', monospace;
34+
font-size: 13px;
35+
}
36+
37+
pre.language-javascript a {
38+
color: aquamarine;
39+
text-decoration: underline;
40+
}
41+
42+
pre.language-javascript a:hover {
43+
text-decoration: none;
44+
}
45+
46+
div.card {
47+
border: none;
48+
overflow-y: auto;
49+
}
50+
51+
div.col-sm-8 > .card {
52+
height: 100%;
53+
}
54+
55+
div.col-sm-4 > .card:first-child {
56+
height: 30%;
57+
}
58+
59+
div.col-sm-4 > .card:last-child {
60+
height: 70%;
61+
}
62+
63+
video#screenpreview {
64+
background-color: lightgrey !important;
65+
background-image: url('https://static0.twilio.com/marketing/bundles/archetype/img/logo-wordmark.svg');
66+
background-position: 50%;
67+
background-repeat: no-repeat;
68+
}
69+
70+
@media (max-width: 900px) {
71+
div.col-sm-8, div.col-sm-4 {
72+
max-width: 100%;
73+
flex: 100%;
74+
}
75+
76+
div.col-sm-8 {
77+
height: 40%;
78+
}
79+
80+
div.col-sm-4 {
81+
height: 60%;
82+
}
83+
84+
pre.language-javascript {
85+
font-size: 12px;
86+
}
87+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<html lang="en">
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7+
<title>Share Your Screen</title>
8+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
9+
<link rel="stylesheet" href="prism.css">
10+
<link rel="stylesheet" href="index.css">
11+
</head>
12+
<body>
13+
<div class="container-fluid">
14+
<div class="row thin-gutters">
15+
<div class="col-sm-6">
16+
<div class="card">
17+
<div class="card-block">
18+
<h4 class="card-title">
19+
Share Your Screen
20+
</h4>
21+
<pre class="language-javascript"></pre>
22+
</div>
23+
</div>
24+
</div>
25+
<div class="col-sm-6">
26+
<div class="card">
27+
<div class="card-block">
28+
<h4 class="card-title">Local Screen</h4>
29+
<video id="screenpreview" autoplay height="480" width="640"></video>
30+
<button id="capturescreen" class="btn btn-primary btn-block">Capture Screen</button>
31+
<button id="stopscreencapture" class="btn btn-primary btn-block">Stop Screen Capture</button>
32+
</div>
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
<script src="index.js"></script>
38+
</body>
39+
</html>

examples/screenshare/public/prism.css

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript */
2+
/**
3+
* okaidia theme for JavaScript, CSS and HTML
4+
* Loosely based on Monokai textmate theme by http://www.monokai.nl/
5+
* @author ocodia
6+
*/
7+
8+
code[class*="language-"],
9+
pre[class*="language-"] {
10+
color: #f8f8f2;
11+
background: none;
12+
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
13+
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
14+
text-align: left;
15+
white-space: pre;
16+
word-spacing: normal;
17+
word-break: normal;
18+
word-wrap: normal;
19+
line-height: 1.5;
20+
21+
-moz-tab-size: 4;
22+
-o-tab-size: 4;
23+
tab-size: 4;
24+
25+
-webkit-hyphens: none;
26+
-moz-hyphens: none;
27+
-ms-hyphens: none;
28+
hyphens: none;
29+
}
30+
31+
/* Code blocks */
32+
pre[class*="language-"] {
33+
padding: 1em;
34+
margin: .5em 0;
35+
overflow: auto;
36+
border-radius: 0.3em;
37+
}
38+
39+
:not(pre) > code[class*="language-"],
40+
pre[class*="language-"] {
41+
background: #272822;
42+
}
43+
44+
/* Inline code */
45+
:not(pre) > code[class*="language-"] {
46+
padding: .1em;
47+
border-radius: .3em;
48+
white-space: normal;
49+
}
50+
51+
.token.comment,
52+
.token.prolog,
53+
.token.doctype,
54+
.token.cdata {
55+
color: #87ceeb;
56+
}
57+
58+
.token.operator,
59+
.token.punctuation {
60+
color: #ff5555;
61+
}
62+
63+
.namespace {
64+
opacity: .7;
65+
}
66+
67+
.token.property,
68+
.token.tag,
69+
.token.constant,
70+
.token.symbol,
71+
.token.deleted {
72+
color: #f92672;
73+
}
74+
75+
.token.boolean {
76+
color: #55ff55;
77+
}
78+
79+
.token.number {
80+
color: #cd5c5c;
81+
}
82+
83+
.token.selector,
84+
.token.attr-name,
85+
.token.string,
86+
.token.char,
87+
.token.builtin,
88+
.token.inserted {
89+
color: #ff55ff;
90+
}
91+
92+
.token.entity,
93+
.token.url,
94+
.language-css .token.string,
95+
.style .token.string,
96+
.token.variable {
97+
color: #ff55ff;
98+
}
99+
100+
.token.function {
101+
color: #ccc;
102+
}
103+
104+
.token.keyword {
105+
color: #55ff55;
106+
}
107+
108+
.token.regex,
109+
.token.important {
110+
color: #fd971f;
111+
}
112+
113+
.token.important,
114+
.token.bold {
115+
font-weight: bold;
116+
}
117+
.token.italic {
118+
font-style: italic;
119+
}
120+
121+
.token.entity {
122+
cursor: help;
123+
}

examples/screenshare/src/helpers.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
3+
const Video = require('twilio-video');
4+
5+
/**
6+
* Create a LocalVideoTrack for your screen. You can then share it
7+
* with other Participants in the Room.
8+
* @param {number} height - Desired vertical resolution in pixels
9+
* @param {number} width - Desired horizontal resolution in pixels
10+
* @returns {Promise<LocalVideoTrack>}
11+
*/
12+
function createScreenTrack(height, width) {
13+
if (typeof navigator === 'undefined'
14+
|| !navigator.mediaDevices
15+
|| !navigator.mediaDevices.getDisplayMedia) {
16+
return Promise.reject(new Error('getDisplayMedia is not supported'));
17+
}
18+
return navigator.mediaDevices.getDisplayMedia({
19+
video: {
20+
height: height,
21+
width: width
22+
}
23+
}).then(function(stream) {
24+
return new Video.LocalVideoTrack(stream.getVideoTracks()[0]);
25+
});
26+
}
27+
28+
exports.createScreenTrack = createScreenTrack;

examples/screenshare/src/index.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const Prism = require('prismjs');
4+
const getSnippet = require('../../util/getsnippet');
5+
const helpers = require('./helpers');
6+
const createScreenTrack = helpers.createScreenTrack;
7+
const captureScreen = document.querySelector('button#capturescreen');
8+
const screenPreview = document.querySelector('video#screenpreview');
9+
const stopScreenCapture = document.querySelector('button#stopscreencapture');
10+
11+
(async function() {
12+
// Load the code snippet.
13+
const snippet = await getSnippet('./helpers.js');
14+
const pre = document.querySelector('pre.language-javascript');
15+
pre.innerHTML = Prism.highlight(snippet, Prism.languages.javascript);
16+
17+
// Hide the "Stop Capture Screen" button.
18+
stopScreenCapture.style.display = 'none';
19+
20+
// The LocalVideoTrack for your screen.
21+
let screenTrack;
22+
23+
captureScreen.onclick = async function() {
24+
try {
25+
// Create and preview your local screen.
26+
screenTrack = await createScreenTrack(720, 1280);
27+
screenTrack.attach(screenPreview);
28+
// Show the "Capture Screen" button after screen capture stops.
29+
screenTrack.on('stopped', toggleButtons);
30+
// Show the "Stop Capture Screen" button.
31+
toggleButtons();
32+
} catch (e) {
33+
alert(e.message);
34+
}
35+
};
36+
37+
stopScreenCapture.onclick = function() {
38+
// Stop capturing your screen.
39+
screenTrack.stop();
40+
}
41+
}());
42+
43+
function toggleButtons() {
44+
captureScreen.style.display = captureScreen.style.display === 'none' ? '' : 'none';
45+
stopScreenCapture.style.display = stopScreenCapture.style.display === 'none' ? '' : 'none';
46+
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"build:examples:localvideofilter": "copyfiles -f examples/localvideofilter/src/helpers.js examples/localvideofilter/public && browserify examples/localvideofilter/src/index.js > examples/localvideofilter/public/index.js",
1212
"build:examples:localvideosnapshot": "copyfiles -f examples/localvideosnapshot/src/helpers.js examples/localvideosnapshot/public && browserify examples/localvideosnapshot/src/index.js > examples/localvideosnapshot/public/index.js",
1313
"build:examples:mediadevices": "copyfiles -f examples/mediadevices/src/helpers.js examples/mediadevices/public && browserify examples/mediadevices/src/index.js > examples/mediadevices/public/index.js",
14+
"build:examples:screenshare": "copyfiles -f examples/screenshare/src/helpers.js examples/screenshare/public && browserify examples/screenshare/src/index.js > examples/screenshare/public/index.js",
1415
"build:quickstart": "browserify quickstart/src/index.js > quickstart/public/index.js",
1516
"clean": "npm-run-all clean:*",
1617
"clean:examples": "npm-run-all clean:examples:*",
@@ -19,6 +20,7 @@
1920
"clean:examples:localvideofilter": "rimraf examples/localvideofilter/public/index.js examples/localvideofilter/public/helpers.js",
2021
"clean:examples:localvideosnapshot": "rimraf examples/localvideosnapshot/public/index.js examples/localvideosnapshot/public/helpers.js",
2122
"clean:examples:mediadevices": "rimraf examples/mediadevices/public/index.js examples/mediadevices/public/helpers.js",
23+
"clean:examples:screenshare": "rimraf examples/screenshare/public/index.js examples/screenshare/public/helpers.js",
2224
"clean:quickstart": "rimraf quickstart/public/index.js",
2325
"start": "npm run clean && npm run build && node server"
2426
},

server/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ var app = express();
2828
'codecpreferences',
2929
'localvideofilter',
3030
'localvideosnapshot',
31-
'mediadevices'
31+
'mediadevices',
32+
'screenshare'
3233
].forEach(function(example) {
3334
var examplePath = path.join(__dirname, `../examples/${example}/public`);
3435
app.use(`/${example}`, express.static(examplePath));

0 commit comments

Comments
 (0)