mirror of https://github.com/OpenVidu/openvidu.git
Merge branch 'master' into mediasoup FIXME CONFLICT
This merge commit includes 2 merge conflicts:
* openvidu-browser/src/OpenVidu/Session.ts
In modern code, the OpenVidu version is obtained through other means.
However in the mediasoup branch this value is used in several of the
*LEGACY.ts files.
* openvidu-browser/src/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts
In the mediasoup branch, the special treatment for ionic was removed:
openvidu-browser: removed Ionic iOS timeout on first subscription
23d64be806
and also the method was converted into async and returned a Promise.
However in master the code is still like the old one.
pull/600/head
commit
5e9511a376
|
@ -20,7 +20,7 @@ Visit [openvidu.io](https://openvidu.io)
|
|||
## Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute.
|
||||
<a href="https://github.com/undefined/undefinedgraphs/contributors"><img src="https://opencollective.com/openvidu/contributors.svg?width=890&button=false" /></a>
|
||||
<a href="https://github.com/OpenVidu/openvidu/contributors"><img src="https://opencollective.com/openvidu/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
|
||||
## Backers
|
||||
|
|
|
@ -19,6 +19,7 @@ module.exports = {
|
|||
],
|
||||
excludeExternals: true,
|
||||
excludePrivate: true,
|
||||
excludeProtected: true,
|
||||
excludeNotExported: true,
|
||||
theme: "default",
|
||||
readme: "none",
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
{
|
||||
"author": "OpenVidu",
|
||||
"dependencies": {
|
||||
"@types/node": "13.13.2",
|
||||
"@types/platform": "1.3.2",
|
||||
"freeice": "2.2.2",
|
||||
"hark": "1.2.3",
|
||||
"platform": "1.3.5",
|
||||
"uuid": "7.0.3",
|
||||
"platform": "1.3.6",
|
||||
"uuid": "8.3.1",
|
||||
"wolfy87-eventemitter": "5.2.9"
|
||||
},
|
||||
"description": "OpenVidu Browser",
|
||||
"devDependencies": {
|
||||
"browserify": "16.5.1",
|
||||
"grunt": "1.1.0",
|
||||
"@types/node": "14.14.7",
|
||||
"@types/platform": "1.3.3",
|
||||
"browserify": "17.0.0",
|
||||
"grunt": "1.3.0",
|
||||
"grunt-cli": "1.3.2",
|
||||
"grunt-contrib-copy": "1.0.0",
|
||||
"grunt-contrib-sass": "1.0.0",
|
||||
"grunt-contrib-uglify": "4.0.1",
|
||||
"grunt-contrib-sass": "2.0.0",
|
||||
"grunt-contrib-uglify": "5.0.0",
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"grunt-postcss": "0.9.0",
|
||||
"grunt-string-replace": "1.3.1",
|
||||
"grunt-ts": "6.0.0-beta.22",
|
||||
"terser": "4.6.11",
|
||||
"tsify": "4.0.1",
|
||||
"tslint": "6.1.1",
|
||||
"typedoc": "0.17.4",
|
||||
"typescript": "3.8.3"
|
||||
"terser": "5.3.8",
|
||||
"tsify": "5.0.2",
|
||||
"tslint": "6.1.3",
|
||||
"typedoc": "0.19.2",
|
||||
"typescript": "4.0.5"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"main": "lib/index.js",
|
||||
|
@ -35,11 +35,11 @@
|
|||
"url": "git://github.com/OpenVidu/openvidu"
|
||||
},
|
||||
"scripts": {
|
||||
"browserify": "VERSION=${VERSION:-dev}; cd src && ../node_modules/browserify/bin/cmd.js Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/openvidu-browser-$VERSION.js -v",
|
||||
"browserify-prod": "VERSION=${VERSION:-dev}; cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/terser/bin/terser --source-map content=inline --output ../static/js/openvidu-browser-$VERSION.min.js",
|
||||
"browserify": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/openvidu-browser-$VERSION.js -v",
|
||||
"browserify-prod": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/terser/bin/terser --source-map content=inline --output ../static/js/openvidu-browser-$VERSION.min.js",
|
||||
"build": "cd src/OpenVidu && ./../../node_modules/typescript/bin/tsc && cd ../.. && ./node_modules/typescript/bin/tsc --declaration src/index.ts --outDir ./lib --sourceMap --lib dom,es5,es2015.promise,scripthost",
|
||||
"docs": "./generate-docs.sh"
|
||||
},
|
||||
"types": "lib/index.d.ts",
|
||||
"version": "2.15.0"
|
||||
"version": "2.16.0"
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
npm run build
|
||||
npm pack
|
||||
cp openvidu-browser-2.14.0.tgz ../../openvidu-tutorials/openvidu-react-native
|
||||
cp openvidu-browser-2.14.0.tgz ../../openvidu-react-native-adapter/
|
|
@ -18,7 +18,8 @@
|
|||
import { Session } from './Session';
|
||||
import { Stream } from './Stream';
|
||||
import { StreamLEGACY } from './StreamLEGACY';
|
||||
import { ConnectionOptions } from '../OpenViduInternal/Interfaces/Private/ConnectionOptions';
|
||||
import { LocalConnectionOptions } from '../OpenViduInternal/Interfaces/Private/LocalConnectionOptions';
|
||||
import { RemoteConnectionOptions } from '../OpenViduInternal/Interfaces/Private/RemoteConnectionOptions';
|
||||
import { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions';
|
||||
import { StreamOptionsServer } from '../OpenViduInternal/Interfaces/Private/StreamOptionsServer';
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
|
@ -52,14 +53,36 @@ export class Connection {
|
|||
data: string;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Role of the connection.
|
||||
* - `SUBSCRIBER`: can subscribe to published Streams of other users by calling [[Session.subscribe]]
|
||||
* - `PUBLISHER`: SUBSCRIBER permissions + can publish their own Streams by calling [[Session.publish]]
|
||||
* - `MODERATOR`: SUBSCRIBER + PUBLISHER permissions + can force the unpublishing or disconnection over a third-party Stream or Connection by call [[Session.forceUnpublish]] and [[Session.forceDisconnect]]
|
||||
*
|
||||
* **Only defined for the local connection. In remote connections will be `undefined`**
|
||||
*/
|
||||
stream: Stream;
|
||||
role: string;
|
||||
|
||||
/**
|
||||
* Whether the streams published by this connection will be recorded or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* **Only defined for the local connection. In remote connections will be `undefined`**
|
||||
*/
|
||||
record: boolean;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
options: ConnectionOptions | undefined;
|
||||
stream?: Stream;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
localOptions: LocalConnectionOptions | undefined;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
remoteOptions: RemoteConnectionOptions | undefined;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
|
@ -74,23 +97,30 @@ export class Connection {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(private session: Session, opts?: ConnectionOptions) {
|
||||
constructor(private session: Session, connectionOptions: LocalConnectionOptions | RemoteConnectionOptions) {
|
||||
let msg = "'Connection' created ";
|
||||
if (!!opts) {
|
||||
// Connection is remote
|
||||
msg += "(remote) with 'connectionId' [" + opts.id + ']';
|
||||
this.options = opts;
|
||||
this.connectionId = opts.id;
|
||||
this.creationTime = opts.createdAt;
|
||||
if (opts.metadata) {
|
||||
this.data = opts.metadata;
|
||||
}
|
||||
if (opts.streams) {
|
||||
this.initRemoteStreams(opts.streams);
|
||||
}
|
||||
} else {
|
||||
if (!!(<LocalConnectionOptions>connectionOptions).role) {
|
||||
// Connection is local
|
||||
this.localOptions = <LocalConnectionOptions>connectionOptions;
|
||||
this.connectionId = this.localOptions.id;
|
||||
this.creationTime = this.localOptions.createdAt;
|
||||
this.data = this.localOptions.metadata;
|
||||
this.rpcSessionId = this.localOptions.sessionId;
|
||||
this.role = this.localOptions.role;
|
||||
this.record = this.localOptions.record;
|
||||
msg += '(local)';
|
||||
} else {
|
||||
// Connection is remote
|
||||
this.remoteOptions = <RemoteConnectionOptions>connectionOptions;
|
||||
this.connectionId = this.remoteOptions.id;
|
||||
this.creationTime = this.remoteOptions.createdAt;
|
||||
if (this.remoteOptions.metadata) {
|
||||
this.data = this.remoteOptions.metadata;
|
||||
}
|
||||
if (this.remoteOptions.streams) {
|
||||
this.initRemoteStreams(this.remoteOptions.streams);
|
||||
}
|
||||
msg += "(remote) with 'connectionId' [" + this.remoteOptions.id + ']';
|
||||
}
|
||||
logger.info(msg);
|
||||
}
|
||||
|
@ -103,7 +133,7 @@ export class Connection {
|
|||
*/
|
||||
sendIceCandidate(candidate: RTCIceCandidate): void {
|
||||
|
||||
logger.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' +
|
||||
logger.debug((!!this.stream!.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' +
|
||||
this.connectionId, candidate);
|
||||
|
||||
this.session.openvidu.sendRequest('onIceCandidate', {
|
||||
|
@ -149,7 +179,7 @@ export class Connection {
|
|||
this.addStream(stream);
|
||||
});
|
||||
|
||||
logger.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts);
|
||||
logger.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream!.inboundStreamOpts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,4 +207,4 @@ export class Connection {
|
|||
this.disposed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,9 +119,9 @@ export class Filter {
|
|||
} else {
|
||||
logger.info('Filter method successfully executed on Stream ' + this.stream.streamId);
|
||||
const oldValue = (<any>Object).assign({}, this.stream.filter);
|
||||
this.stream.filter.lastExecMethod = { method, params: JSON.parse(stringParams) };
|
||||
this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.session, this.stream, 'filter', this.stream.filter, oldValue, 'execFilterMethod')]);
|
||||
this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter, oldValue, 'execFilterMethod')]);
|
||||
this.stream.filter!.lastExecMethod = { method, params: JSON.parse(stringParams) };
|
||||
this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.session, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||
this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
import { Stream } from './Stream';
|
||||
import { LocalRecorderState } from '../OpenViduInternal/Enums/LocalRecorderState';
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,11 @@ declare var MediaRecorder: any;
|
|||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Easy recording of [[Stream]] objects straightaway from the browser. Initialized with [[OpenVidu.initLocalRecorder]] method
|
||||
|
@ -45,7 +50,7 @@ export class LocalRecorder {
|
|||
private connectionId: string;
|
||||
private mediaRecorder: any;
|
||||
private chunks: any[] = [];
|
||||
private blob: Blob;
|
||||
private blob?: Blob;
|
||||
private id: string;
|
||||
private videoPreviewSrc: string;
|
||||
private videoPreview: HTMLVideoElement;
|
||||
|
@ -54,6 +59,7 @@ export class LocalRecorder {
|
|||
* @hidden
|
||||
*/
|
||||
constructor(private stream: Stream) {
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
|
||||
this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
|
||||
this.state = LocalRecorderState.READY;
|
||||
|
@ -170,6 +176,7 @@ export class LocalRecorder {
|
|||
}
|
||||
this.mediaRecorder.pause();
|
||||
this.state = LocalRecorderState.PAUSED;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
@ -188,6 +195,7 @@ export class LocalRecorder {
|
|||
}
|
||||
this.mediaRecorder.resume();
|
||||
this.state = LocalRecorderState.RECORDING;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
@ -209,7 +217,7 @@ export class LocalRecorder {
|
|||
this.videoPreview.id = this.id;
|
||||
this.videoPreview.autoplay = true;
|
||||
|
||||
if (platform.name === 'Safari') {
|
||||
if (platform.isSafariBrowser()) {
|
||||
this.videoPreview.setAttribute('playsinline', 'true');
|
||||
}
|
||||
|
||||
|
@ -274,7 +282,7 @@ export class LocalRecorder {
|
|||
if (this.state !== LocalRecorderState.FINISHED) {
|
||||
throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
|
||||
} else {
|
||||
return this.blob;
|
||||
return this.blob!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,7 +352,7 @@ export class LocalRecorder {
|
|||
}
|
||||
|
||||
const sendable = new FormData();
|
||||
sendable.append('file', this.blob, this.id + '.webm');
|
||||
sendable.append('file', this.blob!, this.id + '.webm');
|
||||
|
||||
http.onreadystatechange = () => {
|
||||
if (http.readyState === 4) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import { LocalRecorder } from './LocalRecorder';
|
|||
import { Publisher } from './Publisher';
|
||||
import { Session } from './Session';
|
||||
import { Stream } from './Stream';
|
||||
import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
|
||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
|
||||
import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
|
||||
|
@ -27,6 +28,7 @@ import { CustomMediaStreamConstraints } from '../OpenViduInternal/Interfaces/Pri
|
|||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||
|
||||
import * as screenSharingAuto from '../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto';
|
||||
import * as screenSharing from '../OpenViduInternal/ScreenSharing/Screen-Capturing';
|
||||
|
@ -38,13 +40,6 @@ import EventEmitter = require('wolfy87-eventemitter');
|
|||
* @hidden
|
||||
*/
|
||||
import RpcBuilder = require('../OpenViduInternal/KurentoUtils/kurento-jsonrpc');
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
import platform = require('platform');
|
||||
|
||||
platform['isIonicIos'] = (platform.product === 'iPhone' || platform.product === 'iPad') && platform.ua!!.indexOf('Safari') === -1;
|
||||
platform['isIonicAndroid'] = platform.os!!.family === 'Android' && platform.name == "Android Browser";
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
|
@ -59,6 +54,11 @@ declare var cordova: any;
|
|||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
/**
|
||||
* Entrypoint of OpenVidu Browser library.
|
||||
* Use it to initialize objects of type [[Session]], [[Publisher]] and [[LocalRecorder]]
|
||||
|
@ -121,11 +121,12 @@ export class OpenVidu {
|
|||
ee = new EventEmitter()
|
||||
|
||||
constructor() {
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.libraryVersion = packageJson.version;
|
||||
logger.info("'OpenVidu' initialized");
|
||||
logger.info("openvidu-browser version: " + this.libraryVersion);
|
||||
|
||||
if (platform.os!!.family === 'iOS' || platform.os!!.family === 'Android') {
|
||||
if (platform.isMobileDevice()) {
|
||||
// Listen to orientationchange only on mobile devices
|
||||
(<any>window).addEventListener('orientationchange', () => {
|
||||
this.publishers.forEach(publisher => {
|
||||
|
@ -138,7 +139,7 @@ export class OpenVidu {
|
|||
|
||||
const getNewVideoDimensions = (): Promise<{ newWidth: number, newHeight: number }> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (platform['isIonicIos']) {
|
||||
if (platform.isIonicIos()) {
|
||||
// iOS Ionic. Limitation: must get new dimensions from an existing video element already inserted into DOM
|
||||
resolve({
|
||||
newWidth: publisher.stream.streamManager.videos[0].video.videoWidth,
|
||||
|
@ -149,8 +150,8 @@ export class OpenVidu {
|
|||
// New resolution got from different places for Chrome and Firefox. Chrome needs a videoWidth and videoHeight of a videoElement.
|
||||
// Firefox needs getSettings from the videoTrack
|
||||
const firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
||||
const newWidth = <number>((platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.width : publisher.videoReference.videoWidth);
|
||||
const newHeight = <number>((platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.height : publisher.videoReference.videoHeight);
|
||||
const newWidth = <number>((platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? firefoxSettings.width : publisher.videoReference.videoWidth);
|
||||
const newHeight = <number>((platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? firefoxSettings.height : publisher.videoReference.videoHeight);
|
||||
resolve({ newWidth, newHeight });
|
||||
}
|
||||
});
|
||||
|
@ -186,6 +187,7 @@ export class OpenVidu {
|
|||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
|
||||
publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
|
||||
this.session.sendVideoData(publisher);
|
||||
}
|
||||
});
|
||||
clearTimeout(repeatUntilChange);
|
||||
|
@ -337,26 +339,20 @@ export class OpenVidu {
|
|||
* @returns 1 if the browser supports OpenVidu, 0 otherwise
|
||||
*/
|
||||
checkSystemRequirements(): number {
|
||||
const browser = platform.name;
|
||||
const family = platform.os!!.family;
|
||||
const userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
||||
|
||||
if(this.isIPhoneOrIPad(userAgent)) {
|
||||
if(this.isIOSWithSafari(userAgent) || platform['isIonicIos']){
|
||||
return 1;
|
||||
}
|
||||
if (platform.isIPhoneOrIPad()) {
|
||||
if (platform.isIOSWithSafari() || platform.isIonicIos()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Accept: Chrome (desktop and Android), Firefox (desktop and Android), Opera (desktop and Android),
|
||||
// Safari (OSX and iOS), Ionic (Android and iOS), Samsung Internet Browser (Android)
|
||||
if (
|
||||
(browser === 'Safari') ||
|
||||
(browser === 'Chrome') || (browser === 'Chrome Mobile') ||
|
||||
(browser === 'Firefox') || (browser === 'Firefox Mobile') ||
|
||||
(browser === 'Opera') || (browser === 'Opera Mobile') ||
|
||||
(browser === 'Android Browser') || (browser === 'Electron') ||
|
||||
(browser === 'Samsung Internet Mobile') || (browser === 'Samsung Internet')
|
||||
// Safari (OSX and iOS), Edge Chromium (>= 80), Ionic (Android and iOS), Samsung Internet Browser (Android)
|
||||
if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() ||
|
||||
platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isOperaBrowser() ||
|
||||
platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isEdgeMobileBrowser() ||
|
||||
platform.isSafariBrowser() || platform.isAndroidBrowser() || platform.isElectron() || platform.isSamsungBrowser()
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -370,22 +366,8 @@ export class OpenVidu {
|
|||
* Checks if the browser supports screen-sharing. Desktop Chrome, Firefox and Opera support screen-sharing
|
||||
* @returns 1 if the browser supports screen-sharing, 0 otherwise
|
||||
*/
|
||||
checkScreenSharingCapabilities(): number {
|
||||
const browser = platform.name;
|
||||
const version = platform?.version ? parseFloat(platform.version) : -1;
|
||||
const family = platform.os!!.family;
|
||||
|
||||
// Reject mobile devices
|
||||
if (family === 'iOS' || family === 'Android') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera') && (browser !== 'Electron') &&
|
||||
(browser === 'Safari' && version < 13)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
checkScreenSharingCapabilities(): boolean {
|
||||
return platform.canScreenShare();
|
||||
}
|
||||
|
||||
|
||||
|
@ -398,7 +380,7 @@ export class OpenVidu {
|
|||
const devices: Device[] = [];
|
||||
|
||||
// Ionic Android devices
|
||||
if (platform['isIonicAndroid'] && typeof cordova != "undefined" && cordova?.plugins?.EnumerateDevicesPlugin) {
|
||||
if (platform.isIonicAndroid() && typeof cordova != "undefined" && cordova?.plugins?.EnumerateDevicesPlugin) {
|
||||
cordova.plugins.EnumerateDevicesPlugin.getEnumerateDevices().then((pluginDevices: Device[]) => {
|
||||
let pluginAudioDevices: Device[] = [];
|
||||
let videoDevices: Device[] = [];
|
||||
|
@ -590,10 +572,10 @@ export class OpenVidu {
|
|||
// Video is deviceId or screen sharing
|
||||
if (options.videoSource === 'screen' ||
|
||||
options.videoSource === 'window' ||
|
||||
(platform.name === 'Electron' && options.videoSource.startsWith('screen:'))) {
|
||||
(platform.isElectron() && options.videoSource.startsWith('screen:'))) {
|
||||
// Video is screen sharing
|
||||
mustAskForAudioTrackLater = !myConstraints.audioTrack && (options.audioSource !== null && options.audioSource !== false);
|
||||
if (navigator.mediaDevices['getDisplayMedia'] && platform.name !== 'Electron') {
|
||||
if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
|
||||
// getDisplayMedia supported
|
||||
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
||||
.then(mediaStream => {
|
||||
|
@ -663,6 +645,7 @@ export class OpenVidu {
|
|||
* - `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 and the [StreamManagerEvent.streamAudioVolumeChange](/en/stable/api/openvidu-browser/classes/streammanagerevent.html) feature
|
||||
* - `forceMediaReconnectionAfterNetworkDrop`: always force WebRTC renegotiation of all the streams of a client after a network loss and reconnection. This can help reducing frozen videos in low quality networks.
|
||||
*
|
||||
* Call this method to override previous values at any moment.
|
||||
*/
|
||||
|
@ -763,9 +746,8 @@ export class OpenVidu {
|
|||
startWs(onConnectSucces: (error: Error) => void): void {
|
||||
const config = {
|
||||
heartbeat: 5000,
|
||||
sendCloseMessage: false,
|
||||
ws: {
|
||||
uri: this.wsUri,
|
||||
uri: this.wsUri + '?sessionId=' + this.session.sessionId,
|
||||
onconnected: onConnectSucces,
|
||||
ondisconnect: this.disconnectCallback.bind(this),
|
||||
onreconnecting: this.reconnectingCallback.bind(this),
|
||||
|
@ -782,6 +764,8 @@ export class OpenVidu {
|
|||
recordingStopped: this.session.onRecordingStopped.bind(this.session),
|
||||
sendMessage: this.session.onNewMessage.bind(this.session),
|
||||
streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
|
||||
connectionPropertyChanged: this.session.onConnectionPropertyChanged.bind(this.session),
|
||||
networkQualityLevelChanged: this.session.onNetworkQualityLevelChangedChanged.bind(this.session),
|
||||
filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session),
|
||||
iceCandidate: this.session.recvIceCandidate.bind(this.session),
|
||||
mediaError: this.session.onMediaError.bind(this.session)
|
||||
|
@ -899,12 +883,12 @@ export class OpenVidu {
|
|||
// Screen sharing
|
||||
|
||||
if (!this.checkScreenSharingCapabilities()) {
|
||||
const error = new OpenViduError(OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0) or Electron. Detected client: ' + platform.name);
|
||||
const error = new OpenViduError(OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0), Edge (>= 80) or Electron. Detected client: ' + platform.getName() + ' ' + platform.getVersion());
|
||||
logger.error(error);
|
||||
reject(error);
|
||||
} else {
|
||||
|
||||
if (platform.name === 'Electron') {
|
||||
if (platform.isElectron()) {
|
||||
const prefix = "screen:";
|
||||
const videoSourceString: string = videoSource;
|
||||
const electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length);
|
||||
|
@ -918,7 +902,7 @@ export class OpenVidu {
|
|||
|
||||
} else {
|
||||
|
||||
if (!!this.advancedConfiguration.screenShareChromeExtension && !(platform.name!.indexOf('Firefox') !== -1) && !navigator.mediaDevices['getDisplayMedia']) {
|
||||
if (!!this.advancedConfiguration.screenShareChromeExtension && !(platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) && !navigator.mediaDevices['getDisplayMedia']) {
|
||||
|
||||
// Custom screen sharing extension for Chrome (and Opera) and no support for MediaDevices.getDisplayMedia()
|
||||
|
||||
|
@ -957,7 +941,7 @@ export class OpenVidu {
|
|||
resolve(myConstraints);
|
||||
} else {
|
||||
// Default screen sharing extension for Chrome/Opera, or is Firefox < 66
|
||||
const firefoxString = platform.name!.indexOf('Firefox') !== -1 ? publisherProperties.videoSource : undefined;
|
||||
const firefoxString = (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? publisherProperties.videoSource : undefined;
|
||||
|
||||
screenSharingAuto.getScreenId(firefoxString, (error, sourceId, screenConstraints) => {
|
||||
if (!!error) {
|
||||
|
@ -1029,17 +1013,25 @@ export class OpenVidu {
|
|||
private reconnectedCallback(): void {
|
||||
logger.warn('Websocket reconnected');
|
||||
if (this.isRoomAvailable()) {
|
||||
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
|
||||
if (!!error) {
|
||||
logger.error(error);
|
||||
logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Connection was already destroyed due to timeout. You are no longer a participant of the Session and your media streams have been destroyed');
|
||||
this.session.onLostConnection("networkDisconnect");
|
||||
this.jsonRpcClient.close(4101, "Reconnection fault");
|
||||
} else {
|
||||
this.jsonRpcClient.resetPing();
|
||||
this.session.onRecoveredConnection();
|
||||
}
|
||||
});
|
||||
if (!!this.session.connection) {
|
||||
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
|
||||
if (!!error) {
|
||||
logger.error(error);
|
||||
logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Connection was already destroyed due to timeout. You are no longer a participant of the Session and your media streams have been destroyed');
|
||||
this.session.onLostConnection("networkDisconnect");
|
||||
this.jsonRpcClient.close(4101, "Reconnection fault");
|
||||
} else {
|
||||
this.jsonRpcClient.resetPing();
|
||||
this.session.onRecoveredConnection();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.warn('There was no previous connection when running reconnection callback');
|
||||
// Make Session object dispatch 'sessionDisconnected' event
|
||||
const sessionDisconnectEvent = new SessionDisconnectedEvent(this.session, 'networkDisconnect');
|
||||
this.session.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
|
||||
sessionDisconnectEvent.callDefaultBehavior();
|
||||
}
|
||||
} else {
|
||||
alert('Connection error. Please reload page.');
|
||||
}
|
||||
|
@ -1057,21 +1049,7 @@ export class OpenVidu {
|
|||
private isScreenShare(videoSource: string) {
|
||||
return videoSource === 'screen' ||
|
||||
videoSource === 'window' ||
|
||||
(platform.name === 'Electron' && videoSource.startsWith('screen:'))
|
||||
(platform.isElectron() && videoSource.startsWith('screen:'))
|
||||
}
|
||||
|
||||
private isIPhoneOrIPad(userAgent): boolean {
|
||||
const isTouchable = 'ontouchend' in document;
|
||||
const isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable;
|
||||
const isIPhone = /\b(\w*iPhone\w*)\b/.test(userAgent) && /\b(\w*Mobile\w*)\b/.test(userAgent) && isTouchable;
|
||||
|
||||
return isIPad || isIPhone;
|
||||
}
|
||||
|
||||
private isIOSWithSafari(userAgent): boolean{
|
||||
return /\b(\w*Apple\w*)\b/.test(navigator.vendor) && /\b(\w*Safari\w*)\b/.test(userAgent)
|
||||
&& !/\b(\w*CriOS\w*)\b/.test(userAgent) && !/\b(\w*FxiOS\w*)\b/.test(userAgent);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -28,15 +28,19 @@ import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPro
|
|||
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
/**
|
||||
* Packs local media streams. Participants can publish it to a session. Initialized with [[OpenVidu.initPublisher]] method
|
||||
*
|
||||
|
@ -95,10 +99,32 @@ export class Publisher extends StreamManager {
|
|||
|
||||
// TODO: CLEAN 2.15.0 LEGACY CODE
|
||||
// THIS LINE:
|
||||
super(!openvidu.openviduServerVersion ? /*2.15.0 or 2.16.0 NOT CONNECTED (LEGACY)*/ new StreamLEGACY((!!openvidu.session) ? openvidu.session : new Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }) : /*2.16.0 CONNECTED (NORMAL API)*/ new Stream(openvidu.session, { publisherProperties: properties, mediaConstraints: {} }), targEl);
|
||||
super(
|
||||
!openvidu.openviduServerVersion
|
||||
// 2.15.0 or 2.16.0 NOT CONNECTED (LEGACY)
|
||||
? new StreamLEGACY(
|
||||
!!openvidu.session
|
||||
? openvidu.session
|
||||
: new Session(openvidu),
|
||||
{ publisherProperties: properties, mediaConstraints: {} }
|
||||
)
|
||||
// 2.16.0 CONNECTED (NORMAL API)
|
||||
: new Stream(openvidu.session, {
|
||||
publisherProperties: properties,
|
||||
mediaConstraints: {},
|
||||
}),
|
||||
targEl
|
||||
);
|
||||
// SHOULD GET BACK TO:
|
||||
// super(new Stream((!!openvidu.session) ? openvidu.session : new Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl);
|
||||
// super(
|
||||
// new Stream(
|
||||
// !!openvidu.session ? openvidu.session : new Session(openvidu),
|
||||
// { publisherProperties: properties, mediaConstraints: {} }
|
||||
// ),
|
||||
// targEl
|
||||
// );
|
||||
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.properties = properties;
|
||||
this.openvidu = openvidu;
|
||||
|
||||
|
@ -130,7 +156,7 @@ export class Publisher extends StreamManager {
|
|||
*/
|
||||
publishAudio(value: boolean): void {
|
||||
if (this.stream.audioActive !== value) {
|
||||
const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream();
|
||||
const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream();
|
||||
affectedMediaStream.getAudioTracks().forEach((track) => {
|
||||
track.enabled = value;
|
||||
});
|
||||
|
@ -149,6 +175,7 @@ export class Publisher extends StreamManager {
|
|||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'audioActive', value, !value, 'publishAudio')]);
|
||||
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'audioActive', value, !value, 'publishAudio')]);
|
||||
this.session.sendVideoData(this.stream.streamManager);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -177,7 +204,7 @@ export class Publisher extends StreamManager {
|
|||
*/
|
||||
publishVideo(value: boolean): void {
|
||||
if (this.stream.videoActive !== value) {
|
||||
const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream();
|
||||
const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream();
|
||||
affectedMediaStream.getVideoTracks().forEach((track) => {
|
||||
track.enabled = value;
|
||||
});
|
||||
|
@ -196,6 +223,7 @@ export class Publisher extends StreamManager {
|
|||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoActive', value, !value, 'publishVideo')]);
|
||||
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'videoActive', value, !value, 'publishVideo')]);
|
||||
this.session.sendVideoData(this.stream.streamManager);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -305,7 +333,7 @@ export class Publisher extends StreamManager {
|
|||
replaceTrack(track: MediaStreamTrack): Promise<any> {
|
||||
|
||||
const replaceMediaStreamTrack = () => {
|
||||
const mediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream();
|
||||
const mediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream();
|
||||
let removedTrack: MediaStreamTrack;
|
||||
if (track.kind === 'video') {
|
||||
removedTrack = mediaStream.getVideoTracks()[0];
|
||||
|
@ -315,6 +343,7 @@ export class Publisher extends StreamManager {
|
|||
mediaStream.removeTrack(removedTrack);
|
||||
removedTrack.stop();
|
||||
mediaStream.addTrack(track);
|
||||
this.session.sendVideoData(this.stream.streamManager, 5, true, 5);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -404,7 +433,7 @@ export class Publisher extends StreamManager {
|
|||
if (this.stream.isSendVideo()) {
|
||||
if (!this.stream.isSendScreen()) {
|
||||
|
||||
if (platform['isIonicIos'] || platform.name === 'Safari') {
|
||||
if (platform.isIonicIos() || platform.isSafariBrowser()) {
|
||||
// iOS Ionic or Safari. Limitation: cannot set videoDimensions directly, as the videoReference is not loaded
|
||||
// if not added to DOM. Must add it to DOM and wait for videoWidth and videoHeight properties to be defined
|
||||
|
||||
|
@ -440,7 +469,7 @@ export class Publisher extends StreamManager {
|
|||
// Orientation must be checked for mobile devices (width and height are reversed)
|
||||
const { width, height } = this.getVideoDimensions(mediaStream);
|
||||
|
||||
if ((platform.os!!.family === 'iOS' || platform.os!!.family === 'Android') && (window.innerHeight > window.innerWidth)) {
|
||||
if (platform.isMobileDevice() && (window.innerHeight > window.innerWidth)) {
|
||||
// Mobile portrait mode
|
||||
this.stream.videoDimensions = {
|
||||
width: height || 0,
|
||||
|
@ -464,8 +493,8 @@ export class Publisher extends StreamManager {
|
|||
};
|
||||
this.screenShareResizeInterval = setInterval(() => {
|
||||
const firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
|
||||
const newWidth = (platform.name === 'Chrome' || platform.name === 'Opera') ? this.videoReference.videoWidth : firefoxSettings.width;
|
||||
const newHeight = (platform.name === 'Chrome' || platform.name === 'Opera') ? this.videoReference.videoHeight : firefoxSettings.height;
|
||||
const newWidth = (platform.isChromeBrowser() || platform.isOperaBrowser()) ? this.videoReference.videoWidth : firefoxSettings.width;
|
||||
const newHeight = (platform.isChromeBrowser() || platform.isOperaBrowser()) ? this.videoReference.videoHeight : firefoxSettings.height;
|
||||
if (this.stream.isLocalStreamPublished &&
|
||||
(newWidth !== this.stream.videoDimensions.width ||
|
||||
newHeight !== this.stream.videoDimensions.height)) {
|
||||
|
@ -488,6 +517,7 @@ export class Publisher extends StreamManager {
|
|||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoDimensions', this.stream.videoDimensions, oldValue, 'screenResized')]);
|
||||
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'videoDimensions', this.stream.videoDimensions, oldValue, 'screenResized')]);
|
||||
this.session.sendVideoData(this.stream.streamManager);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -634,7 +664,7 @@ export class Publisher extends StreamManager {
|
|||
startTime = Date.now();
|
||||
this.setPermissionDialogTimer(timeForDialogEvent);
|
||||
|
||||
if (this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && platform.name !== 'Electron') {
|
||||
if (this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
|
||||
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
||||
.then(mediaStream => {
|
||||
this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
||||
|
@ -683,7 +713,7 @@ export class Publisher extends StreamManager {
|
|||
initializeVideoReference(mediaStream: MediaStream) {
|
||||
this.videoReference = document.createElement('video');
|
||||
|
||||
if (platform.name === 'Safari') {
|
||||
if (platform.isSafariBrowser()) {
|
||||
this.videoReference.setAttribute('playsinline', 'true');
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ import { Capabilities } from '../OpenViduInternal/Interfaces/Public/Capabilities
|
|||
import { EventDispatcher } from './EventDispatcher';
|
||||
import { SignalOptions } from '../OpenViduInternal/Interfaces/Public/SignalOptions';
|
||||
import { SubscriberProperties } from '../OpenViduInternal/Interfaces/Public/SubscriberProperties';
|
||||
import { ConnectionOptions } from '../OpenViduInternal/Interfaces/Private/ConnectionOptions';
|
||||
import { RemoteConnectionOptions } from '../OpenViduInternal/Interfaces/Private/RemoteConnectionOptions';
|
||||
import { LocalConnectionOptions } from '../OpenViduInternal/Interfaces/Private/LocalConnectionOptions';
|
||||
import { ObjMap } from '../OpenViduInternal/Interfaces/Private/ObjMap';
|
||||
import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions';
|
||||
import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent';
|
||||
|
@ -37,17 +38,23 @@ import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisc
|
|||
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
|
||||
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
import { ConnectionPropertyChangedEvent } from '../OpenViduInternal/Events/ConnectionPropertyChangedEvent';
|
||||
import { NetworkQualityLevelChangedEvent } from '../OpenViduInternal/Events/NetworkQualityLevelChangedEvent';
|
||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
/**
|
||||
* Represents a video call. It can also be seen as a videoconference room where multiple users can connect.
|
||||
* Participants who publish their videos to a session can be seen by the rest of users connected to that specific session.
|
||||
|
@ -57,6 +64,7 @@ const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
|||
*
|
||||
* - connectionCreated ([[ConnectionEvent]])
|
||||
* - connectionDestroyed ([[ConnectionEvent]])
|
||||
* - connectionPropertyChanged ([[ConnectionPropertyChangedEvent]]) <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
* - sessionDisconnected ([[SessionDisconnectedEvent]])
|
||||
* - streamCreated ([[StreamEvent]])
|
||||
* - streamDestroyed ([[StreamEvent]])
|
||||
|
@ -66,9 +74,9 @@ const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
|||
* - signal ([[SignalEvent]])
|
||||
* - recordingStarted ([[RecordingEvent]])
|
||||
* - recordingStopped ([[RecordingEvent]])
|
||||
* - networkQualityLevelChanged ([[NetworkQualityLevelChangedEvent]])
|
||||
* - reconnecting
|
||||
* - reconnected
|
||||
*
|
||||
*/
|
||||
export class Session extends EventDispatcher {
|
||||
|
||||
|
@ -88,7 +96,7 @@ export class Session extends EventDispatcher {
|
|||
streamManagers: StreamManager[] = [];
|
||||
|
||||
/**
|
||||
* Object defining the methods that the client is able to call. These are defined by the role of the token used to connect to the Session.
|
||||
* Object defining the methods that the client is able to call. These are defined by the [[Connection.role]].
|
||||
* This object is only defined after [[Session.connect]] has been successfully resolved
|
||||
*/
|
||||
capabilities: Capabilities;
|
||||
|
@ -127,15 +135,23 @@ export class Session extends EventDispatcher {
|
|||
* @hidden
|
||||
*/
|
||||
stopSpeakingEventsEnabledOnce = false;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private videoDataInterval: NodeJS.Timeout;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private videoDataTimeout: NodeJS.Timeout;
|
||||
|
||||
|
||||
// TODO: CLEAN 2.15.0 LEGACY CODE
|
||||
/**
|
||||
* @hidden
|
||||
* @hidden
|
||||
*/
|
||||
isFirstIonicIosSubscriber = true;
|
||||
/**
|
||||
* @hidden
|
||||
* @hidden
|
||||
*/
|
||||
countDownForIonicIosSubscribersActive = true;
|
||||
// END LEGACY CODE
|
||||
|
@ -146,6 +162,7 @@ export class Session extends EventDispatcher {
|
|||
*/
|
||||
constructor(openvidu: OpenVidu) {
|
||||
super();
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.openvidu = openvidu;
|
||||
}
|
||||
|
||||
|
@ -197,7 +214,7 @@ export class Session extends EventDispatcher {
|
|||
reject(error);
|
||||
});
|
||||
} else {
|
||||
reject(new OpenViduError(OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' (version ' + platform.version + ') for ' + platform.os!!.family + ' is not supported in OpenVidu'));
|
||||
reject(new OpenViduError(OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -382,6 +399,7 @@ export class Session extends EventDispatcher {
|
|||
this.connection.addStream(publisher.stream);
|
||||
publisher.stream.publish()
|
||||
.then(() => {
|
||||
this.sendVideoData(publisher, 8, true, 5);
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
|
@ -395,6 +413,7 @@ export class Session extends EventDispatcher {
|
|||
publisher.reestablishStreamPlayingEvent();
|
||||
publisher.stream.publish()
|
||||
.then(() => {
|
||||
this.sendVideoData(publisher, 8, true, 5);
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
|
@ -596,7 +615,7 @@ export class Session extends EventDispatcher {
|
|||
/**
|
||||
* See [[EventDispatcher.on]]
|
||||
*/
|
||||
on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): EventDispatcher {
|
||||
on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityLevelChangedEvent) => void): EventDispatcher {
|
||||
|
||||
super.onAux(type, "Event '" + type + "' triggered by 'Session'", handler);
|
||||
|
||||
|
@ -628,7 +647,7 @@ export class Session extends EventDispatcher {
|
|||
/**
|
||||
* See [[EventDispatcher.once]]
|
||||
*/
|
||||
once(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): Session {
|
||||
once(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityLevelChangedEvent) => void): Session {
|
||||
|
||||
super.onceAux(type, "Event '" + type + "' triggered once by 'Session'", handler);
|
||||
|
||||
|
@ -660,7 +679,7 @@ export class Session extends EventDispatcher {
|
|||
/**
|
||||
* See [[EventDispatcher.off]]
|
||||
*/
|
||||
off(type: string, handler?: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): Session {
|
||||
off(type: string, handler?: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityLevelChangedEvent) => void): Session {
|
||||
|
||||
super.off(type, handler);
|
||||
|
||||
|
@ -699,7 +718,7 @@ export class Session extends EventDispatcher {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
onParticipantJoined(response: ConnectionOptions): void {
|
||||
onParticipantJoined(response: RemoteConnectionOptions): void {
|
||||
// Connection shouldn't exist
|
||||
this.getConnection(response.id, '')
|
||||
|
||||
|
@ -751,9 +770,10 @@ export class Session extends EventDispatcher {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
onParticipantPublished(response: ConnectionOptions): void {
|
||||
onParticipantPublished(response: RemoteConnectionOptions): void {
|
||||
|
||||
const afterConnectionFound = (connection) => {
|
||||
|
||||
this.remoteConnections[connection.connectionId] = connection;
|
||||
|
||||
if (!this.remoteStreamsCreated[connection.stream.streamId]) {
|
||||
|
@ -777,7 +797,7 @@ export class Session extends EventDispatcher {
|
|||
// Update existing Connection
|
||||
connection = con;
|
||||
response.metadata = con.data;
|
||||
connection.options = response;
|
||||
connection.remoteOptions = response;
|
||||
connection.initRemoteStreams(response.streams);
|
||||
afterConnectionFound(connection);
|
||||
})
|
||||
|
@ -801,12 +821,12 @@ export class Session extends EventDispatcher {
|
|||
|
||||
.then(connection => {
|
||||
|
||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', connection.stream, msg.reason);
|
||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', connection.stream!, msg.reason);
|
||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehavior();
|
||||
|
||||
// Deleting the remote stream
|
||||
const streamId: string = connection.stream.streamId;
|
||||
const streamId: string = connection.stream!.streamId;
|
||||
delete this.remoteStreamsCreated[streamId];
|
||||
|
||||
|
||||
|
@ -934,6 +954,44 @@ export class Session extends EventDispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
onConnectionPropertyChanged(msg): void {
|
||||
let oldValue;
|
||||
switch (msg.property) {
|
||||
case 'role':
|
||||
oldValue = this.connection.role.slice();
|
||||
this.connection.role = msg.newValue;
|
||||
this.connection.localOptions!.role = msg.newValue;
|
||||
break;
|
||||
case 'record':
|
||||
oldValue = this.connection.record;
|
||||
msg.newValue = msg.newValue === 'true';
|
||||
this.connection.record = msg.newValue;
|
||||
this.connection.localOptions!.record = msg.newValue;
|
||||
break;
|
||||
}
|
||||
this.ee.emitEvent('connectionPropertyChanged', [new ConnectionPropertyChangedEvent(this, this.connection, msg.property, msg.newValue, oldValue)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
onNetworkQualityLevelChangedChanged(msg): void {
|
||||
if (msg.connectionId === this.connection.connectionId) {
|
||||
this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.newValue, msg.oldValue, this.connection)]);
|
||||
} else {
|
||||
this.getConnection(msg.connectionId, 'Connection not found for connectionId ' + msg.connectionId)
|
||||
.then((connection: Connection) => {
|
||||
this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.newValue, msg.oldValue, connection)]);
|
||||
})
|
||||
.catch(openViduError => {
|
||||
logger.error(openViduError);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -958,9 +1016,9 @@ export class Session extends EventDispatcher {
|
|||
};
|
||||
this.getConnection(msg.senderConnectionId, 'Connection not found for connectionId ' + msg.senderConnectionId + ' owning endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
|
||||
.then(connection => {
|
||||
const stream = connection.stream;
|
||||
const stream: Stream = connection.stream!;
|
||||
stream.getWebRtcPeer().addIceCandidate(candidate).catch(error => {
|
||||
logger.error('Error adding candidate for ' + stream.streamId
|
||||
logger.error('Error adding candidate for ' + stream!.streamId
|
||||
+ ' stream of endpoint ' + msg.endpointName + ': ' + error);
|
||||
});
|
||||
})
|
||||
|
@ -989,7 +1047,7 @@ export class Session extends EventDispatcher {
|
|||
*/
|
||||
onLostConnection(reason: string): void {
|
||||
logger.warn('Lost connection in Session ' + this.sessionId);
|
||||
if (!!this.sessionId && !this.connection.disposed) {
|
||||
if (!!this.sessionId && !!this.connection && !this.connection.disposed) {
|
||||
this.leave(true, reason);
|
||||
}
|
||||
}
|
||||
|
@ -1042,8 +1100,8 @@ export class Session extends EventDispatcher {
|
|||
this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId)
|
||||
.then(connection => {
|
||||
logger.info('Filter event dispatched');
|
||||
const stream: Stream = connection.stream;
|
||||
stream.filter.handlers[response.eventType](new FilterEvent(stream.filter, response.eventType, response.data));
|
||||
const stream: Stream = connection.stream!;
|
||||
stream.filter!.handlers[response.eventType](new FilterEvent(stream.filter!, response.eventType, response.data));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1086,6 +1144,7 @@ export class Session extends EventDispatcher {
|
|||
|
||||
forced = !!forced;
|
||||
logger.info('Leaving Session (forced=' + forced + ')');
|
||||
this.stopVideoDataIntervals();
|
||||
|
||||
if (!!this.connection) {
|
||||
if (!this.connection.disposed && !forced) {
|
||||
|
@ -1119,7 +1178,7 @@ export class Session extends EventDispatcher {
|
|||
const joinParams = {
|
||||
token: (!!token) ? token : '',
|
||||
session: this.sessionId,
|
||||
platform: !!platform.description ? platform.description : 'unknown',
|
||||
platform: !!platform.getDescription() ? platform.getDescription() : 'unknown',
|
||||
metadata: !!this.options.metadata ? this.options.metadata : '',
|
||||
secret: this.openvidu.getSecret(),
|
||||
recorder: this.openvidu.getRecorder()
|
||||
|
@ -1127,6 +1186,63 @@ export class Session extends EventDispatcher {
|
|||
return joinParams;
|
||||
}
|
||||
|
||||
sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1, doInterval: boolean = false, maxLoops: number = 1) {
|
||||
if (
|
||||
platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() ||
|
||||
platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isElectron() ||
|
||||
(platform.isSafariBrowser() && !platform.isIonicIos()) || platform.isAndroidBrowser() ||
|
||||
platform.isSamsungBrowser() || platform.isIonicAndroid() || (platform.isIPhoneOrIPad() && platform.isIOSWithSafari())
|
||||
) {
|
||||
const obtainAndSendVideo = async () => {
|
||||
const statsMap = await streamManager.stream.getRTCPeerConnection().getStats();
|
||||
const arr: any[] = [];
|
||||
statsMap.forEach(stats => {
|
||||
if (("frameWidth" in stats) && ("frameHeight" in stats) && (arr.length === 0)) {
|
||||
arr.push(stats);
|
||||
}
|
||||
});
|
||||
if (arr.length > 0) {
|
||||
this.openvidu.sendRequest('videoData', {
|
||||
height: arr[0].frameHeight,
|
||||
width: arr[0].frameWidth,
|
||||
videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false,
|
||||
audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false
|
||||
}, (error, response) => {
|
||||
if (error) {
|
||||
logger.error("Error sending 'videoData' event", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (doInterval) {
|
||||
let loops = 1;
|
||||
this.videoDataInterval = setInterval(() => {
|
||||
if (loops < maxLoops) {
|
||||
loops++;
|
||||
obtainAndSendVideo();
|
||||
}else {
|
||||
clearInterval(this.videoDataInterval);
|
||||
}
|
||||
}, intervalSeconds * 1000);
|
||||
} else {
|
||||
this.videoDataTimeout = setTimeout(obtainAndSendVideo, intervalSeconds * 1000);
|
||||
}
|
||||
} else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isIonicIos() || platform.isReactNative()) {
|
||||
// Basic version for Firefox and Ionic iOS. They do not support stats
|
||||
this.openvidu.sendRequest('videoData', {
|
||||
height: streamManager.stream.videoDimensions?.height || 0,
|
||||
width: streamManager.stream.videoDimensions?.width || 0,
|
||||
videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false,
|
||||
audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false
|
||||
}, (error, response) => {
|
||||
if (error) {
|
||||
logger.error("Error sending 'videoData' event", error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.error('Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu for Network Quality');
|
||||
}
|
||||
}
|
||||
|
||||
/* Private methods */
|
||||
|
||||
|
@ -1139,35 +1255,33 @@ export class Session extends EventDispatcher {
|
|||
|
||||
const joinParams = this.initializeParams(token);
|
||||
|
||||
this.openvidu.sendRequest('joinRoom', joinParams, (error, response) => {
|
||||
this.openvidu.sendRequest('joinRoom', joinParams, (error, response: LocalConnectionOptions) => {
|
||||
if (!!error) {
|
||||
reject(error);
|
||||
} else {
|
||||
|
||||
// Initialize capabilities object with the role
|
||||
this.capabilities = {
|
||||
subscribe: true,
|
||||
publish: this.openvidu.role !== 'SUBSCRIBER',
|
||||
forceUnpublish: this.openvidu.role === 'MODERATOR',
|
||||
forceDisconnect: this.openvidu.role === 'MODERATOR'
|
||||
};
|
||||
this.processJoinRoomResponse(response);
|
||||
|
||||
// Initialize local Connection object with values returned by openvidu-server
|
||||
this.connection = new Connection(this);
|
||||
|
||||
// FIXME CONFLICT WITH MASTER
|
||||
// In modern code, the OpenVidu version is obtained through other means.
|
||||
// However in the mediasoup branch this value is used in several of the
|
||||
// *LEGACY.ts files.
|
||||
<<<<<<< HEAD
|
||||
this.openvidu.openviduServerVersion = response.openviduServerVersion;
|
||||
this.connection.connectionId = response.id;
|
||||
this.connection.creationTime = response.createdAt;
|
||||
this.connection.data = response.metadata;
|
||||
this.connection.rpcSessionId = response.sessionId;
|
||||
=======
|
||||
this.connection = new Connection(this, response);
|
||||
>>>>>>> master
|
||||
|
||||
// Initialize remote Connections with value returned by openvidu-server
|
||||
const events = {
|
||||
connections: new Array<Connection>(),
|
||||
streams: new Array<Stream>()
|
||||
};
|
||||
const existingParticipants: ConnectionOptions[] = response.value;
|
||||
existingParticipants.forEach(participant => {
|
||||
const connection = new Connection(this, participant);
|
||||
const existingParticipants: RemoteConnectionOptions[] = response.value;
|
||||
existingParticipants.forEach((remoteConnectionOptions: RemoteConnectionOptions) => {
|
||||
const connection = new Connection(this, remoteConnectionOptions);
|
||||
this.remoteConnections[connection.connectionId] = connection;
|
||||
events.connections.push(connection);
|
||||
if (!!connection.stream) {
|
||||
|
@ -1208,6 +1322,11 @@ export class Session extends EventDispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
private stopVideoDataIntervals(): void {
|
||||
clearInterval(this.videoDataInterval);
|
||||
clearTimeout(this.videoDataTimeout);
|
||||
}
|
||||
|
||||
private stringClientMetadata(metadata: any): string {
|
||||
if (typeof metadata !== 'string') {
|
||||
return JSON.stringify(metadata);
|
||||
|
@ -1272,12 +1391,7 @@ export class Session extends EventDispatcher {
|
|||
this.sessionId = <string>queryParams['sessionId'];
|
||||
const secret = queryParams['secret'];
|
||||
const recorder = queryParams['recorder'];
|
||||
const coturnIp = queryParams['coturnIp'];
|
||||
const turnUsername = queryParams['turnUsername'];
|
||||
const turnCredential = queryParams['turnCredential'];
|
||||
const role = queryParams['role'];
|
||||
const webrtcStatsInterval = queryParams['webrtcStatsInterval'];
|
||||
const openviduServerVersion = queryParams['version'];
|
||||
|
||||
if (!!secret) {
|
||||
this.openvidu.secret = secret;
|
||||
|
@ -1285,31 +1399,9 @@ export class Session extends EventDispatcher {
|
|||
if (!!recorder) {
|
||||
this.openvidu.recorder = true;
|
||||
}
|
||||
if (!!turnUsername && !!turnCredential) {
|
||||
const stunUrl = 'stun:' + coturnIp + ':3478';
|
||||
const turnUrl1 = 'turn:' + coturnIp + ':3478';
|
||||
const turnUrl2 = turnUrl1 + '?transport=tcp';
|
||||
this.openvidu.iceServers = [
|
||||
{ urls: [stunUrl] },
|
||||
{ urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
|
||||
];
|
||||
logger.log("STUN/TURN server IP: " + coturnIp);
|
||||
logger.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
|
||||
}
|
||||
if (!!role) {
|
||||
this.openvidu.role = role;
|
||||
}
|
||||
if (!!webrtcStatsInterval) {
|
||||
this.openvidu.webrtcStatsInterval = +webrtcStatsInterval;
|
||||
}
|
||||
if (!!openviduServerVersion) {
|
||||
logger.info("openvidu-server version: " + openviduServerVersion);
|
||||
if (openviduServerVersion !== this.openvidu.libraryVersion) {
|
||||
logger.warn('OpenVidu Server (' + openviduServerVersion +
|
||||
') and OpenVidu Browser (' + this.openvidu.libraryVersion +
|
||||
') versions do NOT match. There may be incompatibilities')
|
||||
}
|
||||
}
|
||||
|
||||
this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
|
||||
this.openvidu.httpUri = 'https://' + url.host;
|
||||
|
@ -1319,4 +1411,32 @@ export class Session extends EventDispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
private processJoinRoomResponse(opts: LocalConnectionOptions) {
|
||||
this.sessionId = opts.session;
|
||||
if (opts.coturnIp != null && opts.turnUsername != null && opts.turnCredential != null) {
|
||||
const stunUrl = 'stun:' + opts.coturnIp + ':3478';
|
||||
const turnUrl1 = 'turn:' + opts.coturnIp + ':3478';
|
||||
const turnUrl2 = turnUrl1 + '?transport=tcp';
|
||||
this.openvidu.iceServers = [
|
||||
{ urls: [stunUrl] },
|
||||
{ urls: [turnUrl1, turnUrl2], username: opts.turnUsername, credential: opts.turnCredential }
|
||||
];
|
||||
logger.log("STUN/TURN server IP: " + opts.coturnIp);
|
||||
logger.log('TURN temp credentials [' + opts.turnUsername + ':' + opts.turnCredential + ']');
|
||||
}
|
||||
this.openvidu.role = opts.role;
|
||||
this.capabilities = {
|
||||
subscribe: true,
|
||||
publish: this.openvidu.role !== 'SUBSCRIBER',
|
||||
forceUnpublish: this.openvidu.role === 'MODERATOR',
|
||||
forceDisconnect: this.openvidu.role === 'MODERATOR'
|
||||
};
|
||||
logger.info("openvidu-server version: " + opts.version);
|
||||
if (opts.version !== this.openvidu.libraryVersion) {
|
||||
logger.warn('OpenVidu Server (' + opts.version +
|
||||
') and OpenVidu Browser (' + this.openvidu.libraryVersion +
|
||||
') versions do NOT match. There may be incompatibilities')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,19 +30,22 @@ import { PublisherSpeakingEvent } from '../OpenViduInternal/Events/PublisherSpea
|
|||
import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
|
||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
import hark = require('hark');
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
/**
|
||||
* Represents each one of the media streams available in OpenVidu Server for certain session.
|
||||
|
@ -108,7 +111,7 @@ export class Stream extends EventDispatcher {
|
|||
* - `"SCREEN"`: when the video source comes from screen-sharing.
|
||||
* - `"CUSTOM"`: when [[PublisherProperties.videoSource]] has been initialized in the Publisher side with a custom MediaStreamTrack when calling [[OpenVidu.initPublisher]]).
|
||||
* - `"IPCAM"`: when the video source comes from an IP camera participant instead of a regular participant (see [IP cameras](/en/stable/advanced-features/ip-cameras/)).
|
||||
*
|
||||
*
|
||||
* If [[hasVideo]] is false, this property is undefined
|
||||
*/
|
||||
typeOfVideo?: string;
|
||||
|
@ -136,10 +139,10 @@ export class Stream extends EventDispatcher {
|
|||
* [[Filter.execMethod]] and remove it with [[Stream.removeFilter]]. Be aware that the client calling this methods must have the
|
||||
* necessary permissions: the token owned by the client must have been initialized with the appropriated `allowedFilters` array.
|
||||
*/
|
||||
filter: Filter;
|
||||
filter?: Filter;
|
||||
|
||||
protected webRtcPeer: WebRtcPeer;
|
||||
protected mediaStream: MediaStream;
|
||||
protected mediaStream?: MediaStream;
|
||||
private webRtcStats: WebRtcStats;
|
||||
|
||||
private isSubscribeToRemote = false;
|
||||
|
@ -203,7 +206,7 @@ export class Stream extends EventDispatcher {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
localMediaStreamWhenSubscribedToRemote: MediaStream;
|
||||
localMediaStreamWhenSubscribedToRemote?: MediaStream;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -212,7 +215,7 @@ export class Stream extends EventDispatcher {
|
|||
constructor(session: Session, options: InboundStreamOptions | OutboundStreamOptions | {}) {
|
||||
|
||||
super();
|
||||
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.session = session;
|
||||
|
||||
if (options.hasOwnProperty('id')) {
|
||||
|
@ -262,7 +265,7 @@ export class Stream extends EventDispatcher {
|
|||
}
|
||||
|
||||
this.ee.on('mediastream-updated', () => {
|
||||
this.streamManager.updateMediaStream(this.mediaStream);
|
||||
this.streamManager.updateMediaStream(this.mediaStream!);
|
||||
logger.debug('Video srcObject [' + this.mediaStream + '] updated in stream [' + this.streamId + ']');
|
||||
});
|
||||
}
|
||||
|
@ -323,7 +326,7 @@ export class Stream extends EventDispatcher {
|
|||
}
|
||||
} else {
|
||||
logger.info('Filter successfully applied on Stream ' + this.streamId);
|
||||
const oldValue: Filter = this.filter;
|
||||
const oldValue: Filter = this.filter!;
|
||||
this.filter = new Filter(type, options);
|
||||
this.filter.stream = this;
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter, oldValue, 'applyFilter')]);
|
||||
|
@ -356,10 +359,10 @@ export class Stream extends EventDispatcher {
|
|||
}
|
||||
} else {
|
||||
logger.info('Filter successfully removed from Stream ' + this.streamId);
|
||||
const oldValue = this.filter;
|
||||
const oldValue = this.filter!;
|
||||
delete this.filter;
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter, oldValue, 'applyFilter')]);
|
||||
this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.streamManager, this, 'filter', this.filter, oldValue, 'applyFilter')]);
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter!, oldValue, 'applyFilter')]);
|
||||
this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.streamManager, this, 'filter', this.filter!, oldValue, 'applyFilter')]);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
@ -382,7 +385,7 @@ export class Stream extends EventDispatcher {
|
|||
* @returns Native MediaStream Web API object
|
||||
*/
|
||||
getMediaStream(): MediaStream {
|
||||
return this.mediaStream;
|
||||
return this.mediaStream!;
|
||||
}
|
||||
|
||||
/* Hidden methods */
|
||||
|
@ -537,7 +540,7 @@ export class Stream extends EventDispatcher {
|
|||
*/
|
||||
isSendScreen(): boolean {
|
||||
let screen = this.outboundStreamOpts.publisherProperties.videoSource === 'screen';
|
||||
if (platform.name === 'Electron') {
|
||||
if (platform.isElectron()) {
|
||||
screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' &&
|
||||
this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:');
|
||||
}
|
||||
|
@ -776,7 +779,7 @@ export class Stream extends EventDispatcher {
|
|||
if (!this.getWebRtcPeer() || !this.getRTCPeerConnection()) {
|
||||
return false;
|
||||
}
|
||||
if (this.isLocal && !!this.session.openvidu.advancedConfiguration.forceMediaReconnectionAfterNetworkDrop) {
|
||||
if (this.isLocal() && !!this.session.openvidu.advancedConfiguration.forceMediaReconnectionAfterNetworkDrop) {
|
||||
logger.warn('OpenVidu Browser advanced configuration option "forceMediaReconnectionAfterNetworkDrop" is enabled. Publisher stream ' + this.streamId + 'will force a reconnection');
|
||||
return true;
|
||||
}
|
||||
|
@ -1022,8 +1025,8 @@ export class Stream extends EventDispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
protected initHarkEvents(): void {
|
||||
if (!!this.mediaStream.getAudioTracks()[0]) {
|
||||
private initHarkEvents(): void {
|
||||
if (!!this.mediaStream!.getAudioTracks()[0]) {
|
||||
// Hark events can only be set if audio track is available
|
||||
if (this.streamManager.remote) {
|
||||
// publisherStartSpeaking/publisherStopSpeaking is only defined for remote streams
|
||||
|
@ -1226,4 +1229,4 @@ export class Stream extends EventDispatcher {
|
|||
(report.type === 'candidate-pair' && report.nominated && report.bytesSent > 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,14 +22,19 @@ import { Event } from '../OpenViduInternal/Events/Event';
|
|||
import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
|
||||
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
/**
|
||||
* Interface in charge of displaying the media streams in the HTML DOM. This wraps any [[Publisher]] and [[Subscriber]] object.
|
||||
* You can insert as many video players fo the same Stream as you want by calling [[StreamManager.addVideoElement]] or
|
||||
|
@ -82,7 +87,7 @@ export class StreamManager extends EventDispatcher {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
firstVideoElement: StreamManagerVideo;
|
||||
firstVideoElement?: StreamManagerVideo;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -101,7 +106,7 @@ export class StreamManager extends EventDispatcher {
|
|||
*/
|
||||
constructor(stream: Stream, targetElement?: HTMLElement | string) {
|
||||
super();
|
||||
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.stream = stream;
|
||||
this.stream.streamManager = this;
|
||||
this.remote = !this.stream.isLocal();
|
||||
|
@ -121,7 +126,7 @@ export class StreamManager extends EventDispatcher {
|
|||
id: '',
|
||||
canplayListenerAdded: false
|
||||
};
|
||||
if (platform.name === 'Safari') {
|
||||
if (platform.isSafariBrowser()) {
|
||||
this.firstVideoElement.video.setAttribute('playsinline', 'true');
|
||||
}
|
||||
this.targetElement = targEl;
|
||||
|
@ -379,7 +384,7 @@ export class StreamManager extends EventDispatcher {
|
|||
video.autoplay = true;
|
||||
video.controls = false;
|
||||
|
||||
if (platform.name === 'Safari') {
|
||||
if (platform.isSafariBrowser()) {
|
||||
video.setAttribute('playsinline', 'true');
|
||||
}
|
||||
|
||||
|
@ -463,7 +468,7 @@ export class StreamManager extends EventDispatcher {
|
|||
updateMediaStream(mediaStream: MediaStream) {
|
||||
this.videos.forEach(streamManagerVideo => {
|
||||
streamManagerVideo.video.srcObject = mediaStream;
|
||||
if (platform['isIonicIos']) {
|
||||
if (platform.isIonicIos()) {
|
||||
// iOS Ionic. LIMITATION: must reinsert the video in the DOM for
|
||||
// the media stream to be updated
|
||||
const vParent = streamManagerVideo.video.parentElement;
|
||||
|
@ -506,7 +511,7 @@ export class StreamManager extends EventDispatcher {
|
|||
}
|
||||
|
||||
private mirrorVideo(video): void {
|
||||
if (!platform['isIonicIos']) {
|
||||
if (!platform.isIonicIos()) {
|
||||
video.style.transform = 'rotateY(180deg)';
|
||||
video.style.webkitTransform = 'rotateY(180deg)';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2020 OpenVidu (https://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.
|
||||
*
|
||||
*/
|
||||
|
||||
import { Connection } from '../../OpenVidu/Connection';
|
||||
import { Session } from '../../OpenVidu/Session';
|
||||
import { Event } from './Event';
|
||||
|
||||
/**
|
||||
* **This feature is part of OpenVidu Pro tier** <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* Defines event `connectionPropertyChanged` dispatched by [[Session]] object.
|
||||
* This event is fired when any property of the local [[Connection]] object changes.
|
||||
* The properties that may change are [[Connection.role]] and [[Connection.record]].
|
||||
*
|
||||
* The only way the Connection properties may change is by updating them through:
|
||||
*
|
||||
* - [API REST](/en/stable/reference-docs/REST-API/#patch-openviduapisessionsltsession_idgtconnectionltconnection_idgt)
|
||||
* - [openvidu-java-client](/en/stable/reference-docs/openvidu-java-client/#update-a-connection)
|
||||
* - [openvidu-node-client](/en/stable/reference-docs/openvidu-node-client/#update-a-connection)<br><br>
|
||||
*/
|
||||
export class ConnectionPropertyChangedEvent extends Event {
|
||||
|
||||
/**
|
||||
* The Connection whose property has changed
|
||||
*/
|
||||
connection: Connection;
|
||||
|
||||
/**
|
||||
* The property of the stream that changed. This value is either `"role"` or `"record"`
|
||||
*/
|
||||
changedProperty: string;
|
||||
|
||||
/**
|
||||
* New value of the property (after change, current value)
|
||||
*/
|
||||
newValue: Object;
|
||||
|
||||
/**
|
||||
* Previous value of the property (before change)
|
||||
*/
|
||||
oldValue: Object;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(target: Session, connection: Connection, changedProperty: string, newValue: Object, oldValue: Object) {
|
||||
super(false, target, 'connectionPropertyChanged');
|
||||
this.connection = connection;
|
||||
this.changedProperty = changedProperty;
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
|
||||
import { Event } from './Event';
|
||||
import { Stream } from '../../OpenVidu/Stream';
|
||||
import { Filter } from '../../OpenVidu/Filter';
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2020 OpenVidu (https://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.
|
||||
*
|
||||
*/
|
||||
|
||||
import { Event } from './Event';
|
||||
import { Session } from '../../OpenVidu/Session';
|
||||
import { Connection } from '../../OpenVidu/Connection';
|
||||
|
||||
/**
|
||||
* **This feature is part of OpenVidu Pro tier** <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* Defines event `networkQualityLevelChanged` dispatched by [[Session]].
|
||||
* This event is fired when the network quality level of a [[Connection]] changes. See [network quality](/en/stable/advanced-features/network-quality/)
|
||||
*/
|
||||
export class NetworkQualityLevelChangedEvent extends Event {
|
||||
|
||||
/**
|
||||
* New value of the network quality level
|
||||
*/
|
||||
newValue: number;
|
||||
|
||||
/**
|
||||
* Old value of the network quality level
|
||||
*/
|
||||
oldValue: number;
|
||||
|
||||
/**
|
||||
* Connection for whom the network quality level changed
|
||||
*/
|
||||
connection: Connection
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(target: Session, newValue: number, oldValue: number, connection: Connection) {
|
||||
super(false, target, 'networkQualityLevelChanged');
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -62,12 +62,12 @@ export class SessionDisconnectedEvent extends Event {
|
|||
// Dispose and delete all remote Connections
|
||||
for (const connectionId in session.remoteConnections) {
|
||||
if (!!session.remoteConnections[connectionId].stream) {
|
||||
session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
|
||||
session.remoteConnections[connectionId].stream.disposeMediaStream();
|
||||
if (session.remoteConnections[connectionId].stream.streamManager) {
|
||||
session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
|
||||
session.remoteConnections[connectionId].stream!.disposeWebRtcPeer();
|
||||
session.remoteConnections[connectionId].stream!.disposeMediaStream();
|
||||
if (session.remoteConnections[connectionId].stream!.streamManager) {
|
||||
session.remoteConnections[connectionId].stream!.streamManager.removeAllVideos();
|
||||
}
|
||||
delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId];
|
||||
delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream!.streamId];
|
||||
session.remoteConnections[connectionId].dispose();
|
||||
}
|
||||
delete session.remoteConnections[connectionId];
|
||||
|
|
|
@ -101,8 +101,8 @@ export class StreamEvent extends Event {
|
|||
|
||||
// Delete StreamOptionsServer from remote Connection
|
||||
const remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
|
||||
if (!!remoteConnection && !!remoteConnection.options) {
|
||||
const streamOptionsServer = remoteConnection.options.streams;
|
||||
if (!!remoteConnection && !!remoteConnection.remoteOptions) {
|
||||
const streamOptionsServer = remoteConnection.remoteOptions.streams;
|
||||
for (let i = streamOptionsServer.length - 1; i >= 0; --i) {
|
||||
if (streamOptionsServer[i].id === this.stream.streamId) {
|
||||
streamOptionsServer.splice(i, 1);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2020 OpenVidu (https://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.
|
||||
*
|
||||
*/
|
||||
|
||||
import { RemoteConnectionOptions } from './RemoteConnectionOptions';
|
||||
|
||||
export interface LocalConnectionOptions {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
metadata: string;
|
||||
value: RemoteConnectionOptions[];
|
||||
session: string; // OpenVidu Session identifier
|
||||
sessionId: string; // JSON-RPC session identifier
|
||||
role: string;
|
||||
record: boolean;
|
||||
coturnIp: string;
|
||||
turnUsername: string;
|
||||
turnCredential: string;
|
||||
version: string;
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
import { StreamOptionsServer } from './StreamOptionsServer';
|
||||
|
||||
export interface ConnectionOptions {
|
||||
export interface RemoteConnectionOptions {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
metadata: string;
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
var RpcBuilder = require('../');
|
||||
var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
|
||||
var OpenViduLogger = require('../../../Logger/OpenViduLogger').OpenViduLogger;
|
||||
|
||||
Date.now = Date.now || function () {
|
||||
return +new Date;
|
||||
|
@ -28,12 +29,11 @@ var RECONNECTING = 'RECONNECTING';
|
|||
var CONNECTED = 'CONNECTED';
|
||||
var DISCONNECTED = 'DISCONNECTED';
|
||||
|
||||
var Logger = console;
|
||||
var Logger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
*
|
||||
* heartbeat: interval in ms for each heartbeat message,
|
||||
* sendCloseMessage : true / false, before closing the connection, it sends a closeSession message
|
||||
* <pre>
|
||||
* ws : {
|
||||
* uri : URI to conntect to,
|
||||
|
@ -250,25 +250,13 @@ function JsonRpcClient(configuration) {
|
|||
|
||||
this.close = function (code, reason) {
|
||||
Logger.debug("Closing with code: " + code + " because: " + reason);
|
||||
|
||||
if (pingInterval != undefined) {
|
||||
Logger.debug("Clearing ping interval");
|
||||
clearInterval(pingInterval);
|
||||
}
|
||||
pingPongStarted = false;
|
||||
enabledPings = false;
|
||||
|
||||
if (configuration.sendCloseMessage) {
|
||||
Logger.debug("Sending close message")
|
||||
this.send('closeSession', null, function (error, result) {
|
||||
if (error) {
|
||||
Logger.error("Error sending close message: " + JSON.stringify(error));
|
||||
}
|
||||
ws.close(code, reason);
|
||||
});
|
||||
} else {
|
||||
ws.close(code, reason);
|
||||
}
|
||||
ws.close(code, reason);
|
||||
}
|
||||
|
||||
// This method is only for testing
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
getScreenId(function (error, sourceId, screen_constraints) {
|
||||
// error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome'
|
||||
// sourceId == null || 'string' || 'firefox'
|
||||
|
||||
|
||||
if(microsoftEdge) {
|
||||
navigator.getDisplayMedia(screen_constraints).then(onSuccess, onFailure);
|
||||
}
|
||||
|
@ -217,4 +217,4 @@ function postGetChromeExtensionStatusMessage() {
|
|||
}, '*');
|
||||
}
|
||||
|
||||
exports.getScreenId = getScreenId;
|
||||
exports.getScreenId = window.getScreenId;
|
|
@ -0,0 +1,205 @@
|
|||
import platform = require("platform");
|
||||
|
||||
export class PlatformUtils {
|
||||
protected static instance: PlatformUtils;
|
||||
constructor() {}
|
||||
|
||||
static getInstance(): PlatformUtils {
|
||||
if (!this.instance) {
|
||||
this.instance = new PlatformUtils();
|
||||
}
|
||||
return PlatformUtils.instance;
|
||||
}
|
||||
|
||||
public isChromeBrowser(): boolean {
|
||||
return platform.name === "Chrome";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isSafariBrowser(): boolean {
|
||||
return platform.name === "Safari";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isChromeMobileBrowser(): boolean {
|
||||
return platform.name === "Chrome Mobile";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isFirefoxBrowser(): boolean {
|
||||
return platform.name === "Firefox";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isFirefoxMobileBrowser(): boolean {
|
||||
return platform.name === "Firefox Mobile";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isOperaBrowser(): boolean {
|
||||
return platform.name === "Opera";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isOperaMobileBrowser(): boolean {
|
||||
return platform.name === "Opera Mobile";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isEdgeBrowser(): boolean {
|
||||
const version = platform?.version ? parseFloat(platform.version) : -1;
|
||||
return platform.name === "Microsoft Edge" && version >= 80;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isEdgeMobileBrowser(): boolean {
|
||||
const version = platform?.version ? parseFloat(platform.version) : -1;
|
||||
return platform.name === "Microsoft Edge" && platform.os?.family === 'Android' && version > 45;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isAndroidBrowser(): boolean {
|
||||
return platform.name === "Android Browser";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isElectron(): boolean {
|
||||
return platform.name === "Electron";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isSamsungBrowser(): boolean {
|
||||
return (
|
||||
platform.name === "Samsung Internet Mobile" ||
|
||||
platform.name === "Samsung Internet"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isIPhoneOrIPad(): boolean {
|
||||
const userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
||||
|
||||
const isTouchable = "ontouchend" in document;
|
||||
const isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable;
|
||||
const isIPhone =
|
||||
/\b(\w*iPhone\w*)\b/.test(userAgent) &&
|
||||
/\b(\w*Mobile\w*)\b/.test(userAgent) &&
|
||||
isTouchable;
|
||||
|
||||
return isIPad || isIPhone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isIOSWithSafari(): boolean {
|
||||
const userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
||||
return (
|
||||
/\b(\w*Apple\w*)\b/.test(navigator.vendor) &&
|
||||
/\b(\w*Safari\w*)\b/.test(userAgent) &&
|
||||
!/\b(\w*CriOS\w*)\b/.test(userAgent) &&
|
||||
!/\b(\w*FxiOS\w*)\b/.test(userAgent)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isIonicIos(): boolean {
|
||||
return this.isIPhoneOrIPad() && platform.ua!!.indexOf("Safari") === -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isIonicAndroid(): boolean {
|
||||
return (
|
||||
platform.os!!.family === "Android" && platform.name == "Android Browser"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isMobileDevice(): boolean {
|
||||
return platform.os!!.family === "iOS" || platform.os!!.family === "Android";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public isReactNative(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public canScreenShare(): boolean {
|
||||
const version = platform?.version ? parseFloat(platform.version) : -1;
|
||||
// Reject mobile devices
|
||||
if (this.isMobileDevice()) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
this.isChromeBrowser() ||
|
||||
this.isFirefoxBrowser() ||
|
||||
this.isOperaBrowser() ||
|
||||
this.isElectron() ||
|
||||
this.isEdgeBrowser() ||
|
||||
(this.isSafariBrowser() && version >= 13)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public getName(): string {
|
||||
return platform.name || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public getVersion(): string {
|
||||
return platform.version || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public getFamily(): string {
|
||||
return platform.os!!.family || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public getDescription(): string {
|
||||
return platform.description || "";
|
||||
}
|
||||
}
|
|
@ -17,12 +17,17 @@
|
|||
|
||||
import freeice = require('freeice');
|
||||
import uuid = require('uuid');
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../Utils/Platform';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
|
||||
export interface WebRtcPeerConfiguration {
|
||||
|
@ -50,6 +55,7 @@ export class WebRtcPeer {
|
|||
private candidategatheringdone = false;
|
||||
|
||||
constructor(protected configuration: WebRtcPeerConfiguration) {
|
||||
platform = PlatformUtils.getInstance();
|
||||
this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
|
||||
|
||||
this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
|
||||
|
@ -139,8 +145,7 @@ export class WebRtcPeer {
|
|||
|
||||
logger.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
|
||||
|
||||
if (platform.name === 'Safari' && platform.ua!!.indexOf('Safari') !== -1) {
|
||||
|
||||
if (platform.isSafariBrowser() && !platform.isIonicIos()) {
|
||||
// Safari (excluding Ionic), at least on iOS just seems to support unified plan, whereas in other browsers is not yet ready and considered experimental
|
||||
if (offerAudio) {
|
||||
this.pc.addTransceiver('audio', {
|
||||
|
@ -280,8 +285,35 @@ export class WebRtcPeer {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
||||
// FIXME CONFLICT WITH MASTER
|
||||
// In the mediasoup branch, the special treatment for ionic was removed:
|
||||
// openvidu-browser: removed Ionic iOS timeout on first subscription
|
||||
// https://github.com/OpenVidu/openvidu/commit/23d64be8063f8fdb2a212ca845e304762f2803f5
|
||||
// and also the method was converted into async and returned a Promise.
|
||||
// However in master the code is still like the old one.
|
||||
<<<<<<< HEAD
|
||||
async setRemoteDescription(sdp: RTCSessionDescriptionInit): Promise<void> {
|
||||
return this.pc.setRemoteDescription(sdp);
|
||||
=======
|
||||
setRemoteDescription(answer: RTCSessionDescriptionInit, needsTimeoutOnProcessAnswer: boolean, resolve: (value?: string | PromiseLike<string> | undefined) => void, reject: (reason?: any) => void) {
|
||||
if (platform.isIonicIos()) {
|
||||
// Ionic iOS platform
|
||||
if (needsTimeoutOnProcessAnswer) {
|
||||
// 400 ms have not elapsed yet since first remote stream triggered Stream#initWebRtcPeerReceive
|
||||
setTimeout(() => {
|
||||
logger.info('setRemoteDescription run after timeout for Ionic iOS device');
|
||||
this.pc.setRemoteDescription(new RTCSessionDescription(answer)).then(() => resolve()).catch(error => reject(error));
|
||||
}, 250);
|
||||
} else {
|
||||
// 400 ms have elapsed
|
||||
this.pc.setRemoteDescription(new RTCSessionDescription(answer)).then(() => resolve()).catch(error => reject(error));
|
||||
}
|
||||
} else {
|
||||
// Rest of platforms
|
||||
this.pc.setRemoteDescription(answer).then(() => resolve()).catch(error => reject(error));
|
||||
}
|
||||
>>>>>>> master
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,4 +401,4 @@ export class WebRtcPeerSendrecv extends WebRtcPeer {
|
|||
configuration.mode = 'sendrecv';
|
||||
super(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,16 @@
|
|||
// tslint:disable:no-string-literal
|
||||
|
||||
import { Stream } from '../../OpenVidu/Stream';
|
||||
import platform = require('platform');
|
||||
import { OpenViduLogger } from '../Logger/OpenViduLogger';
|
||||
import { PlatformUtils } from '../Utils/Platform';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
let platform: PlatformUtils;
|
||||
|
||||
export class WebRtcStats {
|
||||
|
||||
|
@ -60,7 +63,9 @@ export class WebRtcStats {
|
|||
}
|
||||
};
|
||||
|
||||
constructor(private stream: Stream) { }
|
||||
constructor(private stream: Stream) {
|
||||
platform = PlatformUtils.getInstance();
|
||||
}
|
||||
|
||||
public isEnabled(): boolean {
|
||||
return this.webRtcStatsEnabled;
|
||||
|
@ -103,7 +108,7 @@ export class WebRtcStats {
|
|||
return new Promise((resolve, reject) => {
|
||||
this.getStatsAgnostic(this.stream.getRTCPeerConnection(),
|
||||
(stats) => {
|
||||
if ((platform.name!.indexOf('Chrome') !== -1) || (platform.name!.indexOf('Opera') !== -1)) {
|
||||
if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser()) {
|
||||
let localCandidateId, remoteCandidateId, googCandidatePair;
|
||||
const localCandidates = {};
|
||||
const remoteCandidates = {};
|
||||
|
@ -181,7 +186,7 @@ export class WebRtcStats {
|
|||
|
||||
const f = (stats) => {
|
||||
|
||||
if (platform.name!.indexOf('Firefox') !== -1) {
|
||||
if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) {
|
||||
stats.forEach((stat) => {
|
||||
|
||||
let json = {};
|
||||
|
@ -278,7 +283,7 @@ export class WebRtcStats {
|
|||
sendPost(JSON.stringify(json));
|
||||
}
|
||||
});
|
||||
} else if ((platform.name!.indexOf('Chrome') !== -1) || (platform.name!.indexOf('Opera') !== -1)) {
|
||||
} else if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser()) {
|
||||
for (const key of Object.keys(stats)) {
|
||||
const stat = stats[key];
|
||||
if (stat.type === 'ssrc') {
|
||||
|
@ -377,7 +382,7 @@ export class WebRtcStats {
|
|||
logger.log(response);
|
||||
const standardReport = {};
|
||||
|
||||
if (platform.name!.indexOf('Firefox') !== -1) {
|
||||
if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) {
|
||||
Object.keys(response).forEach(key => {
|
||||
logger.log(response[key]);
|
||||
});
|
||||
|
@ -400,13 +405,13 @@ export class WebRtcStats {
|
|||
}
|
||||
|
||||
private getStatsAgnostic(pc, successCb, failureCb) {
|
||||
if (platform.name!.indexOf('Firefox') !== -1) {
|
||||
if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) {
|
||||
// getStats takes args in different order in Chrome and Firefox
|
||||
return pc.getStats(null).then(response => {
|
||||
const report = this.standardizeReport(response);
|
||||
successCb(report);
|
||||
}).catch(failureCb);
|
||||
} else if ((platform.name!.indexOf('Chrome') !== -1) || (platform.name!.indexOf('Opera') !== -1)) {
|
||||
} else if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser()) {
|
||||
// In Chrome, the first two arguments are reversed
|
||||
return pc.getStats((response) => {
|
||||
const report = this.standardizeReport(response);
|
||||
|
|
|
@ -22,7 +22,9 @@ export { StreamEvent } from './OpenViduInternal/Events/StreamEvent';
|
|||
export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent';
|
||||
export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent';
|
||||
export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
export { ConnectionPropertyChangedEvent } from './OpenViduInternal/Events/ConnectionPropertyChangedEvent';
|
||||
export { FilterEvent } from './OpenViduInternal/Events/FilterEvent';
|
||||
export { NetworkQualityLevelChangedEvent } from './OpenViduInternal/Events/NetworkQualityLevelChangedEvent';
|
||||
|
||||
export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities';
|
||||
export { Device } from './OpenViduInternal/Interfaces/Public/Device';
|
||||
|
|
|
@ -50,8 +50,10 @@ public class OpenViduException extends JsonRpcErrorException {
|
|||
DOCKER_NOT_FOUND(709), RECORDING_PATH_NOT_VALID(708), RECORDING_FILE_EMPTY_ERROR(707),
|
||||
RECORDING_DELETE_ERROR_CODE(706), RECORDING_LIST_ERROR_CODE(705), RECORDING_STOP_ERROR_CODE(704),
|
||||
RECORDING_START_ERROR_CODE(703), RECORDING_REPORT_ERROR_CODE(702), RECORDING_COMPLETION_ERROR_CODE(701),
|
||||
|
||||
FORCED_CODEC_NOT_FOUND_IN_SDPOFFER(800);
|
||||
|
||||
FORCED_CODEC_NOT_FOUND_IN_SDPOFFER(800),
|
||||
|
||||
MEDIA_NODE_NOT_FOUND(900), MEDIA_NODE_STATUS_WRONG(901);
|
||||
|
||||
private int value;
|
||||
|
||||
|
|
|
@ -98,6 +98,15 @@ public class ProtocolElements {
|
|||
public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue";
|
||||
public static final String STREAMPROPERTYCHANGED_REASON_PARAM = "reason";
|
||||
|
||||
public static final String CONNECTIONPERTYCHANGED_METHOD = "connectionPropertyChanged";
|
||||
public static final String CONNECTIONROPERTYCHANGED_PROPERTY_PARAM = "property";
|
||||
public static final String CONNECTIONPROPERTYCHANGED_NEWVALUE_PARAM = "newValue";
|
||||
|
||||
public static final String NETWORKQUALITYLEVELCHANGED_METHOD = "networkQualityLevelChanged";
|
||||
public static final String NETWORKQUALITYCHANGED_CONNECTIONID_PARAM = "connectionId";
|
||||
public static final String NETWORKQUALITYCHANGED_NEWVALUE_PARAM = "newValue";
|
||||
public static final String NETWORKQUALITYCHANGED_OLDVALUE_PARAM = "oldValue";
|
||||
|
||||
public static final String FORCEDISCONNECT_METHOD = "forceDisconnect";
|
||||
public static final String FORCEDISCONNECT_CONNECTIONID_PARAM = "connectionId";
|
||||
|
||||
|
@ -127,12 +136,22 @@ public class ProtocolElements {
|
|||
public static final String RECONNECTSTREAM_STREAM_PARAM = "stream";
|
||||
public static final String RECONNECTSTREAM_SDPSTRING_PARAM = "sdpString";
|
||||
|
||||
public static final String VIDEODATA_METHOD = "videoData";
|
||||
|
||||
// ---------------------------- SERVER RESPONSES & EVENTS -----------------
|
||||
|
||||
public static final String PARTICIPANTJOINED_METHOD = "participantJoined";
|
||||
public static final String PARTICIPANTJOINED_USER_PARAM = "id";
|
||||
public static final String PARTICIPANTJOINED_CREATEDAT_PARAM = "createdAt";
|
||||
public static final String PARTICIPANTJOINED_METADATA_PARAM = "metadata";
|
||||
public static final String PARTICIPANTJOINED_VALUE_PARAM = "value";
|
||||
public static final String PARTICIPANTJOINED_SESSION_PARAM = "session";
|
||||
public static final String PARTICIPANTJOINED_VERSION_PARAM = "version";
|
||||
public static final String PARTICIPANTJOINED_RECORD_PARAM = "record";
|
||||
public static final String PARTICIPANTJOINED_ROLE_PARAM = "role";
|
||||
public static final String PARTICIPANTJOINED_COTURNIP_PARAM = "coturnIp";
|
||||
public static final String PARTICIPANTJOINED_TURNUSERNAME_PARAM = "turnUsername";
|
||||
public static final String PARTICIPANTJOINED_TURNCREDENTIAL_PARAM = "turnCredential";
|
||||
|
||||
public static final String PARTICIPANTLEFT_METHOD = "participantLeft";
|
||||
public static final String PARTICIPANTLEFT_NAME_PARAM = "connectionId";
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</parent>
|
||||
|
||||
<artifactId>openvidu-java-client</artifactId>
|
||||
<version>2.15.1</version>
|
||||
<version>2.16.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>OpenVidu Java Client</name>
|
||||
|
|
|
@ -18,77 +18,194 @@
|
|||
package io.openvidu.java.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* See {@link io.openvidu.java.client.Session#getActiveConnections()}
|
||||
* See {@link io.openvidu.java.client.Session#getConnections()}
|
||||
*/
|
||||
public class Connection {
|
||||
|
||||
private String connectionId;
|
||||
private long createdAt;
|
||||
private OpenViduRole role;
|
||||
private String token;
|
||||
private String status;
|
||||
private Long createdAt;
|
||||
private Long activeAt;
|
||||
private String location;
|
||||
private String platform;
|
||||
private String serverData;
|
||||
private String clientData;
|
||||
private ConnectionProperties connectionProperties;
|
||||
private String token;
|
||||
|
||||
protected Map<String, Publisher> publishers;
|
||||
protected List<String> subscribers;
|
||||
protected Map<String, Publisher> publishers = new ConcurrentHashMap<>();
|
||||
protected List<String> subscribers = new ArrayList<>();
|
||||
|
||||
protected Connection(String connectionId, long createdAt, OpenViduRole role, String token, String location,
|
||||
String platform, String serverData, String clientData, Map<String, Publisher> publishers,
|
||||
List<String> subscribers) {
|
||||
this.connectionId = connectionId;
|
||||
this.createdAt = createdAt;
|
||||
this.role = role;
|
||||
this.token = token;
|
||||
this.location = location;
|
||||
this.platform = platform;
|
||||
this.serverData = serverData;
|
||||
this.clientData = clientData;
|
||||
this.publishers = publishers;
|
||||
this.subscribers = subscribers;
|
||||
protected Connection(JsonObject json) {
|
||||
this.resetWithJson(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of the connection. You can call
|
||||
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} passing this
|
||||
* property as parameter
|
||||
* Returns the identifier of the Connection. You can call methods
|
||||
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} or
|
||||
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}
|
||||
* passing this property as parameter
|
||||
*/
|
||||
public String getConnectionId() {
|
||||
return connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp when this connection was established, in UTC milliseconds (ms since
|
||||
* Jan 1, 1970, 00:00:00 UTC)
|
||||
* Returns the status of the Connection. Can be:
|
||||
* <ul>
|
||||
* <li><code>pending</code>: if the Connection is waiting for any user to use
|
||||
* its internal token to connect to the session, calling method <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect"
|
||||
* target ="_blank">Session.connect</a> in OpenVidu Browser.</li>
|
||||
* <li><code>active</code>: if the internal token of the Connection has already
|
||||
* been used by some user to connect to the session, and it cannot be used
|
||||
* again.</li>
|
||||
*/
|
||||
public long createdAt() {
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp when this Connection was created, in UTC milliseconds (ms since Jan
|
||||
* 1, 1970, 00:00:00 UTC)
|
||||
*/
|
||||
public Long createdAt() {
|
||||
return this.createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the role of the connection
|
||||
* Timestamp when this Connection was taken by a user (passing from status
|
||||
* "pending" to "active"), in UTC milliseconds (ms since Jan 1, 1970, 00:00:00
|
||||
* UTC)
|
||||
*/
|
||||
public Long activeAt() {
|
||||
return this.activeAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of Connection.
|
||||
*/
|
||||
public ConnectionType getType() {
|
||||
return this.connectionProperties.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the Connection on the server-side. This value
|
||||
* is set with {@link io.openvidu.java.client.TokenOptions.Builder#data(String)}
|
||||
* when calling {@link io.openvidu.java.client.Session#generateToken()}
|
||||
*/
|
||||
public String getServerData() {
|
||||
return this.connectionProperties.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the streams published by this Connection will be recorded or not.
|
||||
* This only affects <a href=
|
||||
* "https://docs.openvidu.io/en/stable/advanced-features/recording#selecting-streams-to-be-recorded"
|
||||
* target="_blank">INDIVIDUAL recording</a>.
|
||||
*/
|
||||
public boolean record() {
|
||||
return this.connectionProperties.record();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the role of the Connection.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
|
||||
*/
|
||||
public OpenViduRole getRole() {
|
||||
return role;
|
||||
return this.connectionProperties.getRole();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token associated to the connection
|
||||
* Returns the RTSP URI of the Connection.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public String getRtspUri() {
|
||||
return this.connectionProperties.getRtspUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the Connection uses adaptative bitrate (and therefore adaptative
|
||||
* quality) or not. For local network connections that do not require media
|
||||
* transcoding this can be disabled to save CPU power. If you are not sure if
|
||||
* transcoding might be necessary, setting this property to false <strong>may
|
||||
* result in media connections not being established</strong>.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Boolean adaptativeBitrate() {
|
||||
return this.connectionProperties.adaptativeBitrate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the IP camera stream of this Connection will only be enabled when
|
||||
* some user is subscribed to it, or not. This allows you to reduce power
|
||||
* consumption and network bandwidth in your server while nobody is asking to
|
||||
* receive the camera's video. On the counterpart, first user subscribing to the
|
||||
* IP camera stream will take a little longer to receive its video.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Boolean onlyPlayWithSubscribers() {
|
||||
return this.connectionProperties.onlyPlayWithSubscribers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the buffer of the endpoint receiving the IP camera's
|
||||
* stream, in milliseconds. The smaller it is, the less delay the signal will
|
||||
* have, but more problematic will be in unstable networks. Use short buffers
|
||||
* only if there is a quality connection between the IP camera and OpenVidu
|
||||
* Server.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Integer getNetworkCache() {
|
||||
return this.connectionProperties.getNetworkCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token string associated to the Connection. This is the value that
|
||||
* must be sent to the client-side to be consumed in OpenVidu Browser method
|
||||
* <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect"
|
||||
* target="_blank">Session.connect</a>.
|
||||
*/
|
||||
public String getToken() {
|
||||
return token;
|
||||
return this.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display:
|
||||
* inline-block; background-color: rgb(0, 136, 170); color: white; font-weight:
|
||||
* bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size:
|
||||
* 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a>
|
||||
*
|
||||
* Returns the geo location of the connection, with the following format:
|
||||
* <code>"CITY, COUNTRY"</code> (<code>"unknown"</code> if it wasn't possible to
|
||||
|
@ -106,20 +223,11 @@ public class Connection {
|
|||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the connection on the server-side. This value
|
||||
* is set with {@link io.openvidu.java.client.TokenOptions.Builder#data(String)}
|
||||
* when calling {@link io.openvidu.java.client.Session#generateToken()}
|
||||
*/
|
||||
public String getServerData() {
|
||||
return serverData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the connection on the client-side. This value
|
||||
* is set with second parameter of method
|
||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect" target
|
||||
* ="_blank">Session.connect</a> in OpenVidu Browser
|
||||
* is set with second parameter of method <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect"
|
||||
* target ="_blank">Session.connect</a> in OpenVidu Browser
|
||||
*/
|
||||
public String getClientData() {
|
||||
return clientData;
|
||||
|
@ -147,8 +255,171 @@ public class Connection {
|
|||
return this.subscribers;
|
||||
}
|
||||
|
||||
protected JsonObject toJson() {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("connectionId", this.getConnectionId());
|
||||
json.addProperty("status", this.getStatus());
|
||||
json.addProperty("createdAt", this.createdAt());
|
||||
json.addProperty("activeAt", this.activeAt());
|
||||
json.addProperty("location", this.getLocation());
|
||||
json.addProperty("platform", this.getPlatform());
|
||||
json.addProperty("clientData", this.getClientData());
|
||||
json.addProperty("token", this.getToken());
|
||||
|
||||
JsonObject jsonConnectionProperties = this.connectionProperties.toJson("");
|
||||
jsonConnectionProperties.remove("session");
|
||||
json.addProperty("serverData", jsonConnectionProperties.get("data").getAsString());
|
||||
jsonConnectionProperties.remove("data");
|
||||
jsonConnectionProperties.entrySet().forEach(entry -> {
|
||||
json.add(entry.getKey(), entry.getValue());
|
||||
});
|
||||
|
||||
JsonArray pubs = new JsonArray();
|
||||
this.getPublishers().forEach(p -> {
|
||||
pubs.add(p.toJson());
|
||||
});
|
||||
JsonArray subs = new JsonArray();
|
||||
this.getSubscribers().forEach(s -> {
|
||||
subs.add(s);
|
||||
});
|
||||
json.add("publishers", pubs);
|
||||
json.add("subscribers", subs);
|
||||
return json;
|
||||
}
|
||||
|
||||
protected void overrideConnectionProperties(ConnectionProperties newConnectionProperties) {
|
||||
ConnectionProperties.Builder builder = new ConnectionProperties.Builder();
|
||||
// For now only properties role and record can be updated
|
||||
if (newConnectionProperties.getRole() != null) {
|
||||
builder.role(newConnectionProperties.getRole());
|
||||
} else {
|
||||
builder.role(this.connectionProperties.getRole());
|
||||
}
|
||||
if (newConnectionProperties.record() != null) {
|
||||
builder.record(newConnectionProperties.record());
|
||||
} else {
|
||||
builder.record(this.connectionProperties.record());
|
||||
}
|
||||
// Keep old configuration in the rest of properties
|
||||
builder.type(this.connectionProperties.getType()).data(this.connectionProperties.getData())
|
||||
.kurentoOptions(this.connectionProperties.getKurentoOptions())
|
||||
.rtspUri(this.connectionProperties.getRtspUri());
|
||||
if (this.connectionProperties.adaptativeBitrate() != null) {
|
||||
builder.adaptativeBitrate(this.connectionProperties.adaptativeBitrate());
|
||||
}
|
||||
if (this.connectionProperties.onlyPlayWithSubscribers() != null) {
|
||||
builder.onlyPlayWithSubscribers(this.connectionProperties.onlyPlayWithSubscribers());
|
||||
}
|
||||
if (this.connectionProperties.getNetworkCache() != null) {
|
||||
builder.networkCache(this.connectionProperties.getNetworkCache());
|
||||
}
|
||||
this.connectionProperties = builder.build();
|
||||
}
|
||||
|
||||
protected void setSubscribers(List<String> subscribers) {
|
||||
this.subscribers = subscribers;
|
||||
}
|
||||
|
||||
protected Connection resetWithJson(JsonObject json) {
|
||||
|
||||
this.connectionId = json.get("connectionId").getAsString();
|
||||
this.status = json.get("status").getAsString();
|
||||
this.token = !json.get("token").isJsonNull() ? json.get("token").getAsString() : null;
|
||||
|
||||
if (!json.get("publishers").isJsonNull()) {
|
||||
JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray();
|
||||
|
||||
// 1. Set to store fetched publishers and later remove closed ones
|
||||
Set<String> fetchedPublisherIds = new HashSet<>();
|
||||
jsonArrayPublishers.forEach(publisherJsonElement -> {
|
||||
|
||||
JsonObject publisherJson = publisherJsonElement.getAsJsonObject();
|
||||
Publisher publisherObj = new Publisher(publisherJson);
|
||||
String id = publisherObj.getStreamId();
|
||||
fetchedPublisherIds.add(id);
|
||||
|
||||
// 2. Update existing Publisher
|
||||
this.publishers.computeIfPresent(id, (pId, p) -> {
|
||||
p = p.resetWithJson(publisherJson);
|
||||
return p;
|
||||
});
|
||||
|
||||
// 3. Add new Publisher
|
||||
this.publishers.computeIfAbsent(id, pId -> {
|
||||
return publisherObj;
|
||||
});
|
||||
});
|
||||
|
||||
// 4. Remove closed connections from local collection
|
||||
this.publishers.entrySet().removeIf(entry -> !fetchedPublisherIds.contains(entry.getValue().getStreamId()));
|
||||
}
|
||||
|
||||
if (!json.get("subscribers").isJsonNull()) {
|
||||
JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray();
|
||||
|
||||
// 1. Array to store fetched Subscribers and later remove closed ones
|
||||
Set<String> fetchedSubscriberIds = new HashSet<>();
|
||||
jsonArraySubscribers.forEach(subscriber -> {
|
||||
|
||||
String sub = subscriber.getAsJsonObject().get("streamId").getAsString();
|
||||
fetchedSubscriberIds.add(sub);
|
||||
|
||||
if (!this.subscribers.contains(sub)) {
|
||||
// 2. Add new Subscriber
|
||||
this.subscribers.add(sub);
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Remove closed Subscribers from local collection
|
||||
this.subscribers.removeIf(subId -> !fetchedSubscriberIds.contains(subId));
|
||||
}
|
||||
|
||||
if (!json.get("createdAt").isJsonNull()) {
|
||||
this.createdAt = json.get("createdAt").getAsLong();
|
||||
}
|
||||
if (!json.get("activeAt").isJsonNull()) {
|
||||
this.activeAt = json.get("activeAt").getAsLong();
|
||||
}
|
||||
if (!json.get("location").isJsonNull()) {
|
||||
this.location = json.get("location").getAsString();
|
||||
}
|
||||
if (!json.get("platform").isJsonNull()) {
|
||||
this.platform = json.get("platform").getAsString();
|
||||
}
|
||||
if (!json.get("clientData").isJsonNull()) {
|
||||
this.clientData = json.get("clientData").getAsString();
|
||||
}
|
||||
|
||||
// COMMON
|
||||
ConnectionType type = ConnectionType.valueOf(json.get("type").getAsString());
|
||||
String data = (json.has("serverData") && !json.get("serverData").isJsonNull())
|
||||
? json.get("serverData").getAsString()
|
||||
: null;
|
||||
Boolean record = (json.has("record") && !json.get("record").isJsonNull()) ? json.get("record").getAsBoolean()
|
||||
: null;
|
||||
|
||||
// WEBRTC
|
||||
OpenViduRole role = (json.has("role") && !json.get("role").isJsonNull())
|
||||
? OpenViduRole.valueOf(json.get("role").getAsString())
|
||||
: null;
|
||||
|
||||
// IPCAM
|
||||
String rtspUri = (json.has("rtspUri") && !json.get("rtspUri").isJsonNull()) ? json.get("rtspUri").getAsString()
|
||||
: null;
|
||||
Boolean adaptativeBitrate = (json.has("adaptativeBitrate") && !json.get("adaptativeBitrate").isJsonNull())
|
||||
? json.get("adaptativeBitrate").getAsBoolean()
|
||||
: null;
|
||||
Boolean onlyPlayWithSubscribers = (json.has("onlyPlayWithSubscribers")
|
||||
&& !json.get("onlyPlayWithSubscribers").isJsonNull())
|
||||
? json.get("onlyPlayWithSubscribers").getAsBoolean()
|
||||
: null;
|
||||
Integer networkCache = (json.has("networkCache") && !json.get("networkCache").isJsonNull())
|
||||
? json.get("networkCache").getAsInt()
|
||||
: null;
|
||||
this.connectionProperties = new ConnectionProperties(type, data, record, role, null, rtspUri, adaptativeBitrate,
|
||||
onlyPlayWithSubscribers, networkCache);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,403 @@
|
|||
package io.openvidu.java.client;
|
||||
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* See
|
||||
* {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)}
|
||||
*/
|
||||
public class ConnectionProperties {
|
||||
|
||||
private ConnectionType type;
|
||||
// COMMON
|
||||
private String data;
|
||||
private Boolean record;
|
||||
// WEBRTC
|
||||
private OpenViduRole role;
|
||||
private KurentoOptions kurentoOptions;
|
||||
// IPCAM
|
||||
private String rtspUri;
|
||||
private Boolean adaptativeBitrate;
|
||||
private Boolean onlyPlayWithSubscribers;
|
||||
private Integer networkCache;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder for {@link io.openvidu.java.client.ConnectionProperties}
|
||||
*
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private ConnectionType type;
|
||||
// COMMON
|
||||
private String data;
|
||||
private Boolean record;
|
||||
// WEBRTC
|
||||
private OpenViduRole role;
|
||||
private KurentoOptions kurentoOptions;
|
||||
// IPCAM
|
||||
private String rtspUri;
|
||||
private Boolean adaptativeBitrate;
|
||||
private Boolean onlyPlayWithSubscribers;
|
||||
private Integer networkCache;
|
||||
|
||||
/**
|
||||
* Builder for {@link io.openvidu.java.client.ConnectionProperties}.
|
||||
*/
|
||||
public ConnectionProperties build() {
|
||||
return new ConnectionProperties(this.type, this.data, this.record, this.role, this.kurentoOptions,
|
||||
this.rtspUri, this.adaptativeBitrate, this.onlyPlayWithSubscribers, this.networkCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the type of Connection. The
|
||||
* {@link io.openvidu.java.client.ConnectionType} dictates what properties will
|
||||
* have effect:
|
||||
* <ul>
|
||||
* <li>{@link io.openvidu.java.client.ConnectionType#WEBRTC}:
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String)
|
||||
* data},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean)
|
||||
* record},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole)
|
||||
* role},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#kurentoOptions(KurentoOptions)
|
||||
* kurentoOptions}</li>
|
||||
* <li>{@link io.openvidu.java.client.ConnectionType#IPCAM}:
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String)
|
||||
* data},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean)
|
||||
* record},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#rtspUri(String)
|
||||
* rtspUri},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#adaptativeBitrate(boolean)
|
||||
* adaptativeBitrate},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#onlyPlayWithSubscribers(boolean)
|
||||
* onlyPlayWithSubscribers},
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#networkCache(int)
|
||||
* networkCache}</li>
|
||||
* </ul>
|
||||
* If not set by default will be
|
||||
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}.
|
||||
*/
|
||||
public Builder type(ConnectionType type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the secure (server-side) data associated to this
|
||||
* Connection. Every client will receive this data in property
|
||||
* <code>Connection.data</code>. Object <code>Connection</code> can be retrieved
|
||||
* by subscribing to event <code>connectionCreated</code> of Session object in
|
||||
* your clients.
|
||||
* <ul>
|
||||
* <li>If you have provided no data in your clients when calling method
|
||||
* <code>Session.connect(TOKEN, DATA)</code> (<code>DATA</code> not defined),
|
||||
* then <code>Connection.data</code> will only have this
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String)}
|
||||
* property.</li>
|
||||
* <li>If you have provided some data when calling
|
||||
* <code>Session.connect(TOKEN, DATA)</code> (<code>DATA</code> defined), then
|
||||
* <code>Connection.data</code> will have the following structure:
|
||||
* <code>"CLIENT_DATA%/%SERVER_DATA"</code>, being
|
||||
* <code>CLIENT_DATA</code> the second parameter passed in OpenVidu Browser in
|
||||
* method <code>Session.connect</code> and <code>SERVER_DATA</code> this
|
||||
* {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String)}
|
||||
* property.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Builder data(String data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to flag the streams published by this Connection to be
|
||||
* recorded or not. This only affects <a href=
|
||||
* "https://docs.openvidu.io/en/stable/advanced-features/recording#selecting-streams-to-be-recorded"
|
||||
* target="_blank">INDIVIDUAL recording</a>. If not set by default will be true.
|
||||
*/
|
||||
public Builder record(boolean record) {
|
||||
this.record = record;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the role assigned to this Connection. If not set by
|
||||
* default will be {@link io.openvidu.java.client.OpenViduRole#PUBLISHER
|
||||
* PUBLISHER}.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
|
||||
*/
|
||||
public Builder role(OpenViduRole role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set a {@link io.openvidu.java.client.KurentoOptions}
|
||||
* object for this Connection.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
|
||||
*/
|
||||
public Builder kurentoOptions(KurentoOptions kurentoOptions) {
|
||||
this.kurentoOptions = kurentoOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the RTSP URI of an IP camera. For example:
|
||||
* <code>rtsp://your.camera.ip:7777/path</code>
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Builder rtspUri(String rtspUri) {
|
||||
this.rtspUri = rtspUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set whether to use adaptative bitrate (and therefore
|
||||
* adaptative quality) or not. For local network connections that do not require
|
||||
* media transcoding this can be disabled to save CPU power. If you are not sure
|
||||
* if transcoding might be necessary, setting this property to false <strong>may
|
||||
* result in media connections not being established</strong>. Default to
|
||||
* <code>true</code>.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Builder adaptativeBitrate(boolean adaptativeBitrate) {
|
||||
this.adaptativeBitrate = adaptativeBitrate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set whether to enable the IP camera stream only when some
|
||||
* user is subscribed to it, or not. This allows you to reduce power consumption
|
||||
* and network bandwidth in your server while nobody is asking to receive the
|
||||
* camera's video. On the counterpart, first user subscribing to the IP camera
|
||||
* stream will take a little longer to receive its video. Default to
|
||||
* <code>true</code>.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Builder onlyPlayWithSubscribers(boolean onlyPlayWithSubscribers) {
|
||||
this.onlyPlayWithSubscribers = onlyPlayWithSubscribers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the size of the buffer of the endpoint receiving the
|
||||
* IP camera's stream, in milliseconds. The smaller it is, the less delay the
|
||||
* signal will have, but more problematic will be in unstable networks. Use
|
||||
* short buffers only if there is a quality connection between the IP camera and
|
||||
* OpenVidu Server. Default to <code>2000</code>.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Builder networkCache(int networkCache) {
|
||||
this.networkCache = networkCache;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionProperties(ConnectionType type, String data, Boolean record, OpenViduRole role,
|
||||
KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers,
|
||||
Integer networkCache) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.record = record;
|
||||
this.role = role;
|
||||
this.kurentoOptions = kurentoOptions;
|
||||
this.rtspUri = rtspUri;
|
||||
this.adaptativeBitrate = adaptativeBitrate;
|
||||
this.onlyPlayWithSubscribers = onlyPlayWithSubscribers;
|
||||
this.networkCache = networkCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of Connection.
|
||||
*/
|
||||
public ConnectionType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secure (server-side) metadata assigned to this Connection.
|
||||
*/
|
||||
public String getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a> Whether the streams published by this Connection will be
|
||||
* recorded or not. This only affects <a href=
|
||||
* "https://docs.openvidu.io/en/stable/advanced-features/recording#selecting-streams-to-be-recorded"
|
||||
* target="_blank">INDIVIDUAL recording</a>.
|
||||
*/
|
||||
public Boolean record() {
|
||||
return this.record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the role assigned to this Connection.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
|
||||
*/
|
||||
public OpenViduRole getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the KurentoOptions assigned to this Connection.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
|
||||
*/
|
||||
public KurentoOptions getKurentoOptions() {
|
||||
return this.kurentoOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RTSP URI of this Connection.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public String getRtspUri() {
|
||||
return this.rtspUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this Connection uses adaptative bitrate (and therefore adaptative
|
||||
* quality) or not. For local network connections that do not require media
|
||||
* transcoding this can be disabled to save CPU power. If you are not sure if
|
||||
* transcoding might be necessary, setting this property to false <strong>may
|
||||
* result in media connections not being established</strong>.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Boolean adaptativeBitrate() {
|
||||
return this.adaptativeBitrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to enable the IP camera stream only when some user is subscribed to
|
||||
* it. This allows you to reduce power consumption and network bandwidth in your
|
||||
* server while nobody is asking to receive the camera's video. On the
|
||||
* counterpart, first user subscribing to the IP camera stream will take a
|
||||
* little longer to receive its video.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Boolean onlyPlayWithSubscribers() {
|
||||
return this.onlyPlayWithSubscribers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the buffer of the endpoint receiving the IP camera's stream, in
|
||||
* milliseconds. The smaller it is, the less delay the signal will have, but
|
||||
* more problematic will be in unstable networks. Use short buffers only if
|
||||
* there is a quality connection between the IP camera and OpenVidu Server.
|
||||
*
|
||||
* <br>
|
||||
* <br>
|
||||
* <strong>Only for
|
||||
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
|
||||
*/
|
||||
public Integer getNetworkCache() {
|
||||
return this.networkCache;
|
||||
}
|
||||
|
||||
public JsonObject toJson(String sessionId) {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("session", sessionId);
|
||||
// COMMON
|
||||
if (getType() != null) {
|
||||
json.addProperty("type", getType().name());
|
||||
} else {
|
||||
json.add("type", JsonNull.INSTANCE);
|
||||
}
|
||||
if (getData() != null) {
|
||||
json.addProperty("data", getData());
|
||||
} else {
|
||||
json.add("data", JsonNull.INSTANCE);
|
||||
}
|
||||
if (record() != null) {
|
||||
json.addProperty("record", record());
|
||||
} else {
|
||||
json.add("record", JsonNull.INSTANCE);
|
||||
}
|
||||
// WEBRTC
|
||||
if (getRole() != null) {
|
||||
json.addProperty("role", getRole().name());
|
||||
} else {
|
||||
json.add("role", JsonNull.INSTANCE);
|
||||
}
|
||||
if (this.kurentoOptions != null) {
|
||||
json.add("kurentoOptions", kurentoOptions.toJson());
|
||||
} else {
|
||||
json.add("kurentoOptions", JsonNull.INSTANCE);
|
||||
}
|
||||
// IPCAM
|
||||
if (getRtspUri() != null) {
|
||||
json.addProperty("rtspUri", getRtspUri());
|
||||
} else {
|
||||
json.add("rtspUri", JsonNull.INSTANCE);
|
||||
}
|
||||
if (adaptativeBitrate() != null) {
|
||||
json.addProperty("adaptativeBitrate", adaptativeBitrate());
|
||||
} else {
|
||||
json.add("adaptativeBitrate", JsonNull.INSTANCE);
|
||||
}
|
||||
if (onlyPlayWithSubscribers() != null) {
|
||||
json.addProperty("onlyPlayWithSubscribers", onlyPlayWithSubscribers());
|
||||
} else {
|
||||
json.add("onlyPlayWithSubscribers", JsonNull.INSTANCE);
|
||||
}
|
||||
if (getNetworkCache() != null) {
|
||||
json.addProperty("networkCache", getNetworkCache());
|
||||
} else {
|
||||
json.add("networkCache", JsonNull.INSTANCE);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package io.openvidu.java.client;
|
||||
|
||||
/**
|
||||
* See
|
||||
* {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)}
|
||||
*/
|
||||
public enum ConnectionType {
|
||||
|
||||
/**
|
||||
* WebRTC connection. This is the normal type of Connection for a regular user
|
||||
* connecting to a session from an application.
|
||||
*/
|
||||
WEBRTC,
|
||||
|
||||
/**
|
||||
* IP camera connection. This is the type of Connection used by IP cameras to
|
||||
* connect to a session.
|
||||
*/
|
||||
IPCAM
|
||||
}
|
|
@ -17,6 +17,11 @@
|
|||
|
||||
package io.openvidu.java.client;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* See {@link io.openvidu.java.client.TokenOptions#getKurentoOptions()}
|
||||
*/
|
||||
|
@ -105,10 +110,10 @@ public class KurentoOptions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defines the maximum number of Kbps that the client owning the token will be
|
||||
* able to receive from Kurento Media Server. 0 means unconstrained. Giving a
|
||||
* value to this property will override the global configuration set in <a
|
||||
* href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* Defines the maximum number of Kbps that the Connection will be able to
|
||||
* receive from Kurento Media Server per media stream. 0 means unconstrained.
|
||||
* Giving a value to this property will override the global configuration set in
|
||||
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||
* <code>OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH</code>) for every incoming
|
||||
* stream of the user owning the token. <br>
|
||||
|
@ -122,10 +127,10 @@ public class KurentoOptions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defines the minimum number of Kbps that the client owning the token will try
|
||||
* to receive from Kurento Media Server. 0 means unconstrained. Giving a value
|
||||
* to this property will override the global configuration set in <a href=
|
||||
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* Defines the minimum number of Kbps that the Connection will try to receive
|
||||
* from Kurento Media Server per media stream. 0 means unconstrained. Giving a
|
||||
* value to this property will override the global configuration set in
|
||||
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||
* <code>OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH</code>) for every incoming
|
||||
* stream of the user owning the token.
|
||||
|
@ -135,10 +140,10 @@ public class KurentoOptions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defines the maximum number of Kbps that the client owning the token will be
|
||||
* able to send to Kurento Media Server. 0 means unconstrained. Giving a value
|
||||
* to this property will override the global configuration set in <a href=
|
||||
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* Defines the maximum number of Kbps that the Connection will be able to send
|
||||
* to Kurento Media Server per media stream. 0 means unconstrained. Giving a
|
||||
* value to this property will override the global configuration set in
|
||||
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||
* <code>OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH</code>) for every outgoing
|
||||
* stream of the user owning the token. <br>
|
||||
|
@ -151,10 +156,10 @@ public class KurentoOptions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defines the minimum number of Kbps that the client owning the token will try
|
||||
* to send to Kurento Media Server. 0 means unconstrained. Giving a value to
|
||||
* this property will override the global configuration set in <a href=
|
||||
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* Defines the minimum number of Kbps that the Connection will try to send to
|
||||
* Kurento Media Server per media stream. 0 means unconstrained. Giving a value
|
||||
* to this property will override the global configuration set in
|
||||
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||
* <code>OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH</code>) for every outgoing
|
||||
* stream of the user owning the token.
|
||||
|
@ -164,13 +169,50 @@ public class KurentoOptions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defines the names of the filters the user owning the token will be able to
|
||||
* apply. See
|
||||
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/" target= "_blank">Voice and
|
||||
* video filters</a>
|
||||
* Defines the names of the filters the Connection will be able to apply to its
|
||||
* published streams. See
|
||||
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/"
|
||||
* target= "_blank">Voice and video filters</a>.
|
||||
*/
|
||||
public String[] getAllowedFilters() {
|
||||
return allowedFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the Connection can apply certain filter. See
|
||||
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/"
|
||||
* target= "_blank">Voice and video filters</a>.
|
||||
*/
|
||||
public boolean isFilterAllowed(String filterType) {
|
||||
if (filterType == null) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.stream(allowedFilters).anyMatch(filterType::equals);
|
||||
}
|
||||
|
||||
public JsonObject toJson() {
|
||||
JsonObject json = new JsonObject();
|
||||
if (this.getVideoMaxRecvBandwidth() != null) {
|
||||
json.addProperty("videoMaxRecvBandwidth", this.getVideoMaxRecvBandwidth());
|
||||
}
|
||||
if (this.getVideoMinRecvBandwidth() != null) {
|
||||
json.addProperty("videoMinRecvBandwidth", this.getVideoMinRecvBandwidth());
|
||||
}
|
||||
if (this.getVideoMaxSendBandwidth() != null) {
|
||||
json.addProperty("videoMaxSendBandwidth", this.getVideoMaxSendBandwidth());
|
||||
}
|
||||
if (this.getVideoMinSendBandwidth() != null) {
|
||||
json.addProperty("videoMinSendBandwidth", this.getVideoMinSendBandwidth());
|
||||
}
|
||||
if (this.getAllowedFilters().length > 0) {
|
||||
JsonArray filtersJson = new JsonArray();
|
||||
String[] filters = this.getAllowedFilters();
|
||||
for (String filter : filters) {
|
||||
filtersJson.add(filter);
|
||||
}
|
||||
json.add("allowedFilters", filtersJson);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
|
@ -70,16 +69,19 @@ public class OpenVidu {
|
|||
protected HttpClient httpClient;
|
||||
protected Map<String, Session> activeSessions = new ConcurrentHashMap<>();
|
||||
|
||||
protected final static String API_SESSIONS = "api/sessions";
|
||||
protected final static String API_TOKENS = "api/tokens";
|
||||
protected final static String API_RECORDINGS = "api/recordings";
|
||||
protected final static String API_RECORDINGS_START = "/start";
|
||||
protected final static String API_RECORDINGS_STOP = "/stop";
|
||||
protected final static String API_PATH = "openvidu/api";
|
||||
protected final static String API_SESSIONS = API_PATH + "/sessions";
|
||||
protected final static String API_TOKENS = API_PATH + "/tokens";
|
||||
protected final static String API_RECORDINGS = API_PATH + "/recordings";
|
||||
protected final static String API_RECORDINGS_START = API_RECORDINGS + "/start";
|
||||
protected final static String API_RECORDINGS_STOP = API_RECORDINGS + "/stop";
|
||||
|
||||
/**
|
||||
* @param urlOpenViduServer Public accessible IP where your instance of OpenVidu
|
||||
* Server is up an running
|
||||
* @param secret Secret used on OpenVidu Server initialization
|
||||
* @param hostname URL where your instance of OpenVidu Server is up an running.
|
||||
* It must be the full URL (e.g.
|
||||
* <code>https://12.34.56.78:1234/</code>)
|
||||
*
|
||||
* @param secret Secret used on OpenVidu Server initialization
|
||||
*/
|
||||
public OpenVidu(String hostname, String secret) {
|
||||
|
||||
|
@ -192,16 +194,19 @@ public class OpenVidu {
|
|||
public Recording startRecording(String sessionId, RecordingProperties properties)
|
||||
throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
|
||||
HttpPost request = new HttpPost(this.hostname + API_RECORDINGS + API_RECORDINGS_START);
|
||||
HttpPost request = new HttpPost(this.hostname + API_RECORDINGS_START);
|
||||
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("session", sessionId);
|
||||
json.addProperty("name", properties.name());
|
||||
json.addProperty("outputMode", properties.outputMode().name());
|
||||
json.addProperty("outputMode", properties.outputMode() != null ? properties.outputMode().name() : null);
|
||||
json.addProperty("hasAudio", properties.hasAudio());
|
||||
json.addProperty("hasVideo", properties.hasVideo());
|
||||
json.addProperty("shmSize", properties.shmSize());
|
||||
json.addProperty("mediaNode", properties.mediaNode());
|
||||
|
||||
if ((Recording.OutputMode.COMPOSED.equals(properties.outputMode()) || (Recording.OutputMode.COMPOSED_QUICK_START.equals(properties.outputMode())))
|
||||
if ((properties.outputMode() == null || Recording.OutputMode.COMPOSED.equals(properties.outputMode())
|
||||
|| (Recording.OutputMode.COMPOSED_QUICK_START.equals(properties.outputMode())))
|
||||
&& properties.hasVideo()) {
|
||||
json.addProperty("resolution", properties.resolution());
|
||||
json.addProperty("recordingLayout",
|
||||
|
@ -236,8 +241,9 @@ public class OpenVidu {
|
|||
if (activeSession != null) {
|
||||
activeSession.setIsBeingRecorded(true);
|
||||
} else {
|
||||
log.warn("No active session found for sessionId '" + r.getSessionId()
|
||||
+ "'. This instance of OpenVidu Java Client didn't create this session");
|
||||
log.warn(
|
||||
"No active session found for sessionId '{}'. This instance of OpenVidu Java Client didn't create this session",
|
||||
r.getSessionId());
|
||||
}
|
||||
return r;
|
||||
} else {
|
||||
|
@ -352,7 +358,7 @@ public class OpenVidu {
|
|||
* </ul>
|
||||
*/
|
||||
public Recording stopRecording(String recordingId) throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
HttpPost request = new HttpPost(this.hostname + API_RECORDINGS + API_RECORDINGS_STOP + "/" + recordingId);
|
||||
HttpPost request = new HttpPost(this.hostname + API_RECORDINGS_STOP + "/" + recordingId);
|
||||
HttpResponse response;
|
||||
try {
|
||||
response = this.httpClient.execute(request);
|
||||
|
@ -368,8 +374,9 @@ public class OpenVidu {
|
|||
if (activeSession != null) {
|
||||
activeSession.setIsBeingRecorded(false);
|
||||
} else {
|
||||
log.warn("No active session found for sessionId '" + r.getSessionId()
|
||||
+ "'. This instance of OpenVidu Java Client didn't create this session");
|
||||
log.warn(
|
||||
"No active session found for sessionId '{}'. This instance of OpenVidu Java Client didn't create this session",
|
||||
r.getSessionId());
|
||||
}
|
||||
return r;
|
||||
} else {
|
||||
|
@ -492,6 +499,10 @@ public class OpenVidu {
|
|||
* since the last time method {@link io.openvidu.java.client.OpenVidu#fetch()}
|
||||
* was called</strong>. Exceptions to this rule are:
|
||||
* <ul>
|
||||
* <li>Calling
|
||||
* {@link io.openvidu.java.client.OpenVidu#createSession(SessionProperties)
|
||||
* OpenVidu.createSession} automatically adds the new Session object to the
|
||||
* local collection.</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#fetch()} updates that
|
||||
* specific Session status</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#close()} automatically
|
||||
|
@ -531,7 +542,7 @@ public class OpenVidu {
|
|||
* @throws OpenViduJavaClientException
|
||||
*/
|
||||
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
HttpGet request = new HttpGet(this.hostname + API_SESSIONS);
|
||||
HttpGet request = new HttpGet(this.hostname + API_SESSIONS + "?pendingConnections=true");
|
||||
|
||||
HttpResponse response;
|
||||
try {
|
||||
|
@ -543,44 +554,55 @@ public class OpenVidu {
|
|||
try {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
||||
|
||||
JsonObject jsonSessions = httpResponseToJson(response);
|
||||
JsonArray jsonArraySessions = jsonSessions.get("content").getAsJsonArray();
|
||||
|
||||
// Set to store fetched sessionIds and later remove closed sessions
|
||||
Set<String> fetchedSessionIds = new HashSet<>();
|
||||
// Boolean to store if any Session has changed
|
||||
final boolean[] hasChanged = { false };
|
||||
jsonArraySessions.forEach(session -> {
|
||||
String sessionId = (session.getAsJsonObject()).get("sessionId").getAsString();
|
||||
fetchedSessionIds.add(sessionId);
|
||||
this.activeSessions.computeIfPresent(sessionId, (sId, s) -> {
|
||||
|
||||
// 1. Set to store fetched sessionIds and later remove closed ones
|
||||
Set<String> fetchedSessionIds = new HashSet<>();
|
||||
jsonArraySessions.forEach(sessionJsonElement -> {
|
||||
|
||||
JsonObject sessionJson = sessionJsonElement.getAsJsonObject();
|
||||
final Session sessionObj = new Session(this, sessionJson);
|
||||
String id = sessionObj.getSessionId();
|
||||
fetchedSessionIds.add(id);
|
||||
|
||||
// 2. Update existing Session
|
||||
this.activeSessions.computeIfPresent(id, (sId, s) -> {
|
||||
String beforeJSON = s.toJson();
|
||||
s = s.resetSessionWithJson(session.getAsJsonObject());
|
||||
s = s.resetWithJson(sessionJson);
|
||||
String afterJSON = s.toJson();
|
||||
boolean changed = !beforeJSON.equals(afterJSON);
|
||||
hasChanged[0] = hasChanged[0] || changed;
|
||||
log.info("Available session '{}' info fetched. Any change: {}", sessionId, changed);
|
||||
log.info("Available session '{}' info fetched. Any change: {}", id, changed);
|
||||
return s;
|
||||
});
|
||||
this.activeSessions.computeIfAbsent(sessionId, sId -> {
|
||||
log.info("New session '{}' fetched", sessionId);
|
||||
|
||||
// 3. Add new Session
|
||||
this.activeSessions.computeIfAbsent(id, sId -> {
|
||||
log.info("New session '{}' fetched", id);
|
||||
hasChanged[0] = true;
|
||||
return new Session(this, session.getAsJsonObject());
|
||||
return sessionObj;
|
||||
});
|
||||
});
|
||||
|
||||
// Remove closed sessions from activeSessions map
|
||||
this.activeSessions = this.activeSessions.entrySet().stream().filter(entry -> {
|
||||
// 4. Remove closed sessions from local collection
|
||||
this.activeSessions.entrySet().removeIf(entry -> {
|
||||
if (fetchedSessionIds.contains(entry.getKey())) {
|
||||
return true;
|
||||
return false;
|
||||
} else {
|
||||
log.info("Removing closed session {}", entry.getKey());
|
||||
hasChanged[0] = true;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
|
||||
});
|
||||
|
||||
log.info("Active sessions info fetched: {}", this.activeSessions.keySet());
|
||||
return hasChanged[0];
|
||||
|
||||
} else {
|
||||
throw new OpenViduHttpException(statusCode);
|
||||
}
|
||||
|
|
|
@ -17,16 +17,15 @@
|
|||
|
||||
package io.openvidu.java.client;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* See {@link io.openvidu.java.client.Connection#getPublishers()}.
|
||||
*
|
||||
* <br>
|
||||
* This is a backend representation of a published media stream (see
|
||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target="_blank"> OpenVidu
|
||||
* Browser Stream class</a>).
|
||||
* This is a backend representation of a published media stream (see <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target="_blank"> OpenVidu Browser Stream class</a>).
|
||||
*/
|
||||
public class Publisher {
|
||||
|
||||
|
@ -40,36 +39,18 @@ public class Publisher {
|
|||
private String typeOfVideo;
|
||||
private String videoDimensions;
|
||||
|
||||
protected Publisher(String streamId, long createdAt, boolean hasAudio, boolean hasVideo, JsonElement audioActive,
|
||||
JsonElement videoActive, JsonElement frameRate, JsonElement typeOfVideo, JsonElement videoDimensions) {
|
||||
this.streamId = streamId;
|
||||
this.createdAt = createdAt;
|
||||
this.hasAudio = hasAudio;
|
||||
this.hasVideo = hasVideo;
|
||||
if (audioActive != null && !audioActive.isJsonNull()) {
|
||||
this.audioActive = audioActive.getAsBoolean();
|
||||
}
|
||||
if (videoActive != null && !videoActive.isJsonNull()) {
|
||||
this.videoActive = videoActive.getAsBoolean();
|
||||
}
|
||||
if (frameRate != null && !frameRate.isJsonNull()) {
|
||||
this.frameRate = frameRate.getAsInt();
|
||||
}
|
||||
if (typeOfVideo != null && !typeOfVideo.isJsonNull()) {
|
||||
this.typeOfVideo = typeOfVideo.getAsString();
|
||||
}
|
||||
if (videoDimensions != null && !videoDimensions.isJsonNull()) {
|
||||
this.videoDimensions = videoDimensions.getAsString();
|
||||
}
|
||||
protected Publisher(JsonObject json) {
|
||||
this.resetWithJson(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier of the
|
||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> associated to this Publisher. Each Publisher is paired
|
||||
* with only one Stream, so you can identify each Publisher by its
|
||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html#streamid" target=
|
||||
* "_blank"><code>Stream.streamId</code></a>
|
||||
* Returns the unique identifier of the <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> associated to this Publisher. Each Publisher is
|
||||
* paired with only one Stream, so you can identify each Publisher by its
|
||||
* <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html#streamid"
|
||||
* target= "_blank"><code>Stream.streamId</code></a>
|
||||
*/
|
||||
public String getStreamId() {
|
||||
return streamId;
|
||||
|
@ -84,56 +65,70 @@ public class Publisher {
|
|||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public boolean hasVideo() {
|
||||
return this.hasVideo;
|
||||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public boolean hasAudio() {
|
||||
return this.hasAudio;
|
||||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public Boolean isAudioActive() {
|
||||
return this.audioActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public Boolean isVideoActive() {
|
||||
return this.videoActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public Integer getFrameRate() {
|
||||
return this.frameRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public String getTypeOfVideo() {
|
||||
return this.typeOfVideo;
|
||||
}
|
||||
|
||||
/**
|
||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
||||
* See properties of <a href=
|
||||
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
|
||||
* more
|
||||
*/
|
||||
public String getVideoDimensions() {
|
||||
return this.videoDimensions;
|
||||
|
@ -152,4 +147,32 @@ public class Publisher {
|
|||
return json;
|
||||
}
|
||||
|
||||
protected Publisher resetWithJson(JsonObject json) {
|
||||
this.streamId = json.get("streamId").getAsString();
|
||||
this.createdAt = json.get("createdAt").getAsLong();
|
||||
|
||||
if (json.has("mediaOptions") && !json.get("mediaOptions").isJsonNull()) {
|
||||
JsonObject mediaOptions = json.get("mediaOptions").getAsJsonObject();
|
||||
this.hasAudio = mediaOptions.get("hasAudio").getAsBoolean();
|
||||
this.hasVideo = mediaOptions.get("hasVideo").getAsBoolean();
|
||||
if (mediaOptions.has("audioActive") && !mediaOptions.get("audioActive").isJsonNull()) {
|
||||
this.audioActive = mediaOptions.get("audioActive").getAsBoolean();
|
||||
}
|
||||
if (mediaOptions.has("videoActive") && !mediaOptions.get("videoActive").isJsonNull()) {
|
||||
this.videoActive = mediaOptions.get("videoActive").getAsBoolean();
|
||||
}
|
||||
if (mediaOptions.has("frameRate") && !mediaOptions.get("frameRate").isJsonNull()) {
|
||||
this.frameRate = mediaOptions.get("frameRate").getAsInt();
|
||||
}
|
||||
if (mediaOptions.has("typeOfVideo") && !mediaOptions.get("typeOfVideo").isJsonNull()) {
|
||||
this.typeOfVideo = mediaOptions.get("typeOfVideo").getAsString();
|
||||
}
|
||||
if (mediaOptions.has("videoDimensions") && !mediaOptions.get("videoDimensions").isJsonNull()) {
|
||||
this.videoDimensions = mediaOptions.get("videoDimensions").getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,9 +48,8 @@ public class Recording {
|
|||
stopped,
|
||||
|
||||
/**
|
||||
* The recording has finished OK and is available for download through OpenVidu
|
||||
* Server recordings endpoint:
|
||||
* https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION}
|
||||
* The recording has finished being processed and is available for download
|
||||
* through property {@link Recording#getUrl}
|
||||
*/
|
||||
ready,
|
||||
|
||||
|
@ -75,27 +74,25 @@ public class Recording {
|
|||
* Record each stream individually
|
||||
*/
|
||||
INDIVIDUAL,
|
||||
|
||||
|
||||
/**
|
||||
* Works the same way as COMPOSED mode, but the necessary recorder
|
||||
* service module will start some time in advance and won't be terminated
|
||||
* once a specific session recording has ended. This module will remain
|
||||
* up and running as long as the session remains active.<br><br>
|
||||
* Works the same way as COMPOSED mode, but the necessary recorder service
|
||||
* module will start some time in advance and won't be terminated once a
|
||||
* specific session recording has ended. This module will remain up and running
|
||||
* as long as the session remains active.<br>
|
||||
* <br>
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* <strong>Pros vs COMPOSED</strong>: the process of starting the recording will be noticeably
|
||||
* faster. This can be very useful in use cases where a session needs to be
|
||||
* recorded multiple times over time, when a better response time is usually
|
||||
* desirable.
|
||||
* </li>
|
||||
* <li>
|
||||
* <strong>Cons vs COMPOSED</strong>: for every session initialized with COMPOSED_QUICK_START
|
||||
* recording output mode, extra CPU power will be required in OpenVidu Server.
|
||||
* The recording module will be continuously rendering all of the streams being
|
||||
* published to the session even when the session is not being recorded. And that
|
||||
* is for every session configured with COMPOSED_QUICK_START.
|
||||
* </li>
|
||||
* <li><strong>Pros vs COMPOSED</strong>: the process of starting the recording
|
||||
* will be noticeably faster. This can be very useful in use cases where a
|
||||
* session needs to be recorded multiple times over time, when a better response
|
||||
* time is usually desirable.</li>
|
||||
* <li><strong>Cons vs COMPOSED</strong>: for every session initialized with
|
||||
* COMPOSED_QUICK_START recording output mode, extra CPU power will be required
|
||||
* in OpenVidu Server. The recording module will be continuously rendering all
|
||||
* of the streams being published to the session even when the session is not
|
||||
* being recorded. And that is for every session configured with
|
||||
* COMPOSED_QUICK_START.</li>
|
||||
* </ul>
|
||||
*/
|
||||
COMPOSED_QUICK_START;
|
||||
|
@ -129,7 +126,8 @@ public class Recording {
|
|||
OutputMode outputMode = OutputMode.valueOf(json.get("outputMode").getAsString());
|
||||
RecordingProperties.Builder builder = new RecordingProperties.Builder().name(json.get("name").getAsString())
|
||||
.outputMode(outputMode).hasAudio(hasAudio).hasVideo(hasVideo);
|
||||
if ((OutputMode.COMPOSED.equals(outputMode) || OutputMode.COMPOSED_QUICK_START.equals(outputMode)) && hasVideo) {
|
||||
if ((OutputMode.COMPOSED.equals(outputMode) || OutputMode.COMPOSED_QUICK_START.equals(outputMode))
|
||||
&& hasVideo) {
|
||||
builder.resolution(json.get("resolution").getAsString());
|
||||
builder.recordingLayout(RecordingLayout.valueOf(json.get("recordingLayout").getAsString()));
|
||||
JsonElement customLayout = json.get("customLayout");
|
||||
|
@ -219,8 +217,8 @@ public class Recording {
|
|||
/**
|
||||
* URL of the recording. You can access the file from there. It is
|
||||
* <code>null</code> until recording reaches "ready" or "failed" status. If
|
||||
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/" target=
|
||||
* "_blank">OpenVidu Server configuration</a> property
|
||||
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||
* target= "_blank">OpenVidu Server configuration</a> property
|
||||
* <code>OPENVIDU_RECORDING_PUBLIC_ACCESS</code> is false, this path will be
|
||||
* secured with OpenVidu credentials
|
||||
*/
|
||||
|
@ -230,7 +228,8 @@ public class Recording {
|
|||
|
||||
/**
|
||||
* Resolution of the video file. Only defined if OutputMode of the Recording is
|
||||
* set to {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}
|
||||
* set to {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}
|
||||
*/
|
||||
public String getResolution() {
|
||||
return this.recordingProperties.resolution();
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package io.openvidu.java.client;
|
||||
|
||||
import io.openvidu.java.client.Recording.OutputMode;
|
||||
|
||||
/**
|
||||
* See
|
||||
* {@link io.openvidu.java.client.OpenVidu#startRecording(String, RecordingProperties)}
|
||||
|
@ -33,6 +31,7 @@ public class RecordingProperties {
|
|||
private boolean hasAudio;
|
||||
private boolean hasVideo;
|
||||
private long shmSize; // For COMPOSED recording
|
||||
private String mediaNode;
|
||||
|
||||
/**
|
||||
* Builder for {@link io.openvidu.java.client.RecordingProperties}
|
||||
|
@ -40,27 +39,21 @@ public class RecordingProperties {
|
|||
public static class Builder {
|
||||
|
||||
private String name = "";
|
||||
private Recording.OutputMode outputMode = Recording.OutputMode.COMPOSED;
|
||||
private Recording.OutputMode outputMode;
|
||||
private RecordingLayout recordingLayout;
|
||||
private String customLayout;
|
||||
private String resolution;
|
||||
private boolean hasAudio = true;
|
||||
private boolean hasVideo = true;
|
||||
private long shmSize = 536870912L;
|
||||
private String mediaNode;
|
||||
|
||||
/**
|
||||
* Builder for {@link io.openvidu.java.client.RecordingProperties}
|
||||
*/
|
||||
public RecordingProperties build() {
|
||||
if (OutputMode.COMPOSED.equals(this.outputMode) || OutputMode.COMPOSED_QUICK_START.equals(this.outputMode)) {
|
||||
this.recordingLayout = this.recordingLayout != null ? this.recordingLayout : RecordingLayout.BEST_FIT;
|
||||
this.resolution = this.resolution != null ? this.resolution : "1920x1080";
|
||||
if (RecordingLayout.CUSTOM.equals(this.recordingLayout)) {
|
||||
this.customLayout = this.customLayout != null ? this.customLayout : "";
|
||||
}
|
||||
}
|
||||
return new RecordingProperties(this.name, this.outputMode, this.recordingLayout, this.customLayout,
|
||||
this.resolution, this.hasAudio, this.hasVideo, this.shmSize);
|
||||
this.resolution, this.hasAudio, this.hasVideo, this.shmSize, this.mediaNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,11 +95,14 @@ public class RecordingProperties {
|
|||
* method to set the relative path to the specific custom layout you want to
|
||||
* use.<br>
|
||||
* Will only have effect if
|
||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
||||
* has been called with value
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.<br>
|
||||
* See <a href="https://docs.openvidu.io/en/stable/advanced-features/recording#custom-recording-layouts"
|
||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)
|
||||
* Builder.outputMode()} has been called with value
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED
|
||||
* OutputMode.COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START
|
||||
* OutputMode.COMPOSED_QUICK_START}.<br>
|
||||
* See <a href=
|
||||
* "https://docs.openvidu.io/en/stable/advanced-features/recording#custom-recording-layouts"
|
||||
* target="_blank">Custom recording layouts</a> to learn more
|
||||
*/
|
||||
public RecordingProperties.Builder customLayout(String path) {
|
||||
|
@ -119,13 +115,15 @@ public class RecordingProperties {
|
|||
* format "WIDTHxHEIGHT", being both WIDTH and HEIGHT the number of pixels
|
||||
* between 100 and 1999.<br>
|
||||
* Will only have effect if
|
||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
||||
* has been called with value
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}. For
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
|
||||
* individual video files will have the native resolution of the published
|
||||
* stream
|
||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)
|
||||
* Builder.outputMode()} has been called with value
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED
|
||||
* OutputMode.COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START
|
||||
* OutputMode.COMPOSED_QUICK_START}. For
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL
|
||||
* OutputMode.INDIVIDUAL} all individual video files will have the native
|
||||
* resolution of the published stream
|
||||
*/
|
||||
public RecordingProperties.Builder resolution(String resolution) {
|
||||
this.resolution = resolution;
|
||||
|
@ -134,7 +132,8 @@ public class RecordingProperties {
|
|||
|
||||
/**
|
||||
* Call this method to specify whether to record audio or not. Cannot be set to
|
||||
* false at the same time as {@link hasVideo(boolean)}
|
||||
* false at the same time as
|
||||
* {@link RecordingProperties.Builder#hasVideo(boolean)}
|
||||
*/
|
||||
public RecordingProperties.Builder hasAudio(boolean hasAudio) {
|
||||
this.hasAudio = hasAudio;
|
||||
|
@ -143,7 +142,8 @@ public class RecordingProperties {
|
|||
|
||||
/**
|
||||
* Call this method to specify whether to record video or not. Cannot be set to
|
||||
* false at the same time as {@link hasAudio(boolean)}
|
||||
* false at the same time as
|
||||
* {@link RecordingProperties.Builder#hasAudio(boolean)}
|
||||
*/
|
||||
public RecordingProperties.Builder hasVideo(boolean hasVideo) {
|
||||
this.hasVideo = hasVideo;
|
||||
|
@ -160,10 +160,26 @@ public class RecordingProperties {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a> Call this method to force the recording to be hosted in
|
||||
* the Media Node with identifier <code>mediaNodeId</code>. This property only
|
||||
* applies to COMPOSED recordings and is ignored for INDIVIDUAL recordings, that
|
||||
* are always hosted in the same Media Node hosting its Session
|
||||
*/
|
||||
public RecordingProperties.Builder mediaNode(String mediaNodeId) {
|
||||
this.mediaNode = mediaNodeId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected RecordingProperties(String name, Recording.OutputMode outputMode, RecordingLayout layout,
|
||||
String customLayout, String resolution, boolean hasAudio, boolean hasVideo, long shmSize) {
|
||||
String customLayout, String resolution, boolean hasAudio, boolean hasVideo, long shmSize,
|
||||
String mediaNode) {
|
||||
this.name = name;
|
||||
this.outputMode = outputMode;
|
||||
this.recordingLayout = layout;
|
||||
|
@ -172,6 +188,7 @@ public class RecordingProperties {
|
|||
this.hasAudio = hasAudio;
|
||||
this.hasVideo = hasVideo;
|
||||
this.shmSize = shmSize;
|
||||
this.mediaNode = mediaNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,12 +202,12 @@ public class RecordingProperties {
|
|||
|
||||
/**
|
||||
* Defines the mode of recording: {@link Recording.OutputMode#COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} for a
|
||||
* single archive in a grid layout or {@link Recording.OutputMode#INDIVIDUAL}
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} for
|
||||
* a single archive in a grid layout or {@link Recording.OutputMode#INDIVIDUAL}
|
||||
* for one archive for each stream.<br>
|
||||
* <br>
|
||||
*
|
||||
* Default to {@link Recording.OutputMode#COMPOSED}
|
||||
* Default to {@link Recording.OutputMode#COMPOSED OutputMode.COMPOSED}
|
||||
*/
|
||||
public Recording.OutputMode outputMode() {
|
||||
return this.outputMode;
|
||||
|
@ -199,12 +216,14 @@ public class RecordingProperties {
|
|||
/**
|
||||
* Defines the layout to be used in the recording.<br>
|
||||
* Will only have effect if
|
||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
||||
* has been called with value {@link Recording.OutputMode#COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.<br>
|
||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)
|
||||
* Builder.outputMode()} has been called with value
|
||||
* {@link Recording.OutputMode#COMPOSED OutputMode.COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START
|
||||
* OutputMode.COMPOSED_QUICK_START}.<br>
|
||||
* <br>
|
||||
*
|
||||
* Default to {@link RecordingLayout#BEST_FIT}
|
||||
* Default to {@link RecordingLayout#BEST_FIT RecordingLayout.BEST_FIT}
|
||||
*/
|
||||
public RecordingLayout recordingLayout() {
|
||||
return this.recordingLayout;
|
||||
|
@ -214,7 +233,8 @@ public class RecordingProperties {
|
|||
* If {@link io.openvidu.java.client.RecordingProperties#recordingLayout()} is
|
||||
* set to {@link io.openvidu.java.client.RecordingLayout#CUSTOM}, this property
|
||||
* defines the relative path to the specific custom layout you want to use.<br>
|
||||
* See <a href="https://docs.openvidu.io/en/stable/advanced-features/recording#custom-recording-layouts"
|
||||
* See <a href=
|
||||
* "https://docs.openvidu.io/en/stable/advanced-features/recording#custom-recording-layouts"
|
||||
* target="_blank">Custom recording layouts</a> to learn more
|
||||
*/
|
||||
public String customLayout() {
|
||||
|
@ -227,8 +247,8 @@ public class RecordingProperties {
|
|||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
||||
* has been called with value
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}. For
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.
|
||||
* For {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
|
||||
* individual video files will have the native resolution of the published
|
||||
* stream.<br>
|
||||
* <br>
|
||||
|
@ -241,7 +261,7 @@ public class RecordingProperties {
|
|||
|
||||
/**
|
||||
* Defines whether to record audio or not. Cannot be set to false at the same
|
||||
* time as {@link hasVideo()}.<br>
|
||||
* time as {@link RecordingProperties#hasVideo()}.<br>
|
||||
* <br>
|
||||
*
|
||||
* Default to true
|
||||
|
@ -252,7 +272,7 @@ public class RecordingProperties {
|
|||
|
||||
/**
|
||||
* Defines whether to record video or not. Cannot be set to false at the same
|
||||
* time as {@link hasAudio()}.<br>
|
||||
* time as {@link RecordingProperties#hasAudio()}.<br>
|
||||
* <br>
|
||||
*
|
||||
* Default to true
|
||||
|
@ -273,4 +293,18 @@ public class RecordingProperties {
|
|||
return this.shmSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a> The Media Node where to host the recording. The default
|
||||
* option if this property is not defined is the same Media Node hosting the
|
||||
* Session to record. This property only applies to COMPOSED recordings and is
|
||||
* ignored for INDIVIDUAL recordings
|
||||
*/
|
||||
public String mediaNode() {
|
||||
return this.mediaNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,9 +19,10 @@ package io.openvidu.java.client;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -34,6 +35,7 @@ import org.apache.http.HttpHeaders;
|
|||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPatch;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
@ -48,7 +50,7 @@ public class Session {
|
|||
private long createdAt;
|
||||
private OpenVidu openVidu;
|
||||
private SessionProperties properties;
|
||||
private Map<String, Connection> activeConnections = new ConcurrentHashMap<>();
|
||||
private Map<String, Connection> connections = new ConcurrentHashMap<>();
|
||||
private boolean recording = false;
|
||||
|
||||
protected Session(OpenVidu openVidu) throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
|
@ -66,11 +68,11 @@ public class Session {
|
|||
|
||||
protected Session(OpenVidu openVidu, JsonObject json) {
|
||||
this.openVidu = openVidu;
|
||||
this.resetSessionWithJson(json);
|
||||
this.resetWithJson(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique identifier of the Session
|
||||
* Gets the unique identifier of the Session.
|
||||
*
|
||||
* @return The sessionId
|
||||
*/
|
||||
|
@ -80,78 +82,49 @@ public class Session {
|
|||
|
||||
/**
|
||||
* Timestamp when this session was created, in UTC milliseconds (ms since Jan 1,
|
||||
* 1970, 00:00:00 UTC)
|
||||
* 1970, 00:00:00 UTC).
|
||||
*/
|
||||
public long createdAt() {
|
||||
return this.createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new token associated to Session object with default values for
|
||||
* {@link io.openvidu.java.client.TokenOptions}. This always translates into a
|
||||
* new request to OpenVidu Server
|
||||
* @deprecated Use {@link Session#createConnection() Session.createConnection()}
|
||||
* instead to get a {@link io.openvidu.java.client.Connection}
|
||||
* object.
|
||||
*
|
||||
* @return The generated token String
|
||||
*
|
||||
* @return The generated token
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
@Deprecated
|
||||
public String generateToken() throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
return this.generateToken(new TokenOptions.Builder().role(OpenViduRole.PUBLISHER).build());
|
||||
return generateToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new token associated to Session object configured with
|
||||
* <code>tokenOptions</code>. This always translates into a new request to
|
||||
* OpenVidu Server
|
||||
* @deprecated Use
|
||||
* {@link Session#createConnection(io.openvidu.java.client.ConnectionProperties)
|
||||
* Session.createConnection(ConnectionProperties)} instead to get a
|
||||
* {@link io.openvidu.java.client.Connection} object.
|
||||
*
|
||||
* @return The generated token String
|
||||
*
|
||||
* @return The generated token
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
@Deprecated
|
||||
public String generateToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
|
||||
if (!this.hasSessionId()) {
|
||||
this.getSessionId();
|
||||
}
|
||||
|
||||
HttpPost request = new HttpPost(this.openVidu.hostname + OpenVidu.API_TOKENS);
|
||||
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("session", this.sessionId);
|
||||
json.addProperty("role", tokenOptions.getRole().name());
|
||||
json.addProperty("data", tokenOptions.getData());
|
||||
if (tokenOptions.getKurentoOptions() != null) {
|
||||
JsonObject kurentoOptions = new JsonObject();
|
||||
if (tokenOptions.getKurentoOptions().getVideoMaxRecvBandwidth() != null) {
|
||||
kurentoOptions.addProperty("videoMaxRecvBandwidth",
|
||||
tokenOptions.getKurentoOptions().getVideoMaxRecvBandwidth());
|
||||
}
|
||||
if (tokenOptions.getKurentoOptions().getVideoMinRecvBandwidth() != null) {
|
||||
kurentoOptions.addProperty("videoMinRecvBandwidth",
|
||||
tokenOptions.getKurentoOptions().getVideoMinRecvBandwidth());
|
||||
}
|
||||
if (tokenOptions.getKurentoOptions().getVideoMaxSendBandwidth() != null) {
|
||||
kurentoOptions.addProperty("videoMaxSendBandwidth",
|
||||
tokenOptions.getKurentoOptions().getVideoMaxSendBandwidth());
|
||||
}
|
||||
if (tokenOptions.getKurentoOptions().getVideoMinSendBandwidth() != null) {
|
||||
kurentoOptions.addProperty("videoMinSendBandwidth",
|
||||
tokenOptions.getKurentoOptions().getVideoMinSendBandwidth());
|
||||
}
|
||||
if (tokenOptions.getKurentoOptions().getAllowedFilters().length > 0) {
|
||||
JsonArray allowedFilters = new JsonArray();
|
||||
for (String filter : tokenOptions.getKurentoOptions().getAllowedFilters()) {
|
||||
allowedFilters.add(filter);
|
||||
}
|
||||
kurentoOptions.add("allowedFilters", allowedFilters);
|
||||
}
|
||||
json.add("kurentoOptions", kurentoOptions);
|
||||
}
|
||||
StringEntity params;
|
||||
try {
|
||||
params = new StringEntity(json.toString());
|
||||
params = new StringEntity(tokenOptions.toJsonObject(sessionId).toString());
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
||||
}
|
||||
|
@ -180,10 +153,79 @@ public class Session {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as
|
||||
* {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)}
|
||||
* but with default ConnectionProperties values.
|
||||
*
|
||||
* @return The generated {@link io.openvidu.java.client.Connection Connection}
|
||||
* object.
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
public Connection createConnection() throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
return createConnection(
|
||||
new ConnectionProperties.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Connection object associated to Session object and configured
|
||||
* with <code>connectionProperties</code>. Each user connecting to the Session
|
||||
* requires a Connection. The token string value to send to the client side can
|
||||
* be retrieved with {@link io.openvidu.java.client.Connection#getToken()
|
||||
* Connection.getToken()}.
|
||||
*
|
||||
* @return The generated {@link io.openvidu.java.client.Connection Connection}
|
||||
* object.
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
public Connection createConnection(ConnectionProperties connectionProperties)
|
||||
throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
if (!this.hasSessionId()) {
|
||||
this.getSessionId();
|
||||
}
|
||||
|
||||
HttpPost request = new HttpPost(
|
||||
this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection");
|
||||
|
||||
StringEntity params;
|
||||
try {
|
||||
params = new StringEntity(connectionProperties.toJson(sessionId).toString());
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
||||
}
|
||||
|
||||
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
|
||||
request.setEntity(params);
|
||||
|
||||
HttpResponse response;
|
||||
try {
|
||||
response = this.openVidu.httpClient.execute(request);
|
||||
} catch (IOException e2) {
|
||||
throw new OpenViduJavaClientException(e2.getMessage(), e2.getCause());
|
||||
}
|
||||
|
||||
try {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
||||
Connection connection = new Connection(httpResponseToJson(response));
|
||||
this.connections.put(connection.getConnectionId(), connection);
|
||||
return connection;
|
||||
} else {
|
||||
throw new OpenViduHttpException(statusCode);
|
||||
}
|
||||
} finally {
|
||||
EntityUtils.consumeQuietly(response.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gracefully closes the Session: unpublishes all streams and evicts every
|
||||
* participant
|
||||
*
|
||||
* participant.
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
|
@ -217,22 +259,25 @@ public class Session {
|
|||
* connections to the Session
|
||||
* ({@link io.openvidu.java.client.Session#getActiveConnections()}) and use
|
||||
* those values to call
|
||||
* {@link io.openvidu.java.client.Session#forceDisconnect(Connection)} or
|
||||
* {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)}. <br>
|
||||
*
|
||||
* To update every Session object owned by OpenVidu object, call
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch()}
|
||||
*
|
||||
* {@link io.openvidu.java.client.Session#forceDisconnect(Connection)},
|
||||
* {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} or
|
||||
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}.<br>
|
||||
* <br>
|
||||
*
|
||||
* To update all Session objects owned by OpenVidu object at once, call
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch()}.
|
||||
*
|
||||
* @return true if the Session status has changed with respect to the server,
|
||||
* false if not. This applies to any property or sub-property of the
|
||||
* object
|
||||
*
|
||||
* object.
|
||||
*
|
||||
* @throws OpenViduHttpException
|
||||
* @throws OpenViduJavaClientException
|
||||
*/
|
||||
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
String beforeJSON = this.toJson();
|
||||
HttpGet request = new HttpGet(this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId);
|
||||
final String beforeJSON = this.toJson();
|
||||
HttpGet request = new HttpGet(
|
||||
this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "?pendingConnections=true");
|
||||
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponse response;
|
||||
|
@ -245,8 +290,8 @@ public class Session {
|
|||
try {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
||||
this.resetSessionWithJson(httpResponseToJson(response));
|
||||
String afterJSON = this.toJson();
|
||||
this.resetWithJson(httpResponseToJson(response));
|
||||
final String afterJSON = this.toJson();
|
||||
boolean hasChanged = !beforeJSON.equals(afterJSON);
|
||||
log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged);
|
||||
return hasChanged;
|
||||
|
@ -259,16 +304,31 @@ public class Session {
|
|||
}
|
||||
|
||||
/**
|
||||
* Forces the user represented by <code>connection</code> to leave the session.
|
||||
* OpenVidu Browser will trigger the proper events on the client-side
|
||||
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
|
||||
* Removes the Connection from the Session. This can translate into a forced
|
||||
* eviction of a user from the Session if the Connection had status
|
||||
* <code>active</code>, or into a token invalidation if no user had taken the
|
||||
* Connection yet (status <code>pending</code>). <br>
|
||||
* <br>
|
||||
*
|
||||
* In the first case, OpenVidu Browser will trigger the proper events on the
|
||||
* client-side (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
|
||||
* <code>sessionDisconnected</code>) with reason set to
|
||||
* "forceDisconnectByServer" <br>
|
||||
*
|
||||
* You can get <code>connection</code> parameter with
|
||||
* {@link io.openvidu.java.client.Session#fetch()} and then
|
||||
* {@link io.openvidu.java.client.Session#getActiveConnections()}
|
||||
*
|
||||
* <code>"forceDisconnectByServer"</code>. <br>
|
||||
* <br>
|
||||
*
|
||||
* In the second case, the token of the Connection will be invalidated and no
|
||||
* user will be able to connect to the session with it. <br>
|
||||
* <br>
|
||||
*
|
||||
* This method automatically updates the properties of the local affected
|
||||
* objects. This means that there is no need to call
|
||||
* {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the
|
||||
* changes consequence of the execution of this method applied in the local
|
||||
* objects.
|
||||
*
|
||||
* @param connection The Connection to remove
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
|
@ -277,17 +337,13 @@ public class Session {
|
|||
}
|
||||
|
||||
/**
|
||||
* Forces the user with Connection <code>connectionId</code> to leave the
|
||||
* session. OpenVidu Browser will trigger the proper events on the client-side
|
||||
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
|
||||
* <code>sessionDisconnected</code>) with reason set to
|
||||
* "forceDisconnectByServer" <br>
|
||||
*
|
||||
* You can get <code>connectionId</code> parameter with
|
||||
* {@link io.openvidu.java.client.Session#fetch()} (use
|
||||
* {@link io.openvidu.java.client.Connection#getConnectionId()} to get the
|
||||
* `connectionId` you want)
|
||||
*
|
||||
* Same as {@link io.openvidu.java.client.Session#forceDisconnect(Connection)
|
||||
* forceDisconnect(ConnectionProperties)} but providing the
|
||||
* {@link io.openvidu.java.client.Connection#getConnectionId() connectionId}
|
||||
* instead of the Connection object.
|
||||
*
|
||||
* @param connectionId The identifier of the Connection object to remove
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
|
@ -307,13 +363,13 @@ public class Session {
|
|||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
|
||||
// Remove connection from activeConnections map
|
||||
Connection connectionClosed = this.activeConnections.remove(connectionId);
|
||||
Connection connectionClosed = this.connections.remove(connectionId);
|
||||
// Remove every Publisher of the closed connection from every subscriber list of
|
||||
// other connections
|
||||
if (connectionClosed != null) {
|
||||
for (Publisher publisher : connectionClosed.getPublishers()) {
|
||||
String streamId = publisher.getStreamId();
|
||||
for (Connection connection : this.activeConnections.values()) {
|
||||
for (Connection connection : this.connections.values()) {
|
||||
connection.setSubscribers(connection.getSubscribers().stream()
|
||||
.filter(subscriber -> !streamId.equals(subscriber)).collect(Collectors.toList()));
|
||||
}
|
||||
|
@ -334,17 +390,28 @@ public class Session {
|
|||
}
|
||||
|
||||
/**
|
||||
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
|
||||
* proper events on the client-side (<code>streamDestroyed</code>) with reason
|
||||
* set to "forceUnpublishByServer".<br>
|
||||
*
|
||||
* Forces some Connection to unpublish a Stream. OpenVidu Browser will trigger
|
||||
* the proper events in the client-side (<code>streamDestroyed</code>) with
|
||||
* reason set to <code>"forceUnpublishByServer"</code>. <br>
|
||||
* <br>
|
||||
*
|
||||
* You can get <code>publisher</code> parameter with
|
||||
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
|
||||
* each Connection you can call
|
||||
* {@link io.openvidu.java.client.Connection#getPublishers()}. Remember to call
|
||||
* {@link io.openvidu.java.client.Session#fetch()} before to fetch the current
|
||||
* actual properties of the Session from OpenVidu Server
|
||||
*
|
||||
* actual properties of the Session from OpenVidu Server.<br>
|
||||
* <br>
|
||||
*
|
||||
* This method automatically updates the properties of the local affected
|
||||
* objects. This means that there is no need to call
|
||||
* {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the
|
||||
* changes consequence of the execution of this method applied in the local
|
||||
* objects.
|
||||
*
|
||||
* @param publisher The Publisher object to unpublish
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
|
@ -353,19 +420,13 @@ public class Session {
|
|||
}
|
||||
|
||||
/**
|
||||
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
|
||||
* proper events on the client-side (<code>streamDestroyed</code>) with reason
|
||||
* set to "forceUnpublishByServer". <br>
|
||||
*
|
||||
* You can get <code>streamId</code> parameter with
|
||||
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
|
||||
* each Connection you can call
|
||||
* {@link io.openvidu.java.client.Connection#getPublishers()}. Finally
|
||||
* {@link io.openvidu.java.client.Publisher#getStreamId()}) will give you the
|
||||
* <code>streamId</code>. Remember to call
|
||||
* {@link io.openvidu.java.client.Session#fetch()} before to fetch the current
|
||||
* actual properties of the Session from OpenVidu Server
|
||||
*
|
||||
* Same as {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)
|
||||
* forceUnpublish(Publisher)} but providing the
|
||||
* {@link io.openvidu.java.client.Publisher#getStreamId() streamId} instead of
|
||||
* the Publisher object.
|
||||
*
|
||||
* @param streamId The identifier of the Publisher object to remove
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
|
@ -384,7 +445,7 @@ public class Session {
|
|||
try {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
|
||||
for (Connection connection : this.activeConnections.values()) {
|
||||
for (Connection connection : this.connections.values()) {
|
||||
// Try to remove the Publisher from the Connection publishers collection
|
||||
if (connection.publishers.remove(streamId) != null) {
|
||||
continue;
|
||||
|
@ -402,44 +463,194 @@ public class Session {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the list of active connections to the session. <strong>This value
|
||||
* will remain unchanged since the last time method
|
||||
* {@link io.openvidu.java.client.Session#fetch()} was called</strong>.
|
||||
* Exceptions to this rule are:
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a> Updates the properties of a Connection with a
|
||||
* {@link io.openvidu.java.client.ConnectionProperties} object. Only these
|
||||
* properties can be updated:
|
||||
* <ul>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
|
||||
* updates each affected Connection status</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
|
||||
* updates each affected Connection status</li>
|
||||
* <li>{@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole)
|
||||
* ConnectionProperties.Builder.role(OpenViduRole)}</li>
|
||||
* <li>{@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean)
|
||||
* ConnectionProperties.Builder.record(boolean)}</li>
|
||||
* </ul>
|
||||
* <br>
|
||||
* To get the list of active connections with their current actual value, you
|
||||
* must call first {@link io.openvidu.java.client.Session#fetch()} and then
|
||||
* {@link io.openvidu.java.client.Session#getActiveConnections()}
|
||||
*
|
||||
* This method automatically updates the properties of the local affected
|
||||
* objects. This means that there is no need to call
|
||||
* {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the
|
||||
* changes consequence of the execution of this method applied in the local
|
||||
* objects.<br>
|
||||
* <br>
|
||||
*
|
||||
* The affected client will trigger one <a href=
|
||||
* "/en/stable/api/openvidu-browser/classes/connectionpropertychangedevent.html"
|
||||
* target="_blank">ConnectionPropertyChangedEvent</a> for each modified
|
||||
* property.
|
||||
*
|
||||
* @param connectionId The Connection to modify
|
||||
* @param connectionProperties A ConnectionProperties object with the new values
|
||||
* to apply
|
||||
*
|
||||
* @return The updated {@link io.openvidu.java.client.Connection Connection}
|
||||
* object
|
||||
*
|
||||
* @throws OpenViduJavaClientException
|
||||
* @throws OpenViduHttpException
|
||||
*/
|
||||
public List<Connection> getActiveConnections() {
|
||||
return new ArrayList<>(this.activeConnections.values());
|
||||
public Connection updateConnection(String connectionId, ConnectionProperties connectionProperties)
|
||||
throws OpenViduJavaClientException, OpenViduHttpException {
|
||||
|
||||
HttpPatch request = new HttpPatch(
|
||||
this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId);
|
||||
|
||||
StringEntity params;
|
||||
try {
|
||||
params = new StringEntity(connectionProperties.toJson(this.sessionId).toString());
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
||||
}
|
||||
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
|
||||
request.setEntity(params);
|
||||
|
||||
HttpResponse response;
|
||||
try {
|
||||
response = this.openVidu.httpClient.execute(request);
|
||||
} catch (IOException e) {
|
||||
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
|
||||
}
|
||||
|
||||
try {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
||||
log.info("Connection {} updated", connectionId);
|
||||
} else if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
|
||||
log.info("Properties of Connection {} remain the same", connectionId);
|
||||
} else {
|
||||
throw new OpenViduHttpException(statusCode);
|
||||
}
|
||||
JsonObject json = httpResponseToJson(response);
|
||||
|
||||
// Update the actual Connection object with the new options
|
||||
Connection existingConnection = this.connections.get(connectionId);
|
||||
|
||||
if (existingConnection == null) {
|
||||
// The updated Connection is not available in local map
|
||||
Connection newConnection = new Connection(json);
|
||||
this.connections.put(connectionId, newConnection);
|
||||
return newConnection;
|
||||
} else {
|
||||
// The updated Connection was available in local map
|
||||
existingConnection.overrideConnectionProperties(connectionProperties);
|
||||
return existingConnection;
|
||||
}
|
||||
|
||||
} finally {
|
||||
EntityUtils.consumeQuietly(response.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the session is being recorded or not
|
||||
* Returns a Connection of the Session. This method only returns the local
|
||||
* available object and does not query OpenVidu Server. To get the current
|
||||
* actual value you must call first
|
||||
* {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}.
|
||||
*
|
||||
* @param id The Connection to get
|
||||
*
|
||||
* @return The {@link io.openvidu.java.client.Connection Connection} object, or
|
||||
* <code>null</code> if no Connection is found for param <code>id</code>
|
||||
*/
|
||||
public Connection getConnection(String id) {
|
||||
return this.connections.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the Connections of the Session. This method only returns the
|
||||
* local available objects and does not query OpenVidu Server. To get the
|
||||
* current actual value you must call first
|
||||
* {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}.
|
||||
*
|
||||
* <strong>The list of Connections will remain unchanged since the last time
|
||||
* method {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was
|
||||
* called</strong>. Exceptions to this rule are:
|
||||
* <ul>
|
||||
* <li>Calling
|
||||
* {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)
|
||||
* createConnection(ConnectionProperties)} automatically adds the new Connection
|
||||
* object to the local collection.</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
|
||||
* automatically updates each affected local Connection object.</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
|
||||
* automatically updates each affected local Connection object.</li>
|
||||
* <li>Calling
|
||||
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}
|
||||
* automatically updates the attributes of the affected local Connection
|
||||
* object.</li>
|
||||
* </ul>
|
||||
* <br>
|
||||
* To get the list of connections with their current actual value, you must call
|
||||
* first {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or
|
||||
* {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}.
|
||||
*/
|
||||
public List<Connection> getConnections() {
|
||||
return this.connections.values().stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of active Connections of the Session. These are the
|
||||
* Connections returning <code>active</code> in response to
|
||||
* {@link io.openvidu.java.client.Connection#getStatus()}. This method only
|
||||
* returns the local available objects and does not query OpenVidu Server.
|
||||
* <strong>The list of active Connections will remain unchanged since the last
|
||||
* time method {@link io.openvidu.java.client.Session#fetch() Session.fetch()}
|
||||
* or {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was
|
||||
* called</strong>. Exceptions to this rule are:
|
||||
* <ul>
|
||||
* <li>Calling
|
||||
* {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)
|
||||
* createConnection(ConnectionProperties)} automatically adds the new Connection
|
||||
* object to the local collection.</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
|
||||
* automatically updates each affected local Connection object.</li>
|
||||
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
|
||||
* automatically updates each affected local Connection object.</li>
|
||||
* <li>Calling
|
||||
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}
|
||||
* automatically updates the attributes of the affected local Connection
|
||||
* object.</li>
|
||||
* </ul>
|
||||
* <br>
|
||||
* To get the list of active connections with their current actual value, you
|
||||
* must call first {@link io.openvidu.java.client.Session#fetch()
|
||||
* Session.fetch()} or {@link io.openvidu.java.client.OpenVidu#fetch()
|
||||
* OpenVidu.fetch()} OpenVidu.fetch()}.
|
||||
*/
|
||||
public List<Connection> getActiveConnections() {
|
||||
return this.connections.values().stream().filter(con -> "active".equals(con.getStatus()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the session is being recorded or not.
|
||||
*/
|
||||
public boolean isBeingRecorded() {
|
||||
return this.recording;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the properties defining the session
|
||||
* Returns the properties defining the session.
|
||||
*/
|
||||
public SessionProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
private boolean hasSessionId() {
|
||||
return (this.sessionId != null && !this.sessionId.isEmpty());
|
||||
}
|
||||
|
@ -450,27 +661,9 @@ public class Session {
|
|||
}
|
||||
|
||||
HttpPost request = new HttpPost(this.openVidu.hostname + OpenVidu.API_SESSIONS);
|
||||
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("mediaMode", properties.mediaMode().name());
|
||||
json.addProperty("recordingMode", properties.recordingMode().name());
|
||||
json.addProperty("defaultOutputMode", properties.defaultOutputMode().name());
|
||||
json.addProperty("defaultRecordingLayout", properties.defaultRecordingLayout().name());
|
||||
json.addProperty("defaultCustomLayout", properties.defaultCustomLayout());
|
||||
json.addProperty("customSessionId", properties.customSessionId());
|
||||
|
||||
// forcedVideoCodec codec and allowTranscoding could be null because
|
||||
// both default values are loaded by openvidu server
|
||||
if (properties.forcedVideoCodec() != null) {
|
||||
json.addProperty("forcedVideoCodec", properties.forcedVideoCodec().name());
|
||||
}
|
||||
if (properties.isTranscodingAllowed() != null) {
|
||||
json.addProperty("allowTranscoding", properties.isTranscodingAllowed());
|
||||
}
|
||||
|
||||
StringEntity params = null;
|
||||
try {
|
||||
params = new StringEntity(json.toString());
|
||||
params = new StringEntity(properties.toJson().toString());
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
||||
}
|
||||
|
@ -490,19 +683,24 @@ public class Session {
|
|||
JsonObject responseJson = httpResponseToJson(response);
|
||||
this.sessionId = responseJson.get("id").getAsString();
|
||||
this.createdAt = responseJson.get("createdAt").getAsLong();
|
||||
|
||||
// forcedVideoCodec and allowTranscoding values are configured in OpenVidu Server
|
||||
// via configuration or session
|
||||
VideoCodec forcedVideoCodec = VideoCodec.valueOf(responseJson.get("forcedVideoCodec").getAsString());
|
||||
Boolean allowTranscoding = responseJson.get("allowTranscoding").getAsBoolean();
|
||||
|
||||
|
||||
SessionProperties responseProperties = new SessionProperties.Builder()
|
||||
.mediaMode(properties.mediaMode())
|
||||
.recordingMode(properties.recordingMode())
|
||||
.defaultOutputMode(properties.defaultOutputMode())
|
||||
.defaultRecordingLayout(properties.defaultRecordingLayout())
|
||||
.defaultCustomLayout(properties.defaultCustomLayout())
|
||||
.forcedVideoCodec(forcedVideoCodec)
|
||||
.allowTranscoding(allowTranscoding)
|
||||
.build();
|
||||
|
||||
.customSessionId(properties.customSessionId())
|
||||
.mediaMode(properties.mediaMode())
|
||||
.recordingMode(properties.recordingMode())
|
||||
.defaultOutputMode(properties.defaultOutputMode())
|
||||
.defaultRecordingLayout(properties.defaultRecordingLayout())
|
||||
.defaultCustomLayout(properties.defaultCustomLayout())
|
||||
.mediaNode(properties.mediaNode())
|
||||
.forcedVideoCodec(forcedVideoCodec)
|
||||
.allowTranscoding(allowTranscoding)
|
||||
.build();
|
||||
|
||||
this.properties = responseProperties;
|
||||
log.info("Session '{}' created", this.sessionId);
|
||||
} else if (statusCode == org.apache.http.HttpStatus.SC_CONFLICT) {
|
||||
|
@ -530,7 +728,7 @@ public class Session {
|
|||
this.recording = recording;
|
||||
}
|
||||
|
||||
protected Session resetSessionWithJson(JsonObject json) {
|
||||
protected Session resetWithJson(JsonObject json) {
|
||||
this.sessionId = json.get("sessionId").getAsString();
|
||||
this.createdAt = json.get("createdAt").getAsLong();
|
||||
this.recording = json.get("recording").getAsBoolean();
|
||||
|
@ -544,50 +742,44 @@ public class Session {
|
|||
if (json.has("defaultCustomLayout")) {
|
||||
builder.defaultCustomLayout(json.get("defaultCustomLayout").getAsString());
|
||||
}
|
||||
if (json.has("customSessionId")) {
|
||||
builder.customSessionId(json.get("customSessionId").getAsString());
|
||||
}
|
||||
|
||||
if (json.has("forcedVideoCodec")) {
|
||||
builder.forcedVideoCodec(VideoCodec.valueOf(json.get("forcedVideoCodec").getAsString()));
|
||||
}
|
||||
if (json.has("allowTranscoding")) {
|
||||
builder.allowTranscoding(json.get("allowTranscoding").getAsBoolean());
|
||||
}
|
||||
if (this.properties != null && this.properties.customSessionId() != null) {
|
||||
builder.customSessionId(this.properties.customSessionId());
|
||||
} else if (json.has("customSessionId")) {
|
||||
builder.customSessionId(json.get("customSessionId").getAsString());
|
||||
}
|
||||
|
||||
this.properties = builder.build();
|
||||
JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray();
|
||||
this.activeConnections.clear();
|
||||
jsonArrayConnections.forEach(connection -> {
|
||||
JsonObject con = connection.getAsJsonObject();
|
||||
|
||||
Map<String, Publisher> publishers = new ConcurrentHashMap<>();
|
||||
JsonArray jsonArrayPublishers = con.get("publishers").getAsJsonArray();
|
||||
jsonArrayPublishers.forEach(publisher -> {
|
||||
JsonObject pubJson = publisher.getAsJsonObject();
|
||||
JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject();
|
||||
Publisher pub = new Publisher(pubJson.get("streamId").getAsString(),
|
||||
pubJson.get("createdAt").getAsLong(), mediaOptions.get("hasAudio").getAsBoolean(),
|
||||
mediaOptions.get("hasVideo").getAsBoolean(), mediaOptions.get("audioActive"),
|
||||
mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"),
|
||||
mediaOptions.get("videoDimensions"));
|
||||
publishers.put(pub.getStreamId(), pub);
|
||||
// 1. Set to store fetched connections and later remove closed ones
|
||||
Set<String> fetchedConnectionIds = new HashSet<>();
|
||||
jsonArrayConnections.forEach(connectionJsonElement -> {
|
||||
|
||||
JsonObject connectionJson = connectionJsonElement.getAsJsonObject();
|
||||
Connection connectionObj = new Connection(connectionJson);
|
||||
String id = connectionObj.getConnectionId();
|
||||
fetchedConnectionIds.add(id);
|
||||
|
||||
// 2. Update existing Connection
|
||||
this.connections.computeIfPresent(id, (cId, c) -> {
|
||||
c = c.resetWithJson(connectionJson);
|
||||
return c;
|
||||
});
|
||||
|
||||
List<String> subscribers = new ArrayList<>();
|
||||
JsonArray jsonArraySubscribers = con.get("subscribers").getAsJsonArray();
|
||||
jsonArraySubscribers.forEach(subscriber -> {
|
||||
subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString());
|
||||
// 3. Add new Connection
|
||||
this.connections.computeIfAbsent(id, cId -> {
|
||||
return connectionObj;
|
||||
});
|
||||
|
||||
Connection c = new Connection(con.get("connectionId").getAsString(), con.get("createdAt").getAsLong(),
|
||||
OpenViduRole.valueOf(con.get("role").getAsString()),
|
||||
(con.has("token") ? con.get("token").getAsString() : null), con.get("location").getAsString(),
|
||||
con.get("platform").getAsString(), con.get("serverData").getAsString(),
|
||||
con.get("clientData").getAsString(), publishers, subscribers);
|
||||
|
||||
this.activeConnections.put(con.get("connectionId").getAsString(), c);
|
||||
});
|
||||
|
||||
// 4. Remove closed connections from local collection
|
||||
this.connections.entrySet()
|
||||
.removeIf(entry -> !fetchedConnectionIds.contains(entry.getValue().getConnectionId()));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -609,26 +801,10 @@ public class Session {
|
|||
json.addProperty("allowTranscoding", this.properties.isTranscodingAllowed());
|
||||
}
|
||||
JsonObject connections = new JsonObject();
|
||||
connections.addProperty("numberOfElements", this.getActiveConnections().size());
|
||||
connections.addProperty("numberOfElements", this.getConnections().size());
|
||||
JsonArray jsonArrayConnections = new JsonArray();
|
||||
this.getActiveConnections().forEach(con -> {
|
||||
JsonObject c = new JsonObject();
|
||||
c.addProperty("connectionId", con.getConnectionId());
|
||||
c.addProperty("role", con.getRole().name());
|
||||
c.addProperty("token", con.getToken());
|
||||
c.addProperty("clientData", con.getClientData());
|
||||
c.addProperty("serverData", con.getServerData());
|
||||
JsonArray pubs = new JsonArray();
|
||||
con.getPublishers().forEach(p -> {
|
||||
pubs.add(p.toJson());
|
||||
});
|
||||
JsonArray subs = new JsonArray();
|
||||
con.getSubscribers().forEach(s -> {
|
||||
subs.add(s);
|
||||
});
|
||||
c.add("publishers", pubs);
|
||||
c.add("subscribers", subs);
|
||||
jsonArrayConnections.add(c);
|
||||
this.getConnections().forEach(con -> {
|
||||
jsonArrayConnections.add(con.toJson());
|
||||
});
|
||||
connections.add("content", jsonArrayConnections);
|
||||
json.add("connections", connections);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package io.openvidu.java.client;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import io.openvidu.java.client.Recording.OutputMode;
|
||||
|
||||
/**
|
||||
|
@ -30,6 +32,7 @@ public class SessionProperties {
|
|||
private RecordingLayout defaultRecordingLayout;
|
||||
private String defaultCustomLayout;
|
||||
private String customSessionId;
|
||||
private String mediaNode;
|
||||
private VideoCodec forcedVideoCodec;
|
||||
private Boolean allowTranscoding;
|
||||
|
||||
|
@ -44,6 +47,7 @@ public class SessionProperties {
|
|||
private RecordingLayout defaultRecordingLayout = RecordingLayout.BEST_FIT;
|
||||
private String defaultCustomLayout = "";
|
||||
private String customSessionId = "";
|
||||
private String mediaNode;
|
||||
private VideoCodec forcedVideoCodec;
|
||||
private Boolean allowTranscoding;
|
||||
|
||||
|
@ -53,7 +57,7 @@ public class SessionProperties {
|
|||
*/
|
||||
public SessionProperties build() {
|
||||
return new SessionProperties(this.mediaMode, this.recordingMode, this.defaultOutputMode,
|
||||
this.defaultRecordingLayout, this.defaultCustomLayout, this.customSessionId,
|
||||
this.defaultRecordingLayout, this.defaultCustomLayout, this.customSessionId, this.mediaNode,
|
||||
this.forcedVideoCodec, this.allowTranscoding);
|
||||
}
|
||||
|
||||
|
@ -62,7 +66,7 @@ public class SessionProperties {
|
|||
* your clients: routed through OpenVidu Media Node
|
||||
* (<code>MediaMode.ROUTED</code>) or attempting direct p2p connections
|
||||
* (<code>MediaMode.RELAYED</code>, <i>not available yet</i>)
|
||||
*
|
||||
*
|
||||
* Default value is <code>MediaMode.ROUTED</code>
|
||||
*/
|
||||
public SessionProperties.Builder mediaMode(MediaMode mediaMode) {
|
||||
|
@ -120,11 +124,11 @@ public class SessionProperties {
|
|||
* {@link io.openvidu.java.client.RecordingProperties.Builder#customLayout(String)}
|
||||
* with any other value.<br>
|
||||
* <br>
|
||||
*
|
||||
*
|
||||
* Custom layouts are only applicable to recordings with OutputMode
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} (or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) and
|
||||
* RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} (or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START})
|
||||
* and RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
||||
*/
|
||||
public SessionProperties.Builder defaultCustomLayout(String path) {
|
||||
this.defaultCustomLayout = path;
|
||||
|
@ -142,20 +146,55 @@ public class SessionProperties {
|
|||
this.customSessionId = customSessionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this method to define which video codec do you want to be forcibly used for this session.
|
||||
* This allows browsers/clients to use the same codec avoiding transcoding in the media server.
|
||||
* If the browser/client is not compatible with the specified codec and {@link #allowTranscoding(Boolean)}
|
||||
* If the browser/client is not compatible with the specified codec and {@link #allowTranscoding(Boolean)}
|
||||
* is <code>false</code> and exception will occur.
|
||||
*
|
||||
* If forcedVideoCodec is set to NONE, no codec will be forced.
|
||||
*
|
||||
* If forcedVideoCodec is set to NONE, no codec will be forced.
|
||||
*/
|
||||
public SessionProperties.Builder forcedVideoCodec(VideoCodec forcedVideoCodec) {
|
||||
this.forcedVideoCodec = forcedVideoCodec;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this method to define if you want to allow transcoding in the media server or not
|
||||
* when {@link #forcedVideoCodec(VideoCodec)} is not compatible with the browser/client.
|
||||
*/
|
||||
public SessionProperties.Builder allowTranscoding(Boolean allowTranscoding) {
|
||||
this.allowTranscoding = allowTranscoding;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a> Call this method to force the session to be hosted in the
|
||||
* Media Node with identifier <code>mediaNodeId</code>
|
||||
*/
|
||||
public SessionProperties.Builder mediaNode(String mediaNodeId) {
|
||||
this.mediaNode = mediaNodeId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to define which video codec do you want to be forcibly used for this session.
|
||||
* This allows browsers/clients to use the same codec avoiding transcoding in the media server.
|
||||
* If the browser/client is not compatible with the specified codec and {@link #allowTranscoding(Boolean)}
|
||||
* is <code>false</code> and exception will occur.
|
||||
*
|
||||
* If forcedVideoCodec is set to NONE, no codec will be forced.
|
||||
*/
|
||||
public SessionProperties.Builder forcedVideoCodec(VideoCodec forcedVideoCodec) {
|
||||
this.forcedVideoCodec = forcedVideoCodec;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to define if you want to allow transcoding in the media server or not
|
||||
* when {@link #forcedVideoCodec(VideoCodec)} is not compatible with the browser/client.
|
||||
|
@ -174,11 +213,11 @@ public class SessionProperties {
|
|||
this.defaultRecordingLayout = RecordingLayout.BEST_FIT;
|
||||
this.defaultCustomLayout = "";
|
||||
this.customSessionId = "";
|
||||
this.allowTranscoding = false;
|
||||
this.mediaNode = "";
|
||||
}
|
||||
|
||||
private SessionProperties(MediaMode mediaMode, RecordingMode recordingMode, OutputMode outputMode,
|
||||
RecordingLayout layout, String defaultCustomLayout, String customSessionId,
|
||||
RecordingLayout layout, String defaultCustomLayout, String customSessionId, String mediaNode,
|
||||
VideoCodec forcedVideoCodec, Boolean allowTranscoding) {
|
||||
this.mediaMode = mediaMode;
|
||||
this.recordingMode = recordingMode;
|
||||
|
@ -186,6 +225,7 @@ public class SessionProperties {
|
|||
this.defaultRecordingLayout = layout;
|
||||
this.defaultCustomLayout = defaultCustomLayout;
|
||||
this.customSessionId = customSessionId;
|
||||
this.mediaNode = mediaNode;
|
||||
this.forcedVideoCodec = forcedVideoCodec;
|
||||
this.allowTranscoding = allowTranscoding;
|
||||
}
|
||||
|
@ -244,8 +284,8 @@ public class SessionProperties {
|
|||
* with any other value.<br>
|
||||
* Custom layouts are only applicable to recordings with OutputMode
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} (or
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) and
|
||||
* RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START})
|
||||
* and RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
||||
*/
|
||||
public String defaultCustomLayout() {
|
||||
return this.defaultCustomLayout;
|
||||
|
@ -261,14 +301,14 @@ public class SessionProperties {
|
|||
public String customSessionId() {
|
||||
return this.customSessionId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines which video codec is being forced to be used in the browser/client
|
||||
*/
|
||||
public VideoCodec forcedVideoCodec() {
|
||||
return this.forcedVideoCodec;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines if transcoding is allowed or not when {@link #forcedVideoCodec}
|
||||
* is not a compatible codec with the browser/client.
|
||||
|
@ -277,4 +317,54 @@ public class SessionProperties {
|
|||
return this.allowTranscoding;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||
* 3px; font-size: 13px; line-height:21px; font-family: Montserrat,
|
||||
* sans-serif">PRO</a> The Media Node where to host the session. The default
|
||||
* option if this property is not defined is the less loaded Media Node at the
|
||||
* moment the first user joins the session.
|
||||
*/
|
||||
public String mediaNode() {
|
||||
return this.mediaNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines which video codec is being forced to be used in the browser/client
|
||||
*/
|
||||
public VideoCodec forcedVideoCodec() {
|
||||
return this.forcedVideoCodec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if transcoding is allowed or not when {@link #forcedVideoCodec}
|
||||
* is not a compatible codec with the browser/client.
|
||||
*/
|
||||
public Boolean isTranscodingAllowed() {
|
||||
return this.allowTranscoding;
|
||||
}
|
||||
|
||||
protected JsonObject toJson() {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("mediaMode", mediaMode().name());
|
||||
json.addProperty("recordingMode", recordingMode().name());
|
||||
json.addProperty("defaultOutputMode", defaultOutputMode().name());
|
||||
json.addProperty("defaultRecordingLayout", defaultRecordingLayout().name());
|
||||
json.addProperty("defaultCustomLayout", defaultCustomLayout());
|
||||
json.addProperty("customSessionId", customSessionId());
|
||||
if (mediaNode() != null) {
|
||||
JsonObject mediaNodeJson = new JsonObject();
|
||||
mediaNodeJson.addProperty("id", mediaNode());
|
||||
json.add("mediaNode", mediaNodeJson);
|
||||
}
|
||||
if (forcedVideoCodec() != null) {
|
||||
json.addProperty("forcedVideoCodec", forcedVideoCodec().name());
|
||||
}
|
||||
if (isTranscodingAllowed() != null) {
|
||||
json.addProperty("allowTranscoding", isTranscodingAllowed());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,31 +17,42 @@
|
|||
|
||||
package io.openvidu.java.client;
|
||||
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* See {@link io.openvidu.java.client.Session#generateToken(TokenOptions)}
|
||||
* @deprecated Use {@link io.openvidu.java.client.ConnectionProperties
|
||||
* ConnectionProperties} instead
|
||||
*/
|
||||
public class TokenOptions {
|
||||
|
||||
private String data;
|
||||
private OpenViduRole role;
|
||||
private String data;
|
||||
private KurentoOptions kurentoOptions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder for {@link io.openvidu.java.client.TokenOptions}
|
||||
*
|
||||
* @deprecated Use {@link io.openvidu.java.client.ConnectionProperties.Builder
|
||||
* ConnectionProperties.Builder} instead
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private String data = "";
|
||||
private OpenViduRole role = OpenViduRole.PUBLISHER;
|
||||
private String data;
|
||||
private KurentoOptions kurentoOptions;
|
||||
|
||||
/**
|
||||
* Builder for {@link io.openvidu.java.client.TokenOptions}
|
||||
* Builder for {@link io.openvidu.java.client.TokenOptions}.
|
||||
*/
|
||||
public TokenOptions build() {
|
||||
return new TokenOptions(this.data, this.role, this.kurentoOptions);
|
||||
return new TokenOptions(this.role, this.data, this.kurentoOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the role assigned to this token.
|
||||
*/
|
||||
public Builder role(OpenViduRole role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,17 +82,9 @@ public class TokenOptions {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set the role assigned to this token
|
||||
*/
|
||||
public Builder role(OpenViduRole role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to set a {@link io.openvidu.java.client.KurentoOptions}
|
||||
* object for this token
|
||||
* object for this token.
|
||||
*/
|
||||
public Builder kurentoOptions(KurentoOptions kurentoOptions) {
|
||||
this.kurentoOptions = kurentoOptions;
|
||||
|
@ -90,26 +93,26 @@ public class TokenOptions {
|
|||
|
||||
}
|
||||
|
||||
private TokenOptions(String data, OpenViduRole role, KurentoOptions kurentoOptions) {
|
||||
this.data = data;
|
||||
TokenOptions(OpenViduRole role, String data, KurentoOptions kurentoOptions) {
|
||||
this.role = role;
|
||||
this.data = data;
|
||||
this.kurentoOptions = kurentoOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secure (server-side) metadata assigned to this token
|
||||
*/
|
||||
public String getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the role assigned to this token
|
||||
* Returns the role assigned to this token.
|
||||
*/
|
||||
public OpenViduRole getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secure (server-side) metadata assigned to this token.
|
||||
*/
|
||||
public String getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kurento options assigned to this token
|
||||
*/
|
||||
|
@ -117,4 +120,23 @@ public class TokenOptions {
|
|||
return this.kurentoOptions;
|
||||
}
|
||||
|
||||
protected JsonObject toJsonObject(String sessionId) {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("session", sessionId);
|
||||
if (getRole() != null) {
|
||||
json.addProperty("role", getRole().name());
|
||||
} else {
|
||||
json.add("role", JsonNull.INSTANCE);
|
||||
}
|
||||
if (getData() != null) {
|
||||
json.addProperty("data", getData());
|
||||
} else {
|
||||
json.add("data", JsonNull.INSTANCE);
|
||||
}
|
||||
if (this.kurentoOptions != null) {
|
||||
json.add("kurentoOptions", kurentoOptions.toJson());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,4 +45,6 @@ Thumbs.db
|
|||
/lib/
|
||||
|
||||
docs/
|
||||
lib/
|
||||
lib/
|
||||
|
||||
*.tgz
|
||||
|
|
|
@ -12,6 +12,7 @@ module.exports = {
|
|||
externalPattern: "node_modules",
|
||||
excludeExternals: true,
|
||||
excludePrivate: true,
|
||||
excludeProtected: true,
|
||||
excludeNotExported: true,
|
||||
theme: "default",
|
||||
readme: "none",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"author": "OpenVidu",
|
||||
"dependencies": {
|
||||
"axios": "0.19.2",
|
||||
"buffer": "5.6.0"
|
||||
"axios": "0.21.1",
|
||||
"buffer": "6.0.2"
|
||||
},
|
||||
"description": "OpenVidu Node Client",
|
||||
"devDependencies": {
|
||||
"@types/node": "14.0.13",
|
||||
"grunt": "1.1.0",
|
||||
"@types/node": "14.14.7",
|
||||
"grunt": "1.3.0",
|
||||
"grunt-cli": "1.3.2",
|
||||
"grunt-contrib-copy": "1.0.0",
|
||||
"grunt-contrib-sass": "1.0.0",
|
||||
"grunt-contrib-uglify": "4.0.1",
|
||||
"grunt-contrib-sass": "2.0.0",
|
||||
"grunt-contrib-uglify": "5.0.0",
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"grunt-postcss": "0.9.0",
|
||||
"grunt-string-replace": "1.3.1",
|
||||
"grunt-ts": "6.0.0-beta.22",
|
||||
"ts-node": "8.10.2",
|
||||
"tslint": "6.1.1",
|
||||
"typedoc": "0.17.7",
|
||||
"ts-node": "9.0.0",
|
||||
"tslint": "6.1.3",
|
||||
"typedoc": "0.19.2",
|
||||
"typescript": "3.8.3"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
|
@ -33,5 +33,5 @@
|
|||
"docs": "./generate-docs.sh"
|
||||
},
|
||||
"typings": "lib/index.d.ts",
|
||||
"version": "2.15.0"
|
||||
"version": "2.16.0"
|
||||
}
|
||||
|
|
|
@ -15,37 +15,47 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import { OpenViduRole } from './OpenViduRole';
|
||||
import { Publisher } from './Publisher';
|
||||
import { ConnectionProperties } from './ConnectionProperties';
|
||||
import { OpenViduRole } from './OpenViduRole';
|
||||
|
||||
/**
|
||||
* See [[Session.activeConnections]]
|
||||
* See [[Session.connections]]
|
||||
*/
|
||||
export class Connection {
|
||||
|
||||
/**
|
||||
* Identifier of the connection. You can call [[Session.forceDisconnect]] passing this property as parameter
|
||||
* Identifier of the Connection. You can call methods [[Session.forceDisconnect]]
|
||||
* or [[Session.updateConnection]] passing this property as parameter
|
||||
*/
|
||||
connectionId: string;
|
||||
|
||||
/**
|
||||
* Timestamp when this connection was established, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
|
||||
* Returns the status of the Connection. Can be:
|
||||
* - `pending`: if the Connection is waiting for any user to use
|
||||
* its internal token to connect to the session, calling method
|
||||
* [Session.connect](https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect)
|
||||
* in OpenVidu Browser.
|
||||
* - `active`: if the internal token of the Connection has already
|
||||
* been used by some user to connect to the session, and it cannot be used
|
||||
* again.
|
||||
*/
|
||||
status: string;
|
||||
|
||||
/**
|
||||
* Timestamp when the Connection was created, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
|
||||
*/
|
||||
createdAt: number;
|
||||
|
||||
/**
|
||||
* Role of the connection
|
||||
* Timestamp when the Connection was taken by a user (passing from status "pending" to "active")
|
||||
* in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
|
||||
*/
|
||||
role: OpenViduRole;
|
||||
|
||||
/**
|
||||
* Token associated to the connection
|
||||
*/
|
||||
token: string;
|
||||
activeAt: number;
|
||||
|
||||
/**
|
||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
* Geo location of the connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it)
|
||||
* Geo location of the Connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it)
|
||||
*/
|
||||
location: string;
|
||||
|
||||
|
@ -55,16 +65,22 @@ export class Connection {
|
|||
platform: string;
|
||||
|
||||
/**
|
||||
* Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]]
|
||||
*/
|
||||
serverData: string;
|
||||
|
||||
/**
|
||||
* Data associated to the connection on the client-side. This value is set with second parameter of method
|
||||
* Data associated to the Connection on the client-side. This value is set with second parameter of method
|
||||
* [Session.connect](/en/stable/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser
|
||||
*/
|
||||
clientData: string;
|
||||
|
||||
/**
|
||||
* The [[ConnectionProperties]] assigned to the Connection
|
||||
*/
|
||||
connectionProperties: ConnectionProperties;
|
||||
|
||||
/**
|
||||
* Token associated to the Connection. This is the value that must be sent to the client-side to be consumed in OpenVidu Browser
|
||||
* method [Session.connect](https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect).
|
||||
*/
|
||||
token: string;
|
||||
|
||||
/**
|
||||
* Array of Publisher objects this particular Connection is publishing to the Session (each Publisher object has one Stream, uniquely
|
||||
* identified by its `streamId`). You can call [[Session.forceUnpublish]] passing any of this values as parameter
|
||||
|
@ -77,21 +93,112 @@ export class Connection {
|
|||
*/
|
||||
subscribers: string[] = [];
|
||||
|
||||
/**
|
||||
* @hidden deprecated. Inside ConnectionProperties
|
||||
*/
|
||||
role?: OpenViduRole;
|
||||
/**
|
||||
* @hidden deprecated. Inside ConnectionProperties
|
||||
*/
|
||||
serverData?: string;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(connectionId: string, createdAt: number, role: OpenViduRole, token: string, location: string, platform: string, serverData: string, clientData: string,
|
||||
publishers: Publisher[], subscribers: string[]) {
|
||||
this.connectionId = connectionId;
|
||||
this.createdAt = createdAt;
|
||||
this.role = role;
|
||||
this.token = token;
|
||||
this.location = location;
|
||||
this.platform = platform;
|
||||
this.serverData = serverData;
|
||||
this.clientData = clientData;
|
||||
this.publishers = publishers;
|
||||
this.subscribers = subscribers;
|
||||
constructor(json) {
|
||||
this.resetWithJson(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
resetWithJson(json): Connection {
|
||||
|
||||
this.connectionId = json.connectionId;
|
||||
this.status = json.status;
|
||||
this.createdAt = json.createdAt;
|
||||
this.activeAt = json.activeAt;
|
||||
this.location = json.location;
|
||||
this.platform = json.platform;
|
||||
this.clientData = json.clientData;
|
||||
this.token = json.token;
|
||||
if (this.connectionProperties != null) {
|
||||
this.connectionProperties.type = json.type;
|
||||
this.connectionProperties.data = json.serverData;
|
||||
this.connectionProperties.record = json.record;
|
||||
this.connectionProperties.role = json.role;
|
||||
this.connectionProperties.kurentoOptions = json.kurentoOptions;
|
||||
this.connectionProperties.rtspUri = json.rtspUri;
|
||||
this.connectionProperties.adaptativeBitrate = json.adaptativeBitrate;
|
||||
this.connectionProperties.onlyPlayWithSubscribers = json.onlyPlayWithSubscribers;
|
||||
this.connectionProperties.networkCache = json.networkCache;
|
||||
} else {
|
||||
this.connectionProperties = {
|
||||
type: json.type,
|
||||
data: json.serverData,
|
||||
record: json.record,
|
||||
role: json.role,
|
||||
kurentoOptions: json.kurentoOptions,
|
||||
rtspUri: json.rtspUri,
|
||||
adaptativeBitrate: json.adaptativeBitrate,
|
||||
onlyPlayWithSubscribers: json.onlyPlayWithSubscribers,
|
||||
networkCache: json.networkCache
|
||||
}
|
||||
}
|
||||
this.role = json.role;
|
||||
this.serverData = json.serverData;
|
||||
|
||||
// publishers may be null
|
||||
if (json.publishers != null) {
|
||||
|
||||
// 1. Array to store fetched Publishers and later remove closed ones
|
||||
const fetchedPublisherIds: string[] = [];
|
||||
json.publishers.forEach(jsonPublisher => {
|
||||
|
||||
const publisherObj: Publisher = new Publisher(jsonPublisher);
|
||||
fetchedPublisherIds.push(publisherObj.streamId);
|
||||
let storedPublisher = this.publishers.find(c => c.streamId === publisherObj.streamId);
|
||||
|
||||
if (!!storedPublisher) {
|
||||
// 2. Update existing Publisher
|
||||
storedPublisher.resetWithJson(jsonPublisher);
|
||||
} else {
|
||||
// 3. Add new Publisher
|
||||
this.publishers.push(publisherObj);
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Remove closed Publishers from local collection
|
||||
for (var i = this.publishers.length - 1; i >= 0; --i) {
|
||||
if (!fetchedPublisherIds.includes(this.publishers[i].streamId)) {
|
||||
this.publishers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// subscribers may be null
|
||||
if (json.subscribers != null) {
|
||||
|
||||
// 1. Array to store fetched Subscribers and later remove closed ones
|
||||
const fetchedSubscriberIds: string[] = [];
|
||||
json.subscribers.forEach(jsonSubscriber => {
|
||||
fetchedSubscriberIds.push(jsonSubscriber.streamId)
|
||||
if (this.subscribers.indexOf(jsonSubscriber.streamId) === -1) {
|
||||
// 2. Add new Subscriber
|
||||
this.subscribers.push(jsonSubscriber.streamId);
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Remove closed Subscribers from local collection
|
||||
for (var i = this.subscribers.length - 1; i >= 0; --i) {
|
||||
if (!fetchedSubscriberIds.includes(this.subscribers[i])) {
|
||||
this.subscribers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,17 +207,32 @@ export class Connection {
|
|||
equalTo(other: Connection): boolean {
|
||||
let equals: boolean = (
|
||||
this.connectionId === other.connectionId &&
|
||||
this.status === other.status &&
|
||||
this.createdAt === other.createdAt &&
|
||||
this.role === other.role &&
|
||||
this.activeAt === other.activeAt &&
|
||||
this.connectionProperties.type === other.connectionProperties.type &&
|
||||
this.connectionProperties.data === other.connectionProperties.data &&
|
||||
this.connectionProperties.record === other.connectionProperties.record &&
|
||||
this.connectionProperties.role === other.connectionProperties.role &&
|
||||
this.connectionProperties.rtspUri === other.connectionProperties.rtspUri &&
|
||||
this.connectionProperties.adaptativeBitrate === other.connectionProperties.adaptativeBitrate &&
|
||||
this.connectionProperties.onlyPlayWithSubscribers === other.connectionProperties.onlyPlayWithSubscribers &&
|
||||
this.connectionProperties.networkCache === other.connectionProperties.networkCache &&
|
||||
this.token === other.token &&
|
||||
this.location === other.location &&
|
||||
this.platform === other.platform &&
|
||||
this.serverData === other.serverData &&
|
||||
this.clientData === other.clientData &&
|
||||
this.subscribers.length === other.subscribers.length &&
|
||||
this.publishers.length === other.publishers.length);
|
||||
if (equals) {
|
||||
equals = JSON.stringify(this.subscribers) === JSON.stringify(other.subscribers);
|
||||
if (this.connectionProperties.kurentoOptions != null) {
|
||||
equals = JSON.stringify(this.connectionProperties.kurentoOptions) === JSON.stringify(other.connectionProperties.kurentoOptions);
|
||||
} else {
|
||||
equals = (this.connectionProperties.kurentoOptions === other.connectionProperties.kurentoOptions);
|
||||
}
|
||||
}
|
||||
if (equals) {
|
||||
equals = JSON.stringify(this.subscribers.sort()) === JSON.stringify(other.subscribers.sort());
|
||||
if (equals) {
|
||||
let i = 0;
|
||||
while (equals && i < this.publishers.length) {
|
||||
|
@ -125,4 +247,18 @@ export class Connection {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
overrideConnectionProperties(newConnectionProperties: ConnectionProperties): void {
|
||||
// For now only properties record and role
|
||||
if (newConnectionProperties.record != null) {
|
||||
this.connectionProperties.record = newConnectionProperties.record;
|
||||
}
|
||||
if (newConnectionProperties.role != null) {
|
||||
this.connectionProperties.role = newConnectionProperties.role;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2020 OpenVidu (https://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.
|
||||
*
|
||||
*/
|
||||
|
||||
import { ConnectionType } from './ConnectionType';
|
||||
import { OpenViduRole } from './OpenViduRole';
|
||||
|
||||
export interface ConnectionProperties {
|
||||
|
||||
/**
|
||||
* Type of Connection. The [[ConnectionType]] dictates what properties will have effect:
|
||||
*
|
||||
* - **[[ConnectionType.WEBRTC]]**: [[data]], [[record]], [[role]], [[kurentoOptions]]
|
||||
* - **[[ConnectionType.IPCAM]]**: [[data]], [[record]], [[rtspUri]], [[adaptativeBitrate]], [[onlyPlayWithSubscribers]], [[networkCache]]
|
||||
*
|
||||
* @default WEBRTC
|
||||
*/
|
||||
type?: ConnectionType;
|
||||
|
||||
/**
|
||||
* Secure (server-side) data associated to this Connection. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object.
|
||||
* - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[ConnectionProperties.data]] property.
|
||||
* - If you have provided some data when calling `Session.connect(TOKEN, DATA)` (`DATA` defined), then `Connection.data` will have the following structure: `"CLIENT_DATA%/%SERVER_DATA"`, being `CLIENT_DATA` the second
|
||||
* parameter passed in OpenVidu Browser in method `Session.connect` and `SERVER_DATA` this [[ConnectionProperties.data]] property.
|
||||
*/
|
||||
data?: string;
|
||||
|
||||
/**
|
||||
* **This feature is part of OpenVidu Pro tier** <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* Whether to record the streams published by this Connection or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded)
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
record?: boolean;
|
||||
|
||||
/**
|
||||
* The role assigned to this Connection
|
||||
*
|
||||
* **Only for [[ConnectionType.WEBRTC]]**
|
||||
*
|
||||
* @default PUBLISHER
|
||||
*/
|
||||
role?: OpenViduRole;
|
||||
|
||||
/**
|
||||
* **WARNING**: experimental option. This interface may change in the near future
|
||||
*
|
||||
* Some advanced properties setting the configuration that the WebRTC streams of the Connection will have in Kurento Media Server.
|
||||
* You can adjust:
|
||||
* - `videoMaxRecvBandwidth`: maximum number of Kbps that the Connection will be able to receive from Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
|
||||
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
|
||||
* (parameter `OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH`) for every incoming stream of the Connection.
|
||||
* _**WARNING**: the lower value set to this property limits every other bandwidth of the WebRTC pipeline this server-to-client stream belongs to. This includes the user publishing the stream and every other user subscribed to the stream_
|
||||
* - `videoMinRecvBandwidth`: minimum number of Kbps that the cConnection will try to receive from Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
|
||||
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
|
||||
* (parameter `OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH`) for every incoming stream of the Connection.
|
||||
* - `videoMaxSendBandwidth`: maximum number of Kbps that the Connection will be able to send to Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
|
||||
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
|
||||
* (parameter `OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH`) for every outgoing stream of the Connection.
|
||||
* _**WARNING**: this value limits every other bandwidth of the WebRTC pipeline this client-to-server stream belongs to. This includes every other user subscribed to the stream_
|
||||
* - `videoMinSendBandwidth`: minimum number of Kbps that the Connection will try to send to Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
|
||||
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
|
||||
* (parameter `OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH`) for every outgoing stream of the Connection.
|
||||
* - `allowedFilters`: names of the filters the Connection will be able to apply. See [Voice and video filters](/en/stable/advanced-features/filters/)
|
||||
*
|
||||
* **Only for [[ConnectionType.WEBRTC]]**
|
||||
*/
|
||||
kurentoOptions?: {
|
||||
videoMaxRecvBandwidth?: number,
|
||||
videoMinRecvBandwidth?: number,
|
||||
videoMaxSendBandwidth?: number,
|
||||
videoMinSendBandwidth?: number,
|
||||
allowedFilters?: string[]
|
||||
};
|
||||
|
||||
/**
|
||||
* RTSP URI of an IP camera. For example: `rtsp://your.camera.ip:7777/path`
|
||||
*
|
||||
* **Only for [[ConnectionType.IPCAM]]**
|
||||
*/
|
||||
rtspUri?: string;
|
||||
|
||||
/**
|
||||
* Whether to use adaptative bitrate (and therefore adaptative quality) or not. For local network connections
|
||||
* that do not require media transcoding this can be disabled to save CPU power. If you are not sure if transcoding
|
||||
* might be necessary, setting this property to false **may result in media connections not being established**.
|
||||
*
|
||||
* **Only for [[ConnectionType.IPCAM]]**
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
adaptativeBitrate?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to enable the IP camera stream only when some user is subscribed to it, or not. This allows you to reduce
|
||||
* power consumption and network bandwidth in your server while nobody is asking to receive the camera's video.
|
||||
* On the counterpart, first user subscribing to the IP camera stream will take a little longer to receive its video.
|
||||
*
|
||||
* **Only for [[ConnectionType.IPCAM]]**
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
onlyPlayWithSubscribers?: boolean;
|
||||
|
||||
/**
|
||||
* Size of the buffer of the endpoint receiving the IP camera's stream, in milliseconds. The smaller it is, the less
|
||||
* delay the signal will have, but more problematic will be in unstable networks. Use short buffers only if there is
|
||||
* a quality connection between the IP camera and OpenVidu Server.
|
||||
*
|
||||
* **Only for [[ConnectionType.IPCAM]]**
|
||||
*
|
||||
* @default 2000
|
||||
*/
|
||||
networkCache?: number;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2020 OpenVidu (https://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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* See [[Session.createConnection]]
|
||||
*/
|
||||
export enum ConnectionType {
|
||||
|
||||
/**
|
||||
* WebRTC connection. This is the normal type of Connection for a regular user
|
||||
* connecting to a session from an application.
|
||||
*/
|
||||
WEBRTC = 'WEBRTC',
|
||||
|
||||
/**
|
||||
* IP camera connection. This is the type of Connection used by IP cameras to
|
||||
* connect to a session.
|
||||
*/
|
||||
IPCAM = 'IPCAM'
|
||||
}
|
|
@ -17,13 +17,11 @@
|
|||
|
||||
import axios from 'axios';
|
||||
import { Connection } from './Connection';
|
||||
import { Publisher } from './Publisher';
|
||||
import { Recording } from './Recording';
|
||||
import { RecordingProperties } from './RecordingProperties';
|
||||
import { Session } from './Session';
|
||||
import { SessionProperties } from './SessionProperties';
|
||||
import { RecordingLayout } from './RecordingLayout';
|
||||
import { RecordingMode } from 'RecordingMode';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
|
@ -47,29 +45,36 @@ export class OpenVidu {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
static readonly API_RECORDINGS: string = '/api/recordings';
|
||||
static readonly API_PATH: string = '/openvidu/api';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
static readonly API_RECORDINGS_START: string = '/start';
|
||||
static readonly API_SESSIONS = OpenVidu.API_PATH + '/sessions';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
static readonly API_RECORDINGS_STOP: string = '/stop';
|
||||
static readonly API_TOKENS = OpenVidu.API_PATH + '/tokens';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
static readonly API_SESSIONS = '/api/sessions';
|
||||
static readonly API_RECORDINGS: string = OpenVidu.API_PATH + '/recordings';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
static readonly API_TOKENS = '/api/tokens';
|
||||
static readonly API_RECORDINGS_START: string = OpenVidu.API_RECORDINGS + '/start';
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
static readonly API_RECORDINGS_STOP: string = OpenVidu.API_RECORDINGS + '/stop';
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Array of active sessions. **This value will remain unchanged since the last time method [[OpenVidu.fetch]]
|
||||
* was called**. Exceptions to this rule are:
|
||||
*
|
||||
* - Calling [[OpenVidu.createSession]] automatically adds the new Session object to the local collection.
|
||||
* - Calling [[Session.fetch]] updates that specific Session status
|
||||
* - Calling [[Session.close]] automatically removes the Session from the list of active Sessions
|
||||
* - Calling [[Session.forceDisconnect]] automatically updates the inner affected connections for that specific Session
|
||||
|
@ -83,16 +88,18 @@ export class OpenVidu {
|
|||
activeSessions: Session[] = [];
|
||||
|
||||
/**
|
||||
* @param urlOpenViduServer Public accessible IP where your instance of OpenVidu Server is up an running
|
||||
* @param hostname URL where your instance of OpenVidu Server is up an running.
|
||||
* It must be the full URL (e.g. `https://12.34.56.78:1234/`)
|
||||
*
|
||||
* @param secret Secret used on OpenVidu Server initialization
|
||||
*/
|
||||
constructor(private urlOpenViduServer: string, secret: string) {
|
||||
constructor(private hostname: string, secret: string) {
|
||||
this.setHostnameAndPort();
|
||||
this.basicAuth = this.getBasicAuth(secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an OpenVidu session. You can call [[Session.getSessionId]] inside the resolved promise to retrieve the `sessionId`
|
||||
* Creates an OpenVidu session. The session identifier will be available at property [[Session.sessionId]]
|
||||
*
|
||||
* @returns A Promise that is resolved to the [[Session]] if success and rejected with an Error object if not.
|
||||
*/
|
||||
|
@ -140,14 +147,16 @@ export class OpenVidu {
|
|||
data = {
|
||||
session: sessionId,
|
||||
name: !!properties.name ? properties.name : '',
|
||||
outputMode: !!properties.outputMode ? properties.outputMode : Recording.OutputMode.COMPOSED,
|
||||
hasAudio: !!(properties.hasAudio),
|
||||
hasVideo: !!(properties.hasVideo)
|
||||
outputMode: properties.outputMode,
|
||||
hasAudio: properties.hasAudio != null ? properties.hasAudio : null,
|
||||
hasVideo: properties.hasVideo != null ? properties.hasVideo : null,
|
||||
shmSize: properties.shmSize,
|
||||
mediaNode: properties.mediaNode
|
||||
};
|
||||
if (data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]
|
||||
|| data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) {
|
||||
data.resolution = !!properties.resolution ? properties.resolution : '1920x1080';
|
||||
data.recordingLayout = !!properties.recordingLayout ? properties.recordingLayout : RecordingLayout.BEST_FIT;
|
||||
if ((data.hasVideo == null || data.hasVideo) && (data.outputMode == null || data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]
|
||||
|| data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START])) {
|
||||
data.resolution = properties.resolution;
|
||||
data.recordingLayout = !!properties.recordingLayout ? properties.recordingLayout : '';
|
||||
if (data.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
|
||||
data.customLayout = !!properties.customLayout ? properties.customLayout : '';
|
||||
}
|
||||
|
@ -156,20 +165,18 @@ export class OpenVidu {
|
|||
} else {
|
||||
data = JSON.stringify({
|
||||
session: sessionId,
|
||||
name: param2,
|
||||
outputMode: Recording.OutputMode.COMPOSED
|
||||
name: param2
|
||||
});
|
||||
}
|
||||
} else {
|
||||
data = JSON.stringify({
|
||||
session: sessionId,
|
||||
name: '',
|
||||
outputMode: Recording.OutputMode.COMPOSED
|
||||
name: ''
|
||||
});
|
||||
}
|
||||
|
||||
axios.post(
|
||||
this.host + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_START,
|
||||
this.host + OpenVidu.API_RECORDINGS_START,
|
||||
data,
|
||||
{
|
||||
headers: {
|
||||
|
@ -223,7 +230,7 @@ export class OpenVidu {
|
|||
return new Promise<Recording>((resolve, reject) => {
|
||||
|
||||
axios.post(
|
||||
this.host + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId,
|
||||
this.host + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId,
|
||||
undefined,
|
||||
{
|
||||
headers: {
|
||||
|
@ -412,7 +419,7 @@ export class OpenVidu {
|
|||
public fetch(): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
axios.get(
|
||||
this.host + OpenVidu.API_SESSIONS,
|
||||
this.host + OpenVidu.API_SESSIONS + '?pendingConnections=true',
|
||||
{
|
||||
headers: {
|
||||
Authorization: this.basicAuth
|
||||
|
@ -422,47 +429,44 @@ export class OpenVidu {
|
|||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
|
||||
// Array to store fetched sessionIds and later remove closed sessions
|
||||
const fetchedSessionIds: string[] = [];
|
||||
// Boolean to store if any Session has changed
|
||||
let hasChanged = false;
|
||||
|
||||
res.data.content.forEach(session => {
|
||||
fetchedSessionIds.push(session.sessionId);
|
||||
let sessionIndex = -1;
|
||||
let storedSession = this.activeSessions.find((s, index) => {
|
||||
if (s.sessionId === session.sessionId) {
|
||||
sessionIndex = index;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// 1. Array to store fetched sessionIds and later remove closed ones
|
||||
const fetchedSessionIds: string[] = [];
|
||||
res.data.content.forEach(jsonSession => {
|
||||
|
||||
const fetchedSession: Session = new Session(this, jsonSession);
|
||||
fetchedSessionIds.push(fetchedSession.sessionId);
|
||||
let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId);
|
||||
|
||||
if (!!storedSession) {
|
||||
const fetchedSession: Session = new Session(this).resetSessionWithJson(session);
|
||||
|
||||
// 2. Update existing Session
|
||||
const changed: boolean = !storedSession.equalTo(fetchedSession);
|
||||
if (changed) {
|
||||
storedSession = fetchedSession;
|
||||
this.activeSessions[sessionIndex] = storedSession;
|
||||
}
|
||||
storedSession.resetWithJson(jsonSession);
|
||||
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
||||
hasChanged = hasChanged || changed;
|
||||
|
||||
} else {
|
||||
this.activeSessions.push(new Session(this, session));
|
||||
console.log("New session '" + session.sessionId + "' info fetched");
|
||||
|
||||
// 3. Add new Session
|
||||
this.activeSessions.push(fetchedSession);
|
||||
console.log("New session '" + fetchedSession.sessionId + "' info fetched");
|
||||
hasChanged = true;
|
||||
}
|
||||
});
|
||||
// Remove closed sessions from activeSessions array
|
||||
this.activeSessions = this.activeSessions.filter(session => {
|
||||
if (fetchedSessionIds.includes(session.sessionId)) {
|
||||
return true;
|
||||
} else {
|
||||
console.log("Removing closed session '" + session.sessionId + "'");
|
||||
|
||||
// 4. Remove closed sessions from local collection
|
||||
for (var i = this.activeSessions.length - 1; i >= 0; --i) {
|
||||
let sessionId = this.activeSessions[i].sessionId;
|
||||
if (!fetchedSessionIds.includes(sessionId)) {
|
||||
console.log("Removing closed session '" + sessionId + "'");
|
||||
hasChanged = true;
|
||||
return false;
|
||||
this.activeSessions.splice(i, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
||||
resolve(hasChanged);
|
||||
} else {
|
||||
|
@ -498,26 +502,9 @@ export class OpenVidu {
|
|||
const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => {
|
||||
const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId);
|
||||
if (!!connectionExtended) {
|
||||
const publisherArray = [];
|
||||
connection.publishers.forEach(pub => {
|
||||
const publisherExtended = connectionExtended.publishers.find(p => p.streamId === pub.streamId);
|
||||
const pubAux = {};
|
||||
// Standard properties
|
||||
pubAux['streamId'] = pub.streamId;
|
||||
pubAux['createdAt'] = pub.createdAt;
|
||||
const mediaOptions = {
|
||||
audioActive: pub.audioActive,
|
||||
videoActive: pub.videoActive,
|
||||
hasAudio: pub.hasAudio,
|
||||
hasVideo: pub.hasVideo,
|
||||
typeOfVideo: pub.typeOfVideo,
|
||||
frameRate: pub.frameRate,
|
||||
videoDimensions: pub.videoDimensions
|
||||
};
|
||||
pubAux['mediaOptions'] = mediaOptions;
|
||||
const newPublisher = new Publisher(pubAux);
|
||||
// WebRtc properties
|
||||
newPublisher['webRtc'] = {
|
||||
pub['webRtc'] = {
|
||||
kms: {
|
||||
events: publisherExtended.events,
|
||||
localCandidate: publisherExtended.localCandidate,
|
||||
|
@ -529,11 +516,10 @@ export class OpenVidu {
|
|||
remoteSdp: publisherExtended.remoteSdp
|
||||
}
|
||||
};
|
||||
newPublisher['localCandidatePair'] = parseRemoteCandidatePair(newPublisher['webRtc'].kms.remoteCandidate);
|
||||
pub['localCandidatePair'] = parseRemoteCandidatePair(pub['webRtc'].kms.remoteCandidate);
|
||||
if (!!publisherExtended.serverStats) {
|
||||
newPublisher['webRtc'].kms.serverStats = publisherExtended.serverStats;
|
||||
pub['webRtc'].kms.serverStats = publisherExtended.serverStats;
|
||||
}
|
||||
publisherArray.push(newPublisher);
|
||||
});
|
||||
const subscriberArray = [];
|
||||
connection.subscribers.forEach(sub => {
|
||||
|
@ -562,7 +548,6 @@ export class OpenVidu {
|
|||
}
|
||||
subscriberArray.push(subAux);
|
||||
});
|
||||
connection.publishers = publisherArray;
|
||||
connection.subscribers = subscriberArray;
|
||||
}
|
||||
};
|
||||
|
@ -594,68 +579,64 @@ export class OpenVidu {
|
|||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
|
||||
// Array to store fetched sessionIds and later remove closed sessions
|
||||
const fetchedSessionIds: string[] = [];
|
||||
// Global changes
|
||||
let globalChanges = false;
|
||||
// Collection of sessionIds telling whether each one of them has changed or not
|
||||
const sessionChanges: ObjMap<boolean> = {};
|
||||
|
||||
res.data.content.forEach(session => {
|
||||
fetchedSessionIds.push(session.sessionId);
|
||||
let sessionIndex = -1;
|
||||
let storedSession = this.activeSessions.find((s, index) => {
|
||||
if (s.sessionId === session.sessionId) {
|
||||
sessionIndex = index;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!!storedSession) {
|
||||
const fetchedSession: Session = new Session(this).resetSessionWithJson(session);
|
||||
fetchedSession.activeConnections.forEach(connection => {
|
||||
addWebRtcStatsToConnections(connection, session.connections.content);
|
||||
});
|
||||
// 1. Array to store fetched sessionIds and later remove closed ones
|
||||
const fetchedSessionIds: string[] = [];
|
||||
res.data.content.forEach(jsonSession => {
|
||||
|
||||
const fetchedSession: Session = new Session(this, jsonSession);
|
||||
fetchedSession.connections.forEach(connection => {
|
||||
addWebRtcStatsToConnections(connection, jsonSession.connections.content);
|
||||
});
|
||||
fetchedSessionIds.push(fetchedSession.sessionId);
|
||||
let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId);
|
||||
|
||||
if (!!storedSession) {
|
||||
|
||||
// 2. Update existing Session
|
||||
let changed = !storedSession.equalTo(fetchedSession);
|
||||
if (!changed) { // Check if server webrtc information has changed in any Publisher object (Session.equalTo does not check Publisher.webRtc auxiliary object)
|
||||
fetchedSession.activeConnections.forEach((connection, index1) => {
|
||||
fetchedSession.connections.forEach((connection, index1) => {
|
||||
for (let index2 = 0; (index2 < connection['publishers'].length && !changed); index2++) {
|
||||
changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['publishers'][index2]['webRtc']);
|
||||
changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.connections[index1]['publishers'][index2]['webRtc']);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
storedSession = fetchedSession;
|
||||
this.activeSessions[sessionIndex] = storedSession;
|
||||
}
|
||||
storedSession.resetWithJson(jsonSession);
|
||||
storedSession.connections.forEach(connection => {
|
||||
addWebRtcStatsToConnections(connection, jsonSession.connections.content);
|
||||
});
|
||||
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
||||
sessionChanges[storedSession.sessionId] = changed;
|
||||
globalChanges = globalChanges || changed;
|
||||
|
||||
} else {
|
||||
const newSession = new Session(this, session);
|
||||
newSession.activeConnections.forEach(connection => {
|
||||
addWebRtcStatsToConnections(connection, session.connections.content);
|
||||
});
|
||||
this.activeSessions.push(newSession);
|
||||
console.log("New session '" + session.sessionId + "' info fetched");
|
||||
sessionChanges[session.sessionId] = true;
|
||||
|
||||
// 3. Add new Session
|
||||
this.activeSessions.push(fetchedSession);
|
||||
console.log("New session '" + fetchedSession.sessionId + "' info fetched");
|
||||
sessionChanges[fetchedSession.sessionId] = true;
|
||||
globalChanges = true;
|
||||
|
||||
}
|
||||
});
|
||||
// Remove closed sessions from activeSessions array
|
||||
this.activeSessions = this.activeSessions.filter(session => {
|
||||
if (fetchedSessionIds.includes(session.sessionId)) {
|
||||
return true;
|
||||
} else {
|
||||
console.log("Removing closed session '" + session.sessionId + "'");
|
||||
sessionChanges[session.sessionId] = true;
|
||||
|
||||
// 4. Remove closed sessions from local collection
|
||||
for (var i = this.activeSessions.length - 1; i >= 0; --i) {
|
||||
let sessionId = this.activeSessions[i].sessionId;
|
||||
if (!fetchedSessionIds.includes(sessionId)) {
|
||||
console.log("Removing closed session '" + sessionId + "'");
|
||||
sessionChanges[sessionId] = true;
|
||||
globalChanges = true;
|
||||
return false;
|
||||
this.activeSessions.splice(i, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
||||
resolve({ changes: globalChanges, sessionChanges });
|
||||
} else {
|
||||
|
@ -687,7 +668,7 @@ export class OpenVidu {
|
|||
private setHostnameAndPort(): void {
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(this.urlOpenViduServer);
|
||||
url = new URL(this.hostname);
|
||||
} catch (error) {
|
||||
console.error('URL format incorrect', error);
|
||||
throw new Error('URL format incorrect: ' + error);
|
||||
|
|
|
@ -74,6 +74,13 @@ export class Publisher {
|
|||
* @hidden
|
||||
*/
|
||||
constructor(json) {
|
||||
this.resetWithJson(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
resetWithJson(json): Publisher {
|
||||
this.streamId = json.streamId;
|
||||
this.createdAt = json.createdAt;
|
||||
this.hasAudio = json.mediaOptions.hasAudio;
|
||||
|
@ -83,6 +90,7 @@ export class Publisher {
|
|||
this.frameRate = json.mediaOptions.frameRate;
|
||||
this.typeOfVideo = json.mediaOptions.typeOfVideo;
|
||||
this.videoDimensions = json.mediaOptions.videoDimensions;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,7 +83,7 @@ export class Recording {
|
|||
hasVideo: !!json['hasVideo']
|
||||
};
|
||||
if (this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]
|
||||
|| this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) {
|
||||
|| this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) {
|
||||
this.properties.resolution = !!(json['resolution']) ? json['resolution'] : '1920x1080';
|
||||
this.properties.recordingLayout = !!(json['recordingLayout']) ? json['recordingLayout'] : RecordingLayout.BEST_FIT;
|
||||
if (this.properties.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
|
||||
|
@ -103,7 +103,7 @@ export namespace Recording {
|
|||
|
||||
/**
|
||||
* The recording is starting (cannot be stopped). Some recording may not go
|
||||
* through this status and directly reach "started" status
|
||||
* through this status and directly reach "started" status
|
||||
*/
|
||||
starting = 'starting',
|
||||
|
||||
|
@ -113,21 +113,20 @@ export namespace Recording {
|
|||
started = 'started',
|
||||
|
||||
/**
|
||||
* The recording has stopped and is being processed. At some point it will reach
|
||||
* "ready" status
|
||||
*/
|
||||
* The recording has stopped and is being processed. At some point it will reach
|
||||
* "ready" status
|
||||
*/
|
||||
stopped = 'stopped',
|
||||
|
||||
/**
|
||||
* The recording has finished OK and is available for download through OpenVidu
|
||||
* Server recordings endpoint:
|
||||
* https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION}
|
||||
* The recording has finished being processed and is available for download through
|
||||
* property [[Recording.url]]
|
||||
*/
|
||||
ready = 'ready',
|
||||
|
||||
/**
|
||||
* The recording has failed. This status may be reached from "starting",
|
||||
* "started" and "stopped" status
|
||||
* "started" and "stopped" status
|
||||
*/
|
||||
failed = 'failed'
|
||||
}
|
||||
|
@ -141,24 +140,24 @@ export namespace Recording {
|
|||
* Record all streams in a grid layout in a single archive
|
||||
*/
|
||||
COMPOSED = 'COMPOSED',
|
||||
|
||||
/**
|
||||
* Works the same way as COMPOSED mode, but the necessary recorder
|
||||
* service module will start some time in advance and won't be terminated
|
||||
* once a specific session recording has ended. This module will remain
|
||||
* up and running as long as the session remains active.
|
||||
*
|
||||
* - **Pros vs COMPOSED**: the process of starting the recording will be noticeably
|
||||
* faster. This can be very useful in use cases where a session needs to be
|
||||
* recorded multiple times over time, when a better response time is usually
|
||||
* desirable.
|
||||
|
||||
* - **Cons vs COMPOSED**: for every session initialized with COMPOSED_QUICK_START
|
||||
* recording output mode, extra CPU power will be required in OpenVidu Server.
|
||||
* The recording module will be continuously rendering all of the streams being
|
||||
* published to the session even when the session is not being recorded. And that
|
||||
* is for every session configured with COMPOSED_QUICK_START.
|
||||
*/
|
||||
/**
|
||||
* Works the same way as COMPOSED mode, but the necessary recorder
|
||||
* service module will start some time in advance and won't be terminated
|
||||
* once a specific session recording has ended. This module will remain
|
||||
* up and running as long as the session remains active.
|
||||
*
|
||||
* - **Pros vs COMPOSED**: the process of starting the recording will be noticeably
|
||||
* faster. This can be very useful in use cases where a session needs to be
|
||||
* recorded multiple times over time, when a better response time is usually
|
||||
* desirable.
|
||||
|
||||
* - **Cons vs COMPOSED**: for every session initialized with COMPOSED_QUICK_START
|
||||
* recording output mode, extra CPU power will be required in OpenVidu Server.
|
||||
* The recording module will be continuously rendering all of the streams being
|
||||
* published to the session even when the session is not being recorded. And that
|
||||
* is for every session configured with COMPOSED_QUICK_START.
|
||||
*/
|
||||
COMPOSED_QUICK_START = 'COMPOSED_QUICK_START',
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,4 +67,22 @@ export interface RecordingProperties {
|
|||
* Whether or not to record video. Cannot be set to false at the same time as [[RecordingProperties.hasAudio]]
|
||||
*/
|
||||
hasVideo?: boolean;
|
||||
|
||||
/**
|
||||
* If COMPOSED recording, the amount of shared memory reserved for the recording process in bytes.
|
||||
* Minimum 134217728 (128MB). Property ignored if INDIVIDUAL recording. Default to 536870912 (512 MB)
|
||||
*/
|
||||
shmSize?: number;
|
||||
|
||||
/**
|
||||
* **This feature is part of OpenVidu Pro tier** <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* The Media Node where to host the recording. The default option if this property is not defined is the same
|
||||
* Media Node hosting the Session to record. This object defines the following properties as Media Node selector:
|
||||
* - `id`: Media Node unique identifier
|
||||
*/
|
||||
mediaNode?: {
|
||||
id: string;
|
||||
}
|
||||
|
||||
}
|
|
@ -15,11 +15,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
import { Connection } from './Connection';
|
||||
import { ConnectionProperties } from './ConnectionProperties';
|
||||
import { MediaMode } from './MediaMode';
|
||||
import { OpenVidu } from './OpenVidu';
|
||||
import { OpenViduRole } from './OpenViduRole';
|
||||
import { Publisher } from './Publisher';
|
||||
import { Recording } from './Recording';
|
||||
import { RecordingLayout } from './RecordingLayout';
|
||||
|
@ -28,7 +28,6 @@ import { SessionProperties } from './SessionProperties';
|
|||
import { TokenOptions } from './TokenOptions';
|
||||
import { VideoCodec } from './VideoCodec';
|
||||
|
||||
|
||||
export class Session {
|
||||
|
||||
/**
|
||||
|
@ -47,14 +46,26 @@ export class Session {
|
|||
properties: SessionProperties;
|
||||
|
||||
/**
|
||||
* Array of active connections to the session. This property always initialize as an empty array and
|
||||
* **will remain unchanged since the last time method [[Session.fetch]] was called**. Exceptions to this rule are:
|
||||
* Array of Connections to the Session. This property always initialize as an empty array and
|
||||
* **will remain unchanged since the last time method [[Session.fetch]] or [[OpenVidu.fetch]] was called**.
|
||||
* Exceptions to this rule are:
|
||||
*
|
||||
* - Calling [[Session.forceUnpublish]] also automatically updates each affected Connection status
|
||||
* - Calling [[Session.forceDisconnect]] automatically updates each affected Connection status
|
||||
* - Calling [[Session.createConnection]] automatically adds the new Connection object to the local collection.
|
||||
* - Calling [[Session.forceUnpublish]] automatically updates each affected local Connection object.
|
||||
* - Calling [[Session.forceDisconnect]] automatically updates each affected local Connection object.
|
||||
* - Calling [[Session.updateConnection]] automatically updates the attributes of the affected local Connection object.
|
||||
*
|
||||
* To get the array of active connections with their current actual value, you must call [[Session.fetch]] before consulting
|
||||
* property [[activeConnections]]
|
||||
* To get the array of Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]]
|
||||
* before consulting property [[connections]]
|
||||
*/
|
||||
connections: Connection[] = [];
|
||||
|
||||
/**
|
||||
* Array containing the active Connections of the Session. It is a subset of [[Session.connections]] array containing only
|
||||
* those Connections with property [[Connection.status]] to `active`.
|
||||
*
|
||||
* To get the array of active Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]]
|
||||
* before consulting property [[activeConnections]]
|
||||
*/
|
||||
activeConnections: Connection[] = [];
|
||||
|
||||
|
@ -71,7 +82,7 @@ export class Session {
|
|||
// Defined parameter
|
||||
if (!!propertiesOrJson.sessionId) {
|
||||
// Parameter is a JSON representation of Session ('sessionId' property always defined)
|
||||
this.resetSessionWithJson(propertiesOrJson);
|
||||
this.resetWithJson(propertiesOrJson);
|
||||
} else {
|
||||
// Parameter is a SessionProperties object
|
||||
this.properties = propertiesOrJson;
|
||||
|
@ -84,32 +95,23 @@ export class Session {
|
|||
this.properties.recordingMode = !!this.properties.recordingMode ? this.properties.recordingMode : RecordingMode.MANUAL;
|
||||
this.properties.defaultOutputMode = !!this.properties.defaultOutputMode ? this.properties.defaultOutputMode : Recording.OutputMode.COMPOSED;
|
||||
this.properties.defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
|
||||
this.properties.allowTranscoding = !!this.properties.allowTranscoding ? this.properties.allowTranscoding : null;
|
||||
this.properties.forcedVideoCodec = !!this.properties.forcedVideoCodec ? this.properties.forcedVideoCodec : null;
|
||||
this.properties.forcedVideoCodec = !!this.properties.forcedVideoCodec ? this.properties.forcedVideoCodec : undefined;
|
||||
this.properties.allowTranscoding = this.properties.allowTranscoding != null ? this.properties.allowTranscoding : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique identifier of the Session
|
||||
*/
|
||||
public getSessionId(): string {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new token associated to Session object
|
||||
* @deprecated Use [[Session.createConnection]] instead to get a [[Connection]] object.
|
||||
*
|
||||
* @returns A Promise that is resolved to the _token_ if success and rejected with an Error object if not
|
||||
* @returns A Promise that is resolved to the generated _token_ string if success and rejected with an Error object if not
|
||||
*/
|
||||
public generateToken(tokenOptions?: TokenOptions): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
|
||||
const data = JSON.stringify({
|
||||
session: this.sessionId,
|
||||
role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : OpenViduRole.PUBLISHER,
|
||||
data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : '',
|
||||
kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : {},
|
||||
role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : null,
|
||||
data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : null,
|
||||
kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : null
|
||||
});
|
||||
|
||||
axios.post(
|
||||
this.ov.host + OpenVidu.API_TOKENS,
|
||||
data,
|
||||
|
@ -123,26 +125,57 @@ export class Session {
|
|||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
// SUCCESS response from openvidu-server. Resolve token
|
||||
resolve(res.data.id);
|
||||
resolve(res.data.token);
|
||||
} else {
|
||||
// ERROR response from openvidu-server. Resolve HTTP status
|
||||
reject(new Error(res.status.toString()));
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code (not 2xx)
|
||||
reject(new Error(error.response.status.toString()));
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(error.request);
|
||||
reject(new Error(error.request));
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.error('Error', error.message);
|
||||
reject(new Error(error.message));
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Connection object associated to Session object and configured with
|
||||
* `connectionProperties`. Each user connecting to the Session requires a Connection.
|
||||
* The token string value to send to the client side is available at [[Connection.token]].
|
||||
*
|
||||
* @returns A Promise that is resolved to the generated [[Connection]] object if success and rejected with an Error object if not
|
||||
*/
|
||||
public createConnection(connectionProperties?: ConnectionProperties): Promise<Connection> {
|
||||
return new Promise<Connection>((resolve, reject) => {
|
||||
const data = JSON.stringify({
|
||||
role: (!!connectionProperties && !!connectionProperties.role) ? connectionProperties.role : null,
|
||||
data: (!!connectionProperties && !!connectionProperties.data) ? connectionProperties.data : null,
|
||||
record: !!connectionProperties ? connectionProperties.record : null,
|
||||
kurentoOptions: (!!connectionProperties && !!connectionProperties.kurentoOptions) ? connectionProperties.kurentoOptions : null
|
||||
});
|
||||
axios.post(
|
||||
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/connection',
|
||||
data,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': this.ov.basicAuth,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
// SUCCESS response from openvidu-server. Store and resolve Connection
|
||||
const connection = new Connection(res.data);
|
||||
this.connections.push(connection);
|
||||
if (connection.status === 'active') {
|
||||
this.activeConnections.push(connection);
|
||||
}
|
||||
resolve(new Connection(res.data));
|
||||
} else {
|
||||
// ERROR response from openvidu-server. Resolve HTTP status
|
||||
reject(new Error(res.status.toString()));
|
||||
}
|
||||
}).catch(error => {
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -174,29 +207,17 @@ export class Session {
|
|||
reject(new Error(res.status.toString()));
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code (not 2xx)
|
||||
reject(new Error(error.response.status.toString()));
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(error.request);
|
||||
reject(new Error(error.request));
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.error('Error', error.message);
|
||||
reject(new Error(error.message));
|
||||
}
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of active
|
||||
* connections of the Session ([[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]] or [[Session.forceUnpublish]].
|
||||
* Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of
|
||||
* Connections of the Session ([[Session.connections]], [[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]],
|
||||
* [[Session.forceUnpublish]] or [[Session.updateConnection]].
|
||||
*
|
||||
* To update every Session object owned by OpenVidu object, call [[OpenVidu.fetch]]
|
||||
* To update all Session objects owned by OpenVidu object at once, call [[OpenVidu.fetch]]
|
||||
*
|
||||
* @returns A promise resolved to true if the Session status has changed with respect to the server, or to false if not.
|
||||
* This applies to any property or sub-property of the Session object
|
||||
|
@ -205,7 +226,7 @@ export class Session {
|
|||
return new Promise<boolean>((resolve, reject) => {
|
||||
const beforeJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
|
||||
axios.get(
|
||||
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId,
|
||||
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '?pendingConnections=true',
|
||||
{
|
||||
headers: {
|
||||
'Authorization': this.ov.basicAuth,
|
||||
|
@ -216,7 +237,7 @@ export class Session {
|
|||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
// SUCCESS response from openvidu-server
|
||||
this.resetSessionWithJson(res.data);
|
||||
this.resetWithJson(res.data);
|
||||
const afterJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
|
||||
const hasChanged: boolean = !(beforeJSON === afterJSON);
|
||||
console.log("Session info fetched for session '" + this.sessionId + "'. Any change: " + hasChanged);
|
||||
|
@ -226,32 +247,26 @@ export class Session {
|
|||
reject(new Error(res.status.toString()));
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code (not 2xx)
|
||||
reject(new Error(error.response.status.toString()));
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(error.request);
|
||||
reject(new Error(error.request));
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.error('Error', error.message);
|
||||
reject(new Error(error.message));
|
||||
}
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the user with Connection `connectionId` to leave the session. OpenVidu Browser will trigger the proper events on the client-side
|
||||
* (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`
|
||||
* Removes the Connection from the Session. This can translate into a forced eviction of a user from the Session if the
|
||||
* Connection had status `active` or into a token invalidation if no user had taken the Connection yet (status `pending`).
|
||||
*
|
||||
* You can get `connection` parameter from [[Session.activeConnections]] array ([[Connection.connectionId]] for getting each `connectionId` property).
|
||||
* Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server
|
||||
* In the first case, OpenVidu Browser will trigger the proper events in the client-side (`streamDestroyed`, `connectionDestroyed`,
|
||||
* `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`.
|
||||
*
|
||||
* @returns A Promise that is resolved if the user was successfully disconnected and rejected with an Error object if not
|
||||
* In the second case, the token of the Connection will be invalidated and no user will be able to connect to the session with it.
|
||||
*
|
||||
* This method automatically updates the properties of the local affected objects. This means that there is no need to call
|
||||
* [[Session.fetch]] or [[OpenVidu.fetch]]] to see the changes consequence of the execution of this method applied in the local objects.
|
||||
*
|
||||
* @param connection The Connection object to remove from the session, or its `connectionId` property
|
||||
*
|
||||
* @returns A Promise that is resolved if the Connection was successfully removed from the Session and rejected with an Error object if not
|
||||
*/
|
||||
public forceDisconnect(connection: string | Connection): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
|
@ -267,9 +282,9 @@ export class Session {
|
|||
.then(res => {
|
||||
if (res.status === 204) {
|
||||
// SUCCESS response from openvidu-server
|
||||
// Remove connection from activeConnections array
|
||||
// Remove connection from connections array
|
||||
let connectionClosed;
|
||||
this.activeConnections = this.activeConnections.filter(con => {
|
||||
this.connections = this.connections.filter(con => {
|
||||
if (con.connectionId !== connectionId) {
|
||||
return true;
|
||||
} else {
|
||||
|
@ -280,7 +295,7 @@ export class Session {
|
|||
// Remove every Publisher of the closed connection from every subscriber list of other connections
|
||||
if (!!connectionClosed) {
|
||||
connectionClosed.publishers.forEach(publisher => {
|
||||
this.activeConnections.forEach(con => {
|
||||
this.connections.forEach(con => {
|
||||
con.subscribers = con.subscribers.filter(subscriber => {
|
||||
// tslint:disable:no-string-literal
|
||||
if (!!subscriber['streamId']) {
|
||||
|
@ -295,8 +310,9 @@ export class Session {
|
|||
});
|
||||
});
|
||||
} else {
|
||||
console.warn("The closed connection wasn't fetched in OpenVidu Java Client. No changes in the collection of active connections of the Session");
|
||||
console.warn("The closed connection wasn't fetched in OpenVidu Node Client. No changes in the collection of active connections of the Session");
|
||||
}
|
||||
this.updateActiveConnectionsArray();
|
||||
console.log("Connection '" + connectionId + "' closed");
|
||||
resolve();
|
||||
} else {
|
||||
|
@ -305,30 +321,22 @@ export class Session {
|
|||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code (not 2xx)
|
||||
reject(new Error(error.response.status.toString()));
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(error.request);
|
||||
reject(new Error(error.request));
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.error('Error', error.message);
|
||||
reject(new Error(error.message));
|
||||
}
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces some user to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it).
|
||||
* Forces some Connection to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it).
|
||||
* OpenVidu Browser will trigger the proper events on the client-side (`streamDestroyed`) with reason set to `"forceUnpublishByServer"`.
|
||||
*
|
||||
* You can get `publisher` parameter from [[Connection.publishers]] array ([[Publisher.streamId]] for getting each `streamId` property).
|
||||
* Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server
|
||||
* Remember to call [[Session.fetch]] or [[OpenVidu.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server
|
||||
*
|
||||
* This method automatically updates the properties of the local affected objects. This means that there is no need to call
|
||||
* [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects.
|
||||
*
|
||||
* @param publisher The Publisher object to unpublish, or its `streamId` property
|
||||
*
|
||||
* @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not
|
||||
*/
|
||||
|
@ -347,7 +355,7 @@ export class Session {
|
|||
.then(res => {
|
||||
if (res.status === 204) {
|
||||
// SUCCESS response from openvidu-server
|
||||
this.activeConnections.forEach(connection => {
|
||||
this.connections.forEach(connection => {
|
||||
// Try to remove the Publisher from the Connection publishers collection
|
||||
connection.publishers = connection.publishers.filter(pub => pub.streamId !== streamId);
|
||||
// Try to remove the Publisher from the Connection subscribers collection
|
||||
|
@ -363,6 +371,7 @@ export class Session {
|
|||
}
|
||||
}
|
||||
});
|
||||
this.updateActiveConnectionsArray();
|
||||
console.log("Stream '" + streamId + "' unpublished");
|
||||
resolve();
|
||||
} else {
|
||||
|
@ -370,24 +379,79 @@ export class Session {
|
|||
reject(new Error(res.status.toString()));
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code (not 2xx)
|
||||
reject(new Error(error.response.status.toString()));
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(error.request);
|
||||
reject(new Error(error.request));
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.error('Error', error.message);
|
||||
reject(new Error(error.message));
|
||||
}
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* **This feature is part of OpenVidu Pro tier** <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* Updates the properties of a Connection with a [[ConnectionProperties]] object.
|
||||
* Only these properties can be updated:
|
||||
*
|
||||
* - [[ConnectionProperties.role]]
|
||||
* - [[ConnectionProperties.record]]
|
||||
*
|
||||
* This method automatically updates the properties of the local affected objects. This means that there is no need to call
|
||||
* [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects.
|
||||
*
|
||||
* The affected client will trigger one [ConnectionPropertyChangedEvent](/en/stable/api/openvidu-browser/classes/connectionpropertychangedevent.html)
|
||||
* for each modified property.
|
||||
*
|
||||
* @param connectionId The [[Connection.connectionId]] of the Connection object to modify
|
||||
* @param connectionProperties A new [[ConnectionProperties]] object with the updated values to apply
|
||||
*
|
||||
* @returns A Promise that is resolved to the updated [[Connection]] object if the operation was
|
||||
* successful and rejected with an Error object if not
|
||||
*/
|
||||
public updateConnection(connectionId: string, connectionProperties: ConnectionProperties): Promise<Connection | undefined> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
axios.patch(
|
||||
this.ov.host + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId,
|
||||
connectionProperties,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': this.ov.basicAuth,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
console.log('Connection ' + connectionId + ' updated');
|
||||
} else {
|
||||
// ERROR response from openvidu-server. Resolve HTTP status
|
||||
reject(new Error(res.status.toString()));
|
||||
return;
|
||||
}
|
||||
// Update the actual Connection object with the new options
|
||||
const existingConnection: Connection = this.connections.find(con => con.connectionId === connectionId);
|
||||
if (!existingConnection) {
|
||||
// The updated Connection is not available in local map
|
||||
const newConnection: Connection = new Connection(res.data);
|
||||
this.connections.push(newConnection);
|
||||
this.updateActiveConnectionsArray();
|
||||
resolve(newConnection);
|
||||
} else {
|
||||
// The updated Connection was available in local map
|
||||
existingConnection.overrideConnectionProperties(connectionProperties);
|
||||
this.updateActiveConnectionsArray();
|
||||
resolve(existingConnection);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.handleError(error, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public getSessionId(): string {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -399,18 +463,17 @@ export class Session {
|
|||
}
|
||||
|
||||
const mediaMode = !!this.properties.mediaMode ? this.properties.mediaMode : MediaMode.ROUTED;
|
||||
const recordingMode = !!this.properties.recordingMode ? this.properties.recordingMode : RecordingMode.MANUAL;
|
||||
const recordingMode = !!this.properties.recordingMode ? this.properties.recordingMode : RecordingMode.MANUAL;
|
||||
const defaultOutputMode = !!this.properties.defaultOutputMode ? this.properties.defaultOutputMode : Recording.OutputMode.COMPOSED;
|
||||
const defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
|
||||
const defaultCustomLayout = !!this.properties.defaultCustomLayout ? this.properties.defaultCustomLayout : '';
|
||||
const defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
|
||||
const defaultCustomLayout = !!this.properties.defaultCustomLayout ? this.properties.defaultCustomLayout : '';
|
||||
const customSessionId = !!this.properties.customSessionId ? this.properties.customSessionId : '';
|
||||
const forcedVideoCodec = !!this.properties.forcedVideoCodec ? this.properties.forcedVideoCodec : null;
|
||||
const allowTranscoding = !!this.properties.allowTranscoding ? this.properties.allowTranscoding : null;
|
||||
|
||||
const data = JSON.stringify({ mediaMode, recordingMode,
|
||||
defaultOutputMode, defaultRecordingLayout, defaultCustomLayout,
|
||||
customSessionId, forcedVideoCodec, allowTranscoding
|
||||
});
|
||||
const mediaNode = !!this.properties.mediaNode ? this.properties.mediaNode : undefined;
|
||||
const forcedVideoCodec = !!this.properties.forcedVideoCodec ? this.properties.forcedVideoCodec : undefined;
|
||||
const allowTranscoding = this.properties.allowTranscoding != null ? this.properties.allowTranscoding : undefined;
|
||||
|
||||
const data = JSON.stringify({mediaMode, recordingMode, defaultOutputMode, defaultRecordingLayout, defaultCustomLayout,
|
||||
customSessionId, mediaNode, forcedVideoCodec, allowTranscoding});
|
||||
|
||||
axios.post(
|
||||
this.ov.host + OpenVidu.API_SESSIONS,
|
||||
|
@ -431,7 +494,9 @@ export class Session {
|
|||
this.properties.recordingMode = recordingMode;
|
||||
this.properties.defaultOutputMode = defaultOutputMode;
|
||||
this.properties.defaultRecordingLayout = defaultRecordingLayout;
|
||||
this.properties.defaultCustomLayout = defaultCustomLayout;
|
||||
this.properties.customSessionId = customSessionId;
|
||||
this.properties.mediaNode = mediaNode;
|
||||
this.properties.forcedVideoCodec = res.data.forcedVideoCodec;
|
||||
this.properties.allowTranscoding = res.data.allowTranscoding;
|
||||
resolve(this.sessionId);
|
||||
|
@ -467,58 +532,67 @@ export class Session {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
public resetSessionWithJson(json): Session {
|
||||
public resetWithJson(json): Session {
|
||||
this.sessionId = json.sessionId;
|
||||
this.createdAt = json.createdAt;
|
||||
this.recording = json.recording;
|
||||
let customSessionId: string;
|
||||
let defaultCustomLayout: string;
|
||||
if (!!this.properties) {
|
||||
customSessionId = this.properties.customSessionId;
|
||||
defaultCustomLayout = !!json.defaultCustomLayout ? json.defaultCustomLayout : this.properties.defaultCustomLayout;
|
||||
}
|
||||
this.properties = {
|
||||
customSessionId: json.customSessionId,
|
||||
mediaMode: json.mediaMode,
|
||||
recordingMode: json.recordingMode,
|
||||
defaultOutputMode: json.defaultOutputMode,
|
||||
defaultRecordingLayout: json.defaultRecordingLayout,
|
||||
forcedVideoCodec: !!json.forcedVideoCodec ? json.forcedVideoCodec : null,
|
||||
allowTranscoding: !!json.allowTranscoding ? json.allowTranscoding : null
|
||||
defaultCustomLayout: json.defaultCustomLayout,
|
||||
forcedVideoCodec: json.forcedVideoCodec,
|
||||
allowTranscoding: json.allowTranscoding
|
||||
};
|
||||
if (!!customSessionId) {
|
||||
this.properties.customSessionId = customSessionId;
|
||||
} else if (!!json.customSessionId) {
|
||||
this.properties.customSessionId = json.customSessionId;
|
||||
if (json.defaultRecordingLayout == null) {
|
||||
delete this.properties.defaultRecordingLayout;
|
||||
}
|
||||
if (!!defaultCustomLayout) {
|
||||
this.properties.defaultCustomLayout = defaultCustomLayout;
|
||||
if (json.customSessionId == null) {
|
||||
delete this.properties.customSessionId;
|
||||
}
|
||||
if (json.defaultCustomLayout == null) {
|
||||
delete this.properties.defaultCustomLayout;
|
||||
}
|
||||
if (json.mediaNode == null) {
|
||||
delete this.properties.mediaNode;
|
||||
}
|
||||
if (json.forcedVideoCodec == null) {
|
||||
delete this.properties.forcedVideoCodec;
|
||||
}
|
||||
if (json.allowTranscoding == null) {
|
||||
delete this.properties.allowTranscoding;
|
||||
}
|
||||
|
||||
this.activeConnections = [];
|
||||
json.connections.content.forEach(connection => {
|
||||
const publishers: Publisher[] = [];
|
||||
connection.publishers.forEach(publisher => {
|
||||
publishers.push(new Publisher(publisher));
|
||||
});
|
||||
const subscribers: string[] = [];
|
||||
connection.subscribers.forEach(subscriber => {
|
||||
subscribers.push(subscriber.streamId);
|
||||
});
|
||||
this.activeConnections.push(
|
||||
new Connection(
|
||||
connection.connectionId,
|
||||
connection.createdAt,
|
||||
connection.role,
|
||||
connection.token,
|
||||
connection.location,
|
||||
connection.platform,
|
||||
connection.serverData,
|
||||
connection.clientData,
|
||||
publishers,
|
||||
subscribers));
|
||||
// 1. Array to store fetched connections and later remove closed ones
|
||||
const fetchedConnectionIds: string[] = [];
|
||||
json.connections.content.forEach(jsonConnection => {
|
||||
|
||||
const connectionObj: Connection = new Connection(jsonConnection);
|
||||
fetchedConnectionIds.push(connectionObj.connectionId);
|
||||
let storedConnection = this.connections.find(c => c.connectionId === connectionObj.connectionId);
|
||||
|
||||
if (!!storedConnection) {
|
||||
// 2. Update existing Connection
|
||||
storedConnection.resetWithJson(jsonConnection);
|
||||
} else {
|
||||
// 3. Add new Connection
|
||||
this.connections.push(connectionObj);
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Remove closed sessions from local collection
|
||||
for (var i = this.connections.length - 1; i >= 0; --i) {
|
||||
if (!fetchedConnectionIds.includes(this.connections[i].connectionId)) {
|
||||
this.connections.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Order connections by time of creation
|
||||
this.activeConnections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0));
|
||||
this.connections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0));
|
||||
// Populate activeConnections array
|
||||
this.updateActiveConnectionsArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -530,13 +604,13 @@ export class Session {
|
|||
this.sessionId === other.sessionId &&
|
||||
this.createdAt === other.createdAt &&
|
||||
this.recording === other.recording &&
|
||||
this.activeConnections.length === other.activeConnections.length &&
|
||||
this.connections.length === other.connections.length &&
|
||||
JSON.stringify(this.properties) === JSON.stringify(other.properties)
|
||||
);
|
||||
if (equals) {
|
||||
let i = 0;
|
||||
while (equals && i < this.activeConnections.length) {
|
||||
equals = this.activeConnections[i].equalTo(other.activeConnections[i]);
|
||||
while (equals && i < this.connections.length) {
|
||||
equals = this.connections[i].equalTo(other.connections[i]);
|
||||
i++;
|
||||
}
|
||||
return equals;
|
||||
|
@ -556,4 +630,36 @@ export class Session {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private updateActiveConnectionsArray() {
|
||||
this.activeConnections = [];
|
||||
this.connections.forEach(con => {
|
||||
if (con.status === 'active') {
|
||||
this.activeConnections.push(con);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
private handleError(error: AxiosError, reject: (reason?: any) => void) {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code (not 2xx)
|
||||
reject(new Error(error.response.status.toString()));
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.error(error.request);
|
||||
reject(new Error(error.request));
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.error('Error', error.message);
|
||||
reject(new Error(error.message));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,21 +65,31 @@ export interface SessionProperties {
|
|||
* If this parameter is undefined or an empty string, OpenVidu Server will generate a random sessionId for you.
|
||||
*/
|
||||
customSessionId?: string;
|
||||
|
||||
|
||||
/**
|
||||
* **This feature is part of OpenVidu Pro tier** <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
||||
*
|
||||
* The Media Node where to host the session. The default option if this property is not defined is the less loaded
|
||||
* Media Node at the moment the first user joins the session. This object defines the following properties as Media Node selector:
|
||||
* - `id`: Media Node unique identifier
|
||||
*/
|
||||
mediaNode?: {
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* It defines which video codec do you want to be forcibly used for this session.
|
||||
* This allows browsers/clients to use the same codec avoiding transcoding in the media server.
|
||||
* If the browser/client is not compatible with the specified codec and [[allowTranscoding]]
|
||||
* If the browser/client is not compatible with the specified codec and [[allowTranscoding]]
|
||||
* is <code>false</code> and exception will occur.
|
||||
*
|
||||
* If forcedVideoCodec is set to NONE, no codec will be forced.
|
||||
*
|
||||
* If forcedVideoCodec is set to NONE, no codec will be forced.
|
||||
*/
|
||||
forcedVideoCodec?: VideoCodec;
|
||||
|
||||
forcedVideoCodec?: string;
|
||||
|
||||
/**
|
||||
* It defines if you want to allow transcoding in the media server or not
|
||||
* when [[forcedVideoCodec]] is not compatible with the browser/client.
|
||||
*/
|
||||
allowTranscoding?: boolean;
|
||||
|
||||
}
|
||||
|
|
|
@ -18,10 +18,17 @@
|
|||
import { OpenViduRole } from './OpenViduRole';
|
||||
|
||||
/**
|
||||
* See [[Session.generateToken]]
|
||||
* @deprecated Use [[ConnectionProperties]] instead
|
||||
*/
|
||||
export interface TokenOptions {
|
||||
|
||||
/**
|
||||
* The role assigned to this token
|
||||
*
|
||||
* @default PUBLISHER
|
||||
*/
|
||||
role?: OpenViduRole;
|
||||
|
||||
/**
|
||||
* Secure (server-side) data associated to this token. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object.
|
||||
* - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[TokenOptions.data]] property.
|
||||
|
@ -30,11 +37,6 @@ export interface TokenOptions {
|
|||
*/
|
||||
data?: string;
|
||||
|
||||
/**
|
||||
* The role assigned to this token
|
||||
*/
|
||||
role?: OpenViduRole;
|
||||
|
||||
/**
|
||||
* **WARNING**: experimental option. This interface may change in the near future
|
||||
*
|
||||
|
|
|
@ -3,6 +3,8 @@ export * from './OpenViduRole';
|
|||
export * from './Session';
|
||||
export * from './SessionProperties';
|
||||
export * from './TokenOptions';
|
||||
export * from './ConnectionProperties';
|
||||
export * from './ConnectionType';
|
||||
export * from './MediaMode';
|
||||
export * from './RecordingLayout';
|
||||
export * from './RecordingMode';
|
||||
|
|
|
@ -44,18 +44,18 @@ Parameters:
|
|||
# OpenVidu configuration
|
||||
|
||||
OpenViduSecret:
|
||||
Description: "Secret to connect to this OpenVidu Platform. No whitespaces or quotations allowed"
|
||||
Description: "Secret to connect to this OpenVidu Platform. Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')"
|
||||
Type: String
|
||||
AllowedPattern: ^((?!")(?! ).)+$
|
||||
AllowedPattern: ^[a-zA-Z0-9_-]+$
|
||||
NoEcho: true
|
||||
ConstraintDescription: OpenVidu Secret is mandatory
|
||||
ConstraintDescription: "Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')"
|
||||
|
||||
# EC2 Instance configuration
|
||||
|
||||
InstanceType:
|
||||
Description: "Specifies the EC2 instance type for your OpenVidu instance"
|
||||
Type: String
|
||||
Default: t2.xlarge
|
||||
Default: c5.xlarge
|
||||
AllowedValues:
|
||||
- t2.large
|
||||
- t2.xlarge
|
||||
|
@ -115,10 +115,12 @@ Parameters:
|
|||
- false
|
||||
Default: true
|
||||
|
||||
#start_mappings
|
||||
Mappings:
|
||||
OVAMIMAP:
|
||||
eu-west-1:
|
||||
AMI: OV_AMI_ID
|
||||
#end_mappings
|
||||
|
||||
Metadata:
|
||||
'AWS::CloudFormation::Interface':
|
||||
|
@ -272,6 +274,10 @@ Resources:
|
|||
|
||||
# Restart all services
|
||||
pushd /opt/openvidu
|
||||
docker-compose up -d kms
|
||||
until docker-compose ps | grep kms | grep healthy; do
|
||||
echo "Waiting kms..."
|
||||
done
|
||||
docker-compose up -d
|
||||
popd
|
||||
mode: "000755"
|
||||
|
@ -293,6 +299,8 @@ Resources:
|
|||
|
||||
cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenviduServer
|
||||
|
||||
export HOME="/root"
|
||||
|
||||
# Replace .env variables
|
||||
/usr/local/bin/feedGroupVars.sh || { echo "[Openvidu] Parameters incorrect/insufficient"; exit 1; }
|
||||
|
||||
|
@ -306,6 +314,10 @@ Resources:
|
|||
|
||||
# Start openvidu application
|
||||
pushd /opt/openvidu
|
||||
docker-compose up -d kms
|
||||
until docker-compose ps | grep kms | grep healthy; do
|
||||
echo "Waiting kms..."
|
||||
done
|
||||
docker-compose up -d
|
||||
popd
|
||||
|
||||
|
@ -327,10 +339,9 @@ Resources:
|
|||
BlockDeviceMappings:
|
||||
- DeviceName: /dev/sda1
|
||||
Ebs:
|
||||
VolumeType: io1
|
||||
Iops: 200
|
||||
VolumeType: gp2
|
||||
DeleteOnTermination: true
|
||||
VolumeSize: 100
|
||||
VolumeSize: 200
|
||||
|
||||
MyEIP:
|
||||
Type: 'AWS::EC2::EIPAssociation'
|
||||
|
@ -373,11 +384,11 @@ Resources:
|
|||
CidrIp: 0.0.0.0/0
|
||||
- IpProtocol: udp
|
||||
FromPort: 40000
|
||||
ToPort: 65535
|
||||
ToPort: 57000
|
||||
CidrIp: 0.0.0.0/0
|
||||
- IpProtocol: tcp
|
||||
FromPort: 40000
|
||||
ToPort: 65535
|
||||
ToPort: 57000
|
||||
CidrIp: 0.0.0.0/0
|
||||
|
||||
Outputs:
|
||||
|
|
|
@ -141,5 +141,5 @@ Resources:
|
|||
Type: AWS::CloudFormation::WaitCondition
|
||||
CreationPolicy:
|
||||
ResourceSignal:
|
||||
Timeout: PT10M
|
||||
Timeout: PT20M
|
||||
Count: 1
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
#!/bin/bash -x
|
||||
set -eu -o pipefail
|
||||
|
||||
CF_OVP_TARGET=${CF_OVP_TARGET:-nomarket}
|
||||
CF_RELEASE=${CF_RELEASE:-false}
|
||||
AWS_KEY_NAME=${AWS_KEY_NAME:-}
|
||||
|
||||
if [[ $CF_RELEASE == "true" ]]; then
|
||||
git checkout v$OPENVIDU_VERSION
|
||||
fi
|
||||
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID}
|
||||
export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY}
|
||||
export AWS_DEFAULT_REGION=us-east-1
|
||||
else
|
||||
export AWS_DEFAULT_REGION=eu-west-1
|
||||
fi
|
||||
export AWS_DEFAULT_REGION=eu-west-1
|
||||
|
||||
|
||||
DATESTAMP=$(date +%s)
|
||||
TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
||||
|
@ -22,13 +17,13 @@ TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
|||
# Get Latest Ubuntu AMI id from specified region
|
||||
# Parameters
|
||||
# $1 Aws region
|
||||
|
||||
getUbuntuAmiId() {
|
||||
local AMI_ID=$(
|
||||
aws --region ${1} ec2 describe-images \
|
||||
--filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64* \
|
||||
--query 'Images[*].[ImageId,CreationDate]' \
|
||||
--output text \
|
||||
| sort -k2 -r | head -n1 | cut -d$'\t' -f1
|
||||
--filters "Name=name,Values=*ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*" \
|
||||
--query "sort_by(Images, &CreationDate)" \
|
||||
| jq -r 'del(.[] | select(.ImageOwnerAlias != null)) | .[-1].ImageId'
|
||||
)
|
||||
echo $AMI_ID
|
||||
}
|
||||
|
@ -59,6 +54,16 @@ TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-ov-ce-am
|
|||
|
||||
# Update installation script
|
||||
if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then
|
||||
# Avoid overriding existing versions
|
||||
# Only master and non existing versions can be overriden
|
||||
if [[ ${OPENVIDU_VERSION} != "master" ]]; then
|
||||
INSTALL_SCRIPT_EXISTS=true
|
||||
aws s3api head-object --bucket aws.openvidu.io --key install_openvidu_$OPENVIDU_VERSION.sh || INSTALL_SCRIPT_EXISTS=false
|
||||
if [[ ${INSTALL_SCRIPT_EXISTS} == "true" ]]; then
|
||||
echo "Aborting updating s3://aws.openvidu.io/install_openvidu_${OPENVIDU_VERSION}.sh. File actually exists."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
aws s3 cp ../docker-compose/install_openvidu.sh s3://aws.openvidu.io/install_openvidu_$OPENVIDU_VERSION.sh --acl public-read
|
||||
fi
|
||||
|
||||
|
@ -85,11 +90,34 @@ echo "Cleaning up"
|
|||
aws cloudformation delete-stack --stack-name openvidu-ce-${DATESTAMP}
|
||||
|
||||
# Wait for the instance
|
||||
aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID}
|
||||
# Unfortunately, aws cli does not have a way to increase timeout
|
||||
WAIT_RETRIES=0
|
||||
WAIT_MAX_RETRIES=3
|
||||
until [ "${WAIT_RETRIES}" -ge "${WAIT_MAX_RETRIES}" ]
|
||||
do
|
||||
aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} && break
|
||||
WAIT_RETRIES=$((WAIT_RETRIES+1))
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Updating the template
|
||||
sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" CF-OpenVidu.yaml.template > CF-OpenVidu-${OPENVIDU_VERSION}.yaml
|
||||
sed -i "s/OPENVIDU_VERSION/${OPENVIDU_VERSION}/g" CF-OpenVidu-${OPENVIDU_VERSION}.yaml
|
||||
|
||||
# Update CF template
|
||||
if [[ ${UPDATE_CF} == "true" ]]; then
|
||||
# Avoid overriding existing versions
|
||||
# Only master and non existing versions can be overriden
|
||||
if [[ ${OPENVIDU_VERSION} != "master" ]]; then
|
||||
CF_EXIST=true
|
||||
aws s3api head-object --bucket aws.openvidu.io --key CF-OpenVidu-${OPENVIDU_VERSION}.yaml || CF_EXIST=false
|
||||
if [[ ${CF_EXIST} == "true" ]]; then
|
||||
echo "Aborting updating s3://aws.openvidu.io/CF-OpenVidu-${OPENVIDU_VERSION}.yaml. File actually exists."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
aws s3 cp CF-OpenVidu-${OPENVIDU_VERSION}.yaml s3://aws.openvidu.io/CF-OpenVidu-${OPENVIDU_VERSION}.yaml --acl public-read
|
||||
fi
|
||||
|
||||
rm $TEMPJSON
|
||||
rm cfn-mkt-ov-ce-ami.yaml
|
||||
|
|
|
@ -5,14 +5,12 @@ set -eu -o pipefail
|
|||
#
|
||||
# Input parameters:
|
||||
#
|
||||
# OV_AMI_NAME OpenVidu AMI Name
|
||||
# OV_AMI_ID OpenVidu AMI ID
|
||||
# OV_AMI_NAME OpenVidu AMI Name
|
||||
# OV_AMI_ID OpenVidu AMI ID
|
||||
# UPDATE_CF Boolean, true if you want to update CF template by OPENVIDU_VERSION
|
||||
# OPENVIDU_VERSION OpenVidu Version of the CF you want to update. It will update CF-OpenVidu-OPENVIDU_VERSION
|
||||
|
||||
export AWS_DEFAULT_REGION=eu-west-1
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID}
|
||||
export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY}
|
||||
fi
|
||||
|
||||
echo "Making original AMI public"
|
||||
aws ec2 wait image-exists --image-ids ${OV_AMI_ID}
|
||||
|
@ -71,13 +69,54 @@ do
|
|||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
|
||||
# Print and generate replicated AMIS
|
||||
REPLICATED_AMIS_FILE="replicated_amis.yaml"
|
||||
echo "OV IDs"
|
||||
{
|
||||
echo "#start_mappings"
|
||||
echo "Mappings:"
|
||||
echo " OVAMIMAP:"
|
||||
ITER=0
|
||||
for i in "${AMI_IDS[@]}"
|
||||
do
|
||||
AMI_ID=${AMI_IDS[$ITER]}
|
||||
REGION=${REGIONS[$ITER]}
|
||||
echo " ${REGION}:"
|
||||
echo " AMI: ${AMI_ID}"
|
||||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
echo "#end_mappings"
|
||||
echo ""
|
||||
} > "${REPLICATED_AMIS_FILE}" 2>&1
|
||||
|
||||
# Print replicated AMIs
|
||||
cat "${REPLICATED_AMIS_FILE}"
|
||||
|
||||
if [[ ${UPDATE_CF} == "true" ]]; then
|
||||
if [[ ! -z ${OPENVIDU_VERSION} ]]; then
|
||||
# Download s3 file
|
||||
aws s3 cp s3://aws.openvidu.io/CF-OpenVidu-${OPENVIDU_VERSION}.yaml CF-OpenVidu-${OPENVIDU_VERSION}.yaml
|
||||
sed -e "/^#end_mappings/r ${REPLICATED_AMIS_FILE}" -e '/^#start_mappings/,/^#end_mappings/d' -i CF-OpenVidu-${OPENVIDU_VERSION}.yaml
|
||||
aws s3 cp CF-OpenVidu-${OPENVIDU_VERSION}.yaml s3://aws.openvidu.io/CF-OpenVidu-${OPENVIDU_VERSION}.yaml --acl public-read
|
||||
fi
|
||||
fi
|
||||
|
||||
# Print AMI_LIST for delete_amis.sh
|
||||
AMI_LIST=""
|
||||
ITER=0
|
||||
for i in "${AMI_IDS[@]}"
|
||||
do
|
||||
AMI_ID=${AMI_IDS[$ITER]}
|
||||
REGION=${REGIONS[$ITER]}
|
||||
echo " ${REGION}:"
|
||||
echo " AMI: ${AMI_ID}"
|
||||
if [[ ${ITER} -eq 0 ]]; then
|
||||
AMI_LIST="${REGION}:${AMI_ID}"
|
||||
else
|
||||
AMI_LIST="${AMI_LIST},${REGION}:${AMI_ID}"
|
||||
fi
|
||||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
done
|
||||
echo "AMI_LIST: ${AMI_LIST}"
|
||||
|
||||
# Cleaning the house
|
||||
rm "${REPLICATED_AMIS_FILE}"
|
||||
rm CF-OpenVidu-${OPENVIDU_VERSION}.yaml
|
|
@ -39,6 +39,22 @@ LETSENCRYPT_EMAIL=user@example.com
|
|||
# SDKs, REST clients and browsers will have to connect to this port
|
||||
# HTTPS_PORT=443
|
||||
|
||||
# Old paths are considered now deprecated, but still supported by default.
|
||||
# OpenVidu Server will log a WARN message every time a deprecated path is called, indicating
|
||||
# the new path that should be used instead. You can set property SUPPORT_DEPRECATED_API=false
|
||||
# to stop allowing the use of old paths.
|
||||
# Default value is true
|
||||
# SUPPORT_DEPRECATED_API=true
|
||||
|
||||
# If true request to with www will be redirected to non-www requests
|
||||
# Default value is false
|
||||
# REDIRECT_WWW=false
|
||||
|
||||
# How many workers to configure in nginx proxy.
|
||||
# The more workers, the more requests will be handled
|
||||
# Default value is 10240
|
||||
# WORKER_CONNECTIONS=10240
|
||||
|
||||
# Access restrictions
|
||||
# In this section you will be able to restrict the IPs from which you can access to
|
||||
# Openvidu API and the Administration Panel
|
||||
|
@ -110,6 +126,15 @@ OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH=1000
|
|||
# 0 means unconstrained
|
||||
OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH=300
|
||||
|
||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_STREAMS_ALLOW_TRANSCODING=true
|
||||
# when a codec can not be forced, transcoding will be allowed
|
||||
# Default value is VP8
|
||||
# OPENVIDU_STREAMS_FORCED_VIDEO_CODEC=VP8
|
||||
|
||||
# Allow transcoding if codec specified in OPENVIDU_STREAMS_FORCED_VIDEO_CODEC can not be applied
|
||||
# Default value is false
|
||||
# OPENVIDU_STREAMS_ALLOW_TRANSCODING=false
|
||||
|
||||
# true to enable OpenVidu Webhook service. false' otherwise
|
||||
# Values: true | false
|
||||
OPENVIDU_WEBHOOK=false
|
||||
|
@ -138,10 +163,10 @@ OPENVIDU_SESSIONS_GARBAGE_INTERVAL=900
|
|||
OPENVIDU_SESSIONS_GARBAGE_THRESHOLD=3600
|
||||
|
||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_ALLOW_TRANSCODING=true
|
||||
# when a codec can not be forced, transcoding will be allowed
|
||||
# when a codec can not be forced, transcoding will be allowed
|
||||
# OPENVIDU_FORCED_CODEC=VP8
|
||||
|
||||
# Allow transcoding if codec specified in OPENVIDU_FORCED_CODEC can not be applied
|
||||
# Allow transcoding if codec specified in OPENVIDU_FORCED_CODEC can not be applied
|
||||
# OPENVIDU_ALLOW_TRANSCODING=false
|
||||
|
||||
# Call Detail Record enabled
|
||||
|
@ -154,16 +179,16 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
|
|||
|
||||
# Kurento Media Server image
|
||||
# --------------------------
|
||||
# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server-dev
|
||||
# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server
|
||||
# Uncomment the next line and define this variable with KMS image that you want use
|
||||
# KMS_IMAGE=kurento/kurento-media-server:6.14.0
|
||||
# KMS_IMAGE=kurento/kurento-media-server:6.15.0
|
||||
|
||||
# Kurento Media Server Level logs
|
||||
# -------------------------------
|
||||
# Uncomment the next line and define this variable to change
|
||||
# the verbosity level of the logs of KMS
|
||||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
||||
# KMS_DEBUG_LEVEL=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4
|
||||
# KMS_DOCKER_ENV_GST_DEBUG=
|
||||
|
||||
# Openvidu Server Level logs
|
||||
# --------------------------
|
||||
|
|
|
@ -9,11 +9,11 @@ services:
|
|||
#
|
||||
# Default Application
|
||||
#
|
||||
# Openvidu-Call Version: 2.15.0
|
||||
# Openvidu-Call Version: 2.16.0
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
app:
|
||||
image: openvidu/openvidu-call:2.15.0
|
||||
image: openvidu/openvidu-call:2.16.0
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
|
@ -21,3 +21,6 @@ services:
|
|||
- OPENVIDU_URL=http://localhost:5443
|
||||
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||
- CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
# Application based on OpenVidu should be specified in
|
||||
# docker-compose.override.yml file
|
||||
#
|
||||
# This docker-compose file coordinates all services of OpenVidu CE Platform.
|
||||
# This docker-compose file coordinates all services of OpenVidu CE Platform
|
||||
#
|
||||
# This file will be overridden when update OpenVidu Platform
|
||||
#
|
||||
# Openvidu Version: 2.15.0
|
||||
# Openvidu Version: 2.16.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
@ -22,10 +22,10 @@ version: '3.1'
|
|||
services:
|
||||
|
||||
openvidu-server:
|
||||
image: openvidu/openvidu-server:2.15.0
|
||||
image: openvidu/openvidu-server:2.17.0-dev2
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
entrypoint: ['/bin/bash', '-c', 'export COTURN_IP=`/usr/local/bin/discover_my_public_ip.sh`; /usr/local/bin/entrypoint.sh']
|
||||
entrypoint: ['/usr/local/bin/entrypoint.sh']
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||
|
@ -39,9 +39,13 @@ services:
|
|||
- KMS_URIS=["ws://localhost:8888/kurento"]
|
||||
- COTURN_REDIS_IP=127.0.0.1
|
||||
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||
- COTURN_IP=${COTURN_IP:-auto-ipv4}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
kms:
|
||||
image: ${KMS_IMAGE:-kurento/kurento-media-server:6.14.0}
|
||||
image: ${KMS_IMAGE:-kurento/kurento-media-server:6.15.0}
|
||||
restart: always
|
||||
network_mode: host
|
||||
ulimits:
|
||||
|
@ -49,20 +53,29 @@ services:
|
|||
volumes:
|
||||
- /opt/openvidu/kms-crashes:/opt/openvidu/kms-crashes
|
||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||
- /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs
|
||||
environment:
|
||||
- KMS_MIN_PORT=40000
|
||||
- KMS_MAX_PORT=57000
|
||||
- GST_DEBUG=${KMS_DEBUG_LEVEL:-}
|
||||
- GST_DEBUG=${KMS_DOCKER_ENV_GST_DEBUG:-}
|
||||
- KURENTO_LOG_FILE_SIZE=${KMS_DOCKER_ENV_KURENTO_LOG_FILE_SIZE:-100}
|
||||
- KURENTO_LOGS_PATH=/opt/openvidu/kurento-logs
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
redis:
|
||||
image: openvidu/openvidu-redis:1.0.0
|
||||
image: openvidu/openvidu-redis:2.0.0-dev2
|
||||
restart: always
|
||||
network_mode: host
|
||||
environment:
|
||||
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
coturn:
|
||||
image: openvidu/openvidu-coturn:1.0.0
|
||||
image: openvidu/openvidu-coturn:3.0.0-dev2
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
|
@ -72,14 +85,19 @@ services:
|
|||
- DB_PASSWORD=${OPENVIDU_SECRET}
|
||||
- MIN_PORT=57001
|
||||
- MAX_PORT=65535
|
||||
- ENABLE_COTURN_LOGS=true
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
nginx:
|
||||
image: openvidu/openvidu-proxy:3.0.0
|
||||
image: openvidu/openvidu-proxy:5.0.0-dev2
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./certificates:/etc/letsencrypt
|
||||
- ./owncert:/owncert
|
||||
- ./custom-nginx-vhosts:/etc/nginx/vhost.d/
|
||||
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout
|
||||
environment:
|
||||
- DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP}
|
||||
|
@ -91,3 +109,10 @@ services:
|
|||
- ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-}
|
||||
- PROXY_MODE=CE
|
||||
- WITH_APP=true
|
||||
- SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true}
|
||||
- REDIRECT_WWW=${REDIRECT_WWW:-false}
|
||||
- WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240}
|
||||
- PUBLIC_IP=${PROXY_PUBLIC_IP:-auto-ipv4}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# Global variables
|
||||
OPENVIDU_FOLDER=openvidu
|
||||
OPENVIDU_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.16"
|
||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${OPENVIDU_VERSION}
|
||||
|
||||
fatal_error() {
|
||||
|
@ -42,10 +43,6 @@ new_ov_installation() {
|
|||
--output "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/ce/docker-compose/readme.md \
|
||||
--output "${OPENVIDU_FOLDER}/readme.md" || fatal_error "Error when downloading the file 'readme.md'"
|
||||
printf '\n - readme.md'
|
||||
|
||||
# Add execution permissions
|
||||
printf "\n => Adding permission to 'openvidu' program..."
|
||||
chmod +x "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error while adding permission to 'openvidu' program"
|
||||
|
@ -54,6 +51,10 @@ new_ov_installation() {
|
|||
printf "\n => Creating folder 'owncert'..."
|
||||
mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the folder 'owncert'"
|
||||
|
||||
# Create vhost nginx folder
|
||||
printf "\n => Creating folder 'custom-nginx-vhosts'..."
|
||||
mkdir "${OPENVIDU_FOLDER}/custom-nginx-vhosts" || fatal_error "Error while creating the folder 'custom-nginx-vhosts'"
|
||||
|
||||
# Ready to use
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
@ -105,10 +106,13 @@ upgrade_ov() {
|
|||
|
||||
# Uppgrade Openvidu
|
||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && OPENVIDU_PREVIOUS_VERSION=2.13.0
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version"
|
||||
|
||||
# In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is
|
||||
# posible or not. If it is not posible launch a warning and stop the upgrade.
|
||||
if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then
|
||||
fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions."
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
|
@ -146,10 +150,6 @@ upgrade_ov() {
|
|||
--output "${TMP_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/ce/docker-compose/readme.md \
|
||||
--output "${TMP_FOLDER}/readme.md" || fatal_error "Error when downloading the file 'readme.md'"
|
||||
printf '\n - readme.md'
|
||||
|
||||
# Dowloading new images and stoped actual Openvidu
|
||||
printf '\n => Dowloading new images...'
|
||||
printf '\n'
|
||||
|
@ -187,12 +187,14 @@ upgrade_ov() {
|
|||
mv "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/readme.md" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'readme.md'"
|
||||
printf '\n - readme.md'
|
||||
|
||||
cp "${OPENVIDU_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
if [ -d "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-vhosts" ]; then
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-vhosts" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous directory 'custom-nginx-vhosts'"
|
||||
printf '\n - custom-nginx-vhosts'
|
||||
fi
|
||||
|
||||
# Move tmp files to Openvidu
|
||||
printf '\n => Updating files:'
|
||||
|
||||
|
@ -213,9 +215,6 @@ upgrade_ov() {
|
|||
mv "${TMP_FOLDER}/openvidu" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
mv "${TMP_FOLDER}/readme.md" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'readme.md'"
|
||||
printf '\n - readme.md'
|
||||
|
||||
printf "\n => Deleting 'tmp' folder"
|
||||
rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder"
|
||||
|
||||
|
@ -249,7 +248,9 @@ upgrade_ov() {
|
|||
printf '\n'
|
||||
printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}"
|
||||
printf '\n'
|
||||
printf '\n For more information, check readme.md'
|
||||
printf '\n For more information, check:'
|
||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/deploying-on-premises/"
|
||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/upgrading/"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
}
|
||||
|
|
|
@ -159,6 +159,16 @@ generate_report() {
|
|||
printf '\n'
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
printf "\n ---------------------------------------"
|
||||
printf "\n KMS"
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
kurento_logs
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
||||
printf "\n ======================================="
|
||||
printf "\n = CONTAINER ENVS VARIABLES ="
|
||||
printf "\n ======================================="
|
||||
|
@ -189,7 +199,8 @@ usage() {
|
|||
printf "\n\tstart\t\t\tStart all services"
|
||||
printf "\n\tstop\t\t\tStop all services"
|
||||
printf "\n\trestart\t\t\tRestart all stoped and running services"
|
||||
printf "\n\tlogs\t\t\tShow openvidu-server logs"
|
||||
printf "\n\tlogs [-f]\t\tShow openvidu logs."
|
||||
printf "\n\tkms-logs [-f]\t\tShow kms logs"
|
||||
printf "\n\tupgrade\t\t\tUpgrade to the lastest Openvidu version"
|
||||
printf "\n\tupgrade [version]\tUpgrade to the specific Openvidu version"
|
||||
printf "\n\tversion\t\t\tShow version of Openvidu Server"
|
||||
|
@ -198,6 +209,14 @@ usage() {
|
|||
printf "\n"
|
||||
}
|
||||
|
||||
kurento_logs() {
|
||||
if [[ "$1" == "-f" ]]; then
|
||||
tail -f /opt/openvidu/kurento-logs/*.log
|
||||
else
|
||||
cat /opt/openvidu/kurento-logs/*.log
|
||||
fi
|
||||
}
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
docker-compose up -d
|
||||
|
@ -215,7 +234,18 @@ case $1 in
|
|||
;;
|
||||
|
||||
logs)
|
||||
docker-compose logs -f openvidu-server
|
||||
case $2 in
|
||||
"-f")
|
||||
docker-compose logs -f openvidu-server
|
||||
;;
|
||||
*)
|
||||
docker-compose logs openvidu-server
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
kms-logs)
|
||||
kurento_logs $2
|
||||
;;
|
||||
|
||||
upgrade)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
global:
|
||||
owner: openvidu@gmail.com
|
||||
owner: info@openvidu.io
|
||||
qsname: openvidu-ce
|
||||
regions:
|
||||
- us-east-1
|
||||
|
|
|
@ -142,5 +142,5 @@ Resources:
|
|||
Type: AWS::CloudFormation::WaitCondition
|
||||
CreationPolicy:
|
||||
ResourceSignal:
|
||||
Timeout: PT10M
|
||||
Timeout: PT20M
|
||||
Count: 1
|
||||
|
|
|
@ -104,6 +104,12 @@ Resources:
|
|||
Tags:
|
||||
- Key: Name
|
||||
Value: !Ref AWS::StackName
|
||||
BlockDeviceMappings:
|
||||
- DeviceName: /dev/sda1
|
||||
Ebs:
|
||||
VolumeType: gp2
|
||||
DeleteOnTermination: true
|
||||
VolumeSize: 10
|
||||
UserData:
|
||||
"Fn::Base64":
|
||||
!Sub |
|
||||
|
@ -138,5 +144,5 @@ Resources:
|
|||
Type: AWS::CloudFormation::WaitCondition
|
||||
CreationPolicy:
|
||||
ResourceSignal:
|
||||
Timeout: PT10M
|
||||
Timeout: PT20M
|
||||
Count: 1
|
||||
|
|
|
@ -41,6 +41,22 @@ Parameters:
|
|||
LetsEncryptEmail:
|
||||
Description: "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications"
|
||||
Type: String
|
||||
|
||||
Recording:
|
||||
Description: |
|
||||
If 'disabled', recordings will not be active.
|
||||
If 'local' recordings will be saved in EC2 instance locally.
|
||||
If 's3', recordings will be stored in a S3 bucket"
|
||||
Type: String
|
||||
AllowedValues:
|
||||
- disabled
|
||||
- local
|
||||
- s3
|
||||
Default: local
|
||||
|
||||
S3RecordingsBucketName:
|
||||
Description: "S3 Bucket Name"
|
||||
Type: String
|
||||
|
||||
# OpenVidu Configuration
|
||||
|
||||
|
@ -52,39 +68,51 @@ Parameters:
|
|||
ConstraintDescription: OpenVidu Pro License is mandatory
|
||||
|
||||
OpenViduSecret:
|
||||
Description: "Secret to connect to this OpenVidu Platform. No whitespaces or quotations allowed"
|
||||
Description: "Secret to connect to this OpenVidu Platform. Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')"
|
||||
Type: String
|
||||
AllowedPattern: ^((?!")(?! ).)+$
|
||||
AllowedPattern: ^[a-zA-Z0-9_-]+$
|
||||
NoEcho: true
|
||||
ConstraintDescription: OpenVidu Secret is mandatory (no whitespaces or quotations allowed)
|
||||
ConstraintDescription: "Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')"
|
||||
|
||||
MediaNodesStartNumber:
|
||||
Description: "How many Media Nodes do you want on startup (EC2 instances will be launched)"
|
||||
Type: Number
|
||||
Default: 1
|
||||
|
||||
# Kibana configuration
|
||||
|
||||
KibanaUser:
|
||||
Description: "Username for Kibana Dashboard"
|
||||
# Elasticsearch configuration
|
||||
ElasticsearchUser:
|
||||
Description: "Username for Elasticsearch and Kibana"
|
||||
Type: String
|
||||
AllowedPattern: ^((?!")(?! ).)+$
|
||||
ConstraintDescription: Kibana user is mandatory (no whitespaces or quotations allowed)
|
||||
Default: kibanaadmin
|
||||
ConstraintDescription: Elasticsearch user is mandatory (no whitespaces or quotations allowed)
|
||||
Default: elasticadmin
|
||||
|
||||
KibanaPassword:
|
||||
Description: "Password for Kibana Dashboard"
|
||||
ElasticsearchPassword:
|
||||
Description: "Password for Elasticsearch and Kibana"
|
||||
Type: String
|
||||
AllowedPattern: ^((?!")(?! ).)+$
|
||||
NoEcho: true
|
||||
ConstraintDescription: Kibana password is mandatory (no whitespaces or quotations allowed)
|
||||
ConstraintDescription: Elasticsearch password is mandatory (no whitespaces or quotations allowed)
|
||||
|
||||
# Elasticsearch configuration
|
||||
ElasticsearchUrl:
|
||||
Description: "If you have an external Elasticsearch service running, put here the url to the service. If empty, an Elasticsearch service will be deployed next to OpenVidu."
|
||||
Type: String
|
||||
AllowedPattern: (^(http|https):\/\/.*:[1-9]{1,5}+.*$|^$)
|
||||
ConstraintDescription: "It is very important to specify the Elasticsearch URL with the port used by this service. For example: https://es-example:443"
|
||||
|
||||
KibanaUrl:
|
||||
Description: "If you have an external Kibana service running, put here the url to the service. If empty, a Kibana service will be deployed next to OpenVidu."
|
||||
Type: String
|
||||
AllowedPattern: (^(http|https):\/\/.*:[1-9]{1,5}+.*$|^$)
|
||||
ConstraintDescription: "It is very important to specify the url with port used by this service. For example: https://kibana-example:443"
|
||||
|
||||
# EC2 Instance configuration
|
||||
|
||||
AwsInstanceTypeOV:
|
||||
Description: "Specifies the EC2 instance type for your OpenVidu Server Pro Node"
|
||||
Type: String
|
||||
Default: t2.xlarge
|
||||
Default: c5.xlarge
|
||||
AllowedValues:
|
||||
- t2.large
|
||||
- t2.xlarge
|
||||
|
@ -124,7 +152,7 @@ Parameters:
|
|||
AwsInstanceTypeKMS:
|
||||
Description: "Specifies the EC2 instance type for your Media Nodes"
|
||||
Type: String
|
||||
Default: t2.xlarge
|
||||
Default: c5.xlarge
|
||||
AllowedValues:
|
||||
- t2.large
|
||||
- t2.xlarge
|
||||
|
@ -186,6 +214,7 @@ Parameters:
|
|||
- false
|
||||
Default: true
|
||||
|
||||
#start_mappings
|
||||
Mappings:
|
||||
OVAMIMAP:
|
||||
eu-west-1:
|
||||
|
@ -194,6 +223,7 @@ Mappings:
|
|||
KMSAMIMAP:
|
||||
eu-west-1:
|
||||
AMI: KMS_AMI_ID
|
||||
#end_mappings
|
||||
|
||||
Metadata:
|
||||
'AWS::CloudFormation::Interface':
|
||||
|
@ -214,10 +244,17 @@ Metadata:
|
|||
- OpenViduSecret
|
||||
- MediaNodesStartNumber
|
||||
- Label:
|
||||
default: Kibana configuration
|
||||
default: OpenVidu Recording Configuration
|
||||
Parameters:
|
||||
- KibanaUser
|
||||
- KibanaPassword
|
||||
- Recording
|
||||
- S3RecordingsBucketName
|
||||
- Label:
|
||||
default: Elasticsearch and Kibana configuration
|
||||
Parameters:
|
||||
- ElasticsearchUrl
|
||||
- KibanaUrl
|
||||
- ElasticsearchUser
|
||||
- ElasticsearchPassword
|
||||
- Label:
|
||||
default: EC2 Instance configuration
|
||||
Parameters:
|
||||
|
@ -248,6 +285,10 @@ Metadata:
|
|||
default: "URL to the key file (owncert)"
|
||||
LetsEncryptEmail:
|
||||
default: "Email for Let's Encrypt (letsencrypt)"
|
||||
Recording:
|
||||
default: "OpenVidu Recording"
|
||||
S3RecordingsBucketName:
|
||||
default: "S3 Bucket where recordings will be stored"
|
||||
# OpenVidu configuration
|
||||
OpenViduLicense:
|
||||
default: "OpenVidu Pro License key"
|
||||
|
@ -256,10 +297,14 @@ Metadata:
|
|||
OpenViduSecret:
|
||||
default: "Openvidu Secret"
|
||||
# Kibana configuration
|
||||
KibanaUser:
|
||||
default: "Kibana username"
|
||||
KibanaPassword:
|
||||
default: "Kibana password"
|
||||
ElasticsearchUrl:
|
||||
default: "Elasticsearch URL"
|
||||
KibanaUrl:
|
||||
default: "Kibana URL"
|
||||
ElasticsearchUser:
|
||||
default: "Elasticsearch and Kibana username"
|
||||
ElasticsearchPassword:
|
||||
default: "Elasticsearch and Kibana password"
|
||||
# EC2 instance configuration
|
||||
AwsInstanceTypeOV:
|
||||
default: "Instance type for Openvidu Server Pro Node"
|
||||
|
@ -277,8 +322,22 @@ Metadata:
|
|||
default: "Deploy OpenVidu Call application"
|
||||
|
||||
Conditions:
|
||||
WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ""] ]
|
||||
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
||||
WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ''] ]
|
||||
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ''] ]
|
||||
RecordingStorageIsS3: !Equals [ !Ref Recording, 's3' ]
|
||||
CreateS3Bucket: !And
|
||||
- !Equals [!Ref Recording, 's3' ]
|
||||
- !Equals [!Ref S3RecordingsBucketName, '']
|
||||
|
||||
Rules:
|
||||
|
||||
RecordingValidation:
|
||||
RuleCondition:
|
||||
Fn::Or: [ !Equals [!Ref Recording, 'disabled' ], !Equals [!Ref Recording, 'local' ] ]
|
||||
Assertions:
|
||||
- AssertDescription: If recording Storage is 'disabled' or 'local', you don't need to specify a S3 bucket.
|
||||
Assert:
|
||||
Fn::Equals: [ !Ref S3RecordingsBucketName, "" ]
|
||||
|
||||
Resources:
|
||||
|
||||
|
@ -313,6 +372,45 @@ Resources:
|
|||
- 'route53:ChangeResourceRecordSets'
|
||||
- 'route53:ListHostedZones'
|
||||
Resource: '*'
|
||||
- Fn::If:
|
||||
# Only apply this policy if S3 is configured
|
||||
- RecordingStorageIsS3
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 's3:DeleteObject'
|
||||
- 's3:GetObject'
|
||||
- 's3:PutObject'
|
||||
Resource:
|
||||
- Fn::If:
|
||||
# Get bucket name depending if the user defines a bucket name or not
|
||||
- CreateS3Bucket
|
||||
### Unique bucket name using Stack ID
|
||||
- !Join [ "", [ 'arn:aws:s3:::', 'openvidu-recordings-', !Select [0, !Split ["-", !Select [2, !Split [/, !Ref AWS::StackId ]]]], "/*" ]]
|
||||
- !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName, '/*'] ]
|
||||
- Ref: AWS::NoValue
|
||||
- Fn::If:
|
||||
# Only apply this policy if S3 is configured
|
||||
- RecordingStorageIsS3
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 's3:ListBucket'
|
||||
- 's3:GetBucketLocation'
|
||||
Resource:
|
||||
- Fn::If:
|
||||
# Get bucket name depending if the user defines a bucket name or not
|
||||
- CreateS3Bucket
|
||||
### Unique bucket name using Stack ID
|
||||
- !Join [ "", [ 'arn:aws:s3:::', 'openvidu-recordings-', !Select [0, !Split ["-", !Select [2, !Split [/, !Ref AWS::StackId ]]]]]]
|
||||
- !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName ] ]
|
||||
- Ref: AWS::NoValue
|
||||
- Fn::If:
|
||||
# Only apply this policy if S3 is configured
|
||||
- RecordingStorageIsS3
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- s3:ListAllMyBuckets
|
||||
Resource: 'arn:aws:s3:::'
|
||||
- Ref: AWS::NoValue
|
||||
RoleName: !Join [ "-", [ OpenViduManageEC2Role, !Ref 'AWS::StackName', !Ref 'AWS::Region'] ]
|
||||
|
||||
OpenviduInstancesProfile:
|
||||
|
@ -325,6 +423,21 @@ Resources:
|
|||
DependsOn:
|
||||
- OpenViduManageEC2Role
|
||||
|
||||
S3bucket:
|
||||
Type: 'AWS::S3::Bucket'
|
||||
Properties:
|
||||
### Unique bucket name using Stack ID
|
||||
BucketName: !Join ["-" , [ 'openvidu-recordings', !Select [0, !Split ["-", !Select [2, !Split [/, !Ref AWS::StackId ]]]]]]
|
||||
AccessControl: Private
|
||||
PublicAccessBlockConfiguration:
|
||||
BlockPublicAcls: true
|
||||
BlockPublicPolicy: true
|
||||
IgnorePublicAcls : true
|
||||
RestrictPublicBuckets: true
|
||||
DeletionPolicy: Retain
|
||||
UpdateReplacePolicy: Retain
|
||||
Condition: CreateS3Bucket
|
||||
|
||||
OpenViduServer:
|
||||
Type: AWS::EC2::Instance
|
||||
Metadata:
|
||||
|
@ -383,9 +496,15 @@ Resources:
|
|||
sed -i "s/CERTIFICATE_TYPE=selfsigned/CERTIFICATE_TYPE=${WhichCert}/" $WORKINGDIR/.env
|
||||
sed -i "s/LETSENCRYPT_EMAIL=user@example.com/LETSENCRYPT_EMAIL=${LetsEncryptEmail}/" $WORKINGDIR/.env
|
||||
|
||||
# Replace Kibana Conf
|
||||
sed -i "s/KIBANA_USER=kibanaadmin/KIBANA_USER=${KibanaUser}/" $WORKINGDIR/.env
|
||||
sed -i "s/KIBANA_PASSWORD=/KIBANA_PASSWORD=${KibanaPassword}/" $WORKINGDIR/.env
|
||||
# Replace Elastic Search Conf
|
||||
if [[ ! -z "${ElasticsearchUrl}" ]]; then
|
||||
sed -i "s,#OPENVIDU_PRO_ELASTICSEARCH_HOST=,OPENVIDU_PRO_ELASTICSEARCH_HOST=${ElasticsearchUrl}," $WORKINGDIR/.env
|
||||
fi
|
||||
if [[ ! -z "${KibanaUrl}" ]]; then
|
||||
sed -i "s,#OPENVIDU_PRO_KIBANA_HOST=,OPENVIDU_PRO_KIBANA_HOST=${KibanaUrl}," $WORKINGDIR/.env
|
||||
fi
|
||||
sed -i "s/ELASTICSEARCH_USERNAME=elasticadmin/ELASTICSEARCH_USERNAME=${ElasticsearchUser}/" $WORKINGDIR/.env
|
||||
sed -i "s/ELASTICSEARCH_PASSWORD=/ELASTICSEARCH_PASSWORD=${ElasticsearchPassword}/" $WORKINGDIR/.env
|
||||
|
||||
# Replace vars AWS
|
||||
sed -i "s/#AWS_DEFAULT_REGION=/AWS_DEFAULT_REGION=${AWS::Region}/" $WORKINGDIR/.env
|
||||
|
@ -395,6 +514,8 @@ Resources:
|
|||
sed -i "s/#AWS_SUBNET_ID=/AWS_SUBNET_ID=${OpenViduSubnet}/" $WORKINGDIR/.env
|
||||
sed -i "s/#AWS_STACK_ID=/AWS_STACK_ID=$(echo ${AWS::StackId} | sed 's#/#\\/#g')/" $WORKINGDIR/.env
|
||||
sed -i "s/#AWS_STACK_NAME=/AWS_STACK_NAME=${AWS::StackName}/" $WORKINGDIR/.env
|
||||
sed -i "s/#AWS_CLI_DOCKER_TAG=/AWS_CLI_DOCKER_TAG=AWS_DOCKER_TAG/" $WORKINGDIR/.env
|
||||
sed -i "s/#AWS_VOLUME_SIZE=/AWS_VOLUME_SIZE=50/" $WORKINGDIR/.env
|
||||
|
||||
# Get security group id of kms and use it as env variable
|
||||
SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh)
|
||||
|
@ -405,7 +526,20 @@ Resources:
|
|||
sed -i "s/WITH_APP=true/WITH_APP=false/" $WORKINGDIR/docker-compose.yml
|
||||
rm $WORKINGDIR/docker-compose.override.yml
|
||||
fi
|
||||
|
||||
# Recording Configuration
|
||||
if [ "${Recording}" != "disabled" ]; then
|
||||
sed -i "s/OPENVIDU_RECORDING=false/OPENVIDU_RECORDING=true/" $WORKINGDIR/.env
|
||||
sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=${Recording}/" $WORKINGDIR/.env
|
||||
if [ ! -z "${S3RecordingsBucketName}" ]; then
|
||||
sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${S3RecordingsBucketName}/" $WORKINGDIR/.env
|
||||
elif [ "${Recording}" == "s3" ]; then
|
||||
sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${s3BucketName}/" $WORKINGDIR/.env
|
||||
fi
|
||||
fi
|
||||
- kmsAmi: !FindInMap [KMSAMIMAP, !Ref 'AWS::Region', AMI]
|
||||
### Unique bucket name using Stack ID
|
||||
s3BucketName: !Join ["" , [ 'openvidu-recordings-', !Select [0, !Split ["-", !Select [2, !Split [/, !Ref AWS::StackId ]]]]]]
|
||||
mode: "000755"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
|
@ -421,7 +555,7 @@ Resources:
|
|||
'/usr/local/bin/getSecurityGroupKms.sh':
|
||||
content: !Sub |
|
||||
#!/bin/bash -x
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 describe-security-groups \
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 describe-security-groups \
|
||||
--region ${AWS::Region} \
|
||||
--output text \
|
||||
--filters "Name=tag:aws:cloudformation:logical-id,Values=KMSSecurityGroup" \
|
||||
|
@ -433,7 +567,7 @@ Resources:
|
|||
'/usr/local/bin/getSecurityGroupOpenVidu.sh':
|
||||
content: !Sub |
|
||||
#!/bin/bash -x
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 describe-security-groups \
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 describe-security-groups \
|
||||
--region ${AWS::Region} \
|
||||
--output text \
|
||||
--filters "Name=tag:aws:cloudformation:logical-id,Values=OpenViduSecurityGroup" \
|
||||
|
@ -445,7 +579,7 @@ Resources:
|
|||
'/usr/local/bin/getCidrBlocKSubnet.sh':
|
||||
content: !Sub |
|
||||
#!/bin/bash -x
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 describe-subnets \
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 describe-subnets \
|
||||
--region ${AWS::Region} \
|
||||
--output text \
|
||||
--filters "Name=subnet-id,Values=${OpenViduSubnet}" \
|
||||
|
@ -454,25 +588,25 @@ Resources:
|
|||
owner: "root"
|
||||
group: "root"
|
||||
'/usr/local/bin/create_security_group_rules.sh':
|
||||
content: !Sub |
|
||||
content: |
|
||||
#!/bin/bash -x
|
||||
SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh)
|
||||
SECGRPIDOV=$(/usr/local/bin/getSecurityGroupOpenVidu.sh)
|
||||
SUBNET_CIDR=$(/usr/local/bin/getCidrBlocKSubnet.sh)
|
||||
|
||||
# Create Security group rules OpenVidu
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 authorize-security-group-ingress --group-id $SECGRPIDOV --protocol tcp --port 5044 --cidr $SUBNET_CIDR
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 authorize-security-group-ingress --group-id $SECGRPIDOV --protocol tcp --port 9200 --cidr $SUBNET_CIDR
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 authorize-security-group-ingress --group-id $SECGRPIDOV --protocol tcp --port 5044 --cidr $SUBNET_CIDR
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 authorize-security-group-ingress --group-id $SECGRPIDOV --protocol tcp --port 9200 --cidr $SUBNET_CIDR
|
||||
|
||||
# Create security group rules for KMS
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 authorize-security-group-ingress --group-id $SECGRPIDKMS --protocol tcp --port 8888 --cidr $SUBNET_CIDR
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 authorize-security-group-ingress --group-id $SECGRPIDKMS --protocol tcp --port 3000 --cidr $SUBNET_CIDR
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 authorize-security-group-ingress --group-id $SECGRPIDKMS --protocol tcp --port 8888 --cidr $SUBNET_CIDR
|
||||
docker run --rm amazon/aws-cli:AWS_DOCKER_TAG ec2 authorize-security-group-ingress --group-id $SECGRPIDKMS --protocol tcp --port 3000 --cidr $SUBNET_CIDR
|
||||
|
||||
mode: "000755"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
'/usr/local/bin/restartPRO.sh':
|
||||
content: !Sub |
|
||||
content: |
|
||||
#!/bin/bash -x
|
||||
WORKINGDIR=/opt/openvidu
|
||||
|
||||
|
@ -484,7 +618,8 @@ Resources:
|
|||
|
||||
# Restart all services
|
||||
pushd /opt/openvidu
|
||||
docker-compose up -d
|
||||
export FOLLOW_OPENVIDU_LOGS=false
|
||||
./openvidu start
|
||||
popd
|
||||
mode: "000755"
|
||||
owner: "root"
|
||||
|
@ -509,6 +644,8 @@ Resources:
|
|||
|
||||
cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenViduServer
|
||||
|
||||
export HOME="/root"
|
||||
|
||||
# Replace .env variables
|
||||
/usr/local/bin/feedGroupVars.sh || { echo "[Openvidu] Parameters incorrect/insufficient"; exit 1; }
|
||||
|
||||
|
@ -525,7 +662,8 @@ Resources:
|
|||
|
||||
# Start openvidu application
|
||||
pushd /opt/openvidu
|
||||
docker-compose up -d
|
||||
export FOLLOW_OPENVIDU_LOGS=false
|
||||
./openvidu start
|
||||
popd
|
||||
|
||||
# Wait for the app
|
||||
|
@ -537,10 +675,9 @@ Resources:
|
|||
BlockDeviceMappings:
|
||||
- DeviceName: /dev/sda1
|
||||
Ebs:
|
||||
VolumeType: io1
|
||||
Iops: 200
|
||||
VolumeType: gp2
|
||||
DeleteOnTermination: true
|
||||
VolumeSize: 50
|
||||
VolumeSize: 200
|
||||
|
||||
KMSSecurityGroup:
|
||||
Type: 'AWS::EC2::SecurityGroup'
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
#!/bin/bash -x
|
||||
set -eu -o pipefail
|
||||
|
||||
CF_OVP_TARGET=${CF_OVP_TARGET:-nomarket}
|
||||
CF_RELEASE=${CF_RELEASE:-false}
|
||||
AWS_KEY_NAME=${AWS_KEY_NAME:-}
|
||||
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID}
|
||||
export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY}
|
||||
export AWS_DEFAULT_REGION=us-east-1
|
||||
else
|
||||
export AWS_DEFAULT_REGION=eu-west-1
|
||||
if [[ $CF_RELEASE == "true" ]]; then
|
||||
git checkout v$OPENVIDU_PRO_VERSION
|
||||
fi
|
||||
|
||||
if [ "${OPENVIDU_PRO_IS_SNAPSHOT}" == "true" ]; then
|
||||
OPENVIDU_PRO_VERSION=${OPENVIDU_PRO_VERSION}-SNAPSHOT
|
||||
fi
|
||||
export AWS_DEFAULT_REGION=eu-west-1
|
||||
|
||||
DATESTAMP=$(date +%s)
|
||||
TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
||||
|
@ -23,10 +19,9 @@ TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
|||
getUbuntuAmiId() {
|
||||
local AMI_ID=$(
|
||||
aws --region ${1} ec2 describe-images \
|
||||
--filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64* \
|
||||
--query 'Images[*].[ImageId,CreationDate]' \
|
||||
--output text \
|
||||
| sort -k2 -r | head -n1 | cut -d$'\t' -f1
|
||||
--filters "Name=name,Values=*ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*" \
|
||||
--query "sort_by(Images, &CreationDate)" \
|
||||
| jq -r 'del(.[] | select(.ImageOwnerAlias != null)) | .[-1].ImageId'
|
||||
)
|
||||
echo $AMI_ID
|
||||
}
|
||||
|
@ -61,12 +56,22 @@ sed -i "s/AMIUSEAST1/${AMIUSEAST1}/g" cfn-mkt-kms-ami.yaml
|
|||
## KMS AMI
|
||||
|
||||
# Copy template to S3
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
aws s3 cp cfn-mkt-kms-ami.yaml s3://naeva-openvidu-pro
|
||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/naeva-openvidu-pro/cfn-mkt-kms-ami.yaml
|
||||
else
|
||||
aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io
|
||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml
|
||||
aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io
|
||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml
|
||||
|
||||
# Update installation script
|
||||
if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then
|
||||
# Avoid overriding existing versions
|
||||
# Only master and non existing versions can be overriden
|
||||
if [[ ${OPENVIDU_PRO_VERSION} != "master" ]]; then
|
||||
INSTALL_SCRIPT_EXISTS=true
|
||||
aws s3api head-object --bucket aws.openvidu.io --key install_media_node_$OPENVIDU_PRO_VERSION.sh || INSTALL_SCRIPT_EXISTS=false
|
||||
if [[ ${INSTALL_SCRIPT_EXISTS} == "true" ]]; then
|
||||
echo "Aborting updating s3://aws.openvidu.io/install_media_node_${OPENVIDU_PRO_VERSION}.sh. File actually exists."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
aws s3 cp ../docker-compose/media-node/install_media_node.sh s3://aws.openvidu.io/install_media_node_$OPENVIDU_PRO_VERSION.sh --acl public-read
|
||||
fi
|
||||
|
||||
aws cloudformation create-stack \
|
||||
|
@ -94,12 +99,22 @@ aws cloudformation delete-stack --stack-name kms-${DATESTAMP}
|
|||
## OpenVidu AMI
|
||||
|
||||
# Copy template to S3
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
aws s3 cp cfn-mkt-ov-ami.yaml s3://naeva-openvidu-pro
|
||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/naeva-openvidu-pro/cfn-mkt-ov-ami.yaml
|
||||
else
|
||||
aws s3 cp cfn-mkt-ov-ami.yaml s3://aws.openvidu.io
|
||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-ov-ami.yaml
|
||||
|
||||
# Update installation script
|
||||
if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then
|
||||
# Avoid overriding existing versions
|
||||
# Only master and non existing versions can be overriden
|
||||
if [[ ${OPENVIDU_PRO_VERSION} != "master" ]]; then
|
||||
INSTALL_SCRIPT_EXISTS=true
|
||||
aws s3api head-object --bucket aws.openvidu.io --key install_openvidu_pro_$OPENVIDU_PRO_VERSION.sh || INSTALL_SCRIPT_EXISTS=false
|
||||
if [[ ${INSTALL_SCRIPT_EXISTS} == "true" ]]; then
|
||||
echo "Aborting updating s3://aws.openvidu.io/install_openvidu_pro_${OPENVIDU_PRO_VERSION}.sh. File actually exists."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
aws s3 cp ../docker-compose/openvidu-server-pro/install_openvidu_pro.sh s3://aws.openvidu.io/install_openvidu_pro_$OPENVIDU_PRO_VERSION.sh --acl public-read
|
||||
fi
|
||||
|
||||
aws cloudformation create-stack \
|
||||
|
@ -125,15 +140,35 @@ echo "Cleaning up"
|
|||
aws cloudformation delete-stack --stack-name openvidu-${DATESTAMP}
|
||||
|
||||
# Wait for the instance
|
||||
aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID}
|
||||
# Unfortunately, aws cli does not have a way to increase timeout
|
||||
WAIT_RETRIES=0
|
||||
WAIT_MAX_RETRIES=3
|
||||
until [ "${WAIT_RETRIES}" -ge "${WAIT_MAX_RETRIES}" ]
|
||||
do
|
||||
aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} && break
|
||||
WAIT_RETRIES=$((WAIT_RETRIES+1))
|
||||
sleep 5
|
||||
done
|
||||
|
||||
|
||||
# Updating the template
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-mkt-openvidu-server-pro.yaml.template > cfn-mkt-openvidu-server-pro-${OPENVIDU_PRO_VERSION}.yaml
|
||||
sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-mkt-openvidu-server-pro-${OPENVIDU_PRO_VERSION}.yaml
|
||||
else
|
||||
sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-openvidu-server-pro-no-market.yaml.template > cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
||||
sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
||||
sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-openvidu-server-pro-no-market.yaml.template > cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
||||
sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
||||
sed -i "s/AWS_DOCKER_TAG/${AWS_DOCKER_TAG}/g" cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
||||
|
||||
# Update CF template
|
||||
if [[ ${UPDATE_CF} == "true" ]]; then
|
||||
# Avoid overriding existing versions
|
||||
# Only master and non existing versions can be overriden
|
||||
if [[ ${OPENVIDU_PRO_VERSION} != "master" ]]; then
|
||||
CF_EXIST=true
|
||||
aws s3api head-object --bucket aws.openvidu.io --key CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml || CF_EXIST=false
|
||||
if [[ ${CF_EXIST} == "true" ]]; then
|
||||
echo "Aborting updating s3://aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml. File actually exists."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
aws s3 cp cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml s3://aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml --acl public-read
|
||||
fi
|
||||
|
||||
rm $TEMPJSON
|
||||
|
|
|
@ -1,47 +1,24 @@
|
|||
#!/bin/bash -x
|
||||
set -eu -o pipefail
|
||||
|
||||
# Process AMI_LIST
|
||||
AMI_LIST=($(echo "$AMI_LIST" | tr ',' '\n'))
|
||||
|
||||
# Remove the list of AMIs in each region
|
||||
|
||||
export AWS_ACCESS_KEY_ID=
|
||||
export AWS_SECRET_ACCESS_KEY=
|
||||
|
||||
LIST="us-east-2:ami-0b779580e2c11e904
|
||||
us-west-1:ami-085b7176f53c6d7fe
|
||||
us-west-2:ami-029d0ac01cf0f56be
|
||||
ap-south-1:ami-044a9335de8413f90
|
||||
ap-northeast-2:ami-031f6637449d2821d
|
||||
ap-southeast-1:ami-0aba433c88526cc8a
|
||||
ap-southeast-2:ami-0ee526f6103ac2bd9
|
||||
ap-northeast-1:ami-03b3cc03809d43b36
|
||||
ca-central-1:ami-071388f538500db04
|
||||
eu-central-1:ami-080a9cbd1d3e64583
|
||||
eu-west-1:ami-05e6bc185f28b6338
|
||||
eu-west-2:ami-0f06e2c003eef90f1
|
||||
eu-west-3:ami-0fd9b5eaf08fc0936
|
||||
eu-north-1:ami-0e7717a400ba2f1c1
|
||||
sa-east-1:ami-0cd51a71e9791197a
|
||||
us-east-2:ami-0064508c09a32a93f
|
||||
us-west-1:ami-088d1a7099fa57038
|
||||
us-west-2:ami-080d4d462cff92974
|
||||
ap-south-1:ami-00a60b079166e7dd4
|
||||
ap-northeast-2:ami-0f4edc3faf639e044
|
||||
ap-southeast-1:ami-0235dbfa3662608a0
|
||||
ap-southeast-2:ami-0f5f46178512e6e07
|
||||
ap-northeast-1:ami-047b086aa0745ce19
|
||||
ca-central-1:ami-0777b151c44ef9944
|
||||
eu-central-1:ami-00dd31f7b896f233f
|
||||
eu-west-1:ami-0fb9f924ede905546
|
||||
eu-west-2:ami-0defcea3b8c198e1e
|
||||
eu-west-3:ami-0c56da0b482bdf48e
|
||||
eu-north-1:ami-054fc49723d3d516a
|
||||
sa-east-1:ami-0dca8c31325d33c72"
|
||||
|
||||
for line in ${LIST}
|
||||
for line in "${AMI_LIST[@]}"
|
||||
do
|
||||
REGION=$(echo ${line} | cut -d":" -f1)
|
||||
AMI_ID=$(echo ${line} | cut -d":" -f2)
|
||||
export AWS_DEFAULT_REGION=${REGION}
|
||||
aws ec2 deregister-image --image-id $AMI_ID
|
||||
sleep 1
|
||||
REGION=$(echo "${line}" | cut -d":" -f1)
|
||||
AMI_ID=$(echo "${line}" | cut -d":" -f2)
|
||||
export AWS_DEFAULT_REGION=${REGION}
|
||||
|
||||
mapfile -t SNAPSHOTS < <(aws ec2 describe-images --image-ids "$AMI_ID" --output text --query 'Images[*].BlockDeviceMappings[*].Ebs.SnapshotId')
|
||||
echo "Deregistering $AMI_ID"
|
||||
aws ec2 deregister-image --image-id "${AMI_ID}"
|
||||
sleep 1
|
||||
for snapshot in "${SNAPSHOTS[@]}";
|
||||
do
|
||||
echo "Deleting Snapshot $snapshot from $AMI_ID"
|
||||
aws ec2 delete-snapshot --snapshot-id "${snapshot}"
|
||||
sleep 1
|
||||
done
|
||||
done
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash -x
|
||||
#!/bin/bash
|
||||
set -eu -o pipefail
|
||||
|
||||
# Replicate AMIs in all regions
|
||||
|
@ -10,12 +10,11 @@ set -eu -o pipefail
|
|||
#
|
||||
# OV_AMI_NAME OpenVidu AMI Name
|
||||
# OV_AMI_ID OpenVidu AMI ID
|
||||
#
|
||||
# UPDATE_CF Boolean, true if you want to update CF template by OPENVIDU_PRO_VERSION
|
||||
# OPENVIDU_VERSION OpenVidu Version of the CF you want to update. It will update CF-OpenVidu-Pro-OPENVIDU_PRO_VERSION
|
||||
|
||||
export AWS_DEFAULT_REGION=eu-west-1
|
||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
||||
export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID}
|
||||
export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY}
|
||||
fi
|
||||
|
||||
echo "Making original AMIs public"
|
||||
|
||||
|
@ -96,26 +95,82 @@ do
|
|||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
|
||||
echo
|
||||
echo "OpenVidu Server Pro Node AMI IDs"
|
||||
|
||||
# Print and generate replicated AMIS
|
||||
REPLICATED_AMIS_FILE="replicated_amis.yaml"
|
||||
echo "OV AMIs and KMS AMIs replication:"
|
||||
{
|
||||
echo "#start_mappings"
|
||||
echo "Mappings:"
|
||||
echo " OVAMIMAP:"
|
||||
ITER=0
|
||||
for i in "${OPENVIDU_SERVER_PRO_AMI_IDS[@]}"
|
||||
do
|
||||
AMI_ID=${OPENVIDU_SERVER_PRO_AMI_IDS[$ITER]}
|
||||
REGION=${REGIONS[$ITER]}
|
||||
echo " ${REGION}:"
|
||||
echo " AMI: ${AMI_ID}"
|
||||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
echo ""
|
||||
echo " KMSAMIMAP:"
|
||||
ITER=0
|
||||
for i in "${MEDIA_NODE_AMI_IDS[@]}"
|
||||
do
|
||||
AMI_ID=${MEDIA_NODE_AMI_IDS[$ITER]}
|
||||
REGION=${REGIONS[$ITER]}
|
||||
echo " ${REGION}:"
|
||||
echo " AMI: ${AMI_ID}"
|
||||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
echo "#end_mappings"
|
||||
echo ""
|
||||
} > "${REPLICATED_AMIS_FILE}" 2>&1
|
||||
|
||||
# Print replicated AMIs
|
||||
cat "${REPLICATED_AMIS_FILE}"
|
||||
|
||||
if [[ ${UPDATE_CF} == "true" ]]; then
|
||||
if [[ ! -z ${OPENVIDU_PRO_VERSION} ]]; then
|
||||
# Download s3 file
|
||||
aws s3 cp s3://aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml
|
||||
sed -e "/^#end_mappings/r ${REPLICATED_AMIS_FILE}" -e '/^#start_mappings/,/^#end_mappings/d' -i CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml
|
||||
aws s3 cp CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml s3://aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml --acl public-read
|
||||
fi
|
||||
fi
|
||||
|
||||
# Print AMI_LIST for delete_amis.sh
|
||||
AMI_LIST=""
|
||||
ITER=0
|
||||
for i in "${OPENVIDU_SERVER_PRO_AMI_IDS[@]}"
|
||||
do
|
||||
AMI_ID=${OPENVIDU_SERVER_PRO_AMI_IDS[$ITER]}
|
||||
REGION=${REGIONS[$ITER]}
|
||||
echo " ${REGION}:"
|
||||
echo " AMI: ${AMI_ID}"
|
||||
if [[ ${ITER} -eq 0 ]]; then
|
||||
AMI_LIST="${REGION}:${AMI_ID}"
|
||||
else
|
||||
AMI_LIST="${AMI_LIST},${REGION}:${AMI_ID}"
|
||||
fi
|
||||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
echo "AMI_LIST_OV: ${AMI_LIST}"
|
||||
|
||||
echo
|
||||
echo "Media Node AMI IDs"
|
||||
# Print AMI_LIST for delete_amis.sh
|
||||
AMI_LIST=""
|
||||
ITER=0
|
||||
for i in "${MEDIA_NODE_AMI_IDS[@]}"
|
||||
do
|
||||
AMI_ID=${MEDIA_NODE_AMI_IDS[$ITER]}
|
||||
REGION=${REGIONS[$ITER]}
|
||||
echo " ${REGION}:"
|
||||
echo " AMI: ${AMI_ID}"
|
||||
if [[ ${ITER} -eq 0 ]]; then
|
||||
AMI_LIST="${REGION}:${AMI_ID}"
|
||||
else
|
||||
AMI_LIST="${AMI_LIST},${REGION}:${AMI_ID}"
|
||||
fi
|
||||
ITER=$(expr $ITER + 1)
|
||||
done
|
||||
done
|
||||
echo "AMI_LIST_KMS: ${AMI_LIST}"
|
||||
|
||||
# Cleaning the house
|
||||
rm "${REPLICATED_AMIS_FILE}"
|
||||
rm CF-OpenVidu-Pro-${OPENVIDU_PRO_VERSION}.yaml
|
|
@ -0,0 +1,352 @@
|
|||
# OpenVidu configuration
|
||||
# ----------------------
|
||||
# Documentation: https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/
|
||||
|
||||
# NOTE: This file doesn't need to quote assignment values, like most shells do.
|
||||
# All values are stored as-is, even if they contain spaces, so don't quote them.
|
||||
|
||||
# Domain name. If you do not have one, the public IP of the machine.
|
||||
# For example: 198.51.100.1, or openvidu.example.com
|
||||
DOMAIN_OR_PUBLIC_IP=
|
||||
|
||||
# OpenVidu PRO License
|
||||
OPENVIDU_PRO_LICENSE=
|
||||
|
||||
# OpenVidu SECRET used for apps to connect to OpenVidu server and users to access to OpenVidu Dashboard
|
||||
OPENVIDU_SECRET=
|
||||
|
||||
# Certificate type:
|
||||
# - selfsigned: Self signed certificate. Not recommended for production use.
|
||||
# Users will see an ERROR when connected to web page.
|
||||
# - owncert: Valid certificate purchased in a Internet services company.
|
||||
# Please put the certificates files inside folder ./owncert
|
||||
# with names certificate.key and certificate.cert
|
||||
# - letsencrypt: Generate a new certificate using letsencrypt. Please set the
|
||||
# required contact email for Let's Encrypt in LETSENCRYPT_EMAIL
|
||||
# variable.
|
||||
CERTIFICATE_TYPE=selfsigned
|
||||
|
||||
# If CERTIFICATE_TYPE=letsencrypt, you need to configure a valid email for notifications
|
||||
LETSENCRYPT_EMAIL=user@example.com
|
||||
|
||||
# Proxy configuration
|
||||
# If you want to change the ports on which openvidu listens, uncomment the following lines
|
||||
|
||||
# Allows any request to http://DOMAIN_OR_PUBLIC_IP:HTTP_PORT/ to be automatically
|
||||
# redirected to https://DOMAIN_OR_PUBLIC_IP:HTTPS_PORT/.
|
||||
# WARNING: the default port 80 cannot be changed during the first boot
|
||||
# if you have chosen to deploy with the option CERTIFICATE_TYPE=letsencrypt
|
||||
# HTTP_PORT=80
|
||||
|
||||
# Changes the port of all services exposed by OpenVidu.
|
||||
# SDKs, REST clients and browsers will have to connect to this port
|
||||
# HTTPS_PORT=443
|
||||
|
||||
# Old paths are considered now deprecated, but still supported by default.
|
||||
# OpenVidu Server will log a WARN message every time a deprecated path is called, indicating
|
||||
# the new path that should be used instead. You can set property SUPPORT_DEPRECATED_API=false
|
||||
# to stop allowing the use of old paths.
|
||||
# Default value is true
|
||||
# SUPPORT_DEPRECATED_API=true
|
||||
|
||||
# If true request to with www will be redirected to non-www requests
|
||||
# Default value is false
|
||||
# REDIRECT_WWW=false
|
||||
|
||||
# How many workers to configure in nginx proxy.
|
||||
# The more workers, the more requests will be handled
|
||||
# Default value is 10240
|
||||
# WORKER_CONNECTIONS=10240
|
||||
|
||||
# Access restrictions
|
||||
# In this section you will be able to restrict the IPs from which you can access to
|
||||
# Openvidu API and the Administration Panel
|
||||
# WARNING! If you touch this configuration you can lose access to the platform from some IPs.
|
||||
# Use it carefully.
|
||||
|
||||
# This section limits access to the /dashboard (OpenVidu CE) and /inspector (OpenVidu Pro) pages.
|
||||
# The form for a single IP or an IP range is:
|
||||
# ALLOWED_ACCESS_TO_DASHBOARD=198.51.100.1 and ALLOWED_ACCESS_TO_DASHBOARD=198.51.100.0/24
|
||||
# To limit multiple IPs or IP ranges, separate by commas like this:
|
||||
# ALLOWED_ACCESS_TO_DASHBOARD=198.51.100.1, 198.51.100.0/24
|
||||
# ALLOWED_ACCESS_TO_DASHBOARD=
|
||||
|
||||
# This section limits access to the Openvidu REST API.
|
||||
# The form for a single IP or an IP range is:
|
||||
# ALLOWED_ACCESS_TO_RESTAPI=198.51.100.1 and ALLOWED_ACCESS_TO_RESTAPI=198.51.100.0/24
|
||||
# To limit multiple IPs or or IP ranges, separate by commas like this:
|
||||
# ALLOWED_ACCESS_TO_RESTAPI=198.51.100.1, 198.51.100.0/24
|
||||
# ALLOWED_ACCESS_TO_RESTAPI=
|
||||
|
||||
# Mode of cluster management. Can be auto (OpenVidu manages Media Nodes on its own.
|
||||
# Parameter KMS_URIS is ignored) or manual (user must manage Media Nodes. Parameter
|
||||
# KMS_URIS is used: if any uri is provided it must be valid)
|
||||
OPENVIDU_PRO_CLUSTER_MODE=manual
|
||||
|
||||
# Which environment are you using
|
||||
# Possibles values: aws, on_premise
|
||||
OPENVIDU_PRO_CLUSTER_ENVIRONMENT=on_premise
|
||||
|
||||
# Unique identifier of your cluster. Each OpenVidu Server Pro instance corresponds to one cluster.
|
||||
# You can launch as many clusters as you want with your license key.
|
||||
# Cluster ID will always be stored to disk so restarting OpenVidu Server Pro will keep the same previous cluster ID
|
||||
# if this configuration parameter is not given a distinct value.
|
||||
# OPENVIDU_PRO_CLUSTER_ID=
|
||||
|
||||
# The desired number of Media Nodes on startup. First the autodiscovery process is performed.
|
||||
# If there are too many Media Nodes after that, they will be dropped until this number is reached.
|
||||
# If there are not enough, more will be launched.
|
||||
# This only takes place if OPENVIDU_PRO_CLUSTER_MODE is set to auto
|
||||
# If set to zero no media servers will be lauched.
|
||||
# Type: number >= 0
|
||||
#OPENVIDU_PRO_CLUSTER_MEDIA_NODES=
|
||||
|
||||
# How often each running Media Node will send OpenVidu Server Pro Node load metrics, in seconds.
|
||||
# This property is only used when OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY is 'cpu'. Other load strategies
|
||||
# gather information synchronously when required
|
||||
# Type: number >= 0
|
||||
# OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL=
|
||||
|
||||
# Whether to enable or disable autoscaling. With autoscaling the number of Media Nodes will
|
||||
# be automatically adjusted according to existing load
|
||||
# Values: true | false
|
||||
# OPENVIDU_PRO_CLUSTER_AUTOSCALING=false
|
||||
|
||||
# How often the autoscaling algorithm runs, in seconds
|
||||
# Type number >= 0
|
||||
# OPENVIDU_PRO_CLUSTER_AUTOSCALING_INTERVAL=
|
||||
|
||||
# If autoscaling is enabled, the upper limit of Media Nodes that can be reached.
|
||||
# Even when the average load exceeds the threshold, no more Media Nodes will be added to cluster
|
||||
# Type number >= 0
|
||||
# OPENVIDU_PRO_CLUSTER_AUTOSCALING_MAX_NODES=
|
||||
|
||||
# If autoscaling is enabled, the lower limit of Media Nodes that can be reached.
|
||||
# Even when the average load is inferior to the threshold, no more Media Nodes will
|
||||
# be removed from the cluster
|
||||
# OPENVIDU_PRO_CLUSTER_AUTOSCALING_MIN_NODES=
|
||||
|
||||
# If autoscaling is enabled, the upper average load threshold that will trigger the addition
|
||||
# of a new Media Node.
|
||||
# Percentage value (0 min, 100 max)
|
||||
# OPENVIDU_PRO_CLUSTER_AUTOSCALING_MAX_LOAD=
|
||||
|
||||
# If autoscaling is enabled, the lower average load threshold that will trigger the removal
|
||||
# of an existing Media Node.
|
||||
# Percentage value (0 min, 100 max)
|
||||
# OPENVIDU_PRO_CLUSTER_AUTOSCALING_MIN_LOAD=
|
||||
|
||||
# What parameter should be used to distribute the creation of new sessions
|
||||
# (and therefore distribution of load) among all available Media Nodes
|
||||
OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams
|
||||
|
||||
# Whether to enable or disable Network Quality API. You can monitor and
|
||||
# warn users about the quality of their networks with this feature
|
||||
# OPENVIDU_PRO_NETWORK_QUALITY=false
|
||||
|
||||
# If OPENVIDU_PRO_NETWORK_QUALITY=true, how often the network quality
|
||||
# algorithm will be invoked for each user, in seconds
|
||||
# OPENVIDU_PRO_NETWORK_QUALITY_INTERVAL=5
|
||||
|
||||
# Max days until delete indexes in state of rollover on Elasticsearch
|
||||
# Type number >= 0
|
||||
# Default Value is 15
|
||||
# OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE=
|
||||
|
||||
# If you have an external Elasticsearch and Kibana already running, put here the url to elasticsearch and kibana services.
|
||||
# It is very important that both url have the port specified in the url.
|
||||
# If you want to use the deployed Elasticsearch and Kibana locally, keep these variables commented.
|
||||
#OPENVIDU_PRO_ELASTICSEARCH_HOST=
|
||||
#OPENVIDU_PRO_KIBANA_HOST=
|
||||
|
||||
# Where to store recording files. Can be 'local' (local storage) or 's3' (AWS bucket).
|
||||
# You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it.
|
||||
#OPENVIDU_PRO_RECORDING_STORAGE=
|
||||
|
||||
# S3 Bucket where to store recording files. May include paths to allow navigating
|
||||
# folder structures inside the bucket. This property is only taken into account
|
||||
# if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
#OPENVIDU_PRO_AWS_S3_BUCKET=
|
||||
|
||||
# If OPENVIDU_PRO_RECORDING_STORAGE=s3, the collection of HTTP header values that the internal AWS client will use during
|
||||
# the upload process. The property is a key-value map of strings, following the format of a JSON object. For example, for applying
|
||||
# server-side encryption with AES-256, this header is mandatory: {"x-amz-server-side-encryption":"AES256"}.
|
||||
# The list of available headers can be found here: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/Headers.html
|
||||
# This property is only taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
#OPENVIDU_PRO_AWS_S3_HEADERS=
|
||||
|
||||
# If you're instance has a role which has access to read
|
||||
# and write into the s3 bucket, you don't need this parameter
|
||||
# OPENVIDU_PRO_AWS_ACCESS_KEY=
|
||||
|
||||
# AWS credentials secret key from OPENVIDU_PRO_AWS_ACCESS_KEY. This property is only
|
||||
# taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
# If you're instance has a role which has access to read
|
||||
# and write into the s3 bucket, you don't need this parameter
|
||||
# OPENVIDU_PRO_AWS_SECRET_KEY=
|
||||
|
||||
# AWS region in which the S3 bucket is located (e.g. eu-west-1). If not provided,
|
||||
# the region will try to be discovered automatically, although this is not always possible.
|
||||
# This property is only taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
# OPENVIDU_PRO_AWS_REGION=
|
||||
|
||||
# Whether to enable recording module or not
|
||||
OPENVIDU_RECORDING=false
|
||||
|
||||
# Use recording module with debug mode.
|
||||
OPENVIDU_RECORDING_DEBUG=false
|
||||
|
||||
# Openvidu Folder Record used for save the openvidu recording videos. Change it
|
||||
# with the folder you want to use from your host.
|
||||
OPENVIDU_RECORDING_PATH=/opt/openvidu/recordings
|
||||
|
||||
# System path where OpenVidu Server should look for custom recording layouts
|
||||
OPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/custom-layout
|
||||
|
||||
# if true any client can connect to
|
||||
# https://OPENVIDU_SERVER_IP:OPENVIDU_PORT/recordings/any_session_file.mp4
|
||||
# and access any recorded video file. If false this path will be secured with
|
||||
# OPENVIDU_SECRET param just as OpenVidu Server dashboard at
|
||||
# https://OPENVIDU_SERVER_IP:OPENVIDU_PORT
|
||||
# Values: true | false
|
||||
OPENVIDU_RECORDING_PUBLIC_ACCESS=false
|
||||
|
||||
# Which users should receive the recording events in the client side
|
||||
# (recordingStarted, recordingStopped). Can be all (every user connected to
|
||||
# the session), publisher_moderator (users with role 'PUBLISHER' or
|
||||
# 'MODERATOR'), moderator (only users with role 'MODERATOR') or none
|
||||
# (no user will receive these events)
|
||||
OPENVIDU_RECORDING_NOTIFICATION=publisher_moderator
|
||||
|
||||
# Timeout in seconds for recordings to automatically stop (and the session involved to be closed)
|
||||
# when conditions are met: a session recording is started but no user is publishing to it or a session
|
||||
# is being recorded and last user disconnects. If a user publishes within the timeout in either case,
|
||||
# the automatic stop of the recording is cancelled
|
||||
# 0 means no timeout
|
||||
OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT=120
|
||||
|
||||
# Maximum video bandwidth sent from clients to OpenVidu Server, in kbps.
|
||||
# 0 means unconstrained
|
||||
OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH=1000
|
||||
|
||||
# Minimum video bandwidth sent from clients to OpenVidu Server, in kbps.
|
||||
# 0 means unconstrained
|
||||
OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH=300
|
||||
|
||||
# Maximum video bandwidth sent from OpenVidu Server to clients, in kbps.
|
||||
# 0 means unconstrained
|
||||
OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH=1000
|
||||
|
||||
# Minimum video bandwidth sent from OpenVidu Server to clients, in kbps.
|
||||
# 0 means unconstrained
|
||||
OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH=300
|
||||
|
||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_STREAMS_ALLOW_TRANSCODING=true
|
||||
# when a codec can not be forced, transcoding will be allowed
|
||||
# Default value is VP8
|
||||
# OPENVIDU_STREAMS_FORCED_VIDEO_CODEC=VP8
|
||||
|
||||
# Allow transcoding if codec specified in OPENVIDU_STREAMS_FORCED_VIDEO_CODEC can not be applied
|
||||
# Default value is false
|
||||
# OPENVIDU_STREAMS_ALLOW_TRANSCODING=false
|
||||
|
||||
# true to enable OpenVidu Webhook service. false' otherwise
|
||||
# Values: true | false
|
||||
OPENVIDU_WEBHOOK=false
|
||||
|
||||
# HTTP endpoint where OpenVidu Server will send Webhook HTTP POST messages
|
||||
# Must be a valid URL: http(s)://ENDPOINT
|
||||
#OPENVIDU_WEBHOOK_ENDPOINT=
|
||||
|
||||
# List of headers that OpenVidu Webhook service will attach to HTTP POST messages
|
||||
#OPENVIDU_WEBHOOK_HEADERS=
|
||||
|
||||
# List of events that will be sent by OpenVidu Webhook service
|
||||
# Default value is all available events
|
||||
OPENVIDU_WEBHOOK_EVENTS=[sessionCreated,sessionDestroyed,participantJoined,participantLeft,webrtcConnectionCreated,webrtcConnectionDestroyed,recordingStatusChanged,filterEventDispatched,mediaNodeStatusChanged]
|
||||
|
||||
# How often the garbage collector of non active sessions runs.
|
||||
# This helps cleaning up sessions that have been initialized through
|
||||
# REST API (and maybe tokens have been created for them) but have had no users connected.
|
||||
# Default to 900s (15 mins). 0 to disable non active sessions garbage collector
|
||||
OPENVIDU_SESSIONS_GARBAGE_INTERVAL=900
|
||||
|
||||
# Minimum time in seconds that a non active session must have been in existence
|
||||
# for the garbage collector of non active sessions to remove it. Default to 3600s (1 hour).
|
||||
# If non active sessions garbage collector is disabled
|
||||
# (property 'OPENVIDU_SESSIONS_GARBAGE_INTERVAL' to 0) this property is ignored
|
||||
OPENVIDU_SESSIONS_GARBAGE_THRESHOLD=3600
|
||||
|
||||
# Call Detail Record enabled
|
||||
# Whether to enable Call Detail Record or not
|
||||
# Values: true | false
|
||||
OPENVIDU_CDR=false
|
||||
|
||||
# Path where the cdr log files are hosted
|
||||
OPENVIDU_CDR_PATH=/opt/openvidu/cdr
|
||||
|
||||
# Openvidu Server Level logs
|
||||
# --------------------------
|
||||
# Uncomment the next line and define this variable to change
|
||||
# the verbosity level of the logs of Openvidu Service
|
||||
# RECOMENDED VALUES: INFO for normal logs DEBUG for more verbose logs
|
||||
# OV_CE_DEBUG_LEVEL=INFO
|
||||
|
||||
# OpenVidu Java Options
|
||||
# --------------------------
|
||||
# Uncomment the next line and define this to add options to java command
|
||||
# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058
|
||||
# JAVA_OPTIONS=-Xms2048m -Xmx4096m
|
||||
|
||||
# ElasticSearch Java Options
|
||||
# --------------------------
|
||||
# Uncomment the next line and define this to add options to java command of Elasticsearch
|
||||
# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058
|
||||
# By default ElasticSearch is configured to use "-Xms2g -Xmx2g" as Java Min and Max memory heap allocation
|
||||
# ES_JAVA_OPTS=-Xms2048m -Xmx4096m
|
||||
|
||||
# Kibana And ElasticSearch Credentials Configuration
|
||||
# --------------------------
|
||||
# Kibana And ElasticSearch Basic Auth configuration (Credentials)
|
||||
# This credentials will aso be valid for Kibana dashboard
|
||||
ELASTICSEARCH_USERNAME=elasticadmin
|
||||
ELASTICSEARCH_PASSWORD=
|
||||
|
||||
# Media Node Configuration
|
||||
# --------------------------
|
||||
# You can add any KMS environment variable as described in the
|
||||
# documentation of the docker image: https://hub.docker.com/r/kurento/kurento-media-server
|
||||
# If you want to add an environment variable to KMS, you must add a variable using this prefix: 'KMS_DOCKER_ENV_',
|
||||
# followed by the environment variable you want to setup.
|
||||
# For example if you want to setup KMS_MIN_PORT to 50000, it would be KMS_DOCKER_ENV_KMS_MIN_PORT=50000
|
||||
|
||||
# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server
|
||||
# Uncomment the next line and define this variable with KMS image that you want use
|
||||
# By default, KMS_IMAGE is defined in media nodes and it does not need to be specified unless
|
||||
# you want to use a specific version of KMS
|
||||
# KMS_IMAGE=kurento/kurento-media-server:6.15.0
|
||||
|
||||
# Uncomment the next line and define this variable to change
|
||||
# the verbosity level of the logs of KMS
|
||||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
||||
# KMS_DOCKER_ENV_GST_DEBUG=
|
||||
|
||||
# Cloudformation configuration
|
||||
# --------------------------
|
||||
# If you're working outside AWS ignore this section
|
||||
#AWS_DEFAULT_REGION=
|
||||
#AWS_IMAGE_ID=
|
||||
#AWS_INSTANCE_TYPE=
|
||||
#AWS_KEY_NAME=
|
||||
#AWS_SUBNET_ID=
|
||||
#AWS_SECURITY_GROUP=
|
||||
#AWS_STACK_ID=
|
||||
#AWS_STACK_NAME=
|
||||
#AWS_CLI_DOCKER_TAG=
|
||||
#AWS_VOLUME_SIZE=
|
||||
|
||||
# AWS ASG configuration
|
||||
# --------------------------
|
||||
RM_REDIS_IP=
|
||||
RM_REDIS_PORT=
|
||||
RM_SQS_QUEUE=
|
|
@ -0,0 +1,48 @@
|
|||
filebeat.inputs:
|
||||
- type: container
|
||||
paths:
|
||||
- '/var/lib/docker/containers/*/*.log'
|
||||
|
||||
processors:
|
||||
- add_docker_metadata:
|
||||
host: "unix:///var/run/docker.sock"
|
||||
- add_host_metadata:
|
||||
netinfo.enabled: true
|
||||
|
||||
- decode_json_fields:
|
||||
fields: ["message"]
|
||||
target: "json"
|
||||
overwrite_keys: true
|
||||
- drop_event:
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: openvidu/openvidu-coturn
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/elasticsearch/elasticsearch
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/kibana/kibana
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/beats/filebeat-oss
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/beats/metricbeat-oss
|
||||
- add_fields:
|
||||
fields:
|
||||
cluster-id: ${OPENVIDU_PRO_CLUSTER_ID:undefined}
|
||||
|
||||
output:
|
||||
elasticsearch:
|
||||
hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
|
||||
indices:
|
||||
- index: "filebeat-redis-%{+yyyy.MM.dd}"
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: openvidu/openvidu-redis
|
||||
- index: "filebeat-nginx-%{+yyyy.MM.dd}"
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: openvidu/openvidu-proxy
|
||||
|
||||
|
||||
logging.json: true
|
||||
logging.metrics.enabled: false
|
||||
setup.ilm.enabled: false
|
|
@ -0,0 +1,10 @@
|
|||
metricbeat.modules:
|
||||
- module: nginx
|
||||
metricsets: ["stubstatus"]
|
||||
enabled: true
|
||||
period: 10s
|
||||
hosts: ["http://127.0.0.1"]
|
||||
server_status_path: "nginx_status"
|
||||
output:
|
||||
elasticsearch:
|
||||
hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
set -eu -o pipefail
|
||||
|
||||
# Set debug mode
|
||||
DEBUG=${DEBUG:-false}
|
||||
[ "$DEBUG" == "true" ] && set -x
|
||||
|
||||
OUTPUT=$(mktemp -t openvidu-autodiscover-XXX --suffix .json)
|
||||
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 describe-instances \
|
||||
--output text \
|
||||
--filters "Name=instance-state-name,Values=running" \
|
||||
"Name=tag:ov-cluster-member,Values=kms" \
|
||||
"Name=tag:ov-stack-name,Values=${AWS_STACK_NAME}" \
|
||||
"Name=tag:ov-stack-region,Values=${AWS_DEFAULT_REGION}" \
|
||||
--query 'Reservations[*].Instances[*].{id:InstanceId,ip:PrivateIpAddress}' > ${OUTPUT}
|
||||
|
||||
cat ${OUTPUT} | jq --raw-input --slurp 'split("\n") | map(split("\t")) | .[0:-1] | map( { "id": .[0], "ip": .[1] } )'
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
set -e -o pipefail
|
||||
|
||||
# Set debug mode
|
||||
DEBUG=${DEBUG:-false}
|
||||
[ "$DEBUG" == "true" ] && set -x
|
||||
|
||||
ID=$1
|
||||
[ -z "${ID}" ] && { echo "Must provide instance ID"; exit 1; }
|
||||
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 terminate-instances --instance-ids ${ID} --output json
|
|
@ -0,0 +1,69 @@
|
|||
#!/bin/bash
|
||||
set -e -o pipefail
|
||||
|
||||
# Set debug mode
|
||||
DEBUG=${DEBUG:-false}
|
||||
[ "$DEBUG" == "true" ] && set -x
|
||||
|
||||
TMPFILE=$(mktemp -t openvidu-userdata-XXX --suffix .txt)
|
||||
OUTPUT=$(mktemp -t openvidu-launch-kms-XXX --suffix .json)
|
||||
ERROUTPUT=$(mktemp -t openvidu-launch-kms-XXX --suffix .err)
|
||||
|
||||
trap exit_on_error ERR
|
||||
|
||||
exit_on_error () {
|
||||
ERROR_TYPE=$(cat ${ERROUTPUT} | awk '{ print $4 }' | sed -r 's/\(|\)//g' | tr -d '\n')
|
||||
|
||||
case ${ERROR_TYPE}
|
||||
in
|
||||
"InvalidParameterValue")
|
||||
echo -e "Parameter invalid " $(cat ${ERROUTPUT}) >&2
|
||||
exit 1
|
||||
;;
|
||||
|
||||
"UnauthorizedOperation")
|
||||
MSG_COD=$(cat ${ERROUTPUT} | awk -F: '{ print $3 }')
|
||||
MSG_DEC=$(docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} sts decode-authorization-message --encoded-message ${MSG_COD})
|
||||
|
||||
echo -e "Unauthorized " $(cat ${MSG_DEC}) >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo -e "Unknown error " $(cat ${ERROUTPUT}) >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 run-instances \
|
||||
--image-id ${AWS_IMAGE_ID} --count 1 \
|
||||
--instance-type ${AWS_INSTANCE_TYPE} \
|
||||
--key-name ${AWS_KEY_NAME} \
|
||||
--subnet-id ${AWS_SUBNET_ID} \
|
||||
--tag-specifications "ResourceType=instance,Tags=[{Key='Name',Value='Kurento Media Server'},{Key='ov-cluster-member',Value='kms'},{Key='ov-stack-name',Value='${AWS_STACK_NAME}'},{Key='ov-stack-region',Value='${AWS_DEFAULT_REGION}'}]" \
|
||||
--iam-instance-profile Name="OpenViduInstanceProfile-${AWS_STACK_NAME}-${AWS_DEFAULT_REGION}" \
|
||||
--block-device-mappings "DeviceName=/dev/sda1,Ebs={DeleteOnTermination=True,VolumeType='gp2',VolumeSize='${AWS_VOLUME_SIZE}'}" \
|
||||
--security-group-ids ${AWS_SECURITY_GROUP} > ${OUTPUT} 2> ${ERROUTPUT}
|
||||
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 wait instance-running --instance-ids $(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .InstanceId')
|
||||
|
||||
# Generating the output
|
||||
KMS_IP=$(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .NetworkInterfaces[0] | .PrivateIpAddress')
|
||||
KMS_ID=$(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .InstanceId')
|
||||
|
||||
# Wait media-node controller
|
||||
attempt_counter=0
|
||||
max_attempts=10
|
||||
|
||||
until $(curl --output /dev/null --silent --head --fail -u OPENVIDUAPP:${OPENVIDU_SECRET} http://${KMS_IP}:3000/media-node/status); do
|
||||
if [ ${attempt_counter} -eq ${max_attempts} ];then
|
||||
exit 1
|
||||
fi
|
||||
attempt_counter=$(($attempt_counter+1))
|
||||
sleep 5
|
||||
done
|
||||
|
||||
jq -n \
|
||||
--arg id "${KMS_ID}" \
|
||||
--arg ip "${KMS_IP}" \
|
||||
'{ id: $id, ip: $ip }'
|
|
@ -0,0 +1,26 @@
|
|||
version: '3.1'
|
||||
|
||||
services:
|
||||
# --------------------------------------------------------------
|
||||
#
|
||||
# Change this if your want use your own application.
|
||||
# It's very important expose your application in port 5442
|
||||
# and use the http protocol.
|
||||
#
|
||||
# Default Application
|
||||
#
|
||||
# Openvidu-Call Version: 2.16.0
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
app:
|
||||
image: openvidu/openvidu-call:2.16.0
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
- SERVER_PORT=5442
|
||||
- OPENVIDU_URL=http://localhost:5443
|
||||
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||
- CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
|
@ -0,0 +1,141 @@
|
|||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# DO NOT MODIFY THIS FILE !!!
|
||||
#
|
||||
# Configuration properties should be specified in .env file
|
||||
#
|
||||
# Application based on OpenVidu should be specified in
|
||||
# docker-compose.override.yml file
|
||||
#
|
||||
# This docker-compose file coordinates all services of OpenVidu Pro Platform
|
||||
#
|
||||
# This file will be overridden when update OpenVidu Platform
|
||||
#
|
||||
# Openvidu Version: 2.16.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
|
||||
openvidu-server:
|
||||
image: openvidu/openvidu-server-pro:2.17.0-dev5
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
entrypoint: ['/usr/local/bin/entrypoint.sh']
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:${OPENVIDU_RECORDING_CUSTOM_LAYOUT}
|
||||
- ${OPENVIDU_CDR_PATH}:${OPENVIDU_CDR_PATH}
|
||||
- ./cluster:/opt/openvidu/cluster
|
||||
- .env:${PWD}/.env
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- SERVER_SSL_ENABLED=false
|
||||
- SERVER_PORT=5443
|
||||
- KMS_URIS=[]
|
||||
- OPENVIDU_WEBHOOK=false
|
||||
- OPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook
|
||||
- OPENVIDU_PRO_REPLICATION_MANAGER_WEBHOOK=http://127.0.0.1:4443/openvidu/replication-manager-webhook?OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||
- COTURN_REDIS_IP=127.0.0.1
|
||||
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||
- COTURN_IP=${COTURN_IP:-auto-ipv4}
|
||||
- OPENVIDU_PRO_CLUSTER=true
|
||||
- OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||
- WAIT_KIBANA_URL=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
|
||||
- DOTENV_PATH=${PWD}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
replication-manager:
|
||||
image: openvidu/replication-manager:1.0.0-dev5
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
- SERVER_PORT=4443
|
||||
- SERVER_SSL_ENABLED=false
|
||||
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||
- LOCAL_OPENVIDU_SERVER_URI=http://127.0.0.1:5443/
|
||||
- REDIS_HOST=${RM_REDIS_IP}
|
||||
- REDIS_PORT=${RM_REDIS_PORT}
|
||||
- REDIS_PASS=${OPENVIDU_SECRET}
|
||||
- REDIS_TIMEOUT=5
|
||||
- REDIS_DB=replicationmanager
|
||||
- MEDIANODE_AS_NOTIFICATION_QUEUE=${RM_SQS_QUEUE}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
redis:
|
||||
image: openvidu/openvidu-redis:2.0.0-dev2
|
||||
restart: always
|
||||
network_mode: host
|
||||
environment:
|
||||
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
coturn:
|
||||
image: openvidu/openvidu-coturn:3.0.0-dev2
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
- REDIS_IP=127.0.0.1
|
||||
- TURN_LISTEN_PORT=3478
|
||||
- DB_NAME=0
|
||||
- DB_PASSWORD=${OPENVIDU_SECRET}
|
||||
- MIN_PORT=40000
|
||||
- MAX_PORT=65535
|
||||
- TURN_PUBLIC_IP=${TURN_PUBLIC_IP:-auto-ipv4}
|
||||
- ENABLE_COTURN_LOGS=true
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
metricbeat:
|
||||
image: docker.elastic.co/beats/metricbeat-oss:7.8.0
|
||||
network_mode: host
|
||||
restart: always
|
||||
user: root
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||
volumes:
|
||||
- ./beats/metricbeat.yml:/usr/share/metricbeat/metricbeat.yml:ro
|
||||
command: >
|
||||
/bin/bash -c "metricbeat -e -strict.perms=false
|
||||
`if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi`
|
||||
`if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`"
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
filebeat:
|
||||
image: docker.elastic.co/beats/filebeat-oss:7.8.0
|
||||
network_mode: host
|
||||
restart: always
|
||||
user: root
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||
volumes:
|
||||
- ./beats/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
|
||||
- /var/lib/docker:/var/lib/docker:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
command: >
|
||||
/bin/bash -c "filebeat -e -strict.perms=false
|
||||
`if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi`
|
||||
`if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`"
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
|
@ -0,0 +1,398 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Global variables
|
||||
OPENVIDU_FOLDER=openvidu
|
||||
OPENVIDU_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="master"
|
||||
AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws
|
||||
ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch
|
||||
BEATS_FOLDER=${OPENVIDU_FOLDER}/beats
|
||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${OPENVIDU_VERSION}
|
||||
|
||||
fatal_error() {
|
||||
printf "\n =======¡ERROR!======="
|
||||
printf "\n %s" "$1"
|
||||
printf "\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
new_ov_installation() {
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
printf '\n Install Openvidu PRO %s' "${OPENVIDU_VERSION}"
|
||||
printf '\n ======================================='
|
||||
printf '\n'
|
||||
|
||||
# Create folder openvidu-docker-compose
|
||||
printf '\n => Creating folder '%s'...' "${OPENVIDU_FOLDER}"
|
||||
mkdir "${OPENVIDU_FOLDER}" || fatal_error "Error while creating the folder '${OPENVIDU_FOLDER}'"
|
||||
|
||||
# Create aws scripts folder
|
||||
printf "\n => Creating folder 'cluster/aws'..."
|
||||
mkdir -p "${AWS_SCRIPTS_FOLDER}" || fatal_error "Error while creating the folder 'cluster/aws'"
|
||||
|
||||
# Create beats folder
|
||||
printf "\n => Creating folder 'beats'..."
|
||||
mkdir -p "${BEATS_FOLDER}" || fatal_error "Error while creating the folder 'beats'"
|
||||
|
||||
# Create elasticsearch folder
|
||||
printf "\n => Creating folder 'elasticsearch'..."
|
||||
mkdir -p "${ELASTICSEARCH_FOLDER}" || fatal_error "Error while creating the folder 'elasticsearch'"
|
||||
|
||||
printf "\n => Changing permission to 'elasticsearch' folder..."
|
||||
chown 1000:1000 "${ELASTICSEARCH_FOLDER}" || fatal_error "Error while changing permission to 'elasticsearch' folder"
|
||||
|
||||
# Download necessary files
|
||||
printf '\n => Downloading Openvidu PRO files:'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/cluster/aws/openvidu_autodiscover.sh \
|
||||
--output "${AWS_SCRIPTS_FOLDER}/openvidu_autodiscover.sh" || fatal_error "Error when downloading the file 'openvidu_autodiscover.sh'"
|
||||
printf '\n - openvidu_autodiscover.sh'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/cluster/aws/openvidu_drop.sh \
|
||||
--output "${AWS_SCRIPTS_FOLDER}/openvidu_drop.sh" || fatal_error "Error when downloading the file 'openvidu_drop.sh'"
|
||||
printf '\n - openvidu_drop.sh'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/cluster/aws/openvidu_launch_kms.sh \
|
||||
--output "${AWS_SCRIPTS_FOLDER}/openvidu_launch_kms.sh" || fatal_error "Error when downloading the file 'openvidu_launch_kms.sh'"
|
||||
printf '\n - openvidu_launch_kms.sh'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/beats/filebeat.yml \
|
||||
--output "${BEATS_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
||||
printf '\n - filebeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/beats/metricbeat.yml \
|
||||
--output "${BEATS_FOLDER}/metricbeat.yml" || fatal_error "Error when downloading the file 'metricbeat.yml'"
|
||||
printf '\n - metricbeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/.env \
|
||||
--output "${OPENVIDU_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/docker-compose.override.yml \
|
||||
--output "${OPENVIDU_FOLDER}/docker-compose.override.yml" || fatal_error "Error when downloading the file 'docker-compose.override.yml'"
|
||||
printf '\n - docker-compose.override.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/docker-compose.yml \
|
||||
--output "${OPENVIDU_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/openvidu \
|
||||
--output "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
# Add execution permissions
|
||||
printf "\n => Adding permission:"
|
||||
|
||||
chmod +x "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error while adding permission to 'openvidu' program"
|
||||
printf '\n - openvidu'
|
||||
|
||||
chmod +x "${AWS_SCRIPTS_FOLDER}/openvidu_autodiscover.sh" || fatal_error "Error while adding permission to 'openvidu_autodiscover.sh' program"
|
||||
printf '\n - openvidu_autodiscover.sh'
|
||||
|
||||
chmod +x "${AWS_SCRIPTS_FOLDER}/openvidu_drop.sh" || fatal_error "Error while adding permission to 'openvidu' openvidu_drop.sh"
|
||||
printf '\n - openvidu_drop.sh'
|
||||
|
||||
chmod +x "${AWS_SCRIPTS_FOLDER}/openvidu_launch_kms.sh" || fatal_error "Error while adding permission to 'openvidu_launch_kms.sh' program"
|
||||
printf '\n - openvidu_launch_kms.sh'
|
||||
|
||||
# Create own certificated folder
|
||||
printf "\n => Creating folder 'owncert'..."
|
||||
mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the folder 'owncert'"
|
||||
|
||||
# Create vhost nginx folder
|
||||
printf "\n => Creating folder 'custom-nginx-vhosts'..."
|
||||
mkdir "${OPENVIDU_FOLDER}/custom-nginx-vhosts" || fatal_error "Error while creating the folder 'custom-nginx-vhosts'"
|
||||
|
||||
# Ready to use
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
printf '\n Openvidu PRO successfully installed.'
|
||||
printf '\n ======================================='
|
||||
printf '\n'
|
||||
printf '\n 1. Go to openvidu folder:'
|
||||
printf '\n $ cd openvidu'
|
||||
printf '\n'
|
||||
printf '\n 2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, '
|
||||
printf '\n OPENVIDU_SECRET, and ELASTICSEARCH_PASSWORD in .env file:'
|
||||
printf '\n $ nano .env'
|
||||
printf '\n'
|
||||
printf '\n 3. Start OpenVidu'
|
||||
printf '\n $ ./openvidu start'
|
||||
printf '\n'
|
||||
printf "\n CAUTION: The folder 'openvidu/elasticsearch' use user and group 1000 permissions. "
|
||||
printf "\n This folder is necessary for store elasticsearch data."
|
||||
printf "\n For more information, check:"
|
||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
exit 0
|
||||
}
|
||||
|
||||
upgrade_ov() {
|
||||
# Search local Openvidu installation
|
||||
printf '\n'
|
||||
printf '\n ============================================'
|
||||
printf '\n Search Previous Installation of Openvidu'
|
||||
printf '\n ============================================'
|
||||
printf '\n'
|
||||
|
||||
SEARCH_IN_FOLDERS=(
|
||||
"${PWD}"
|
||||
"/opt/${OPENVIDU_FOLDER}"
|
||||
)
|
||||
|
||||
for folder in "${SEARCH_IN_FOLDERS[@]}"; do
|
||||
printf "\n => Searching in '%s' folder..." "${folder}"
|
||||
|
||||
if [ -f "${folder}/docker-compose.yml" ]; then
|
||||
OPENVIDU_PREVIOUS_FOLDER="${folder}"
|
||||
|
||||
printf "\n => Found installation in folder '%s'" "${folder}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
[ -z "${OPENVIDU_PREVIOUS_FOLDER}" ] && fatal_error "No previous Openvidu installation found"
|
||||
|
||||
# Uppgrade Openvidu
|
||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version"
|
||||
|
||||
# In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is
|
||||
# posible or not. If it is not posible launch a warning and stop the upgrade.
|
||||
if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then
|
||||
fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions."
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
printf '\n Upgrade Openvidu PRO %s to %s' "${OPENVIDU_PREVIOUS_VERSION}" "${OPENVIDU_VERSION}"
|
||||
printf '\n ======================================='
|
||||
printf '\n'
|
||||
|
||||
ROLL_BACK_FOLDER="${OPENVIDU_PREVIOUS_FOLDER}/.old-${OPENVIDU_PREVIOUS_VERSION}"
|
||||
TMP_FOLDER="${OPENVIDU_PREVIOUS_FOLDER}/tmp"
|
||||
ACTUAL_FOLDER="${PWD}"
|
||||
USE_OV_CALL=$(grep -E '^ image: openvidu/openvidu-call:.*$' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.override.yml" | tr -d '[:space:]')
|
||||
|
||||
printf "\n Creating rollback folder '%s'..." ".old-${OPENVIDU_PREVIOUS_VERSION}"
|
||||
mkdir "${ROLL_BACK_FOLDER}" || fatal_error "Error while creating the folder '.old-${OPENVIDU_PREVIOUS_VERSION}'"
|
||||
|
||||
printf "\n Creating temporal folder 'tmp'..."
|
||||
mkdir "${TMP_FOLDER}" || fatal_error "Error while creating the folder 'temporal'"
|
||||
|
||||
# Download necessary files
|
||||
printf '\n => Downloading new Openvidu PRO files:'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/cluster/aws/openvidu_autodiscover.sh \
|
||||
--output "${TMP_FOLDER}/openvidu_autodiscover.sh" || fatal_error "Error when downloading the file 'openvidu_autodiscover.sh'"
|
||||
printf '\n - openvidu_autodiscover.sh'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/cluster/aws/openvidu_drop.sh \
|
||||
--output "${TMP_FOLDER}/openvidu_drop.sh" || fatal_error "Error when downloading the file 'openvidu_drop.sh'"
|
||||
printf '\n - openvidu_drop.sh'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/cluster/aws/openvidu_launch_kms.sh \
|
||||
--output "${TMP_FOLDER}/openvidu_launch_kms.sh" || fatal_error "Error when downloading the file 'openvidu_launch_kms.sh'"
|
||||
printf '\n - openvidu_launch_kms.sh'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/beats/filebeat.yml \
|
||||
--output "${TMP_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
||||
printf '\n - filebeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/beats/metricbeat.yml \
|
||||
--output "${TMP_FOLDER}/metricbeat.yml" || fatal_error "Error when downloading the file 'metricbeat.yml'"
|
||||
printf '\n - metricbeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/.env \
|
||||
--output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/docker-compose.override.yml \
|
||||
--output "${TMP_FOLDER}/docker-compose.override.yml" || fatal_error "Error when downloading the file 'docker-compose.override.yml'"
|
||||
printf '\n - docker-compose.override.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/docker-compose.yml \
|
||||
--output "${TMP_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/aws-asg-openvidu-server-pro/openvidu \
|
||||
--output "${TMP_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
# Dowloading new images and stoped actual Openvidu
|
||||
printf '\n => Dowloading new images...'
|
||||
printf '\n'
|
||||
sleep 1
|
||||
|
||||
printf "\n => Moving to 'tmp' folder..."
|
||||
printf '\n'
|
||||
cd "${TMP_FOLDER}" || fatal_error "Error when moving to 'tmp' folder"
|
||||
printf '\n'
|
||||
docker-compose pull | true
|
||||
|
||||
printf '\n => Stoping Openvidu...'
|
||||
printf '\n'
|
||||
sleep 1
|
||||
|
||||
printf "\n => Moving to 'openvidu' folder..."
|
||||
printf '\n'
|
||||
cd "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error when moving to 'openvidu' folder"
|
||||
printf '\n'
|
||||
docker-compose down | true
|
||||
|
||||
printf '\n'
|
||||
printf '\n => Moving to working dir...'
|
||||
cd "${ACTUAL_FOLDER}" || fatal_error "Error when moving to working dir"
|
||||
|
||||
# Move old files to rollback folder
|
||||
printf '\n => Moving previous installation files to rollback folder:'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
if [ ! -z "${USE_OV_CALL}" ]; then
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.override.yml" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'docker-compose.override.yml'"
|
||||
printf '\n - docker-compose.override.yml'
|
||||
fi
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'cluster/aws'"
|
||||
printf '\n - cluster/aws'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/beats" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'beats'"
|
||||
printf '\n - beats'
|
||||
|
||||
cp "${OPENVIDU_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
if [ -d "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-vhosts" ]; then
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-vhosts" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous directory 'custom-nginx-vhosts'"
|
||||
printf '\n - custom-nginx-vhosts'
|
||||
fi
|
||||
|
||||
# Move tmp files to Openvidu
|
||||
printf '\n => Updating files:'
|
||||
|
||||
mv "${TMP_FOLDER}/docker-compose.yml" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
if [ ! -z "${USE_OV_CALL}" ]; then
|
||||
mv "${TMP_FOLDER}/docker-compose.override.yml" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'docker-compose.override.yml'"
|
||||
printf '\n - docker-compose.override.yml'
|
||||
else
|
||||
mv "${TMP_FOLDER}/docker-compose.override.yml" "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.override.yml-${OPENVIDU_VERSION}" || fatal_error "Error while updating 'docker-compose.override.yml'"
|
||||
printf '\n - docker-compose.override.yml-%s' "${OPENVIDU_VERSION}"
|
||||
fi
|
||||
|
||||
mv "${TMP_FOLDER}/.env" "${OPENVIDU_PREVIOUS_FOLDER}/.env-${OPENVIDU_VERSION}" || fatal_error "Error while moving previous '.env'"
|
||||
printf '\n - .env-%s' "${OPENVIDU_VERSION}"
|
||||
|
||||
mv "${TMP_FOLDER}/openvidu" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
mkdir "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" || fatal_error "Error while creating the folder 'cluster/aws'"
|
||||
|
||||
mkdir "${OPENVIDU_PREVIOUS_FOLDER}/beats" || fatal_error "Error while creating the folder 'beats'"
|
||||
|
||||
mv "${TMP_FOLDER}/openvidu_autodiscover.sh" "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" || fatal_error "Error while updating 'openvidu_autodiscover.sh'"
|
||||
printf '\n - openvidu_autodiscover.sh'
|
||||
|
||||
mv "${TMP_FOLDER}/openvidu_drop.sh" "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" || fatal_error "Error while updating 'openvidu_drop.sh'"
|
||||
printf '\n - openvidu_drop.sh'
|
||||
|
||||
mv "${TMP_FOLDER}/openvidu_launch_kms.sh" "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" || fatal_error "Error while updating 'openvidu_launch_kms.sh'"
|
||||
printf '\n - openvidu_launch_kms.sh'
|
||||
|
||||
mv "${TMP_FOLDER}/filebeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/filebeat.yml" || fatal_error "Error while updating 'filebeat.yml'"
|
||||
printf '\n - filebeat.yml'
|
||||
|
||||
mv "${TMP_FOLDER}/metricbeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/metricbeat.yml" || fatal_error "Error while updating 'metricbeat.yml'"
|
||||
printf '\n - metricbeat.yml'
|
||||
|
||||
printf "\n => Deleting 'tmp' folder"
|
||||
rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder"
|
||||
|
||||
# Add execution permissions
|
||||
printf "\n => Adding permission to 'openvidu' program..."
|
||||
|
||||
chmod +x "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" || fatal_error "Error while adding permission to 'openvidu' program"
|
||||
printf '\n - openvidu'
|
||||
|
||||
chmod +x "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws/openvidu_autodiscover.sh" || fatal_error "Error while adding permission to 'openvidu_autodiscover.sh' program"
|
||||
printf '\n - openvidu_autodiscover.sh'
|
||||
|
||||
chmod +x "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws/openvidu_drop.sh" || fatal_error "Error while adding permission to 'openvidu' openvidu_drop.sh"
|
||||
printf '\n - openvidu_drop.sh'
|
||||
|
||||
chmod +x "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws/openvidu_launch_kms.sh" || fatal_error "Error while adding permission to 'openvidu_launch_kms.sh' program"
|
||||
printf '\n - openvidu_launch_kms.sh'
|
||||
|
||||
# Define old mode: On Premise or Cloud Formation
|
||||
OLD_MODE=$(grep -E "Installation Mode:.*$" "${ROLL_BACK_FOLDER}/docker-compose.yml" | awk '{ print $4,$5 }')
|
||||
[ ! -z "${OLD_MODE}" ] && sed -i -r "s/Installation Mode:.+/Installation Mode: ${OLD_MODE}/" "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml"
|
||||
|
||||
# In Aws, update AMI ID
|
||||
AWS_REGION=$(grep -E "AWS_DEFAULT_REGION=.*$" "${OPENVIDU_PREVIOUS_FOLDER}/.env" | cut -d'=' -f2)
|
||||
if [[ ! -z ${AWS_REGION} ]]; then
|
||||
NEW_AMI_ID=$(curl https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_VERSION//v}.yaml --silent |
|
||||
sed -n -e '/KMSAMIMAP:/,/Metadata:/ p' |
|
||||
grep -A 1 ${AWS_REGION} | grep AMI | tr -d " " | cut -d":" -f2)
|
||||
[[ -z ${NEW_AMI_ID} ]] && fatal_error "Error while getting new AWS_IMAGE_ID for Media Nodes"
|
||||
sed -i "s/.*AWS_IMAGE_ID=.*/AWS_IMAGE_ID=${NEW_AMI_ID}/" "${OPENVIDU_PREVIOUS_FOLDER}/.env" || fatal_error "Error while updating new AWS_IMAGE_ID for Media Nodes"
|
||||
fi
|
||||
|
||||
|
||||
# Ready to use
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf '\n ================================================'
|
||||
printf "\n Openvidu successfully upgraded to version %s" "${OPENVIDU_VERSION}"
|
||||
printf '\n ================================================'
|
||||
printf '\n'
|
||||
printf "\n 1. A new file 'docker-compose.yml' has been created with the new OpenVidu %s services" "${OPENVIDU_VERSION}"
|
||||
printf '\n'
|
||||
printf "\n 2. The previous file '.env' remains intact, but a new file '.env-%s' has been created." "${OPENVIDU_VERSION}"
|
||||
printf "\n Transfer any configuration you wish to keep in the upgraded version from '.env' to '.env-%s'." "${OPENVIDU_VERSION}"
|
||||
printf "\n When you are OK with it, rename and leave as the only '.env' file of the folder the new '.env-%s'." "${OPENVIDU_VERSION}"
|
||||
printf '\n'
|
||||
printf "\n 3. If you were using Openvidu Call application, it has been automatically updated in file 'docker-compose.override.yml'."
|
||||
printf "\n However, if you were using your own application, a file called 'docker-compose.override.yml-%s'" "${OPENVIDU_VERSION}"
|
||||
printf "\n has been created with the latest version of Openvidu Call. If you don't plan to use it you can delete it."
|
||||
printf '\n'
|
||||
printf '\n 4. Start new version of Openvidu'
|
||||
printf '\n $ ./openvidu start'
|
||||
printf '\n'
|
||||
printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
# Check docker and docker-compose installation
|
||||
if ! command -v docker > /dev/null; then
|
||||
echo "You don't have docker installed, please install it and re-run the command"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose > /dev/null; then
|
||||
echo "You don't have docker-compose installed, please install it and re-run the command"
|
||||
exit 0
|
||||
else
|
||||
COMPOSE_VERSION=$(docker-compose version --short | sed "s/-rc[0-9]*//")
|
||||
if ! printf '%s\n%s\n' "1.24" "$COMPOSE_VERSION" | sort -V -C; then
|
||||
echo "You need a docker-compose version equal or higher than 1.24, please update your docker-compose and re-run the command"; \
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check type of installation
|
||||
if [[ ! -z "$1" && "$1" == "upgrade" ]]; then
|
||||
upgrade_ov
|
||||
else
|
||||
new_ov_installation
|
||||
fi
|
|
@ -0,0 +1,301 @@
|
|||
#!/bin/bash
|
||||
|
||||
upgrade_ov() {
|
||||
UPGRADE_SCRIPT_URL="https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/install_openvidu_pro_OVVERSION.sh"
|
||||
HTTP_STATUS=$(curl -s -o /dev/null -I -w "%{http_code}" ${UPGRADE_SCRIPT_URL//OVVERSION/$1})
|
||||
|
||||
printf " => Upgrading Openvidu PRO to '%s' version" "$1"
|
||||
|
||||
if [ "$HTTP_STATUS" == "200" ]; then
|
||||
printf "\n => Downloading and upgrading new version"
|
||||
printf "\n"
|
||||
|
||||
curl --silent ${UPGRADE_SCRIPT_URL//OVVERSION/$1} | bash -s upgrade
|
||||
else
|
||||
printf "\n =======¡ERROR!======="
|
||||
printf "\n Openvidu PRO Version '%s' not exist" "$1"
|
||||
printf "\n"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
collect_basic_information() {
|
||||
LINUX_VERSION=$(lsb_release -d)
|
||||
DOCKER_PS=$(docker ps)
|
||||
DOCKER_VERSION=$(docker version --format '{{.Server.Version}}')
|
||||
DOCKER_COMPOSE_VERSION=$(docker-compose version --short)
|
||||
OV_FOLDER="${PWD}"
|
||||
OV_VERSION=$(grep 'Openvidu Version:' "${OV_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
||||
CONTAINERS=$(docker ps | awk '{if(NR>1) print $NF}')
|
||||
|
||||
if [ ! -z "$(grep -E '^ image: openvidu/openvidu-call:.*$' "${OV_FOLDER}/docker-compose.override.yml" | tr -d '[:space:]')" ]; then
|
||||
OV_CALL_VERSION=$(grep -E 'Openvidu-Call Version:' "${OV_FOLDER}/docker-compose.override.yml" | awk '{ print $4 }')
|
||||
fi
|
||||
[ -z "${OV_CALL_VERSION}" ] && OV_CALL_VERSION="No present"
|
||||
|
||||
OV_TYPE_INSTALLATION=$(grep 'Installation Mode:' "${OV_FOLDER}/docker-compose.yml" | awk '{ print $4,$5 }')
|
||||
TREE_OV_DIRECTORY=$(find "." ! -path '*/0/*' | sed -e "s/[^-][^\/]*\// |/g" -e "s/|\([^ ]\)/|-\1/")
|
||||
}
|
||||
|
||||
version_ov() {
|
||||
collect_basic_information
|
||||
|
||||
printf '\nOpenvidu Information:'
|
||||
printf '\n'
|
||||
printf '\n Installation Type: %s' "${OV_TYPE_INSTALLATION}"
|
||||
printf '\n Openvidu Version: %s' "${OV_VERSION}"
|
||||
printf '\n Openvidu Call Version: %s' "${OV_CALL_VERSION}"
|
||||
printf '\n'
|
||||
printf '\nSystem Information:'
|
||||
printf '\n'
|
||||
printf '\n Linux Version:'
|
||||
printf '\n - %s' "${LINUX_VERSION}"
|
||||
printf '\n Docker Version: %s' "${DOCKER_VERSION}"
|
||||
printf '\n Docker Compose Version: %s' "${DOCKER_COMPOSE_VERSION}"
|
||||
printf '\n'
|
||||
printf '\nInstallation Information:'
|
||||
printf '\n'
|
||||
printf '\n Installation Folder: %s' "${OV_FOLDER}"
|
||||
printf '\n Installation Folder Tree:'
|
||||
printf '\n%s' "$(echo "${TREE_OV_DIRECTORY}" | sed -e 's/.//' -e ':a' -e 'N;$!ba' -e 's/\n/\n\t/g')"
|
||||
printf '\n'
|
||||
printf '\nDocker Running Services:'
|
||||
printf '\n'
|
||||
printf '\n %s' "$(echo "${DOCKER_PS}" | sed -e ':a' -e 'N;$!ba' -e 's/\n/\n\t/g')"
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
generate_report() {
|
||||
collect_basic_information
|
||||
|
||||
REPORT_CREATION_DATE=$(date +"%d-%m-%Y")
|
||||
REPORT_CREATION_TIME=$(date +"%H:%M:%S")
|
||||
REPORT_NAME="openvidu-report-${REPORT_CREATION_DATE}-$(date +"%H-%M").txt"
|
||||
REPORT_OUPUT="${OV_FOLDER}/${REPORT_NAME}"
|
||||
|
||||
{
|
||||
printf "\n ======================================="
|
||||
printf "\n = REPORT INFORMATION ="
|
||||
printf "\n ======================================="
|
||||
printf '\n'
|
||||
printf '\n Creation Date: %s' "${REPORT_CREATION_DATE}"
|
||||
printf '\n Creation Time: %s' "${REPORT_CREATION_TIME}"
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n = OPENVIDU INFORMATION ="
|
||||
printf "\n ======================================="
|
||||
printf '\n'
|
||||
printf '\n Installation Type: %s' "${OV_TYPE_INSTALLATION}"
|
||||
printf '\n Openvidu Version: %s' "${OV_VERSION}"
|
||||
printf '\n Openvidu Call Version: %s' "${OV_CALL_VERSION}"
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n = SYSTEM INFORMATION ="
|
||||
printf "\n ======================================="
|
||||
printf '\n'
|
||||
printf '\n Linux Version:'
|
||||
printf '\n - %s' "${LINUX_VERSION}"
|
||||
printf '\n Docker Version: %s' "${DOCKER_VERSION}"
|
||||
printf '\n Docker Compose Version: %s' "${DOCKER_COMPOSE_VERSION}"
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n = INSTALLATION INFORMATION ="
|
||||
printf "\n ======================================="
|
||||
printf '\n'
|
||||
printf '\n Installation Folder: %s' "${OV_FOLDER}"
|
||||
printf '\n Installation Folder Tree:'
|
||||
printf '\n%s' "$(echo "${TREE_OV_DIRECTORY}" | sed -e 's/.//' -e ':a' -e 'N;$!ba' -e 's/\n/\n\t/g')"
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n = DOCKER RUNNING SERVICES ="
|
||||
printf "\n ======================================="
|
||||
printf '\n'
|
||||
printf '\n %s' "$(echo "${DOCKER_PS}" | sed -e ':a' -e 'N;$!ba' -e 's/\n/\n\t/g')"
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n = CONFIGURATION FILES ="
|
||||
printf "\n ======================================="
|
||||
printf '\n'
|
||||
printf '\n ================ .env ================='
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
||||
cat < "${OV_FOLDER}/.env" | sed -r -e "s/OPENVIDU_SECRET=.+/OPENVIDU_SECRET=****/" -e "s/OPENVIDU_PRO_LICENSE=.+/OPENVIDU_PRO_LICENSE=****/" -e "s/ELASTICSEARCH_PASSWORD=.+/ELASTICSEARCH_PASSWORD=****/"
|
||||
|
||||
printf '\n'
|
||||
printf '\n ========= docker-compose.yml =========='
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
||||
cat "${OV_FOLDER}/docker-compose.yml"
|
||||
|
||||
printf '\n'
|
||||
printf '\n ==== docker-compose.override.yml ===='
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
||||
if [ -f "${OV_FOLDER}/docker-compose.override.yml" ]; then
|
||||
cat < "${OV_FOLDER}/docker-compose.override.yml"
|
||||
else
|
||||
printf '\n The docker-compose.override.yml file is not present'
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n = LOGS ="
|
||||
printf "\n ======================================="
|
||||
|
||||
for CONTAINER in $CONTAINERS
|
||||
do
|
||||
printf '\n'
|
||||
printf "\n ---------------------------------------"
|
||||
printf "\n %s" $CONTAINER
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
docker logs $CONTAINER
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
done
|
||||
|
||||
printf "\n ======================================="
|
||||
printf "\n = CONTAINER ENVS VARIABLES ="
|
||||
printf "\n ======================================="
|
||||
|
||||
for CONTAINER in $CONTAINERS
|
||||
do
|
||||
printf '\n'
|
||||
printf "\n ======================================="
|
||||
printf "\n %s" $CONTAINER
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
docker exec $CONTAINER env
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
done
|
||||
|
||||
} >> "${REPORT_OUPUT}" 2>&1
|
||||
|
||||
printf "\n Generation of the report completed with success"
|
||||
printf "\n You can get your report at path '%s'" "${REPORT_OUPUT}"
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
is_external_url() {
|
||||
local URL=$1
|
||||
if [[ -z "$URL" ]]; then
|
||||
return 1
|
||||
fi
|
||||
if [[ "${URL}" == *"localhost"* ]] || [[ "${URL}" == *"127.0.0.1"* ]] || [[ "${URL}" == *"::1"* ]]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
start_openvidu() {
|
||||
local RUN_LOCAL_ES
|
||||
local RUN_LOCAL_KIBANA
|
||||
local CONFIGURED_ELASTICSEARCH_HOST
|
||||
local CONFIGURED_KIBANA_HOST
|
||||
CONFIGURED_ELASTICSEARCH_HOST=$(grep -v '^#' .env | grep OPENVIDU_PRO_ELASTICSEARCH_HOST | cut -d '=' -f2)
|
||||
CONFIGURED_KIBANA_HOST=$(grep -v '^#' .env | grep OPENVIDU_PRO_KIBANA_HOST | cut -d '=' -f2)
|
||||
RUN_LOCAL_ES=true
|
||||
RUN_LOCAL_KIBANA=true
|
||||
if is_external_url "${CONFIGURED_ELASTICSEARCH_HOST}"; then
|
||||
printf "Configured external elasticsearch: %s" "${CONFIGURED_ELASTICSEARCH_HOST}"
|
||||
printf "\n"
|
||||
RUN_LOCAL_ES=false
|
||||
fi
|
||||
if is_external_url "${CONFIGURED_KIBANA_HOST}"; then
|
||||
printf "Configured external kibana: %s" "${CONFIGURED_KIBANA_HOST}"
|
||||
printf "\n"
|
||||
RUN_LOCAL_KIBANA=false
|
||||
fi
|
||||
docker-compose up -d \
|
||||
$(if [ "${RUN_LOCAL_ES}" == "false" ]; then echo '--scale elasticsearch=0'; fi) \
|
||||
$(if [ "${RUN_LOCAL_KIBANA}" == "false" ]; then echo '--scale kibana=0'; fi)
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf "Usage: \n\t openvidu [command]"
|
||||
printf "\n\nAvailable Commands:"
|
||||
printf "\n\tstart\t\t\tStart all services"
|
||||
printf "\n\tstop\t\t\tStop all services"
|
||||
printf "\n\trestart\t\t\tRestart all stoped and running services"
|
||||
printf "\n\tlogs\t\t\tShow openvidu-server logs"
|
||||
printf "\n\tupgrade\t\t\tUpgrade to the lastest Openvidu version"
|
||||
printf "\n\tupgrade [version]\tUpgrade to the specific Openvidu version"
|
||||
printf "\n\tversion\t\t\tShow version of Openvidu Server"
|
||||
printf "\n\treport\t\t\tGenerate a report with the current status of Openvidu"
|
||||
printf "\n\thelp\t\t\tShow help for openvidu command"
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
[[ -z "${FOLLOW_OPENVIDU_LOGS}" ]] && FOLLOW_OPENVIDU_LOGS=true
|
||||
|
||||
case $1 in
|
||||
|
||||
start)
|
||||
start_openvidu
|
||||
if [[ "${FOLLOW_OPENVIDU_LOGS}" == "true" ]]; then
|
||||
docker-compose logs -f openvidu-server
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
docker-compose down
|
||||
;;
|
||||
|
||||
restart)
|
||||
docker-compose down
|
||||
start_openvidu
|
||||
if [[ "${FOLLOW_OPENVIDU_LOGS}" == "true" ]]; then
|
||||
docker-compose logs -f openvidu-server
|
||||
fi
|
||||
;;
|
||||
|
||||
logs)
|
||||
docker-compose logs -f openvidu-server
|
||||
;;
|
||||
|
||||
upgrade)
|
||||
if [ -z "$2" ]; then
|
||||
UPGRADE_VERSION="latest"
|
||||
else
|
||||
UPGRADE_VERSION="$2"
|
||||
fi
|
||||
|
||||
read -r -p " You're about to update Openvidu PRO to '${UPGRADE_VERSION}' version. Are you sure? [y/N]: " response
|
||||
case "$response" in
|
||||
[yY][eE][sS]|[yY])
|
||||
upgrade_ov "${UPGRADE_VERSION}"
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
version)
|
||||
version_ov
|
||||
;;
|
||||
|
||||
report)
|
||||
read -r -p " You are about to generate a report on the current status of Openvidu, this may take some time. Do you want to continue? [y/N]: " response
|
||||
case "$response" in
|
||||
[yY][eE][sS]|[yY])
|
||||
generate_report
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
|
@ -1,30 +0,0 @@
|
|||
# KMS Configuration
|
||||
# --------------------------
|
||||
|
||||
# NOTE: This file doesn't need to quote assignment values, like most shells do.
|
||||
# All values are stored as-is, even if they contain spaces, so don't quote them.
|
||||
|
||||
# Kurento Media Server image
|
||||
# --------------------------
|
||||
# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server-dev
|
||||
# Uncomment the next line and define this variable with KMS image that you want use
|
||||
# KMS_IMAGE=kurento/kurento-media-server:6.14.0
|
||||
|
||||
# Kurento Media Server Level logs
|
||||
# -------------------------------
|
||||
# Uncomment the next line and define this variable to change
|
||||
# the verbosity level of the logs of KMS
|
||||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
||||
# KMS_DEBUG_LEVEL=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4
|
||||
|
||||
# Metricbeat ElasticSearch Image
|
||||
# -------------------------------
|
||||
# Docker hub kurento media server: https://www.docker.elastic.co/
|
||||
# Uncomment the next line and define this variable with METRICBEAT_IMAGE image that you want use
|
||||
# METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat:7.8.0
|
||||
|
||||
# FileBeat ElasticSearch Image
|
||||
# -------------------------------
|
||||
# Docker hub kurento media server: https://www.docker.elastic.co/
|
||||
# Uncomment the next line and define this variable with FILEBEAT_IMAGE image that you want use
|
||||
# FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat:7.8.0
|
|
@ -3,5 +3,4 @@ echo "Creating dir for beats"
|
|||
mkdir -p /opt/openvidu/beats
|
||||
echo "Copying beat config files"
|
||||
cp /beats/filebeat.yml /opt/openvidu/beats/filebeat.yml
|
||||
cp /beats/metricbeat-elasticsearch.yml /opt/openvidu/beats/metricbeat-elasticsearch.yml
|
||||
cp /beats/metricbeat-openvidu.yml /opt/openvidu/beats/metricbeat-openvidu.yml
|
||||
cp /beats/metricbeat-elasticsearch.yml /opt/openvidu/beats/metricbeat-elasticsearch.yml
|
|
@ -5,6 +5,14 @@ filebeat.inputs:
|
|||
multiline.pattern: '^\d*:\d*:\d*'
|
||||
multiline.negate: true
|
||||
multiline.match: after
|
||||
- type: log
|
||||
paths:
|
||||
- /opt/openvidu/kurento-logs/*.log
|
||||
fields:
|
||||
kurento-media-server: true
|
||||
ip: ${MEDIA_NODE_IP}
|
||||
cluster-id: ${CLUSTER_ID}
|
||||
fields_under_root: true
|
||||
|
||||
processors:
|
||||
- add_docker_metadata:
|
||||
|
@ -19,23 +27,21 @@ processors:
|
|||
- add_fields:
|
||||
fields:
|
||||
ip: ${MEDIA_NODE_IP}
|
||||
|
||||
cluster-id: ${CLUSTER_ID}
|
||||
|
||||
output:
|
||||
elasticsearch:
|
||||
hosts: ["${OPENVIDU_SERVER_PRO_IP}:9200"]
|
||||
indices:
|
||||
- index: "filebeat-kurento-%{+yyyy.MM.dd}"
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: kurento/kurento-media-server
|
||||
- equals:
|
||||
kurento-media-server: true
|
||||
pipelines:
|
||||
- pipeline: kurento-pipeline
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: kurento/kurento-media-server
|
||||
- equals:
|
||||
kurento-media-server: true
|
||||
|
||||
logging.json: true
|
||||
logging.metrics.enabled: false
|
||||
setup.ilm.enabled: true
|
||||
setup.ilm.policy_name: "openvidu_cleanup_policy"
|
||||
setup.ilm.enabled: false
|
|
@ -1,14 +1,34 @@
|
|||
output:
|
||||
elasticsearch:
|
||||
hosts: ["${OPENVIDU_SERVER_PRO_IP}:9200"]
|
||||
metricbeat.modules:
|
||||
- module: system
|
||||
metricsets: [cpu]
|
||||
enabled: true
|
||||
period: ${OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL}s
|
||||
metricsets:
|
||||
- cpu
|
||||
#- diskio
|
||||
- memory
|
||||
- network
|
||||
- filesystem
|
||||
- fsstat
|
||||
#- process
|
||||
- process_summary
|
||||
- uptime
|
||||
filesystem.ignore_types: [nfs, smbfs, autofs, devtmpfs, devpts, hugetlbfs, tmpfs, sysfs, securityfs, cgroup2, cgroup, pstore, debugfs, configfs, fusectl, proc, fuse.lxcfs, squashfs]
|
||||
processes: ['.*']
|
||||
# process.include_top_n:
|
||||
# by_cpu: 2
|
||||
# by_memory: 2
|
||||
processors:
|
||||
- drop_event:
|
||||
when:
|
||||
or:
|
||||
- regexp:
|
||||
system.network.name: '^(veth|lo|docker|br-)($|)'
|
||||
- regexp:
|
||||
system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host)($|/)'
|
||||
- regexp:
|
||||
system.filesystem.mount_point: '^/hostfs/(sys|cgroup|proc|dev|etc|host)($|/)'
|
||||
enabled: true
|
||||
period: ${OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL}0s
|
||||
cpu.metrics: [normalized_percentages]
|
||||
fields: {ip: "${MEDIA_NODE_IP}"}
|
||||
fields: {ip: "${MEDIA_NODE_IP}", cluster-id: "${CLUSTER_ID}"}
|
||||
pipeline:
|
||||
queue.mem.events: 0
|
||||
setup.ilm.enabled: false
|
||||
setup.ilm.enabled: false
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
output:
|
||||
logstash.hosts: ["${OPENVIDU_SERVER_PRO_IP}:5044"]
|
||||
metricbeat.modules:
|
||||
- module: system
|
||||
metricsets: [cpu]
|
||||
enabled: true
|
||||
period: ${OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL}s
|
||||
processes: ['.*']
|
||||
cpu.metrics: [normalized_percentages]
|
||||
fields: {ip: "${MEDIA_NODE_IP}"}
|
||||
pipeline:
|
||||
queue.mem.events: 0
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
# This docker-compose file coordinates all services of OpenVidu CE Platform.
|
||||
#
|
||||
# Openvidu Version: 2.15.0
|
||||
# Openvidu Version: 2.16.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
@ -16,20 +16,24 @@ version: '3.1'
|
|||
|
||||
services:
|
||||
media-node-controller:
|
||||
image: openvidu/media-node-controller:1.0.0
|
||||
image: openvidu/media-node-controller:3.0.0-dev4
|
||||
restart: always
|
||||
ulimits:
|
||||
core: -1
|
||||
entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh']
|
||||
environment:
|
||||
- KMS_IMAGE=${KMS_IMAGE:-kurento/kurento-media-server:6.14.0}
|
||||
- KMS_DEBUG_LEVEL=${KMS_DEBUG_LEVEL:-}
|
||||
- METRICBEAT_IMAGE=${METRICBEAT_IMAGE:-docker.elastic.co/beats/metricbeat:7.8.0}
|
||||
- FILEBEAT_IMAGE=${FILEBEAT_IMAGE:-docker.elastic.co/beats/filebeat:7.8.0}
|
||||
- KMS_IMAGE=kurento/kurento-media-server:6.15.0
|
||||
- METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0
|
||||
- FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0
|
||||
- OPENVIDU_RECORDING_IMAGE=openvidu/openvidu-recording:2.17.0-dev1
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- /opt/openvidu/recordings:/opt/openvidu/recordings
|
||||
- /opt/openvidu/beats:/opt/openvidu/beats
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs
|
||||
- ./beats:/beats
|
||||
logging:
|
||||
options:
|
||||
max-size: "100M"
|
||||
|
|
|
@ -2,8 +2,16 @@
|
|||
|
||||
MEDIA_NODE_FOLDER=kms
|
||||
MEDIA_NODE_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.16"
|
||||
BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats
|
||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${MEDIA_NODE_VERSION}
|
||||
IMAGES=(
|
||||
"kurento-media-server"
|
||||
"docker.elastic.co/beats/filebeat"
|
||||
"docker.elastic.co/beats/metricbeat"
|
||||
"openvidu/media-node-controller"
|
||||
)
|
||||
|
||||
fatal_error() {
|
||||
printf "\n =======¡ERROR!======="
|
||||
printf "\n %s" "$1"
|
||||
|
@ -11,6 +19,27 @@ fatal_error() {
|
|||
exit 0
|
||||
}
|
||||
|
||||
docker_command_by_container_image() {
|
||||
IMAGE_NAME=$1
|
||||
COMMAND=$2
|
||||
if [[ ! -z "${IMAGE_NAME}" ]]; then
|
||||
CONTAINERS=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}')
|
||||
for CONTAINER_ID in ${CONTAINERS[@]}; do
|
||||
if [[ ! -z "${CONTAINER_ID}" ]] && [[ ! -z "${COMMAND}" ]]; then
|
||||
bash -c "docker ${COMMAND} ${CONTAINER_ID}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
stop_containers() {
|
||||
printf "Stopping containers..."
|
||||
for IMAGE in ${IMAGES[@]}; do
|
||||
docker_command_by_container_image "${IMAGE}" "rm -f"
|
||||
done
|
||||
}
|
||||
|
||||
new_media_node_installation() {
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
|
@ -33,10 +62,6 @@ new_media_node_installation() {
|
|||
--output "${MEDIA_NODE_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/.env \
|
||||
--output "${MEDIA_NODE_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/media_node \
|
||||
--output "${MEDIA_NODE_FOLDER}/media_node" || fatal_error "Error when downloading the file 'media_node'"
|
||||
printf '\n - media_node'
|
||||
|
@ -49,10 +74,6 @@ new_media_node_installation() {
|
|||
--output "${BEATS_FOLDER}/metricbeat-elasticsearch.yml" || fatal_error "Error when downloading the file 'metricbeat-elasticsearch.yml'"
|
||||
printf '\n - metricbeat-elasticsearch.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-openvidu.yml \
|
||||
--output "${BEATS_FOLDER}/metricbeat-openvidu.yml" || fatal_error "Error when downloading the file 'metricbeat-openvidu.yml'"
|
||||
printf '\n - metricbeat-openvidu.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/beats/copy_config_files.sh \
|
||||
--output "${BEATS_FOLDER}/copy_config_files.sh" || fatal_error "Error when downloading the file 'copy_config_files.sh'"
|
||||
printf '\n - copy_config_files.sh'
|
||||
|
@ -68,12 +89,14 @@ new_media_node_installation() {
|
|||
# Pull images
|
||||
printf "\n => Pulling images...\n"
|
||||
cd "${MEDIA_NODE_FOLDER}" || fatal_error "Error when moving to '${MEDIA_NODE_FOLDER}' folder"
|
||||
KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | sed 's/\(^.*KMS_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
||||
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
||||
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
||||
KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | cut -d"=" -f2)
|
||||
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | cut -d"=" -f2)
|
||||
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | cut -d"=" -f2)
|
||||
OPENVIDU_RECORDING_IMAGE=$(cat docker-compose.yml | grep OPENVIDU_RECORDING_IMAGE | cut -d"=" -f2)
|
||||
docker pull $KMS_IMAGE || fatal "Error while pulling docker image: $KMS_IMAGE"
|
||||
docker pull $METRICBEAT_IMAGE || fatal "Error while pulling docker image: $METRICBEAT_IMAGE"
|
||||
docker pull $FILEBEAT_IMAGE || fatal "Error while pulling docker image: $FILEBEAT_IMAGE"
|
||||
docker pull $OPENVIDU_RECORDING_IMAGE || fatal "Error while pulling docker image: $OPENVIDU_RECORDING_IMAGE"
|
||||
docker-compose pull | true
|
||||
|
||||
# Ready to use
|
||||
|
@ -81,16 +104,28 @@ new_media_node_installation() {
|
|||
printf '\n ======================================='
|
||||
printf "\n Media Node successfully installed."
|
||||
printf '\n ======================================='
|
||||
printf "\n"
|
||||
printf '\n'
|
||||
printf '\n 1. Go to kms folder:'
|
||||
printf '\n $ cd kms'
|
||||
printf "\n"
|
||||
printf '\n'
|
||||
printf '\n 2. Start Media Node Controller'
|
||||
printf '\n $ ./media_node start'
|
||||
printf '\n'
|
||||
printf "\n For more information, check:"
|
||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions"
|
||||
printf '\n 3. This will run a service at port 3000 which OpenVidu will use to deploy necessary containers.'
|
||||
printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine'
|
||||
printf '\n in file located at "/opt/openvidu/.env" with this format:'
|
||||
printf '\n ...'
|
||||
printf '\n KMS_URIS=["ws://<MEDIA_NODE_PRIVATE_IP>:8888/kurento"]'
|
||||
printf '\n ...'
|
||||
printf '\n You can also add this node from inspector'
|
||||
printf '\n'
|
||||
printf '\n 4. Start or restart OpenVidu Pro and all containers will be provisioned'
|
||||
printf '\n automatically to all the media nodes configured in "KMS_URIS"'
|
||||
printf '\n More info about Media Nodes deployment here:'
|
||||
printf "\n --> https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#set-the-number-of-media-nodes-on-startup"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}"
|
||||
printf '\n'
|
||||
exit 0
|
||||
}
|
||||
|
@ -123,10 +158,13 @@ upgrade_media_node() {
|
|||
|
||||
# Uppgrade Media Node
|
||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${MEDIA_NODE_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && OPENVIDU_PREVIOUS_VERSION=2.14.0
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version"
|
||||
|
||||
# In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is
|
||||
# posible or not. If it is not posible launch a warning and stop the upgrade.
|
||||
if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then
|
||||
fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions."
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
|
@ -151,10 +189,6 @@ upgrade_media_node() {
|
|||
--output "${TMP_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/.env \
|
||||
--output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/media_node \
|
||||
--output "${TMP_FOLDER}/media_node" || fatal_error "Error when downloading the file 'media_node'"
|
||||
printf '\n - media_node'
|
||||
|
@ -167,10 +201,6 @@ upgrade_media_node() {
|
|||
--output "${TMP_FOLDER}/metricbeat-elasticsearch.yml" || fatal_error "Error when downloading the file 'metricbeat-elasticsearch.yml'"
|
||||
printf '\n - metricbeat-elasticsearch.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-openvidu.yml \
|
||||
--output "${TMP_FOLDER}/metricbeat-openvidu.yml" || fatal_error "Error when downloading the file 'metricbeat-openvidu.yml'"
|
||||
printf '\n - metricbeat-openvidu.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/beats/copy_config_files.sh \
|
||||
--output "${TMP_FOLDER}/copy_config_files.sh" || fatal_error "Error when downloading the file 'copy_config_files.sh'"
|
||||
printf '\n - copy_config_files.sh'
|
||||
|
@ -182,16 +212,24 @@ upgrade_media_node() {
|
|||
|
||||
printf "\n => Moving to 'tmp' folder..."
|
||||
printf '\n'
|
||||
cd "${TMP_FOLDER}" || fatal_error "Error when moving to '${TMP_FOLDER}' folder"
|
||||
|
||||
printf '\n => Stoping Media Node containers...'
|
||||
printf '\n'
|
||||
sleep 1
|
||||
|
||||
stop_containers
|
||||
|
||||
# Pull images
|
||||
printf "\n => Pulling images...\n"
|
||||
cd "${TMP_FOLDER}" || fatal_error "Error when moving to '${TMP_FOLDER}' folder"
|
||||
KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | sed 's/\(^.*KMS_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
||||
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
||||
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
||||
KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | cut -d"=" -f2)
|
||||
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | cut -d"=" -f2)
|
||||
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | cut -d"=" -f2)
|
||||
OPENVIDU_RECORDING_IMAGE=$(cat docker-compose.yml | grep OPENVIDU_RECORDING_IMAGE | cut -d"=" -f2)
|
||||
docker pull $KMS_IMAGE || fatal "Error while pulling docker image: $KMS_IMAGE"
|
||||
docker pull $METRICBEAT_IMAGE || fatal "Error while pulling docker image: $METRICBEAT_IMAGE"
|
||||
docker pull $FILEBEAT_IMAGE || fatal "Error while pulling docker image: $FILEBEAT_IMAGE"
|
||||
docker pull $OPENVIDU_RECORDING_IMAGE || fatal "Error while pulling docker image: $OPENVIDU_RECORDING_IMAGE"
|
||||
docker-compose pull | true
|
||||
|
||||
printf '\n => Stoping Media Node...'
|
||||
|
@ -216,14 +254,8 @@ upgrade_media_node() {
|
|||
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/media_node" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||
printf '\n - media_node'
|
||||
|
||||
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/readme.md" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'readme.md'"
|
||||
printf '\n - readme.md'
|
||||
|
||||
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/nginx_conf" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'nginx_conf'"
|
||||
printf '\n - nginx_conf'
|
||||
|
||||
cp "${MEDIA_NODE_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'"
|
||||
printf '\n - .env'
|
||||
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'beats' folder"
|
||||
printf '\n - beats'
|
||||
|
||||
# Move tmp files to Openvidu
|
||||
printf '\n => Updating files:'
|
||||
|
@ -231,9 +263,6 @@ upgrade_media_node() {
|
|||
mv "${TMP_FOLDER}/docker-compose.yml" "${MEDIA_NODE_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
||||
mv "${TMP_FOLDER}/.env" "${MEDIA_NODE_PREVIOUS_FOLDER}/.env-${MEDIA_NODE_VERSION}" || fatal_error "Error while moving previous '.env'"
|
||||
printf '\n - .env-%s' "${MEDIA_NODE_VERSION}"
|
||||
|
||||
mv "${TMP_FOLDER}/media_node" "${MEDIA_NODE_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'media_node'"
|
||||
printf '\n - media_node'
|
||||
|
||||
|
@ -245,9 +274,6 @@ upgrade_media_node() {
|
|||
mv "${TMP_FOLDER}/metricbeat-elasticsearch.yml" "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" || fatal_error "Error while updating 'metricbeat-elasticsearch.yml'"
|
||||
printf '\n - metricbeat-elasticsearch.yml'
|
||||
|
||||
mv "${TMP_FOLDER}/metricbeat-openvidu.yml" "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" || fatal_error "Error while updating 'metricbeat-openvidu.yml'"
|
||||
printf '\n - metricbeat-openvidu.yml'
|
||||
|
||||
mv "${TMP_FOLDER}/copy_config_files.sh" "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" || fatal_error "Error while updating 'copy_config_files.sh'"
|
||||
printf '\n - copy_config_files.sh'
|
||||
|
||||
|
@ -275,17 +301,27 @@ upgrade_media_node() {
|
|||
printf '\n'
|
||||
printf "\n 1. A new file 'docker-compose.yml' has been created with the new OpenVidu %s services" "${OPENVIDU_VERSION}"
|
||||
printf '\n'
|
||||
printf "\n 2. The previous file '.env' remains intact, but a new file '.env-%s' has been created." "${OPENVIDU_VERSION}"
|
||||
printf "\n Transfer any configuration you wish to keep in the upgraded version from '.env' to '.env-%s'." "${OPENVIDU_VERSION}"
|
||||
printf "\n When you are OK with it, rename and leave as the only '.env' file of the folder the new '.env-%s'." "${OPENVIDU_VERSION}"
|
||||
printf "\n 2. This new version %s does not need any .env file. Everything is configured from OpenVidu Pro" "${OPENVIDU_VERSION}"
|
||||
printf '\n'
|
||||
printf '\n 3. Start new version of Media Node'
|
||||
printf '\n $ ./media_node start'
|
||||
printf '\n'
|
||||
printf '\n 4. This will run a service at port 3000 which OpenVidu will use to deploy necessary containers.'
|
||||
printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine'
|
||||
printf '\n in file located at "/opt/openvidu/.env" with this format:'
|
||||
printf '\n ...'
|
||||
printf '\n KMS_URIS=["ws://<MEDIA_NODE_PRIVATE_IP>:8888/kurento"]'
|
||||
printf '\n ...'
|
||||
printf '\n You can also add Media Nodes from inspector'
|
||||
printf '\n'
|
||||
printf '\n 5. Start or restart OpenVidu Pro and all containers will be provisioned'
|
||||
printf '\n automatically to all the media nodes configured in "KMS_URIS"'
|
||||
printf '\n More info about Media Nodes deployment here:'
|
||||
printf "\n --> https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#set-the-number-of-media-nodes-on-startup"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
# Check docker and docker-compose installation
|
||||
|
|
|
@ -1,5 +1,41 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Deployed images in media-node
|
||||
IMAGES=(
|
||||
"kurento-media-server"
|
||||
"docker.elastic.co/beats/filebeat"
|
||||
"docker.elastic.co/beats/metricbeat"
|
||||
"openvidu/media-node-controller"
|
||||
)
|
||||
|
||||
docker_command_by_container_image() {
|
||||
IMAGE_NAME=$1
|
||||
COMMAND=$2
|
||||
if [[ ! -z "${IMAGE_NAME}" ]]; then
|
||||
CONTAINERS=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}')
|
||||
for CONTAINER_ID in ${CONTAINERS[@]}; do
|
||||
if [[ ! -z "${CONTAINER_ID}" ]] && [[ ! -z "${COMMAND}" ]]; then
|
||||
bash -c "docker ${COMMAND} ${CONTAINER_ID}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
stop_containers() {
|
||||
printf "Stopping containers..."
|
||||
for IMAGE in ${IMAGES[@]}; do
|
||||
docker_command_by_container_image "${IMAGE}" "rm -f"
|
||||
done
|
||||
}
|
||||
kurento_logs() {
|
||||
if [[ "$1" == "-f" ]]; then
|
||||
tail -f /opt/openvidu/kurento-logs/*.log
|
||||
else
|
||||
cat /opt/openvidu/kurento-logs/*.log
|
||||
fi
|
||||
}
|
||||
|
||||
upgrade_media_node() {
|
||||
UPGRADE_SCRIPT_URL="https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/install_media_node_OVVERSION.sh"
|
||||
HTTP_STATUS=$(curl -s -o /dev/null -I -w "%{http_code}" ${UPGRADE_SCRIPT_URL//OVVERSION/$1})
|
||||
|
@ -140,6 +176,16 @@ generate_report() {
|
|||
printf '\n'
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
printf "\n ---------------------------------------"
|
||||
printf "\n KMS"
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
kurento_logs
|
||||
printf "\n ---------------------------------------"
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
||||
printf "\n ======================================="
|
||||
printf "\n = CONTAINER ENVS VARIABLES ="
|
||||
printf "\n ======================================="
|
||||
|
@ -170,7 +216,8 @@ usage() {
|
|||
printf "\n\tstart\t\t\tStart media node service"
|
||||
printf "\n\tstop\t\t\tStop media node service"
|
||||
printf "\n\trestart\t\t\tRestart media node service"
|
||||
printf "\n\tlogs\t\t\tShow media node logs"
|
||||
printf "\n\tlogs [-f]\t\tShow media-node-controller logs."
|
||||
printf "\n\tkms-logs [-f]\t\tShow kms logs"
|
||||
printf "\n\tupgrade\t\t\tUpgrade to the lastest Media Node version"
|
||||
printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version"
|
||||
printf "\n\tversion\t\t\tShow version of Media Node"
|
||||
|
@ -179,15 +226,6 @@ usage() {
|
|||
printf "\n"
|
||||
}
|
||||
|
||||
stop_containers() {
|
||||
CONTAINERS=$(docker ps | awk '{if(NR>1) print $NF}')
|
||||
for CONTAINER in $CONTAINERS
|
||||
do
|
||||
[ "$(docker ps -a | grep ${CONTAINER})" ] && docker stop ${CONTAINER}
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
case $1 in
|
||||
|
||||
start)
|
||||
|
@ -208,7 +246,18 @@ case $1 in
|
|||
;;
|
||||
|
||||
logs)
|
||||
docker-compose logs -f media-node-controller
|
||||
case $2 in
|
||||
"-f")
|
||||
docker-compose logs -f media-node-controller
|
||||
;;
|
||||
*)
|
||||
docker-compose logs media-node-controller
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
kms-logs)
|
||||
kurento_logs $2
|
||||
;;
|
||||
|
||||
upgrade)
|
||||
|
|
|
@ -42,6 +42,22 @@ LETSENCRYPT_EMAIL=user@example.com
|
|||
# SDKs, REST clients and browsers will have to connect to this port
|
||||
# HTTPS_PORT=443
|
||||
|
||||
# Old paths are considered now deprecated, but still supported by default.
|
||||
# OpenVidu Server will log a WARN message every time a deprecated path is called, indicating
|
||||
# the new path that should be used instead. You can set property SUPPORT_DEPRECATED_API=false
|
||||
# to stop allowing the use of old paths.
|
||||
# Default value is true
|
||||
# SUPPORT_DEPRECATED_API=true
|
||||
|
||||
# If true request to with www will be redirected to non-www requests
|
||||
# Default value is false
|
||||
# REDIRECT_WWW=false
|
||||
|
||||
# How many workers to configure in nginx proxy.
|
||||
# The more workers, the more requests will be handled
|
||||
# Default value is 10240
|
||||
# WORKER_CONNECTIONS=10240
|
||||
|
||||
# Access restrictions
|
||||
# In this section you will be able to restrict the IPs from which you can access to
|
||||
# Openvidu API and the Administration Panel
|
||||
|
@ -71,6 +87,12 @@ OPENVIDU_PRO_CLUSTER_MODE=manual
|
|||
# Possibles values: aws, on_premise
|
||||
OPENVIDU_PRO_CLUSTER_ENVIRONMENT=on_premise
|
||||
|
||||
# Unique identifier of your cluster. Each OpenVidu Server Pro instance corresponds to one cluster.
|
||||
# You can launch as many clusters as you want with your license key.
|
||||
# Cluster ID will always be stored to disk so restarting OpenVidu Server Pro will keep the same previous cluster ID
|
||||
# if this configuration parameter is not given a distinct value.
|
||||
# OPENVIDU_PRO_CLUSTER_ID=
|
||||
|
||||
# The desired number of Media Nodes on startup. First the autodiscovery process is performed.
|
||||
# If there are too many Media Nodes after that, they will be dropped until this number is reached.
|
||||
# If there are not enough, more will be launched.
|
||||
|
@ -85,7 +107,6 @@ OPENVIDU_PRO_CLUSTER_ENVIRONMENT=on_premise
|
|||
# Type: number >= 0
|
||||
# OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL=
|
||||
|
||||
|
||||
# Whether to enable or disable autoscaling. With autoscaling the number of Media Nodes will
|
||||
# be automatically adjusted according to existing load
|
||||
# Values: true | false
|
||||
|
@ -119,13 +140,55 @@ OPENVIDU_PRO_CLUSTER_AUTOSCALING=false
|
|||
# (and therefore distribution of load) among all available Media Nodes
|
||||
OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams
|
||||
|
||||
# Whether to enable or disable Network Quality API. You can monitor and
|
||||
# warn users about the quality of their networks with this feature
|
||||
# OPENVIDU_PRO_NETWORK_QUALITY=false
|
||||
|
||||
# If OPENVIDU_PRO_NETWORK_QUALITY=true, how often the network quality
|
||||
# algorithm will be invoked for each user, in seconds
|
||||
# OPENVIDU_PRO_NETWORK_QUALITY_INTERVAL=5
|
||||
|
||||
# Max days until delete indexes in state of rollover on Elasticsearch
|
||||
# Type number >= 0
|
||||
# Default Value is 15
|
||||
# OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE=
|
||||
|
||||
# Private IP of OpenVidu Server Pro
|
||||
# For example 192.168.1.101
|
||||
# OPENVIDU_PRO_PRIVATE_IP=
|
||||
# If you have an external Elasticsearch and Kibana already running, put here the url to elasticsearch and kibana services.
|
||||
# It is very important that both url have the port specified in the url.
|
||||
# If you want to use the deployed Elasticsearch and Kibana locally, keep these variables commented.
|
||||
#OPENVIDU_PRO_ELASTICSEARCH_HOST=
|
||||
#OPENVIDU_PRO_KIBANA_HOST=
|
||||
|
||||
# Where to store recording files. Can be 'local' (local storage) or 's3' (AWS bucket).
|
||||
# You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it.
|
||||
#OPENVIDU_PRO_RECORDING_STORAGE=
|
||||
|
||||
# S3 Bucket where to store recording files. May include paths to allow navigating
|
||||
# folder structures inside the bucket. This property is only taken into account
|
||||
# if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
#OPENVIDU_PRO_AWS_S3_BUCKET=
|
||||
|
||||
# If OPENVIDU_PRO_RECORDING_STORAGE=s3, the collection of HTTP header values that the internal AWS client will use during
|
||||
# the upload process. The property is a key-value map of strings, following the format of a JSON object. For example, for applying
|
||||
# server-side encryption with AES-256, this header is mandatory: {"x-amz-server-side-encryption":"AES256"}.
|
||||
# The list of available headers can be found here: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/Headers.html
|
||||
# This property is only taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
#OPENVIDU_PRO_AWS_S3_HEADERS=
|
||||
|
||||
# If you're instance has a role which has access to read
|
||||
# and write into the s3 bucket, you don't need this parameter
|
||||
# OPENVIDU_PRO_AWS_ACCESS_KEY=
|
||||
|
||||
# AWS credentials secret key from OPENVIDU_PRO_AWS_ACCESS_KEY. This property is only
|
||||
# taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
# If you're instance has a role which has access to read
|
||||
# and write into the s3 bucket, you don't need this parameter
|
||||
# OPENVIDU_PRO_AWS_SECRET_KEY=
|
||||
|
||||
# AWS region in which the S3 bucket is located (e.g. eu-west-1). If not provided,
|
||||
# the region will try to be discovered automatically, although this is not always possible.
|
||||
# This property is only taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3
|
||||
# OPENVIDU_PRO_AWS_REGION=
|
||||
|
||||
# Whether to enable recording module or not
|
||||
OPENVIDU_RECORDING=false
|
||||
|
@ -178,12 +241,14 @@ OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH=1000
|
|||
# 0 means unconstrained
|
||||
OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH=300
|
||||
|
||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_ALLOW_TRANSCODING=true
|
||||
# when a codec can not be forced, transcoding will be allowed
|
||||
# OPENVIDU_FORCED_CODEC=VP8
|
||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_STREAMS_ALLOW_TRANSCODING=true
|
||||
# when a codec can not be forced, transcoding will be allowed
|
||||
# Default value is VP8
|
||||
# OPENVIDU_STREAMS_FORCED_VIDEO_CODEC=VP8
|
||||
|
||||
# Allow transcoding if codec specified in OPENVIDU_FORCED_CODEC can not be applied
|
||||
# OPENVIDU_ALLOW_TRANSCODING=false
|
||||
# Allow transcoding if codec specified in OPENVIDU_STREAMS_FORCED_VIDEO_CODEC can not be applied
|
||||
# Default value is false
|
||||
# OPENVIDU_STREAMS_ALLOW_TRANSCODING=false
|
||||
|
||||
# true to enable OpenVidu Webhook service. false' otherwise
|
||||
# Values: true | false
|
||||
|
@ -227,17 +292,44 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
|
|||
# RECOMENDED VALUES: INFO for normal logs DEBUG for more verbose logs
|
||||
# OV_CE_DEBUG_LEVEL=INFO
|
||||
|
||||
# Java Options
|
||||
# OpenVidu Java Options
|
||||
# --------------------------
|
||||
# Uncomment the next line and define this to add options to java command
|
||||
# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058
|
||||
# JAVA_OPTIONS=-Xms2048m -Xmx4096m
|
||||
|
||||
# Kibana And ElasticSearch Configuration
|
||||
# ElasticSearch Java Options
|
||||
# --------------------------
|
||||
# Kibana dashboard configuration (Credentials)
|
||||
KIBANA_USER=kibanaadmin
|
||||
KIBANA_PASSWORD=
|
||||
# Uncomment the next line and define this to add options to java command of Elasticsearch
|
||||
# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058
|
||||
# By default ElasticSearch is configured to use "-Xms2g -Xmx2g" as Java Min and Max memory heap allocation
|
||||
# ES_JAVA_OPTS=-Xms2048m -Xmx4096m
|
||||
|
||||
# Kibana And ElasticSearch Credentials Configuration
|
||||
# --------------------------
|
||||
# Kibana And ElasticSearch Basic Auth configuration (Credentials)
|
||||
# This credentials will aso be valid for Kibana dashboard
|
||||
ELASTICSEARCH_USERNAME=elasticadmin
|
||||
ELASTICSEARCH_PASSWORD=
|
||||
|
||||
# Media Node Configuration
|
||||
# --------------------------
|
||||
# You can add any KMS environment variable as described in the
|
||||
# documentation of the docker image: https://hub.docker.com/r/kurento/kurento-media-server
|
||||
# If you want to add an environment variable to KMS, you must add a variable using this prefix: 'KMS_DOCKER_ENV_',
|
||||
# followed by the environment variable you want to setup.
|
||||
# For example if you want to setup KMS_MIN_PORT to 50000, it would be KMS_DOCKER_ENV_KMS_MIN_PORT=50000
|
||||
|
||||
# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server
|
||||
# Uncomment the next line and define this variable with KMS image that you want use
|
||||
# By default, KMS_IMAGE is defined in media nodes and it does not need to be specified unless
|
||||
# you want to use a specific version of KMS
|
||||
# KMS_IMAGE=kurento/kurento-media-server:6.15.0
|
||||
|
||||
# Uncomment the next line and define this variable to change
|
||||
# the verbosity level of the logs of KMS
|
||||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
||||
# KMS_DOCKER_ENV_GST_DEBUG=
|
||||
|
||||
# Cloudformation configuration
|
||||
# --------------------------
|
||||
|
@ -250,3 +342,5 @@ KIBANA_PASSWORD=
|
|||
#AWS_SECURITY_GROUP=
|
||||
#AWS_STACK_ID=
|
||||
#AWS_STACK_NAME=
|
||||
#AWS_CLI_DOCKER_TAG=
|
||||
#AWS_VOLUME_SIZE=
|
||||
|
|
|
@ -13,20 +13,36 @@ processors:
|
|||
fields: ["message"]
|
||||
target: "json"
|
||||
overwrite_keys: true
|
||||
- drop_event:
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: openvidu/openvidu-coturn
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/elasticsearch/elasticsearch
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/kibana/kibana
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/beats/filebeat-oss
|
||||
- contains:
|
||||
container.image.name: docker.elastic.co/beats/metricbeat-oss
|
||||
- add_fields:
|
||||
fields:
|
||||
cluster-id: ${OPENVIDU_PRO_CLUSTER_ID:undefined}
|
||||
|
||||
output:
|
||||
elasticsearch:
|
||||
hosts: ["elasticsearch:9200"]
|
||||
hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
|
||||
indices:
|
||||
- index: "filebeat-redis-%{+yyyy.MM.dd}"
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: openvidu/openvidu-redis
|
||||
- index: "filebeat-coturn-%{+yyyy.MM.dd}"
|
||||
- index: "filebeat-nginx-%{+yyyy.MM.dd}"
|
||||
when.or:
|
||||
- contains:
|
||||
container.image.name: openvidu/openvidu-coturn
|
||||
container.image.name: openvidu/openvidu-proxy
|
||||
|
||||
|
||||
logging.json: true
|
||||
logging.metrics.enabled: false
|
||||
logging.metrics.enabled: false
|
||||
setup.ilm.enabled: false
|
|
@ -0,0 +1,10 @@
|
|||
metricbeat.modules:
|
||||
- module: nginx
|
||||
metricsets: ["stubstatus"]
|
||||
enabled: true
|
||||
period: 10s
|
||||
hosts: ["http://127.0.0.1"]
|
||||
server_status_path: "nginx_status"
|
||||
output:
|
||||
elasticsearch:
|
||||
hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
|
|
@ -7,7 +7,7 @@ DEBUG=${DEBUG:-false}
|
|||
|
||||
OUTPUT=$(mktemp -t openvidu-autodiscover-XXX --suffix .json)
|
||||
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 describe-instances \
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 describe-instances \
|
||||
--output text \
|
||||
--filters "Name=instance-state-name,Values=running" \
|
||||
"Name=tag:ov-cluster-member,Values=kms" \
|
||||
|
|
|
@ -8,4 +8,4 @@ DEBUG=${DEBUG:-false}
|
|||
ID=$1
|
||||
[ -z "${ID}" ] && { echo "Must provide instance ID"; exit 1; }
|
||||
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 terminate-instances --instance-ids ${ID} --output json
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 terminate-instances --instance-ids ${ID} --output json
|
||||
|
|
|
@ -23,7 +23,7 @@ exit_on_error () {
|
|||
|
||||
"UnauthorizedOperation")
|
||||
MSG_COD=$(cat ${ERROUTPUT} | awk -F: '{ print $3 }')
|
||||
MSG_DEC=$(docker run --rm amazon/aws-cli:2.0.7 sts decode-authorization-message --encoded-message ${MSG_COD})
|
||||
MSG_DEC=$(docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} sts decode-authorization-message --encoded-message ${MSG_COD})
|
||||
|
||||
echo -e "Unauthorized " $(cat ${MSG_DEC}) >&2
|
||||
exit 1
|
||||
|
@ -35,16 +35,17 @@ exit_on_error () {
|
|||
esac
|
||||
}
|
||||
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 run-instances \
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 run-instances \
|
||||
--image-id ${AWS_IMAGE_ID} --count 1 \
|
||||
--instance-type ${AWS_INSTANCE_TYPE} \
|
||||
--key-name ${AWS_KEY_NAME} \
|
||||
--subnet-id ${AWS_SUBNET_ID} \
|
||||
--tag-specifications "ResourceType=instance,Tags=[{Key='Name',Value='Kurento Media Server'},{Key='ov-cluster-member',Value='kms'},{Key='ov-stack-name',Value='${AWS_STACK_NAME}'},{Key='ov-stack-region',Value='${AWS_DEFAULT_REGION}'}]" \
|
||||
--iam-instance-profile Name="OpenViduInstanceProfile-${AWS_STACK_NAME}-${AWS_DEFAULT_REGION}" \
|
||||
--block-device-mappings "DeviceName=/dev/sda1,Ebs={DeleteOnTermination=True,VolumeType='gp2',VolumeSize='${AWS_VOLUME_SIZE}'}" \
|
||||
--security-group-ids ${AWS_SECURITY_GROUP} > ${OUTPUT} 2> ${ERROUTPUT}
|
||||
|
||||
docker run --rm amazon/aws-cli:2.0.7 ec2 wait instance-running --instance-ids $(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .InstanceId')
|
||||
docker run --rm amazon/aws-cli:${AWS_CLI_DOCKER_TAG} ec2 wait instance-running --instance-ids $(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .InstanceId')
|
||||
|
||||
# Generating the output
|
||||
KMS_IP=$(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .NetworkInterfaces[0] | .PrivateIpAddress')
|
||||
|
|
|
@ -9,11 +9,11 @@ services:
|
|||
#
|
||||
# Default Application
|
||||
#
|
||||
# Openvidu-Call Version: 2.15.0
|
||||
# Openvidu-Call Version: 2.16.0
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
app:
|
||||
image: openvidu/openvidu-call:2.15.0
|
||||
image: openvidu/openvidu-call:2.16.0
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
|
@ -21,3 +21,6 @@ services:
|
|||
- OPENVIDU_URL=http://localhost:5443
|
||||
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||
- CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
# Application based on OpenVidu should be specified in
|
||||
# docker-compose.override.yml file
|
||||
#
|
||||
# This docker-compose file coordinates all services of OpenVidu CE Platform.
|
||||
# This docker-compose file coordinates all services of OpenVidu Pro Platform
|
||||
#
|
||||
# This file will be overridden when update OpenVidu Platform
|
||||
#
|
||||
# Openvidu Version: 2.15.1
|
||||
# Openvidu Version: 2.16.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
@ -22,10 +22,10 @@ version: '3.1'
|
|||
services:
|
||||
|
||||
openvidu-server:
|
||||
image: openvidu/openvidu-server-pro:2.15.1
|
||||
image: openvidu/openvidu-server-pro:2.17.0-dev5
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
entrypoint: ['/bin/bash', '-c', 'export COTURN_IP=`/usr/local/bin/discover_my_public_ip.sh`; /usr/local/bin/entrypoint.sh']
|
||||
entrypoint: ['/usr/local/bin/entrypoint.sh']
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||
|
@ -41,21 +41,28 @@ services:
|
|||
- KMS_URIS=[]
|
||||
- COTURN_REDIS_IP=127.0.0.1
|
||||
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||
- COTURN_IP=${COTURN_IP:-auto-ipv4}
|
||||
- OPENVIDU_PRO_CLUSTER=true
|
||||
- OPENVIDU_PRO_KIBANA_HOST=http://127.0.0.1/kibana
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=http://127.0.0.1:9200
|
||||
- WAIT_KIBANA_URL=http://127.0.0.1:5601/api/status
|
||||
- OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||
- WAIT_KIBANA_URL=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
|
||||
- DOTENV_PATH=${PWD}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
redis:
|
||||
image: openvidu/openvidu-redis:1.0.0
|
||||
image: openvidu/openvidu-redis:2.0.0-dev2
|
||||
restart: always
|
||||
network_mode: host
|
||||
environment:
|
||||
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
coturn:
|
||||
image: openvidu/openvidu-coturn:1.0.0
|
||||
image: openvidu/openvidu-coturn:3.0.0-dev2
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
environment:
|
||||
|
@ -63,17 +70,22 @@ services:
|
|||
- TURN_LISTEN_PORT=3478
|
||||
- DB_NAME=0
|
||||
- DB_PASSWORD=${OPENVIDU_SECRET}
|
||||
- MIN_PORT=57001
|
||||
- MIN_PORT=40000
|
||||
- MAX_PORT=65535
|
||||
- TURN_PUBLIC_IP=${TURN_PUBLIC_IP:-auto-ipv4}
|
||||
- ENABLE_COTURN_LOGS=true
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
nginx:
|
||||
image: openvidu/openvidu-proxy:3.0.0
|
||||
image: openvidu/openvidu-proxy:5.0.0-dev2
|
||||
restart: on-failure
|
||||
network_mode: host
|
||||
entrypoint: ['/bin/sh', '-c', 'htpasswd -bc /etc/nginx/kibana.htpasswd "${KIBANA_USER}" "${KIBANA_PASSWORD}" && /usr/local/bin/entrypoint.sh']
|
||||
volumes:
|
||||
- ./certificates:/etc/letsencrypt
|
||||
- ./owncert:/owncert
|
||||
- ./custom-nginx-vhosts:/etc/nginx/vhost.d/
|
||||
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout
|
||||
environment:
|
||||
- DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP}
|
||||
|
@ -85,31 +97,84 @@ services:
|
|||
- ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-}
|
||||
- PROXY_MODE=PRO
|
||||
- WITH_APP=true
|
||||
- SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true}
|
||||
- REDIRECT_WWW=${REDIRECT_WWW:-false}
|
||||
- WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240}
|
||||
- PUBLIC_IP=${PROXY_PUBLIC_IP:-auto-ipv4}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
|
||||
elasticsearch:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
|
||||
restart: always
|
||||
environment:
|
||||
- discovery.type=single-node
|
||||
- xpack.security.enabled=true
|
||||
- "ES_JAVA_OPTS=${ES_JAVA_OPTS:--Xms2g -Xmx2g}"
|
||||
ports:
|
||||
- 9200:9200
|
||||
volumes:
|
||||
- ./elasticsearch:/usr/share/elasticsearch/data
|
||||
command: >
|
||||
/bin/bash -c "elasticsearch-users useradd ${ELASTICSEARCH_USERNAME}
|
||||
-p ${ELASTICSEARCH_PASSWORD} -r superuser;
|
||||
docker-entrypoint.sh"
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:7.8.0
|
||||
restart: always
|
||||
environment:
|
||||
- SERVER_BASEPATH="/kibana"
|
||||
- xpack.security.enabled=true
|
||||
- ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
|
||||
- ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
|
||||
ports:
|
||||
- 5601:5601
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
filebeat:
|
||||
image: docker.elastic.co/beats/filebeat:7.8.0
|
||||
metricbeat:
|
||||
image: docker.elastic.co/beats/metricbeat-oss:7.8.0
|
||||
network_mode: host
|
||||
restart: always
|
||||
user: root
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||
volumes:
|
||||
- ./beats/metricbeat.yml:/usr/share/metricbeat/metricbeat.yml:ro
|
||||
command: >
|
||||
/bin/bash -c "metricbeat -e -strict.perms=false
|
||||
`if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi`
|
||||
`if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`"
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
||||
filebeat:
|
||||
image: docker.elastic.co/beats/filebeat-oss:7.8.0
|
||||
network_mode: host
|
||||
restart: always
|
||||
user: root
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||
volumes:
|
||||
- ./beats/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
|
||||
- /var/lib/docker:/var/lib/docker:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
command: filebeat -e -strict.perms=false
|
||||
command: >
|
||||
/bin/bash -c "filebeat -e -strict.perms=false
|
||||
`if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi`
|
||||
`if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`"
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# Global variables
|
||||
OPENVIDU_FOLDER=openvidu
|
||||
OPENVIDU_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.16"
|
||||
AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws
|
||||
ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch
|
||||
BEATS_FOLDER=${OPENVIDU_FOLDER}/beats
|
||||
|
@ -60,6 +61,10 @@ new_ov_installation() {
|
|||
--output "${BEATS_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
||||
printf '\n - filebeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml \
|
||||
--output "${BEATS_FOLDER}/metricbeat.yml" || fatal_error "Error when downloading the file 'metricbeat.yml'"
|
||||
printf '\n - metricbeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env \
|
||||
--output "${OPENVIDU_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
@ -95,6 +100,10 @@ new_ov_installation() {
|
|||
printf "\n => Creating folder 'owncert'..."
|
||||
mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the folder 'owncert'"
|
||||
|
||||
# Create vhost nginx folder
|
||||
printf "\n => Creating folder 'custom-nginx-vhosts'..."
|
||||
mkdir "${OPENVIDU_FOLDER}/custom-nginx-vhosts" || fatal_error "Error while creating the folder 'custom-nginx-vhosts'"
|
||||
|
||||
# Ready to use
|
||||
printf '\n'
|
||||
printf '\n'
|
||||
|
@ -105,13 +114,15 @@ new_ov_installation() {
|
|||
printf '\n 1. Go to openvidu folder:'
|
||||
printf '\n $ cd openvidu'
|
||||
printf '\n'
|
||||
printf '\n 2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, OPENVIDU_SECRET, and KIBANA_PASSWORD in .env file:'
|
||||
printf '\n 2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, '
|
||||
printf '\n OPENVIDU_SECRET, and ELASTICSEARCH_PASSWORD in .env file:'
|
||||
printf '\n $ nano .env'
|
||||
printf '\n'
|
||||
printf '\n 3. Start OpenVidu'
|
||||
printf '\n $ ./openvidu start'
|
||||
printf '\n'
|
||||
printf "\n CAUTION: The folder 'openvidu/elasticsearch' use user and group 1000 permissions. This folder is necessary for store elasticsearch data."
|
||||
printf "\n CAUTION: The folder 'openvidu/elasticsearch' use user and group 1000 permissions. "
|
||||
printf "\n This folder is necessary for store elasticsearch data."
|
||||
printf "\n For more information, check:"
|
||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions"
|
||||
printf '\n'
|
||||
|
@ -147,10 +158,13 @@ upgrade_ov() {
|
|||
|
||||
# Uppgrade Openvidu
|
||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && OPENVIDU_PREVIOUS_VERSION=2.13.0
|
||||
[ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version"
|
||||
|
||||
# In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is
|
||||
# posible or not. If it is not posible launch a warning and stop the upgrade.
|
||||
if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then
|
||||
fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions."
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
printf '\n ======================================='
|
||||
|
@ -188,6 +202,10 @@ upgrade_ov() {
|
|||
--output "${TMP_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
||||
printf '\n - filebeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml \
|
||||
--output "${TMP_FOLDER}/metricbeat.yml" || fatal_error "Error when downloading the file 'metricbeat.yml'"
|
||||
printf '\n - metricbeat.yml'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env \
|
||||
--output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
@ -243,15 +261,20 @@ upgrade_ov() {
|
|||
mv "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/readme.md" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'readme.md'"
|
||||
printf '\n - readme.md'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'cluster/aws'"
|
||||
printf '\n - cluster/aws'
|
||||
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/beats" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'beats'"
|
||||
printf '\n - beats'
|
||||
|
||||
cp "${OPENVIDU_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
if [ -d "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-vhosts" ]; then
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-vhosts" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous directory 'custom-nginx-vhosts'"
|
||||
printf '\n - custom-nginx-vhosts'
|
||||
fi
|
||||
|
||||
# Move tmp files to Openvidu
|
||||
printf '\n => Updating files:'
|
||||
|
||||
|
@ -288,6 +311,9 @@ upgrade_ov() {
|
|||
mv "${TMP_FOLDER}/filebeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/filebeat.yml" || fatal_error "Error while updating 'filebeat.yml'"
|
||||
printf '\n - filebeat.yml'
|
||||
|
||||
mv "${TMP_FOLDER}/metricbeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/metricbeat.yml" || fatal_error "Error while updating 'metricbeat.yml'"
|
||||
printf '\n - metricbeat.yml'
|
||||
|
||||
printf "\n => Deleting 'tmp' folder"
|
||||
rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder"
|
||||
|
||||
|
@ -311,16 +337,15 @@ upgrade_ov() {
|
|||
[ ! -z "${OLD_MODE}" ] && sed -i -r "s/Installation Mode:.+/Installation Mode: ${OLD_MODE}/" "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml"
|
||||
|
||||
# In Aws, update AMI ID
|
||||
CHECK_AWS=$(curl -s -o /dev/null -w "%{http_code}" http://169.254.169.254)
|
||||
if [[ ${CHECK_AWS} == "200" ]]; then
|
||||
AWS_REGION=$(grep -E "AWS_DEFAULT_REGION=.*$" "${OPENVIDU_PREVIOUS_FOLDER}/.env" | cut -d'=' -f2)
|
||||
[[ -z ${AWS_REGION} ]] && fatal_error "Error while getting AWS_REGION"
|
||||
AWS_REGION=$(grep -E "AWS_DEFAULT_REGION=.*$" "${OPENVIDU_PREVIOUS_FOLDER}/.env" | cut -d'=' -f2)
|
||||
if [[ ! -z ${AWS_REGION} ]]; then
|
||||
NEW_AMI_ID=$(curl https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_VERSION//v}.yaml --silent |
|
||||
sed -n -e '/KMSAMIMAP:/,/Metadata:/ p' |
|
||||
grep -A 1 ${AWS_REGION} | grep AMI | tr -d " " | cut -d":" -f2)
|
||||
[[ -z ${NEW_AMI_ID} ]] && fatal_error "Error while getting new AWS_IMAGE_ID for Media Nodes"
|
||||
sed -i "s/.*AWS_IMAGE_ID=.*/AWS_IMAGE_ID=${NEW_AMI_ID}/" "${OPENVIDU_PREVIOUS_FOLDER}/.env" || fatal_error "Error while updating new AWS_IMAGE_ID for Media Nodes"
|
||||
fi
|
||||
|
||||
|
||||
# Ready to use
|
||||
printf '\n'
|
||||
|
|
|
@ -120,7 +120,7 @@ generate_report() {
|
|||
printf '\n'
|
||||
printf '\n'
|
||||
|
||||
cat < "${OV_FOLDER}/.env" | sed -r -e "s/OPENVIDU_SECRET=.+/OPENVIDU_SECRET=****/" -e "s/OPENVIDU_PRO_LICENSE=.+/OPENVIDU_PRO_LICENSE=****/" -e "s/KIBANA_PASSWORD=.+/KIBANA_PASSWORD=****/"
|
||||
cat < "${OV_FOLDER}/.env" | sed -r -e "s/OPENVIDU_SECRET=.+/OPENVIDU_SECRET=****/" -e "s/OPENVIDU_PRO_LICENSE=.+/OPENVIDU_PRO_LICENSE=****/" -e "s/ELASTICSEARCH_PASSWORD=.+/ELASTICSEARCH_PASSWORD=****/"
|
||||
|
||||
printf '\n'
|
||||
printf '\n ========= docker-compose.yml =========='
|
||||
|
@ -183,6 +183,42 @@ generate_report() {
|
|||
printf "\n"
|
||||
}
|
||||
|
||||
is_external_url() {
|
||||
local URL=$1
|
||||
if [[ -z "$URL" ]]; then
|
||||
return 1
|
||||
fi
|
||||
if [[ "${URL}" == *"localhost"* ]] || [[ "${URL}" == *"127.0.0.1"* ]] || [[ "${URL}" == *"::1"* ]]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
start_openvidu() {
|
||||
local RUN_LOCAL_ES
|
||||
local RUN_LOCAL_KIBANA
|
||||
local CONFIGURED_ELASTICSEARCH_HOST
|
||||
local CONFIGURED_KIBANA_HOST
|
||||
CONFIGURED_ELASTICSEARCH_HOST=$(grep -v '^#' .env | grep OPENVIDU_PRO_ELASTICSEARCH_HOST | cut -d '=' -f2)
|
||||
CONFIGURED_KIBANA_HOST=$(grep -v '^#' .env | grep OPENVIDU_PRO_KIBANA_HOST | cut -d '=' -f2)
|
||||
RUN_LOCAL_ES=true
|
||||
RUN_LOCAL_KIBANA=true
|
||||
if is_external_url "${CONFIGURED_ELASTICSEARCH_HOST}"; then
|
||||
printf "Configured external elasticsearch: %s" "${CONFIGURED_ELASTICSEARCH_HOST}"
|
||||
printf "\n"
|
||||
RUN_LOCAL_ES=false
|
||||
fi
|
||||
if is_external_url "${CONFIGURED_KIBANA_HOST}"; then
|
||||
printf "Configured external kibana: %s" "${CONFIGURED_KIBANA_HOST}"
|
||||
printf "\n"
|
||||
RUN_LOCAL_KIBANA=false
|
||||
fi
|
||||
docker-compose up -d \
|
||||
$(if [ "${RUN_LOCAL_ES}" == "false" ]; then echo '--scale elasticsearch=0'; fi) \
|
||||
$(if [ "${RUN_LOCAL_KIBANA}" == "false" ]; then echo '--scale kibana=0'; fi)
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf "Usage: \n\t openvidu [command]"
|
||||
printf "\n\nAvailable Commands:"
|
||||
|
@ -198,11 +234,15 @@ usage() {
|
|||
printf "\n"
|
||||
}
|
||||
|
||||
[[ -z "${FOLLOW_OPENVIDU_LOGS}" ]] && FOLLOW_OPENVIDU_LOGS=true
|
||||
|
||||
case $1 in
|
||||
|
||||
start)
|
||||
docker-compose up -d
|
||||
docker-compose logs -f openvidu-server
|
||||
start_openvidu
|
||||
if [[ "${FOLLOW_OPENVIDU_LOGS}" == "true" ]]; then
|
||||
docker-compose logs -f openvidu-server
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
|
@ -211,8 +251,10 @@ case $1 in
|
|||
|
||||
restart)
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
docker-compose logs -f openvidu-server
|
||||
start_openvidu
|
||||
if [[ "${FOLLOW_OPENVIDU_LOGS}" == "true" ]]; then
|
||||
docker-compose logs -f openvidu-server
|
||||
fi
|
||||
;;
|
||||
|
||||
logs)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
global:
|
||||
owner: openvidu@gmail.com
|
||||
owner: info@openvidu.io
|
||||
qsname: openvidu-pro-clustering
|
||||
regions:
|
||||
- us-east-1
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y coturn curl
|
||||
&& apt-get install -y coturn curl dnsutils
|
||||
|
||||
COPY ./configuration-files.sh /tmp/
|
||||
COPY ./entrypoint.sh /usr/local/bin
|
||||
|
@ -11,4 +11,4 @@ RUN chmod +x /tmp/configuration-files.sh \
|
|||
&& chmod +x /usr/local/bin/entrypoint.sh \
|
||||
&& chmod +x /usr/local/bin/discover_my_public_ip.sh
|
||||
|
||||
CMD /usr/local/bin/entrypoint.sh
|
||||
ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue