Skip to content

Commit 595b122

Browse files
authored
VIDEO-5729 - Auto Render Hints example (#185)
* Adding Auto renderhints example. Co-authored-by: joma <joma@twilio.com>
1 parent de923f1 commit 595b122

File tree

16 files changed

+548
-123
lines changed

16 files changed

+548
-123
lines changed

.gitignore

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,32 +47,8 @@ jspm_packages
4747
package-lock.json
4848

4949
# The generated index.js
50-
quickstart/public/index.js
51-
examples/bandwidthconstraints/public/index.js
52-
examples/codecpreferences/public/index.js
53-
examples/dominantspeaker/public/index.js
54-
examples/localvideofilter/public/index.js
55-
examples/localvideosnapshot/public/index.js
56-
examples/mediadevices/public/index.js
57-
examples/networkquality/public/index.js
58-
examples/reconnection/public/index.js
59-
examples/screenshare/public/index.js
60-
examples/localmediacontrols/public/index.js
61-
examples/remotereconnection/public/index.js
62-
examples/datatracks/public/index.js
63-
examples/renderhint/public/index.js
50+
**/public/index.js
6451

6552
# The generated helpers.js
66-
examples/bandwidthconstraints/public/helpers.js
67-
examples/codecpreferences/public/helpers.js
68-
examples/dominantspeaker/public/helpers.js
69-
examples/localvideofilter/public/helpers*.js
70-
examples/localvideosnapshot/public/helpers.js
71-
examples/mediadevices/public/helpers.js
72-
examples/networkquality/public/helpers.js
73-
examples/reconnection/public/helpers.js
74-
examples/screenshare/public/helpers.js
75-
examples/localmediacontrols/public/helpers.js
76-
examples/remotereconnection/public/helpers.js
77-
examples/datatracks/public/helpers.js
78-
examples/renderhint/public/helpers.js
53+
**/public/helpers.js
54+
**/public/helpers*.js
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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+
[data-toggle="collapse"].collapsed .if-not-collapsed {
12+
display: none;
13+
}
14+
15+
[data-toggle="collapse"]:not(.collapsed) .if-collapsed {
16+
display: none;
17+
}
18+
19+
.align {
20+
align-content: flex-start;
21+
}
22+
23+
div.container-fluid {
24+
height: 100%;
25+
}
26+
27+
div.row {
28+
height: 100%;
29+
}
30+
31+
div.row.thin-gutters {
32+
margin: 0 2px 0 2px;
33+
}
34+
35+
div.row.thin-gutters > .col,
36+
div.row.thin-gutters > [class*="col-"] {
37+
padding: 8px 8px;
38+
}
39+
40+
div.card {
41+
border: none;
42+
overflow-y: auto;
43+
}
44+
45+
div.card-block {
46+
margin: 5px;
47+
}
48+
49+
div.col-sm-6, div.col-sm-6 {
50+
max-height: fit-content;
51+
}
52+
53+
54+
pre.language-javascript {
55+
font-family: 'Roboto Mono', monospace;
56+
font-size: 13px;
57+
}
58+
59+
pre.language-javascript a {
60+
color: aquamarine;
61+
text-decoration: underline;
62+
}
63+
64+
pre.language-javascript a:hover {
65+
text-decoration: none;
66+
}
67+
68+
div#media-container {
69+
position: relative;
70+
display: grid;
71+
grid-template-areas: 'content';
72+
max-width: 100%;
73+
}
74+
75+
span#trackIsSwitchedOff {
76+
position: absolute;
77+
z-index: 3;
78+
width: 67px;
79+
font-size: .9em;
80+
right: 1%;
81+
top: 1%;
82+
align-items: center;
83+
max-width: max-content;
84+
}
85+
86+
video {
87+
width: 100% !important;
88+
height: auto !important;
89+
border: none;
90+
}
91+
92+
div#bg-img {
93+
width: 100% !important;
94+
height: auto !important;
95+
background-color: lightgrey !important;
96+
background-image: url('https://static0.twilio.com/marketing/bundles/archetype/img/logo-wordmark.svg');
97+
background-position: 50%;
98+
background-repeat: no-repeat;
99+
box-sizing: content-box;
100+
}
101+
102+
div.bitrategraph {
103+
margin-top: 5px;
104+
text-align: center;
105+
}
106+
107+
@media (max-width: 900px) {
108+
div.col-sm-8, div.col-sm-4 {
109+
max-width: 100%;
110+
flex: 100%;
111+
}
112+
113+
div.col-sm-8 {
114+
height: 40%;
115+
}
116+
117+
div.col-sm-4 {
118+
height: 60%;
119+
}
120+
121+
pre.language-javascript {
122+
font-size: 12px;
123+
}
124+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6+
<title>Video Track Automatic Controls</title>
7+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
8+
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.2/css/all.css" integrity="sha384-vSIIfh2YWi9wW0r9iZe7RJPrKwp6bG+s9QZMoITbCckVJqGCCRhc+ccxNcdpHuYu" 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 align">
15+
<div class="col-sm-6">
16+
<div class="card">
17+
<div class="card-block">
18+
<h4 class="card-title">
19+
Video Track Automatic Controls
20+
</h4>
21+
<button class="btn btn-primary collapsed d-md-none" type="button" data-toggle="collapse" data-target="#collapseSnippet" aria-expanded="false" aria-controls="collapseSnippet">
22+
<span class="if-collapsed">Show Code</span>
23+
<span class="if-not-collapsed">Hide Code</span>
24+
</button>
25+
<div class="collapse dont-collapse-sm d-md-block" id="collapseSnippet">
26+
<pre id="shown-snippet" class="language-javascript"></pre>
27+
</div>
28+
</div>
29+
</div>
30+
</div>
31+
<div class="col-sm-6">
32+
<div class="card">
33+
<div class="card-block">
34+
<h4 class="card-title">Remote Video Controls</h4>
35+
<div id="userControls">
36+
<div class="card-block">
37+
Toggle Visibility:
38+
<button id="showVideo" type="button" class="btn btn-primary disabled">Show</button>
39+
<button id="hideVideo" type="button" class="btn btn-primary disabled">Hide</button>
40+
</div>
41+
<div class="card-block">
42+
Video Size:
43+
<select id= "renderDimensionsOption" class="btn btn-primary dropdown-toggle disabled">
44+
<option value="" disabled selected hidden>Render Dimensions</option>
45+
<option value="qHD">960x540</option>
46+
<option value="VGA">640x480</option>
47+
<option value="QCIF">176x144</option>
48+
</select>
49+
</div>
50+
</div>
51+
<div class="card-block">
52+
<h4 class="card-title">Remote Video Track</h4>
53+
<div id="media-container" style="width: 960px; height: 540px">
54+
<div id="bg-img" aria-hidden="true" hidden></div>
55+
<video id="remotevideo" aria-hidden="true"></video>
56+
<span id="trackIsSwitchedOff" class="badge badge-success"></span>
57+
</div>
58+
</div>
59+
<h4 class="card-title">Video Bitrate</h4>
60+
<div id="videobitrategraph" class="bitrategraph">
61+
<canvas id="videobitratecanvas"></canvas>
62+
</div>
63+
</div>
64+
</div>
65+
</div>
66+
</div>
67+
</div>
68+
<script src="index.js"></script>
69+
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
70+
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
71+
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
72+
</body>
73+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
var Video = require('twilio-video');
4+
5+
/**
6+
* Connect to a Room with 'auto' mode. This is the default mode.
7+
* @param {string} token - AccessToken for joining the Room
8+
* @returns {Room}
9+
*/
10+
function joinRoom(token) {
11+
return Video.connect(token, {
12+
name: 'my-cool-room',
13+
bandwidthProfile: {
14+
video: {
15+
contentPreferencesMode: 'auto',
16+
clientTrackSwitchOffControl: 'auto'
17+
}
18+
}
19+
});
20+
}
21+
22+
module.exports.joinRoom = joinRoom;

examples/autorenderhint/src/index.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
'use strict'
2+
3+
const Prism = require('prismjs');
4+
const Video = require('twilio-video');
5+
const getSnippet = require('../../util/getsnippet');
6+
const getRoomCredentials = require('../../util/getroomcredentials');
7+
const setupBitrateGraph = require('../../util/setupbitrategraph');
8+
const helpers = require('./helpers');
9+
const joinRoom = helpers.joinRoom;
10+
11+
const bgImg = document.querySelector('div#bg-img');
12+
const mediaContainer = document.querySelector('div#media-container');
13+
const renderDimensionsOption = document.querySelector('select#renderDimensionsOption');
14+
const videoEl = document.querySelector('video#remotevideo');
15+
const showVideo = document.querySelector('button#showVideo');
16+
const hideVideo = document.querySelector('button#hideVideo');
17+
const trackIsSwitchedOffIndicator = document.querySelector('span#trackIsSwitchedOff');
18+
let roomP1 = null;
19+
let stopVideoBitrateGraph = null;
20+
21+
const handleIsSwitchedOff = (isTrackSwitchedOff) => {
22+
if(isTrackSwitchedOff) {
23+
trackIsSwitchedOffIndicator.textContent = 'Off';
24+
trackIsSwitchedOffIndicator.classList.remove('badge-success');
25+
trackIsSwitchedOffIndicator.classList.add('badge-danger');
26+
} else {
27+
trackIsSwitchedOffIndicator.textContent = 'On';
28+
trackIsSwitchedOffIndicator.classList.remove('badge-danger');
29+
trackIsSwitchedOffIndicator.classList.add('badge-success');
30+
}
31+
}
32+
33+
(async function(){
34+
// Load the code snippet.
35+
const snippet = await getSnippet('./helpers.js');
36+
const pre = document.querySelector('pre.language-javascript');
37+
38+
pre.innerHTML = Prism.highlight(snippet, Prism.languages.javascript);
39+
40+
const logger = Video.Logger.getLogger('twilio-video');
41+
logger.setLevel('silent');
42+
43+
// Get the credentials to connect to the Room.
44+
const credsP1 = await getRoomCredentials();
45+
const credsP2 = await getRoomCredentials();
46+
47+
// Create room instance and name for participants to join.
48+
roomP1 = await joinRoom(credsP1.token);
49+
50+
// Create the video track for the Remote Participant.
51+
const videoTrack = await Video.createLocalVideoTrack();
52+
53+
// Connecting remote participant.
54+
const roomP2 = await Video.connect(credsP2.token, {
55+
name: 'my-cool-room',
56+
bandwidthProfile: {
57+
video: {
58+
contentPreferencesMode: 'auto',
59+
clientTrackSwitchOffControl: 'auto'
60+
}
61+
},
62+
tracks: [ videoTrack ]
63+
});
64+
65+
// Set video bitrate graph.
66+
let startVideoBitrateGraph = setupBitrateGraph('video', 'videobitrategraph', 'videobitratecanvas');
67+
68+
// Attach RemoteVideoTrack
69+
roomP1.on('trackSubscribed', track => {
70+
if(track.kind === 'video') {
71+
track.attach(videoEl);
72+
handleIsSwitchedOff(track.isSwitchedOff);
73+
stopVideoBitrateGraph = startVideoBitrateGraph(roomP1, 1000);
74+
75+
showVideo.classList.remove('disabled');
76+
hideVideo.classList.remove('disabled');
77+
renderDimensionsOption.classList.remove('disabled');
78+
79+
track.on('switchedOff', track => {
80+
handleIsSwitchedOff(track.isSwitchedOff);
81+
});
82+
track.on('switchedOn', track => {
83+
handleIsSwitchedOff(track.isSwitchedOff);
84+
});
85+
}
86+
});
87+
88+
// Show RemoteVideoTrack
89+
showVideo.onclick = event => {
90+
videoEl.hidden = false;
91+
bgImg.hidden = true;
92+
}
93+
94+
// Hide RemoteVideoTrack
95+
hideVideo.onclick = event => {
96+
videoEl.hidden = true;
97+
bgImg.hidden = false;
98+
}
99+
100+
const renderDimensionsObj = {
101+
qHD: { width: 960, height: 540 },
102+
VGA: { width: 640, height: 480 },
103+
QCIF: { width: 176, height: 144}
104+
}
105+
106+
// Adjust Remote Video element size.
107+
renderDimensionsOption.addEventListener('change', () => {
108+
const renderDimensions = renderDimensionsObj[renderDimensionsOption.value];
109+
mediaContainer.style.height = `${renderDimensions.height}px`;
110+
mediaContainer.style.width = `${renderDimensions.width}px`;
111+
});
112+
113+
// Disconnect from the Room
114+
window.onbeforeunload = () => {
115+
if (stopVideoBitrateGraph) {
116+
stopVideoBitrateGraph();
117+
stopVideoBitrateGraph = null;
118+
}
119+
roomP1.disconnect();
120+
roomP2.disconnect();
121+
}
122+
}());

0 commit comments

Comments
 (0)