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"); } }); // On every asynchronous exception... session.on('exception', (exception) => { console.warn(exception); }); 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//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) }); }); }