openvidu/openvidu-browser/lib/OpenVidu/OpenVidu.js

585 lines
27 KiB
JavaScript

"use strict";
/*
* (C) Copyright 2017-2018 OpenVidu (http://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
exports.__esModule = true;
var __1 = require("..");
var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
var VersionAdapter_1 = require("../OpenViduInternal/VersionAdapter");
var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
var platform = require("platform");
/**
* @hidden
*/
var SECRET_PARAM = '?secret=';
/**
* @hidden
*/
var RECORDER_PARAM = '&recorder=';
/**
* Entrypoint of OpenVidu Browser library.
* Use it to initialize objects of type [[Session]], [[Publisher]] and [[LocalRecorder]]
*/
var OpenVidu = /** @class */ (function () {
function OpenVidu() {
this.secret = '';
this.recorder = false;
/**
* @hidden
*/
this.advancedConfiguration = {};
console.info("'OpenVidu' initialized");
}
/**
* Returns a session with id `sessionId`
* @param sessionId Session unique ID generated in openvidu-server
*/
OpenVidu.prototype.initSession = function (sessionId) {
this.session = new __1.Session(sessionId, this);
return this.session;
};
/**
* Returns a new publisher
*
* #### Events dispatched
*
* The [[Publisher]] object will dispatch an `accessDialogOpened` event, only if the pop-up shown by the browser to request permissions for the camera is opened. You can use this event to alert the user about granting permissions
* for your website. An `accessDialogClosed` event will also be dispatched after user clicks on "Allow" or "Block" in the pop-up.
*
* The [[Publisher]] object will dispatch an `accessAllowed` or `accessDenied` event once it has been granted access to the requested input devices or not.
*
* The [[Publisher]] object will dispatch a `videoElementCreated` event once the HTML video element has been added to DOM (if _targetElement_ not null or undefined)
*
* The [[Publisher]] object will dispatch a `videoPlaying` event once the local video starts playing (only if `videoElementCreated` event has been previously dispatched)
*
* @param targetElement HTML DOM element (or its `id` attribute) in which the video element of the Publisher will be inserted (see [[PublisherProperties.insertMode]]). If null or undefined no default video will be created for this Publisher
* (you can always access the native MediaStream object by calling _Publisher.stream.getMediaStream()_ and use it as _srcObject_ of any HTML video element)
* @param completionHandler `error` parameter is null if `initPublisher` succeeds, and is defined if it fails.
* `completionHandler` function is called before the Publisher dispatches an `accessAllowed` or an `accessDenied` event
*/
OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) {
var properties;
if (!!param2 && (typeof param2 !== 'function')) {
// Matches 'initPublisher(targetElement, properties)' or 'initPublisher(targetElement, properties, completionHandler)'
properties = param2;
// DEPRECATED WARNING
properties = VersionAdapter_1.adaptPublisherProperties(properties);
properties = {
audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined,
frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined),
insertMode: (typeof properties.insertMode !== 'undefined') ? properties.insertMode : VideoInsertMode_1.VideoInsertMode.APPEND,
mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true,
publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
};
}
else {
// Matches 'initPublisher(targetElement)' or 'initPublisher(targetElement, completionHandler)'
properties = {
insertMode: VideoInsertMode_1.VideoInsertMode.APPEND,
mirror: true,
publishAudio: true,
publishVideo: true,
resolution: '640x480'
};
}
var publisher = new __1.Publisher(targetElement, properties, this);
var completionHandler;
if (!!param2 && (typeof param2 === 'function')) {
completionHandler = param2;
}
else if (!!param3) {
completionHandler = param3;
}
publisher.initialize()
.then(function () {
if (completionHandler !== undefined) {
completionHandler(undefined);
}
publisher.emitEvent('accessAllowed', []);
})["catch"](function (error) {
if (!!completionHandler !== undefined) {
completionHandler(error);
}
publisher.emitEvent('accessDenied', []);
});
return publisher;
};
OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) {
var _this = this;
return new Promise(function (resolve, reject) {
var publisher;
var callback = function (error) {
if (!!error) {
reject(error);
}
else {
resolve(publisher);
}
};
if (!!properties) {
publisher = _this.initPublisher(targetElement, properties, callback);
}
else {
publisher = _this.initPublisher(targetElement, callback);
}
});
};
/**
* Returns a new local recorder for recording streams straight away from the browser
* @param stream Stream to record
*/
OpenVidu.prototype.initLocalRecorder = function (stream) {
return new __1.LocalRecorder(stream);
};
/**
* Checks if the browser supports OpenVidu
* @returns 1 if the browser supports OpenVidu, 0 otherwise
*/
OpenVidu.prototype.checkSystemRequirements = function () {
var browser = platform.name;
var version = platform.version;
if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
(browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') &&
(browser !== 'Opera') && (browser !== 'Opera Mobile') &&
(browser !== 'Safari')) {
return 0;
}
else {
return 1;
}
};
/**
* Collects information about the media input devices available on the system. You can pass property `deviceId` of a [[Device]] object as value of `audioSource` or `videoSource` properties in [[initPublisher]] method
*/
OpenVidu.prototype.getDevices = function () {
return new Promise(function (resolve, reject) {
navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
var devices = [];
deviceInfos.forEach(function (deviceInfo) {
if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') {
devices.push({
kind: deviceInfo.kind,
deviceId: deviceInfo.deviceId,
label: deviceInfo.label
});
}
});
resolve(devices);
})["catch"](function (error) {
console.error('Error getting devices', error);
reject(error);
});
});
};
/**
* Get a MediaStream object that you can customize before calling [[initPublisher]] (pass _MediaStreamTrack_ property of the _MediaStream_ value resolved by the Promise as `audioSource` or `videoSource` properties in [[initPublisher]])
*
* Parameter `options` is the same as in [[initPublisher]] second parameter (of type [[PublisherProperties]]), but only the following properties will be applied: `audioSource`, `videoSource`, `frameRate`, `resolution`
*
* To customize the Publisher's video, the API for HTMLCanvasElement is very useful. For example, to get a black-and-white video at 10 fps and HD resolution with no sound:
* ```
* var OV = new OpenVidu();
* var FRAME_RATE = 10;
*
* OV.getUserMedia({
* audioSource: false;
* videoSource: undefined,
* resolution: '1280x720',
* frameRate: FRAME_RATE
* })
* .then(mediaStream => {
*
* var videoTrack = mediaStream.getVideoTracks()[0];
* var video = document.createElement('video');
* video.srcObject = new MediaStream([videoTrack]);
*
* var canvas = document.createElement('canvas');
* var ctx = canvas.getContext('2d');
* ctx.filter = 'grayscale(100%)';
*
* video.addEventListener('play', () => {
* var loop = () => {
* if (!video.paused && !video.ended) {
* ctx.drawImage(video, 0, 0, 300, 170);
* setTimeout(loop, 1000/ FRAME_RATE); // Drawing at 10 fps
* }
* };
* loop();
* });
* video.play();
*
* var grayVideoTrack = canvas.captureStream(FRAME_RATE).getVideoTracks()[0];
* var publisher = this.OV.initPublisher(
* myHtmlTarget,
* {
* audioSource: false,
* videoSource: grayVideoTrack
* });
* });
* ```
*/
OpenVidu.prototype.getUserMedia = function (options) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.generateMediaConstraints(options)
.then(function (constraints) {
navigator.mediaDevices.getUserMedia(constraints)
.then(function (mediaStream) {
resolve(mediaStream);
})["catch"](function (error) {
var errorName;
var errorMessage = error.toString();
if (!(options.videoSource === 'screen')) {
errorName = (options.videoSource === false || options.videoSource === null) ? OpenViduError_1.OpenViduErrorName.MICROPHONE_ACCESS_DENIED : OpenViduError_1.OpenViduErrorName.CAMERA_ACCESS_DENIED;
}
else {
errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
}
reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
});
})["catch"](function (error) {
reject(error);
});
});
};
/* tslint:disable:no-empty */
/**
* Disable all logging except error level
*/
OpenVidu.prototype.enableProdMode = function () {
console.log = function () { };
console.debug = function () { };
console.info = function () { };
console.warn = function () { };
};
/* tslint:enable:no-empty */
/**
* Set OpenVidu advanced configuration options. Currently `configuration` is an object with the following optional properties (see [[OpenViduAdvancedConfiguration]] for more details):
* - `iceServers`: set custom STUN/TURN servers to be used by OpenVidu Browser
* - `screenShareChromeExtension`: url to a custom screen share extension for Chrome to be used instead of the default one, based on ours [https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension](https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension)
* - `publisherSpeakingEventsOptions`: custom configuration for the [[PublisherSpeakingEvent]] feature
*/
OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
this.advancedConfiguration = configuration;
};
/* Hidden methods */
/**
* @hidden
*/
OpenVidu.prototype.getUrlWithoutSecret = function (url) {
if (!url) {
console.error('sessionId is not defined');
}
if (url.indexOf(SECRET_PARAM) !== -1) {
url = url.substring(0, url.lastIndexOf(SECRET_PARAM));
}
return url;
};
/**
* @hidden
*/
OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
var _this = this;
return new Promise(function (resolve, reject) {
var audio, video;
if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) {
audio = false;
}
else if (publisherProperties.audioSource === undefined) {
audio = true;
}
else {
audio = publisherProperties.audioSource;
}
if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) {
video = false;
}
else {
video = {
height: {
ideal: 480
},
width: {
ideal: 640
}
};
}
var mediaConstraints = {
audio: audio,
video: video
};
if (typeof mediaConstraints.audio === 'string') {
mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } };
}
if (mediaConstraints.video) {
if (!!publisherProperties.resolution) {
var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
var width = Number(widthAndHeight[0]);
var height = Number(widthAndHeight[1]);
mediaConstraints.video.width.ideal = width;
mediaConstraints.video.height.ideal = height;
}
if (!!publisherProperties.frameRate) {
mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate };
}
if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') {
if (publisherProperties.videoSource === 'screen') {
if (platform.name !== 'Chrome' && platform.name !== 'Firefox') {
var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name);
console.error(error);
reject(error);
}
else {
if (!!_this.advancedConfiguration.screenShareChromeExtension) {
// Custom screen sharing extension for Chrome
var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim();
screenSharing.getChromeExtensionStatus(extensionId, function (status) {
if (status === 'installed-enabled') {
screenSharing.getScreenConstraints(function (error, screenConstraints) {
if (!!error && error === 'permission-denied') {
var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
console.error(error_1);
reject(error_1);
}
else {
mediaConstraints.video = screenConstraints;
resolve(mediaConstraints);
}
});
}
if (status === 'installed-disabled') {
var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
console.error(error);
reject(error);
}
if (status === 'not-installed') {
var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension);
console.error(error);
reject(error);
}
});
}
else {
// Default screen sharing extension for Chrome
screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
if (!!error) {
if (error === 'not-installed') {
var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk');
console.error(error_2);
reject(error_2);
}
else if (error === 'installed-disabled') {
var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
console.error(error_3);
reject(error_3);
}
else if (error === 'permission-denied') {
var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
console.error(error_4);
reject(error_4);
}
}
else {
mediaConstraints.video = screenConstraints.video;
resolve(mediaConstraints);
}
});
}
publisherProperties.videoSource = 'screen';
}
}
else {
// tslint:disable-next-line:no-string-literal
mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource };
resolve(mediaConstraints);
}
}
else {
resolve(mediaConstraints);
}
}
else {
resolve(mediaConstraints);
}
});
};
/**
* @hidden
*/
OpenVidu.prototype.startWs = function (onConnectSucces) {
var config = {
heartbeat: 5000,
sendCloseMessage: false,
ws: {
uri: this.wsUri,
useSockJS: false,
onconnected: onConnectSucces,
ondisconnect: this.disconnectCallback.bind(this),
onreconnecting: this.reconnectingCallback.bind(this),
onreconnected: this.reconnectedCallback.bind(this)
},
rpc: {
requestTimeout: 15000,
participantJoined: this.session.onParticipantJoined.bind(this.session),
participantPublished: this.session.onParticipantPublished.bind(this.session),
participantUnpublished: this.session.onParticipantUnpublished.bind(this.session),
participantLeft: this.session.onParticipantLeft.bind(this.session),
participantEvicted: this.session.onParticipantEvicted.bind(this.session),
recordingStarted: this.session.onRecordingStarted.bind(this.session),
recordingStopped: this.session.onRecordingStopped.bind(this.session),
sendMessage: this.session.onNewMessage.bind(this.session),
iceCandidate: this.session.recvIceCandidate.bind(this.session),
mediaError: this.session.onMediaError.bind(this.session)
}
};
this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
};
/**
* @hidden
*/
OpenVidu.prototype.closeWs = function () {
this.jsonRpcClient.close();
};
/**
* @hidden
*/
OpenVidu.prototype.processOpenViduUrl = function (url) {
var secret = this.getSecretFromUrl(url);
var recorder = this.getRecorderFromUrl(url);
if (!!secret) {
this.secret = secret;
}
if (!!recorder) {
this.recorder = recorder;
}
this.wsUri = this.getFinalWsUrl(url);
};
/**
* @hidden
*/
OpenVidu.prototype.sendRequest = function (method, params, callback) {
if (params && params instanceof Function) {
callback = params;
params = {};
}
console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
this.jsonRpcClient.send(method, params, callback);
};
/**
* @hidden
*/
OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) {
var is = (!!mediaSource &&
mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' &&
mediaSource.id !== undefined && typeof mediaSource.id === 'string' &&
mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' &&
mediaSource.label !== undefined && typeof mediaSource.label === 'string' &&
mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' &&
mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string');
return is;
};
/**
* @hidden
*/
OpenVidu.prototype.getWsUri = function () {
return this.wsUri;
};
/**
* @hidden
*/
OpenVidu.prototype.getSecret = function () {
return this.secret;
};
/**
* @hidden
*/
OpenVidu.prototype.getRecorder = function () {
return this.recorder;
};
/* Private methods */
OpenVidu.prototype.disconnectCallback = function () {
console.warn('Websocket connection lost');
if (this.isRoomAvailable()) {
this.session.onLostConnection();
}
else {
alert('Connection error. Please reload page.');
}
};
OpenVidu.prototype.reconnectingCallback = function () {
console.warn('Websocket connection lost (reconnecting)');
if (this.isRoomAvailable()) {
this.session.onLostConnection();
}
else {
alert('Connection error. Please reload page.');
}
};
OpenVidu.prototype.reconnectedCallback = function () {
console.warn('Websocket reconnected');
};
OpenVidu.prototype.isRoomAvailable = function () {
if (this.session !== undefined && this.session instanceof __1.Session) {
return true;
}
else {
console.warn('Session instance not found');
return false;
}
};
OpenVidu.prototype.getSecretFromUrl = function (url) {
var secret = '';
if (url.indexOf(SECRET_PARAM) !== -1) {
var endOfSecret = url.lastIndexOf(RECORDER_PARAM);
if (endOfSecret !== -1) {
secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, endOfSecret);
}
else {
secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, url.length);
}
}
return secret;
};
OpenVidu.prototype.getRecorderFromUrl = function (url) {
var recorder = '';
if (url.indexOf(RECORDER_PARAM) !== -1) {
recorder = url.substring(url.lastIndexOf(RECORDER_PARAM) + RECORDER_PARAM.length, url.length);
}
return Boolean(recorder).valueOf();
};
OpenVidu.prototype.getFinalWsUrl = function (url) {
url = this.getUrlWithoutSecret(url).substring(0, url.lastIndexOf('/')) + '/room';
if (url.indexOf('.ngrok.io') !== -1) {
// OpenVidu server URL referes to a ngrok IP: secure wss protocol and delete port of URL
url = url.replace('ws://', 'wss://');
var regex = /\.ngrok\.io:\d+/;
url = url.replace(regex, '.ngrok.io');
}
else if ((url.indexOf('localhost') !== -1) || (url.indexOf('127.0.0.1') !== -1)) {
// OpenVidu server URL referes to localhost IP
}
return url;
};
return OpenVidu;
}());
exports.OpenVidu = OpenVidu;
//# sourceMappingURL=OpenVidu.js.map