var Janus = require('../externals/janus.nojquery');
var Promise = require('bluebird/js/release/bluebird');
var DataChannel = require('../modules/datachannel');
/**
* VideoRoom usecase
* @class
* @classdesc VideoRoom usecase
* @param {object} onEvents Event handlers: onCreated, onError, onJoined, onDestroyed, onPeerJoined, onPeerLeft
* @param {object} domElements DOM elements: videos
* @param {object} options options: stream
* @return {Promise} VideoRoom methods: createVideoroom, destroyVideoroom, getPeers, joinVideoroom, toggleAudio, toggleVideo
* @example
* var onEvents = {
* onCreated: function(id) {
* // Created
* },
* onError: function(cause, code) {
* // Error
* },
* onJoined: function() {
* // Joined
* },
* onDestroyed: function() {
* // Destroyed
* },
* onPeerJoined: function(id, display) {
* // Peer Joined
* },
* onPeerLeft: function(id, display) {
* // Peer Left
* }
* };
*
* var domElements = {
* videos: document.getElementById('videortc-videos') // App container
* };
*
* var options = {
* stream: {
* audioEnabled: true,
* videoEnabled: true,
* aDeviceId: null,
* vDeviceId: null,
* voiceProcessor: false
* }
* };
*
* usecases.videoRoom(onEvents, domElements, options)
* .then(function(action) {
* // Use Case has been atacched succesfully
* ...
* })
* .catch(function(cause) {
* // Error attaching the Use Case
* console.log("Error Attach " + cause );
* })
*/
var videoRoom = function(onEvents, domElements, options) {
if(!domElements || !domElements.videos || domElements.videos.nodeType !== 1) return null;
// Stream options
var streamOptions = (options && options.stream) ? options.stream : {};
if(!streamOptions.audioEnabled) streamOptions.audioEnabled = false;
if(!streamOptions.videoEnabled) streamOptions.videoEnabled = false;
if(!streamOptions.aDeviceId) streamOptions.aDeviceId = undefined;
if(!streamOptions.vDeviceId) streamOptions.vDeviceId = undefined;
if(!streamOptions.voiceProcessor) streamOptions.voiceProcessor = false;
// Vars
var videoroomHandle = null;
var screenRoomHandle = null;
var feeds = [];
var bitrateTimer = [];
var idVideoroom;
var nPeers = 1;
var roomPin = null;
var username = null;
/**
* Close the current UseCase. It's recommended combine with disconnect method
* @return {nothing}
* @example
* action.closeUsecase();
* myVideoApp.disconnect(); // Recommended
*/
var closeUsecase = function() {
if(domElements) {
for (var element in domElements) {
if (!domElements.hasOwnProperty(element)) continue;
var obj = domElements[element];
if(obj && obj.innerHTML) obj.innerHTML = '';
}
}
};
/**
* Creates a new VideoRoom / Conference
* @param {Boolean} isPrivate Is private?
* @param {string} adminKey Administrator Room Key (Destroy)
* @param {string} userKey User Room Key (Join)
* @param {string|enum} quality Quality: "high", "medium" or "low"
* @param {integer} maxPublishers Number of publishers/peers
* @param {Boolean} isRecord Record the videoroom
* @return {nothing}
* @example
* action.createVideoroom(true, 'MyP455w0rd', 'Us3rPw', 'medium', 6, false);
*/
var createVideoroom = function(isPrivate, adminKey, userKey, quality, maxPublishers, isRecord) {
var bitRate = 128000;
var mPublishers = maxPublishers;
if(quality.toLowerCase() === 'high') bitRate = 256000;
if(quality.toLowerCase() === 'medium') bitRate = 128000;
if(quality.toLowerCase() === 'low') bitRate = 64000;
if(maxPublishers > 6) mPublishers = 6;
var register = {
"request": "create",
"is_private": isPrivate || true,
"secret": adminKey || Date.now()+'', // To destroy
"bitrate": bitRate,
"publishers": mPublishers || 6,
"record": isRecord || false
};
if(userKey) register.pin = userKey;
videoroomHandle.send({
"message": register,
"success": function(data) {
// VideoRoom created
if(onEvents && onEvents.onCreated) onEvents.onCreated(data.room);
}
});
};
/**
* Destroys a Videoroom (Admin key is required)
* @param {integer} id VideoRoom Id
* @param {string} adminKey Administrator Room Key
* @return {nothing}
* @example
* action.destroyVideoroom(743267423, 'MyP455w0rd');
*/
var destroyVideoroom = function(id, adminKey) {
var request = {
"request": "destroy",
"room": id,
"secret": adminKey
};
videoroomHandle.send({"message": request});
};
/**
* Join into a VideoRoom
* @param {string} name User Name
* @param {integer} idRoom VideoRoom ID
* @param {string} pin Videoroom PIN to Join (Optional)
* @return {nothing}
* @example
* action.joinVideoroom('Mike', 743267423, 'ivr1234');
*/
var joinVideoroom = function(name, idRoom, pin) {
username = name || 'Peer';
idVideoroom = idRoom || 1234;
var register = { "request": "join", "room": idVideoroom, "ptype": "publisher", "display": username };
if(pin){
roomPin = pin;
register.pin = roomPin;
}
videoroomHandle.send({"message": register});
};
/**
* Gets the number of peers/users connected into the current Videoroom
* @return {integer} Number of peers/users connected into the current Videoroom
*/
var getPeers = function() {
return nPeers;
};
/**
* Toggle Audio stream (Mute/Unmute)
* @return {boolean} Is audio muted?
* @example
* action.toggleAudio(); // true or false
*/
var toggleAudio = function() {
if (videoroomHandle.isAudioMuted()) videoroomHandle.unmuteAudio();
else videoroomHandle.muteAudio();
return videoroomHandle.isAudioMuted();
};
/**
* Toggle Video stream (Mute/Unmute)
* @return {boolean} Is video muted?
* @example
* action.toggleVideo(); // true or false
*/
var toggleVideo = function() {
if (videoroomHandle.isVideoMuted()) videoroomHandle.unmuteVideo();
else videoroomHandle.muteVideo();
return videoroomHandle.isVideoMuted();
};
/**
* New Remote Feed
* @param {integer} id Id
* @param {string} display Name
* @return {nothing}
* @private
*/
var newRemoteFeed = function(id, display) {
// A new feed has been published, create a new plugin handle and attach to it as a listener
var remoteFeed = null;
window.VideoRTC.connection.handle.attach(
{
plugin: "janus.plugin.videoroom",
success: function(pluginHandle) {
remoteFeed = pluginHandle;
// We wait for the plugin to send us an offer
var listen = { "request": "join", "room": idVideoroom || 1234, "ptype": "listener", "feed": id };
if(roomPin) listen.pin = roomPin;
remoteFeed.send({"message": listen});
},
error: function(error) {
Janus.error(" -- Error attaching plugin...", error);
},
onmessage: function(msg, jsep) {
Janus.debug(" ::: Got a message (listener) :::");
var event = msg["videoroom"];
Janus.debug("Event: " + event);
if(event != undefined && event != null) {
if(event === "attached") {
// Subscriber created and attached
for(var i=1;i<6;i++) {
if(feeds[i] === undefined || feeds[i] === null) {
feeds[i] = remoteFeed;
remoteFeed.rfindex = i;
break;
}
}
remoteFeed.rfid = msg["id"];
remoteFeed.rfdisplay = msg["display"];
//Janus.log("Successfully attached to feed " + remoteFeed.rfid + " (" + remoteFeed.rfdisplay + ") in room " + msg["room"]);
} else if(msg["error"] !== undefined && msg["error"] !== null) {
Janus.error(msg["error"]);
} else {
// What has just happened?
}
}
if(jsep !== undefined && jsep !== null) {
Janus.debug("Handling SDP as well...");
Janus.debug(jsep);
// Answer and attach
remoteFeed.createAnswer(
{
jsep: jsep,
media: { audioSend: false, videoSend: false, data: true }, // We want recvonly audio/video
success: function(jsep) {
Janus.debug("Got SDP!");
Janus.debug(jsep);
var body = { "request": "start", "room": idVideoroom };
remoteFeed.send({"message": body, "jsep": jsep});
},
error: function(error) {
Janus.error("WebRTC error:", error);
}
});
}
},
onlocalstream: function(stream) {
// The subscriber stream is recvonly, we don't expect anything here
},
onremotestream: function(stream) {
Janus.debug("Remote feed #" + remoteFeed.rfindex);
var generateLabel = function(id, content, backgroundColor, position) {
var output = '';
output += '<span id="'+id+'" style="';
output += ' position:absolute;margin:10px;padding:3px 5px;color:white;font-weight:bold;border-radius:5px;';
output += 'background:'+backgroundColor+';';
output += position;
output += '">'+content+'</span>';
return output;
};
var container = domElements.videos;
var target = document.getElementById('container-remote'+remoteFeed.rfindex);
var tpl = '';
if(!target || target.innerHTML.length === 0) {
tpl += '<video autoplay poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" id="videoremote'+remoteFeed.rfindex+'"></video>';
tpl += generateLabel('remote-name'+remoteFeed.rfindex, remoteFeed.rfdisplay, '#55D8D5', 'left:0; margin-top: 10px;');
tpl += generateLabel('remote-resolution'+remoteFeed.rfindex, '', '#8DCC6D', 'left:0; margin-top: 40px;');
tpl += generateLabel('remote-bitrate'+remoteFeed.rfindex, '', '#FF6E5F', 'left:0; margin-top: 70px;');
var newNode = document.createElement('div');
newNode.id = 'container-remote'+remoteFeed.rfindex;
newNode.className = 'videortc-video-container';
newNode.innerHTML = tpl;
container.appendChild(newNode);
var videoElem = document.getElementById('videoremote'+remoteFeed.rfindex);
videoElem.onplaying = function() {
var width = this.videoWidth;
var height = this.videoHeight;
document.getElementById('remote-resolution'+remoteFeed.rfindex).innerHTML = width+'x'+height;
if(window.VideoRTC.getBrowser() === 'firefox') {
// Firefox Stable has a bug: width and height are not immediately available after a playing
setTimeout(function() {
var width = videoElem.videoWidth;
var height = videoElem.videoHeight;
document.getElementById('remote-resolution'+remoteFeed.rfindex).innerHTML = width+'x'+height;
}, 2000);
}
};
Janus.attachMediaStream(videoElem, stream);
var videoTracks = stream.getVideoTracks();
if(videoTracks === null || videoTracks === undefined || videoTracks.length === 0 || videoTracks[0].muted) {
// No remote video
var nodeNoCamera = document.createElement('div');
nodeNoCamera.innerHTML = 'No camera available';
nodeNoCamera.style.position = "relative";
nodeNoCamera.style.height = "100%";
nodeNoCamera.style.width = "100%";
nodeNoCamera.style.top = "100%";
nodeNoCamera.style.left = "50%";
nodeNoCamera.style.transform = "translate(-50%,-50%)";
nodeNoCamera.className = "no-camera-available";
newNode.insertBefore(nodeNoCamera, newNode.firstChild);
if(streamOptions.voiceProcessor) {
nodeNoCamera.innerHTML = '';
var nodeVolume = document.createElement('span');
nodeVolume.className = "volume-level-processor";
nodeNoCamera.insertBefore(nodeVolume, nodeNoCamera.firstChild);
setVoiceProcessor(stream, nodeVolume);
}
// We Hide Bitrate and Resolution labels
for(var i = 0; i < newNode.childNodes.length; i++) {
if(newNode.childNodes[i].id && (newNode.childNodes[i].id.indexOf('remote-resolution') >= 0 || newNode.childNodes[i].id.indexOf('remote-bitrate') >= 0 )) {
newNode.childNodes[i].style.display = 'none';
}
}
}
bitrateTimer[remoteFeed.rfindex] = setInterval(function() {
// Display updated bitrate, if supported
var bitrate = remoteFeed.getBitrate();
document.getElementById('remote-bitrate'+remoteFeed.rfindex).innerHTML = bitrate;
}, 1000);
}
nPeers++;
//if(onEvents && onEvents.onAcceptedVideo) onEvents.onAcceptedVideo();
},
oncleanup: function() {
Janus.log(" ::: Got a cleanup notification (remote feed " + id + ") :::");
//$('#waitingvideo'+remoteFeed.rfindex).remove();
//$('#curbitrate'+remoteFeed.rfindex).remove();
//$('#curres'+remoteFeed.rfindex).remove();
if(bitrateTimer[remoteFeed.rfindex] !== null && bitrateTimer[remoteFeed.rfindex] !== null)
clearInterval(bitrateTimer[remoteFeed.rfindex]);
bitrateTimer[remoteFeed.rfindex] = null;
},
ondataopen: function () {
Janus.log("The DataChannel is available!");
if(onEvents && onEvents.onAcceptedData) onEvents.onAcceptedData();
},
ondata: function (data) {
Janus.debug("We got data from the DataChannel! " + data);
DataChannel.receive(data, onEvents.onDataReceived);
}
});
};
/**
* Publish Own Stream
* @return {nothing}
* @private
*/
var publishOwnStream = function() {
videoroomHandle.createOffer(
{
media: {
audioRecv: false,
audioSend: streamOptions.audioEnabled,
videoRecv: false,
videoSend: streamOptions.videoEnabled,
data: true,
audio: {
deviceId: {
exact: streamOptions.aDeviceId || undefined
}
},
video: {
deviceId: {
exact: streamOptions.vDeviceId || undefined
}
}
}, // Publishers are sendonly
success: function(jsep) {
var publish = { "request": "configure", "audio": true, "video": true, "data": true };
videoroomHandle.send({"message": publish, "jsep": jsep});
},
error: function(error) {
Janus.error("WebRTC error:", error);
publishOwnStream();
}
}
);
};
var setVoiceProcessor = function(stream, nodeNoCamera) {
var audioCtx = new AudioContext();
var source = audioCtx.createMediaStreamSource(stream);
// We create an analyzer
var analyser = audioCtx.createAnalyser();
analyser.smoothingTimeConstant = 0.3;
analyser.fftSize = 1024;
// We create an audio processor
var processor = audioCtx.createScriptProcessor(2048, 1, 1);
processor.onaudioprocess = function(audio) {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
// Average
var prom = 0;
for (var i = 0; i < array.length; i++) {
prom += array[i];
}
prom = prom / array.length;
var ratio = 0.7;
prom = ratio*prom;
// We paint the border box
nodeNoCamera.style.border = "solid " + prom + "px";
nodeNoCamera.style["border-radius"] = (15 + prom) + "px";
}
source.connect(analyser);
analyser.connect(processor);
processor.connect(audioCtx.destination);
};
var joinScreenroom = function(screenRoom) {
window.VideoRTC.connection.handle.attach({
plugin: "janus.plugin.videoroom",
success: function(pluginHandle) {
console.log(pluginHandle);
// Plugin attached! 'pluginHandle' is our handle
screenRoomHandle = pluginHandle;
console.log(screenRoomHandle);
var register = { "request": "join", "room": screenRoom, "ptype": "publisher", "display": username + '-screen' || 'ScreenClient' };
if(roomPin) register.pin = roomPin;
screenRoomHandle.send({"message": register});
},
error: function(cause) {
console.log("Error: " + cause);
},
consentDialog: function(on) {
},
onmessage: function(msg, jsep) {
var event = msg.videoroom;
if(event !== undefined && event !== null) {
if(event === "joined") {
if(msg["publishers"] !== undefined && msg["publishers"] !== null) {
var list = msg["publishers"];
Janus.debug("Got a list of available publishers/feeds:");
Janus.debug(list);
for(var f in list) {
var id = list[f]["id"];
var display = list[f]["display"];
Janus.debug(" >> [" + id + "] " + display);
//listenScreenSharing(screenRoom, id);
}
}
} else if(event === "destroyed") {
Janus.warn("The room has been destroyed!");
} else if(event === "event") {
if(msg["publishers"] !== undefined && msg["publishers"] !== null) {
var list = msg["publishers"];
Janus.debug("Got a list of available publishers/feeds:");
Janus.debug(list);
for(var f in list) {
var id = list[f]["id"];
var display = list[f]["display"];
Janus.debug(" >> [" + id + "] " + display);
//listenScreenSharing(screenRoom, id);
}
} else if(msg["leaving"] !== undefined && msg["leaving"] !== null) {
var leaving = msg["leaving"];
Janus.log("Publisher left: " + leaving);
var container = domElements.screenRemote;
container.innerHTML = '';
container.style = '';
//container.className = '';
screenFeed.detach();
if(onEvents && onEvents.onScreensharingClosed) onEvents.onScreensharingClosed();
} else if(msg["unpublished"] !== undefined && msg["unpublished"] !== null) {
var unpublished = msg["unpublished"];
Janus.log("Publisher left: " + unpublished);
var container = domElements.screenRemote;
container.innerHTML = '';
container.style = '';
//container.className = '';
screenFeed.detach();
} else if(msg["error"] !== undefined && msg["error"] !== null) {
Janus.error(msg["error"]);
}
}
}
if(jsep !== undefined && jsep !== null) {
Janus.debug("Handling SDP as well...");
Janus.debug(jsep);
screenRoomHandle.handleRemoteJsep({jsep: jsep});
}
},
onlocalstream: function(stream) {
// We have a local stream (getUserMedia worked!) to display
//var container = domElements.screenLocal;
//container.innerHTML = '<video autoplay poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" id="screenClient"></video>';
//var videoElem = document.getElementById('screenClient');
//Janus.attachMediaStream(videoElem, stream);
//videoElem.muted = true;
},
onremotestream: function(stream) {
},
oncleanup: function() {
},
detached: function() {
}
});
};
var startScreensharing = function(screenId, cOk, cKo) {
if(window.location.protocol !== 'https:') {
cKo ('Screensharing requires HTTPS');
return false;
}
if(window.isMobile) {
cKo ('Screensharing is not available on Mobile devices');
return false;
}
if(!Janus.isExtensionEnabled()) {
cKo("You're using a recent version of Chrome but don't have the screensharing extension installed: click <b><a href='https://chrome.google.com/webstore/detail/videortc-screensharing/pkilckpboojemoogepfpkgbihkfkikel' target='_blank'>here</a></b> to do so");
return false;
}
var capture = 'screen';
console.log(screenRoomHandle);
screenRoomHandle.createOffer(
{
//media: { audioRecv: false, videoRecv: false, audioSend: useAudio, videoSend: true}, // Publishers are sendonly
media: { video: capture, audio: false, videoRecv: false },
success: function(jsep) {
var publish = { "request": "configure", "audio": false, "video": true, "data": false };
screenRoomHandle.send({"message": publish, "jsep": jsep});
cOk();
},
error: function(error) {
console.log(error);
if(error && error.name === 'NotAllowedError' && window.getBrowser() === 'firefox') {
cKo('Firefox needs that the domain this web application is from is listed in Allowed domains.');
}
Janus.error("WebRTC error:", error);
}
}
);
};
var stopScreensharing = function(cOk, cKo) {
var leave = { "request": "leave" };
screenRoomHandle.send({"message": leave});
screenRoomHandle.detach();
joinScreenroom(idVideoroom);
//var container = domElements.screenLocal;
//container.innerHTML = '';
//container.style = '';
cOk();
};
var sendData = function(type, data, cOk, cKo, filename) {
DataChannel.send(type, data, cOk, cKo, filename);
};
return new Promise(function (resolve, reject) {
window.VideoRTC.connection.handle.attach({
plugin: "janus.plugin.videoroom",
success: function(pluginHandle) {
// Plugin attached! 'pluginHandle' is our handle
videoroomHandle = pluginHandle;
var cbks = {
fileOk: onEvents.onFileTransferOk || function() {},
fileKo: onEvents.onFileTransferKo || function() {}
};
console.log(cbks);
var result = DataChannel.initialize({}, pluginHandle, cbks);
if(!result) console.log("Datachannel options can't be loaded:");
resolve({
closeUsecase: closeUsecase,
createVideoroom: createVideoroom,
destroyVideoroom: destroyVideoroom,
getPeers: getPeers,
joinVideoroom: joinVideoroom,
sendData: sendData,
startScreensharing: startScreensharing,
stopScreensharing: stopScreensharing,
toggleAudio: toggleAudio,
toggleVideo: toggleVideo
});
},
error: function(cause) {
// Couldn't attach to the plugin
Janus.error(" -- Error attaching plugin...", error);
reject(cause);
},
consentDialog: function(on) {
// e.g., Darken the screen if on=true (getUserMedia incoming), restore it otherwise
},
onmessage: function(msg, jsep) {
// We got a message/event (msg) from the plugin
// If jsep is not null, this involves a WebRTC negotiation
var error = msg["error"];
var code = msg["error_code"];
if(error != null && error != undefined) {
Janus.error(error);
if(onEvents && onEvents.onError) onEvents.onError(error, code);
return;
}
var event = msg["videoroom"];
if(event !== undefined && event !== null) {
if(event === "joined") {
// Publisher/manager created, negotiate WebRTC and attach to existing feeds, if any
publishOwnStream();
// Any new feed to attach to?
if(msg["publishers"] !== undefined && msg["publishers"] !== null) {
var list = msg["publishers"];
Janus.debug("Got a list of available publishers/feeds:");
Janus.debug(list);
for(var f in list) {
var id = list[f]["id"];
var display = list[f]["display"];
Janus.debug(" >> [" + id + "] " + display);
newRemoteFeed(id, display)
}
}
if(onEvents && onEvents.onJoined) onEvents.onJoined();
joinScreenroom(idVideoroom);
} else if(event === "destroyed") {
// The room has been destroyed
Janus.warn("The room has been destroyed!");
if(onEvents && onEvents.onDestroyed) onEvents.onDestroyed();
} else if(event === "event") {
// Any new feed to attach to?
if(msg["publishers"] !== undefined && msg["publishers"] !== null) {
var list = msg["publishers"];
Janus.debug("Got a list of available publishers/feeds:");
Janus.debug(list);
for(var f in list) {
var id = list[f]["id"];
var display = list[f]["display"];
Janus.debug(" >> [" + id + "] " + display);
newRemoteFeed(id, display)
}
if(onEvents && onEvents.onPeerJoined) onEvents.onPeerJoined(id, display);
} else if(msg["leaving"] !== undefined && msg["leaving"] !== null) {
// One of the publishers has gone away?
var leaving = msg["leaving"];
Janus.log("Publisher left: " + leaving);
var remoteFeed = null;
for(var i=1; i<6; i++) {
if(feeds[i] != null && feeds[i] != undefined && feeds[i].rfid == leaving) {
remoteFeed = feeds[i];
break;
}
}
if(remoteFeed != null) {
nPeers--;
Janus.debug("Feed " + remoteFeed.rfid + " (" + remoteFeed.rfdisplay + ") has left the room, detaching");
if(onEvents && onEvents.onPeerLeft) onEvents.onPeerLeft(remoteFeed.rfid, remoteFeed.rfdisplay);
document.getElementById('container-remote'+remoteFeed.rfindex).remove();
feeds[remoteFeed.rfindex] = null;
remoteFeed.detach();
}
} else if(msg["unpublished"] !== undefined && msg["unpublished"] !== null) {
// One of the publishers has unpublished?
var unpublished = msg["unpublished"];
Janus.log("Publisher left: " + unpublished);
if(unpublished === 'ok') {
// That's us
videoroomHandle.hangup();
return;
}
var remoteFeed = null;
for(var i=1; i<6; i++) {
if(feeds[i] != null && feeds[i] != undefined && feeds[i].rfid == unpublished) {
remoteFeed = feeds[i];
break;
}
}
if(remoteFeed != null) {
nPeers--;
Janus.debug("Feed " + remoteFeed.rfid + " (" + remoteFeed.rfdisplay + ") has left the room, detaching");
if(onEvents && onEvents.onPeerLeft) onEvents.onPeerLeft(remoteFeed.rfid, remoteFeed.rfdisplay);
document.getElementById('container-remote'+remoteFeed.rfindex).remove();
feeds[remoteFeed.rfindex] = null;
remoteFeed.detach();
}
} else if(msg["error"] !== undefined && msg["error"] !== null) {
if(onEvents && onEvents.onError) onEvents.onError(msg["error"], msg["error_code"]);
}
}
}
if(jsep !== undefined && jsep !== null) {
Janus.debug("Handling SDP as well...");
Janus.debug(jsep);
videoroomHandle.handleRemoteJsep({jsep: jsep});
}
},
onlocalstream: function(stream) {
// We have a local stream (getUserMedia worked!) to display
Janus.debug(" ::: Got a local stream :::");
var container = domElements.videos;
var newNode = document.createElement('div');
newNode.id = 'localvideo';
newNode.className = 'videortc-video-container';
newNode.innerHTML = '<video autoplay poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" id="videolocal1"></video>';
container.insertBefore(newNode, container.firstChild);
var videoElem = document.getElementById('videolocal1');
Janus.attachMediaStream(videoElem, stream);
videoElem.muted = true;
var videoTracks = stream.getVideoTracks();
if(videoTracks === null || videoTracks === undefined || videoTracks.length === 0) {
// No remote video
var nodeNoCamera = document.createElement('div');
nodeNoCamera.innerHTML = 'No camera available';
nodeNoCamera.style.position = "relative";
nodeNoCamera.style.height = "100%";
nodeNoCamera.style.width = "100%";
nodeNoCamera.style.top = "100%";
nodeNoCamera.style.left = "50%";
nodeNoCamera.style.transform = "translate(-50%,-50%)";
nodeNoCamera.className = "no-camera-available";
newNode.insertBefore(nodeNoCamera, newNode.firstChild);
if(streamOptions.voiceProcessor) {
nodeNoCamera.innerHTML = '';
var nodeVolume = document.createElement('span');
nodeVolume.className = "volume-level-processor";
nodeNoCamera.insertBefore(nodeVolume, nodeNoCamera.firstChild);
setVoiceProcessor(stream, nodeVolume);
}
}
},
onremotestream: function(stream) {
// The publisher stream is sendonly, we don't expect anything here
Janus.debug(" ::: Got a remote stream :::");
},
oncleanup: function() {
// PeerConnection with the plugin closed, clean the UI
// The plugin handle is still valid so we can create a new one
},
detached: function() {
// Connection with the plugin closed, get rid of its features
// The plugin handle is not valid anymore
}
});
});
};
exports.videoRoom = videoRoom;