openvidu-tutorials: openvidu-hark-events

This commit is contained in:
pabloFuente 2021-03-30 18:10:34 +02:00
parent ee7994c149
commit c28d656b5d
6 changed files with 10964 additions and 0 deletions

View File

@ -0,0 +1,13 @@
#!/bin/bash
# For this script to properly run, repository https://github.com/OpenVidu/openvidu.git should be
# cloned at the same level as this https://github.com/OpenVidu/openvidu-tutorials.git repository
cd ../../openvidu/openvidu-browser || exit
if [ ! -d node_modules ]; then
npm install
npm run build
fi
export VERSION=2.17.0
npm run browserify
mv static/js/openvidu-browser-2.17.0.js ../../openvidu-tutorials/openvidu-hark-events/web/

View File

@ -0,0 +1,382 @@
var OV;
var session;
var publisher;
var subscriber;
function joinSession() {
var mySessionId = document.getElementById("sessionId").value;
OV = new OpenVidu();
OV.enableProdMode();
session = OV.initSession();
session.on("streamCreated", function (event) {
if (!subscriber) {
subscriber = session.subscribe(event.stream, "subscriber");
}
});
getToken(mySessionId).then(token => {
session.connect(token)
.then(() => {
document.getElementById("session-header").innerText = mySessionId;
document.getElementById("join").style.display = "none";
document.getElementById("session").style.display = "block";
publisher = OV.initPublisher("publisher");
session.publish(publisher);
})
.catch(error => {
console.log("There was an error connecting to the session:", error.code, error.message);
});
});
}
function leaveSession() {
session.disconnect();
document.getElementById("join").style.display = "block";
document.getElementById("session").style.display = "none";
}
window.onbeforeunload = function () {
if (session) session.disconnect()
};
let publisherStartSpeakingSession = [];
let publisherStopSpeakingSession = [];
let publisherStartSpeakingPublisher = [];
let publisherStopSpeakingPublisher = [];
let publisherStartSpeakingSubscriber = [];
let publisherStopSpeakingSubscriber = [];
let streamAudioVolumeChangePublisher = [];
let streamAudioVolumeChangeSubscriber = [];
function attachHandlerHtml(arrayName, handlerNumber, removeCallback) {
const element = document.createElement('input');
element.type = 'button';
element.className = 'handler-btn';
element.id = arrayName + '-handler' + handlerNumber;
element.value = 'Handler ' + handlerNumber;
element.onclick = () => {
removeCallback();
};
document.getElementById(arrayName).append(element);
}
function removeHandlerHtml(regexId) {
const regexp = new RegExp('^' + regexId + '$');
const elements = document.getElementById('handlers').getElementsByClassName('handler-btn');
for (let i = elements.length - 1; i >= 0; i--) {
let elem = elements[i];
if (regexp.test(elem.id)) {
elem.parentNode.removeChild(elem);
}
}
}
function offEvent(eventName, target, array, handler, handlerNumber) {
if (handler != null) {
target.off(eventName, handler);
array.splice(array.indexOf(handler), 1);
removeHandlerHtml(eventName + target.constructor.name + '-handler' + handlerNumber);
} else {
target.off(eventName);
array = [];
removeHandlerHtml(eventName + target.constructor.name + '-handler.+');
}
return array;
}
function onPublisherStartSpeakingSession() {
const handlerNumber = publisherStartSpeakingSession.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStartSpeaking triggered by ' + event.target.constructor.name + ' and belonging to ' + (event.connection.stream.streamManager.remote ? 'Subscriber' : 'Publisher'));
}
publisherStartSpeakingSession.push(handler);
attachHandlerHtml('publisherStartSpeakingSession', handlerNumber, () => offEvent('publisherStartSpeaking', session, publisherStartSpeakingSession, handler, handlerNumber));
session.on('publisherStartSpeaking', handler);
}
function oncePublisherStartSpeakingSession() {
const handlerNumber = publisherStartSpeakingSession.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStartSpeaking (ONCE) triggered by ' + event.target.constructor.name + ' and belonging to ' + (event.connection.stream.streamManager.remote ? 'Subscriber' : 'Publisher'));
publisherStartSpeakingSession.splice(publisherStartSpeakingSession.indexOf(handler), 1);
removeHandlerHtml('publisherStartSpeakingSession-handler' + handlerNumber);
}
publisherStartSpeakingSession.push(handler);
attachHandlerHtml('publisherStartSpeakingSession', handlerNumber, () => offEvent('publisherStartSpeaking', session, publisherStartSpeakingSession, handler, handlerNumber));
session.once('publisherStartSpeaking', handler);
}
function offPublisherStartSpeakingSession(handler) {
const availableHandlers = publisherStartSpeakingSession.length;
publisherStartSpeakingSession = offEvent('publisherStartSpeaking', session, publisherStartSpeakingSession);
console.log('Available publisherStartSpeaking handlers for Session: ' + availableHandlers + '. Remaining: ' + publisherStartSpeakingSession.length);
}
function onPublisherStopSpeakingSession() {
const handlerNumber = publisherStopSpeakingSession.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStopSpeaking triggered by ' + event.target.constructor.name + ' and belonging to ' + (event.connection.stream.streamManager.remote ? 'Subscriber' : 'Publisher'));
}
publisherStopSpeakingSession.push(handler);
attachHandlerHtml('publisherStopSpeakingSession', handlerNumber, () => offEvent('publisherStopSpeaking', session, publisherStopSpeakingSession, handler, handlerNumber));
session.on('publisherStopSpeaking', handler);
}
function oncePublisherStopSpeakingSession() {
const handlerNumber = publisherStopSpeakingSession.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStopSpeaking (ONCE) triggered by ' + event.target.constructor.name + ' and belonging to ' + (event.connection.stream.streamManager.remote ? 'Subscriber' : 'Publisher'));
publisherStopSpeakingSession.splice(publisherStopSpeakingSession.indexOf(handler), 1);
removeHandlerHtml('publisherStopSpeakingSession-handler' + handlerNumber);
}
publisherStopSpeakingSession.push(handler);
attachHandlerHtml('publisherStopSpeakingSession', handlerNumber, () => offEvent('publisherStopSpeaking', session, publisherStopSpeakingSession, handler, handlerNumber));
session.once('publisherStopSpeaking', handler);
}
function offPublisherStopSpeakingSession() {
const availableHandlers = publisherStopSpeakingSession.length;
publisherStopSpeakingSession = offEvent('publisherStopSpeaking', session, publisherStopSpeakingSession);
console.log('Available publisherStopSpeaking handlers for Session: ' + availableHandlers + '. Remaining: ' + publisherStopSpeakingSession.length);
}
function onPublisherStartSpeakingPublisher() {
const handlerNumber = publisherStartSpeakingPublisher.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStartSpeaking triggered by ' + event.target.constructor.name);
}
publisherStartSpeakingPublisher.push(handler);
attachHandlerHtml('publisherStartSpeakingPublisher', handlerNumber, () => offEvent('publisherStartSpeaking', publisher, publisherStartSpeakingPublisher, handler, handlerNumber));
publisher.on('publisherStartSpeaking', handler);
}
function oncePublisherStartSpeakingPublisher() {
const handlerNumber = publisherStartSpeakingPublisher.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStartSpeaking (ONCE) triggered by ' + event.target.constructor.name);
publisherStartSpeakingPublisher.splice(publisherStartSpeakingPublisher.indexOf(handler), 1);
removeHandlerHtml('publisherStartSpeakingPublisher-handler' + handlerNumber);
}
publisherStartSpeakingPublisher.push(handler);
attachHandlerHtml('publisherStartSpeakingPublisher', handlerNumber, () => offEvent('publisherStartSpeaking', publisher, publisherStartSpeakingPublisher, handler, handlerNumber));
publisher.once('publisherStartSpeaking', handler);
}
function offPublisherStartSpeakingPublisher() {
const availableHandlers = publisherStartSpeakingPublisher.length;
publisherStartSpeakingPublisher = offEvent('publisherStartSpeaking', publisher, publisherStartSpeakingPublisher);
console.log('Available publisherStartSpeaking handlers for Publisher: ' + availableHandlers + '. Remaining: ' + publisherStartSpeakingPublisher.length);
}
function onPublisherStopSpeakingPublisher() {
const handlerNumber = publisherStopSpeakingPublisher.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStopSpeaking triggered by ' + event.target.constructor.name);
}
publisherStopSpeakingPublisher.push(handler);
attachHandlerHtml('publisherStopSpeakingPublisher', handlerNumber, () => offEvent('publisherStopSpeaking', publisher, publisherStopSpeakingPublisher, handler, handlerNumber));
publisher.on('publisherStopSpeaking', handler);
}
function oncePublisherStopSpeakingPublisher() {
const handlerNumber = publisherStopSpeakingPublisher.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStopSpeaking (ONCE) triggered by ' + event.target.constructor.name);
publisherStopSpeakingPublisher.splice(publisherStopSpeakingPublisher.indexOf(handler), 1);
removeHandlerHtml('publisherStopSpeakingPublisher-handler' + handlerNumber);
}
publisherStopSpeakingPublisher.push(handler);
attachHandlerHtml('publisherStopSpeakingPublisher', handlerNumber, () => offEvent('publisherStopSpeaking', publisher, publisherStopSpeakingPublisher, handler, handlerNumber));
publisher.once('publisherStopSpeaking', handler);
}
function offPublisherStopSpeakingPublisher() {
const availableHandlers = publisherStopSpeakingPublisher.length;
publisherStopSpeakingPublisher = offEvent('publisherStopSpeaking', publisher, publisherStopSpeakingPublisher);
console.log('Available publisherStopSpeaking handlers for Publisher: ' + availableHandlers + '. Remaining: ' + publisherStopSpeakingPublisher.length);
}
function onPublisherStartSpeakingSubscriber() {
const handlerNumber = publisherStartSpeakingSubscriber.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStartSpeaking triggered by ' + event.target.constructor.name);
}
publisherStartSpeakingSubscriber.push(handler);
attachHandlerHtml('publisherStartSpeakingSubscriber', handlerNumber, () => offEvent('publisherStartSpeaking', subscriber, publisherStartSpeakingSubscriber, handler, handlerNumber));
subscriber.on('publisherStartSpeaking', handler);
}
function oncePublisherStartSpeakingSubscriber() {
const handlerNumber = publisherStartSpeakingSubscriber.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStartSpeaking (ONCE) triggered by ' + event.target.constructor.name);
publisherStartSpeakingSubscriber.splice(publisherStartSpeakingSubscriber.indexOf(handler), 1);
removeHandlerHtml('publisherStartSpeakingSubscriber-handler' + handlerNumber);
}
publisherStartSpeakingSubscriber.push(handler);
attachHandlerHtml('publisherStartSpeakingSubscriber', handlerNumber, () => offEvent('publisherStartSpeaking', subscriber, publisherStartSpeakingSubscriber, handler, handlerNumber));
subscriber.once('publisherStartSpeaking', handler);
}
function offPublisherStartSpeakingSubscriber() {
const availableHandlers = publisherStartSpeakingSubscriber.length;
publisherStartSpeakingSubscriber = offEvent('publisherStartSpeaking', subscriber, publisherStartSpeakingSubscriber);
console.log('Available publisherStartSpeaking handlers for Subscriber: ' + availableHandlers + '. Remaining: ' + publisherStartSpeakingSubscriber.length);
}
function onPublisherStopSpeakingSubscriber() {
const handlerNumber = publisherStopSpeakingSubscriber.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStopSpeaking triggered by ' + event.target.constructor.name);
}
publisherStopSpeakingSubscriber.push(handler);
attachHandlerHtml('publisherStopSpeakingSubscriber', handlerNumber, () => offEvent('publisherStopSpeaking', subscriber, publisherStopSpeakingSubscriber, handler, handlerNumber));
subscriber.on('publisherStopSpeaking', handler);
}
function oncePublisherStopSpeakingSubscriber() {
const handlerNumber = publisherStopSpeakingSubscriber.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing publisherStopSpeaking (ONCE) triggered by ' + event.target.constructor.name);
publisherStopSpeakingSubscriber.splice(publisherStopSpeakingSubscriber.indexOf(handler), 1);
removeHandlerHtml('publisherStopSpeakingSubscriber-handler' + handlerNumber);
}
publisherStopSpeakingSubscriber.push(handler);
attachHandlerHtml('publisherStopSpeakingSubscriber', handlerNumber, () => offEvent('publisherStopSpeaking', subscriber, publisherStopSpeakingSubscriber, handler, handlerNumber));
subscriber.once('publisherStopSpeaking', handler);
}
function offPublisherStopSpeakingSubscriber() {
const availableHandlers = publisherStopSpeakingSubscriber.length;
publisherStopSpeakingSubscriber = offEvent('publisherStopSpeaking', subscriber, publisherStopSpeakingSubscriber);
console.log('Available publisherStopSpeaking handlers for Subscriber: ' + availableHandlers + '. Remaining: ' + publisherStopSpeakingSubscriber.length);
}
function onStreamAudioVolumeChangePublisher() {
const handlerNumber = streamAudioVolumeChangePublisher.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing streamAudioVolumeChange triggered by ' + event.target.constructor.name);
}
streamAudioVolumeChangePublisher.push(handler);
attachHandlerHtml('streamAudioVolumeChangePublisher', handlerNumber, () => offEvent('streamAudioVolumeChange', publisher, streamAudioVolumeChangePublisher, handler, handlerNumber));
publisher.on('streamAudioVolumeChange', handler);
}
function onceStreamAudioVolumeChangePublisher() {
const handlerNumber = streamAudioVolumeChangePublisher.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing streamAudioVolumeChange (ONCE) triggered by ' + event.target.constructor.name);
streamAudioVolumeChangePublisher.splice(streamAudioVolumeChangePublisher.indexOf(handler), 1);
removeHandlerHtml('streamAudioVolumeChangePublisher-handler' + handlerNumber);
}
streamAudioVolumeChangePublisher.push(handler);
attachHandlerHtml('streamAudioVolumeChangePublisher', handlerNumber, () => offEvent('streamAudioVolumeChange', publisher, streamAudioVolumeChangePublisher, handler, handlerNumber));
publisher.once('streamAudioVolumeChange', handler);
}
function offStreamAudioVolumeChangePublisher() {
const availableHandlers = streamAudioVolumeChangePublisher.length;
streamAudioVolumeChangePublisher = offEvent('streamAudioVolumeChange', publisher, streamAudioVolumeChangePublisher);
console.log('Available streamAudioVolumeChange handlers for Publisher: ' + availableHandlers + '. Remaining: ' + streamAudioVolumeChangePublisher.length);
}
function onStreamAudioVolumeChangeSubscriber() {
const handlerNumber = streamAudioVolumeChangeSubscriber.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing streamAudioVolumeChange triggered by ' + event.target.constructor.name);
}
streamAudioVolumeChangeSubscriber.push(handler);
attachHandlerHtml('streamAudioVolumeChangeSubscriber', handlerNumber, () => offEvent('streamAudioVolumeChange', subscriber, streamAudioVolumeChangeSubscriber, handler, handlerNumber));
subscriber.on('streamAudioVolumeChange', handler);
}
function onceStreamAudioVolumeChangeSubscriber() {
const handlerNumber = streamAudioVolumeChangeSubscriber.length + 1;
const handler = event => {
console.log('Handler ' + handlerNumber + ' processing streamAudioVolumeChange (ONCE) triggered by ' + event.target.constructor.name);
streamAudioVolumeChangeSubscriber.splice(streamAudioVolumeChangeSubscriber.indexOf(handler), 1);
removeHandlerHtml('streamAudioVolumeChangeSubscriber-handler' + handlerNumber);
}
streamAudioVolumeChangeSubscriber.push(handler);
attachHandlerHtml('streamAudioVolumeChangeSubscriber', handlerNumber, () => offEvent('streamAudioVolumeChange', subscriber, streamAudioVolumeChangeSubscriber, handler, handlerNumber));
subscriber.once('streamAudioVolumeChange', handler);
}
function offStreamAudioVolumeChangeSubscriber() {
const availableHandlers = streamAudioVolumeChangeSubscriber.length;
streamAudioVolumeChangeSubscriber = offEvent('streamAudioVolumeChange', subscriber, streamAudioVolumeChangeSubscriber);
console.log('Available streamAudioVolumeChange handlers for Subscriber: ' + availableHandlers + '. Remaining: ' + streamAudioVolumeChangeSubscriber.length);
}
/**
* --------------------------
* SERVER-SIDE RESPONSIBILITY
* --------------------------
* These methods retrieve the mandatory user token from OpenVidu Server.
* This behavior MUST BE IN YOUR SERVER-SIDE IN PRODUCTION (by using
* the API REST, openvidu-java-client or openvidu-node-client):
* 1) Initialize a Session in OpenVidu Server (POST /openvidu/api/sessions)
* 2) Create a Connection in OpenVidu Server (POST /openvidu/api/sessions/<SESSION_ID>/connection)
* 3) The Connection.token must be consumed in Session.connect() method
*/
var OPENVIDU_SERVER_URL = "https://" + location.hostname + ":4443";
var OPENVIDU_SERVER_SECRET = "MY_SECRET";
function getToken(mySessionId) {
return createSession(mySessionId).then(sessionId => createToken(sessionId));
}
function createSession(sessionId) { // See https://docs.openvidu.io/en/stable/reference-docs/REST-API/#post-openviduapisessions
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: OPENVIDU_SERVER_URL + "/openvidu/api/sessions",
data: JSON.stringify({
customSessionId: sessionId
}),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:" + OPENVIDU_SERVER_SECRET),
"Content-Type": "application/json"
},
success: response => resolve(response.id),
error: (error) => {
if (error.status === 409) {
resolve(sessionId);
} else {
console.warn('No connection to OpenVidu Server. This may be a certificate error at ' + OPENVIDU_SERVER_URL);
if (window.confirm('No connection to OpenVidu Server. This may be a certificate error at \"' + OPENVIDU_SERVER_URL + '\"\n\nClick OK to navigate and accept it. ' +
'If no certificate warning is shown, then check that your OpenVidu Server is up and running at "' + OPENVIDU_SERVER_URL + '"')) {
location.assign(OPENVIDU_SERVER_URL + '/accept-certificate');
}
}
}
});
});
}
function createToken(sessionId) { // See https://docs.openvidu.io/en/stable/reference-docs/REST-API/#post-openviduapisessionsltsession_idgtconnection
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: OPENVIDU_SERVER_URL + '/openvidu/api/sessions/' + sessionId + '/connection',
data: JSON.stringify({}),
headers: {
'Authorization': 'Basic ' + btoa('OPENVIDUAPP:' + OPENVIDU_SERVER_SECRET),
'Content-Type': 'application/json',
},
success: (response) => resolve(response.token),
error: (error) => reject(error)
});
});
}

View File

@ -0,0 +1,128 @@
<html>
<head>
<title>openvidu-hark-events</title>
<link rel="shortcut icon" href="resources/images/favicon.ico" type="image/x-icon">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-2.17.0.js"></script>
<script src="app.js"></script>
</head>
<body>
<div id="join">
<h1>Join a video session</h1>
<form onsubmit="joinSession(); return false">
<p>
<label>Session:</label>
<input type="text" id="sessionId" value="SessionA" required>
</p>
<p>
<input type="submit" value="JOIN">
</p>
</form>
</div>
<div id="session" style="display: none;">
<h1 id="session-header"></h1>
<input type="button" onclick="leaveSession()" value="LEAVE">
<div>
<h4>Session</h4>
<input type="button" onclick="onPublisherStartSpeakingSession()" value="onPublisherStartSpeakingSession">
<input type="button" onclick="oncePublisherStartSpeakingSession()"
value="oncePublisherStartSpeakingSession">
<input type="button" onclick="offPublisherStartSpeakingSession()" value="offPublisherStartSpeakingSession">
<input type="button" onclick="onPublisherStopSpeakingSession()" value="onPublisherStopSpeakingSession">
<input type="button" onclick="oncePublisherStopSpeakingSession()" value="oncePublisherStopSpeakingSession">
<input type="button" onclick="offPublisherStopSpeakingSession()" value="offPublisherStopSpeakingSession">
</div>
<div>
<h4>Publisher</h4>
<input type="button" onclick="onPublisherStartSpeakingPublisher()"
value="onPublisherStartSpeakingPublisher">
<input type="button" onclick="oncePublisherStartSpeakingPublisher()"
value="oncePublisherStartSpeakingPublisher">
<input type="button" onclick="offPublisherStartSpeakingPublisher()"
value="offPublisherStartSpeakingPublisher">
<input type="button" onclick="onPublisherStopSpeakingPublisher()" value="onPublisherStopSpeakingPublisher">
<input type="button" onclick="oncePublisherStopSpeakingPublisher()"
value="oncePublisherStopSpeakingPublisher">
<input type="button" onclick="offPublisherStopSpeakingPublisher()"
value="offPublisherStopSpeakingPublisher">
<input type="button" onclick="onStreamAudioVolumeChangePublisher()"
value="onStreamAudioVolumeChangePublisher">
<input type="button" onclick="onceStreamAudioVolumeChangePublisher()"
value="onceStreamAudioVolumeChangePublisher">
<input type="button" onclick="offStreamAudioVolumeChangePublisher()"
value="offStreamAudioVolumeChangePublisher">
</div>
<div>
<h4>Subscriber</h4>
<input type="button" onclick="onPublisherStartSpeakingSubscriber()"
value="onPublisherStartSpeakingSubscriber">
<input type="button" onclick="oncePublisherStartSpeakingSubscriber()"
value="oncePublisherStartSpeakingSubscriber">
<input type="button" onclick="offPublisherStartSpeakingSubscriber()"
value="offPublisherStartSpeakingSubscriber">
<input type="button" onclick="onPublisherStopSpeakingSubscriber()"
value="onPublisherStopSpeakingSubscriber">
<input type="button" onclick="oncePublisherStopSpeakingSubscriber()"
value="oncePublisherStopSpeakingSubscriber">
<input type="button" onclick="offPublisherStopSpeakingSubscriber()"
value="offPublisherStopSpeakingSubscriber">
<input type="button" onclick="onStreamAudioVolumeChangeSubscriber()"
value="onStreamAudioVolumeChangeSubscriber">
<input type="button" onclick="onceStreamAudioVolumeChangeSubscriber()"
value="onceStreamAudioVolumeChangeSubscriber">
<input type="button" onclick="offStreamAudioVolumeChangeSubscriber()"
value="offStreamAudioVolumeChangeSubscriber">
</div>
<div id="handlers">
<h4>Handlers</h4>
<div id="publisherStartSpeakingSession">
<h5>publisherStartSpeaking (Session)</h5>
</div>
<div id="publisherStopSpeakingSession">
<h5>publisherStopSpeaking (Session)</h5>
</div>
<div id="publisherStartSpeakingPublisher">
<h5>publisherStartSpeaking (Publisher)</h5>
</div>
<div id="publisherStopSpeakingPublisher">
<h5>publisherStopSpeaking (Publisher)</h5>
</div>
<div id="streamAudioVolumeChangePublisher">
<h5>streamAudioVolumeChange (Publisher)</h5>
</div>
<div id="publisherStartSpeakingSubscriber">
<h5>publisherStartSpeaking (Subscriber)</h5>
</div>
<div id="publisherStopSpeakingSubscriber">
<h5>publisherStopSpeaking (Subscriber)</h5>
</div>
<div id="streamAudioVolumeChangeSubscriber">
<h5>streamAudioVolumeChange (Subscriber)</h5>
</div>
</div>
<div>
<div id="publisher">
<h3>YOU</h3>
</div>
<div id="subscriber">
<h3>OTHERS</h3>
</div>
</div>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,43 @@
html, body {
height: 100%;
font-family: "Open Sans", sans-serif;
}
html {
display: table;
margin: auto;
}
body {
display: table-cell;
vertical-align: middle;
text-align: center;
}
#publisher {
float: left;
margin: 10px;
width: 40%;
}
#subscriber {
float: right;
margin: 10px;
width: 40%;
}
video {
width: 70%;
margin: 10px auto 0 auto;
display: block;
}
#handlers > div {
display: inline-block;
margin-right: 20px;
}
.handler-btn {
display: inline-block;
margin: auto;
}