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
|
## Contributors
|
||||||
|
|
||||||
This project exists thanks to all the people who contribute.
|
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
|
## Backers
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ module.exports = {
|
||||||
],
|
],
|
||||||
excludeExternals: true,
|
excludeExternals: true,
|
||||||
excludePrivate: true,
|
excludePrivate: true,
|
||||||
|
excludeProtected: true,
|
||||||
excludeNotExported: true,
|
excludeNotExported: true,
|
||||||
theme: "default",
|
theme: "default",
|
||||||
readme: "none",
|
readme: "none",
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
{
|
{
|
||||||
"author": "OpenVidu",
|
"author": "OpenVidu",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "13.13.2",
|
|
||||||
"@types/platform": "1.3.2",
|
|
||||||
"freeice": "2.2.2",
|
"freeice": "2.2.2",
|
||||||
"hark": "1.2.3",
|
"hark": "1.2.3",
|
||||||
"platform": "1.3.5",
|
"platform": "1.3.6",
|
||||||
"uuid": "7.0.3",
|
"uuid": "8.3.1",
|
||||||
"wolfy87-eventemitter": "5.2.9"
|
"wolfy87-eventemitter": "5.2.9"
|
||||||
},
|
},
|
||||||
"description": "OpenVidu Browser",
|
"description": "OpenVidu Browser",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browserify": "16.5.1",
|
"@types/node": "14.14.7",
|
||||||
"grunt": "1.1.0",
|
"@types/platform": "1.3.3",
|
||||||
|
"browserify": "17.0.0",
|
||||||
|
"grunt": "1.3.0",
|
||||||
"grunt-cli": "1.3.2",
|
"grunt-cli": "1.3.2",
|
||||||
"grunt-contrib-copy": "1.0.0",
|
"grunt-contrib-copy": "1.0.0",
|
||||||
"grunt-contrib-sass": "1.0.0",
|
"grunt-contrib-sass": "2.0.0",
|
||||||
"grunt-contrib-uglify": "4.0.1",
|
"grunt-contrib-uglify": "5.0.0",
|
||||||
"grunt-contrib-watch": "1.1.0",
|
"grunt-contrib-watch": "1.1.0",
|
||||||
"grunt-postcss": "0.9.0",
|
"grunt-postcss": "0.9.0",
|
||||||
"grunt-string-replace": "1.3.1",
|
"grunt-string-replace": "1.3.1",
|
||||||
"grunt-ts": "6.0.0-beta.22",
|
"grunt-ts": "6.0.0-beta.22",
|
||||||
"terser": "4.6.11",
|
"terser": "5.3.8",
|
||||||
"tsify": "4.0.1",
|
"tsify": "5.0.2",
|
||||||
"tslint": "6.1.1",
|
"tslint": "6.1.3",
|
||||||
"typedoc": "0.17.4",
|
"typedoc": "0.19.2",
|
||||||
"typescript": "3.8.3"
|
"typescript": "4.0.5"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
|
|
@ -35,11 +35,11 @@
|
||||||
"url": "git://github.com/OpenVidu/openvidu"
|
"url": "git://github.com/OpenVidu/openvidu"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"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": "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}; 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-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",
|
"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"
|
"docs": "./generate-docs.sh"
|
||||||
},
|
},
|
||||||
"types": "lib/index.d.ts",
|
"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 { Session } from './Session';
|
||||||
import { Stream } from './Stream';
|
import { Stream } from './Stream';
|
||||||
import { StreamLEGACY } from './StreamLEGACY';
|
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 { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions';
|
||||||
import { StreamOptionsServer } from '../OpenViduInternal/Interfaces/Private/StreamOptionsServer';
|
import { StreamOptionsServer } from '../OpenViduInternal/Interfaces/Private/StreamOptionsServer';
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
|
|
@ -52,14 +53,36 @@ export class Connection {
|
||||||
data: string;
|
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
|
* @hidden
|
||||||
*/
|
*/
|
||||||
options: ConnectionOptions | undefined;
|
stream?: Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
localOptions: LocalConnectionOptions | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
remoteOptions: RemoteConnectionOptions | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
|
@ -74,23 +97,30 @@ export class Connection {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
constructor(private session: Session, opts?: ConnectionOptions) {
|
constructor(private session: Session, connectionOptions: LocalConnectionOptions | RemoteConnectionOptions) {
|
||||||
let msg = "'Connection' created ";
|
let msg = "'Connection' created ";
|
||||||
if (!!opts) {
|
if (!!(<LocalConnectionOptions>connectionOptions).role) {
|
||||||
// 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 {
|
|
||||||
// Connection is local
|
// 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)';
|
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);
|
logger.info(msg);
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +133,7 @@ export class Connection {
|
||||||
*/
|
*/
|
||||||
sendIceCandidate(candidate: RTCIceCandidate): void {
|
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.connectionId, candidate);
|
||||||
|
|
||||||
this.session.openvidu.sendRequest('onIceCandidate', {
|
this.session.openvidu.sendRequest('onIceCandidate', {
|
||||||
|
|
@ -149,7 +179,7 @@ export class Connection {
|
||||||
this.addStream(stream);
|
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;
|
this.disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,9 +119,9 @@ export class Filter {
|
||||||
} else {
|
} else {
|
||||||
logger.info('Filter method successfully executed on Stream ' + this.stream.streamId);
|
logger.info('Filter method successfully executed on Stream ' + this.stream.streamId);
|
||||||
const oldValue = (<any>Object).assign({}, this.stream.filter);
|
const oldValue = (<any>Object).assign({}, this.stream.filter);
|
||||||
this.stream.filter.lastExecMethod = { method, params: JSON.parse(stringParams) };
|
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.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.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
import { Stream } from './Stream';
|
import { Stream } from './Stream';
|
||||||
import { LocalRecorderState } from '../OpenViduInternal/Enums/LocalRecorderState';
|
import { LocalRecorderState } from '../OpenViduInternal/Enums/LocalRecorderState';
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
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();
|
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
let platform: PlatformUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Easy recording of [[Stream]] objects straightaway from the browser. Initialized with [[OpenVidu.initLocalRecorder]] method
|
* 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 connectionId: string;
|
||||||
private mediaRecorder: any;
|
private mediaRecorder: any;
|
||||||
private chunks: any[] = [];
|
private chunks: any[] = [];
|
||||||
private blob: Blob;
|
private blob?: Blob;
|
||||||
private id: string;
|
private id: string;
|
||||||
private videoPreviewSrc: string;
|
private videoPreviewSrc: string;
|
||||||
private videoPreview: HTMLVideoElement;
|
private videoPreview: HTMLVideoElement;
|
||||||
|
|
@ -54,6 +59,7 @@ export class LocalRecorder {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
constructor(private stream: Stream) {
|
constructor(private stream: Stream) {
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
|
this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
|
||||||
this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
|
this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
|
||||||
this.state = LocalRecorderState.READY;
|
this.state = LocalRecorderState.READY;
|
||||||
|
|
@ -170,6 +176,7 @@ export class LocalRecorder {
|
||||||
}
|
}
|
||||||
this.mediaRecorder.pause();
|
this.mediaRecorder.pause();
|
||||||
this.state = LocalRecorderState.PAUSED;
|
this.state = LocalRecorderState.PAUSED;
|
||||||
|
resolve();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
|
|
@ -188,6 +195,7 @@ export class LocalRecorder {
|
||||||
}
|
}
|
||||||
this.mediaRecorder.resume();
|
this.mediaRecorder.resume();
|
||||||
this.state = LocalRecorderState.RECORDING;
|
this.state = LocalRecorderState.RECORDING;
|
||||||
|
resolve();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +217,7 @@ export class LocalRecorder {
|
||||||
this.videoPreview.id = this.id;
|
this.videoPreview.id = this.id;
|
||||||
this.videoPreview.autoplay = true;
|
this.videoPreview.autoplay = true;
|
||||||
|
|
||||||
if (platform.name === 'Safari') {
|
if (platform.isSafariBrowser()) {
|
||||||
this.videoPreview.setAttribute('playsinline', 'true');
|
this.videoPreview.setAttribute('playsinline', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +282,7 @@ export class LocalRecorder {
|
||||||
if (this.state !== LocalRecorderState.FINISHED) {
|
if (this.state !== LocalRecorderState.FINISHED) {
|
||||||
throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
|
throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
|
||||||
} else {
|
} else {
|
||||||
return this.blob;
|
return this.blob!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,7 +352,7 @@ export class LocalRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendable = new FormData();
|
const sendable = new FormData();
|
||||||
sendable.append('file', this.blob, this.id + '.webm');
|
sendable.append('file', this.blob!, this.id + '.webm');
|
||||||
|
|
||||||
http.onreadystatechange = () => {
|
http.onreadystatechange = () => {
|
||||||
if (http.readyState === 4) {
|
if (http.readyState === 4) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import { LocalRecorder } from './LocalRecorder';
|
||||||
import { Publisher } from './Publisher';
|
import { Publisher } from './Publisher';
|
||||||
import { Session } from './Session';
|
import { Session } from './Session';
|
||||||
import { Stream } from './Stream';
|
import { Stream } from './Stream';
|
||||||
|
import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
|
||||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||||
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
|
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
|
||||||
import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
|
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 { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||||
|
|
||||||
import * as screenSharingAuto from '../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto';
|
import * as screenSharingAuto from '../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto';
|
||||||
import * as screenSharing from '../OpenViduInternal/ScreenSharing/Screen-Capturing';
|
import * as screenSharing from '../OpenViduInternal/ScreenSharing/Screen-Capturing';
|
||||||
|
|
@ -38,13 +40,6 @@ import EventEmitter = require('wolfy87-eventemitter');
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
import RpcBuilder = require('../OpenViduInternal/KurentoUtils/kurento-jsonrpc');
|
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
|
* @hidden
|
||||||
|
|
@ -59,6 +54,11 @@ declare var cordova: any;
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
let platform: PlatformUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entrypoint of OpenVidu Browser library.
|
* Entrypoint of OpenVidu Browser library.
|
||||||
* Use it to initialize objects of type [[Session]], [[Publisher]] and [[LocalRecorder]]
|
* Use it to initialize objects of type [[Session]], [[Publisher]] and [[LocalRecorder]]
|
||||||
|
|
@ -121,11 +121,12 @@ export class OpenVidu {
|
||||||
ee = new EventEmitter()
|
ee = new EventEmitter()
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
this.libraryVersion = packageJson.version;
|
this.libraryVersion = packageJson.version;
|
||||||
logger.info("'OpenVidu' initialized");
|
logger.info("'OpenVidu' initialized");
|
||||||
logger.info("openvidu-browser version: " + this.libraryVersion);
|
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
|
// Listen to orientationchange only on mobile devices
|
||||||
(<any>window).addEventListener('orientationchange', () => {
|
(<any>window).addEventListener('orientationchange', () => {
|
||||||
this.publishers.forEach(publisher => {
|
this.publishers.forEach(publisher => {
|
||||||
|
|
@ -138,7 +139,7 @@ export class OpenVidu {
|
||||||
|
|
||||||
const getNewVideoDimensions = (): Promise<{ newWidth: number, newHeight: number }> => {
|
const getNewVideoDimensions = (): Promise<{ newWidth: number, newHeight: number }> => {
|
||||||
return new Promise((resolve, reject) => {
|
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
|
// iOS Ionic. Limitation: must get new dimensions from an existing video element already inserted into DOM
|
||||||
resolve({
|
resolve({
|
||||||
newWidth: publisher.stream.streamManager.videos[0].video.videoWidth,
|
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.
|
// 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
|
// Firefox needs getSettings from the videoTrack
|
||||||
const firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
const firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
||||||
const newWidth = <number>((platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.width : publisher.videoReference.videoWidth);
|
const newWidth = <number>((platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? firefoxSettings.width : publisher.videoReference.videoWidth);
|
||||||
const newHeight = <number>((platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.height : publisher.videoReference.videoHeight);
|
const newHeight = <number>((platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? firefoxSettings.height : publisher.videoReference.videoHeight);
|
||||||
resolve({ newWidth, newHeight });
|
resolve({ newWidth, newHeight });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -186,6 +187,7 @@ export class OpenVidu {
|
||||||
} else {
|
} else {
|
||||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
|
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')]);
|
publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
|
||||||
|
this.session.sendVideoData(publisher);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
clearTimeout(repeatUntilChange);
|
clearTimeout(repeatUntilChange);
|
||||||
|
|
@ -337,26 +339,20 @@ export class OpenVidu {
|
||||||
* @returns 1 if the browser supports OpenVidu, 0 otherwise
|
* @returns 1 if the browser supports OpenVidu, 0 otherwise
|
||||||
*/
|
*/
|
||||||
checkSystemRequirements(): number {
|
checkSystemRequirements(): number {
|
||||||
const browser = platform.name;
|
|
||||||
const family = platform.os!!.family;
|
|
||||||
const userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
|
||||||
|
|
||||||
if(this.isIPhoneOrIPad(userAgent)) {
|
if (platform.isIPhoneOrIPad()) {
|
||||||
if(this.isIOSWithSafari(userAgent) || platform['isIonicIos']){
|
if (platform.isIOSWithSafari() || platform.isIonicIos()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept: Chrome (desktop and Android), Firefox (desktop and Android), Opera (desktop and Android),
|
// 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)
|
// Safari (OSX and iOS), Edge Chromium (>= 80), Ionic (Android and iOS), Samsung Internet Browser (Android)
|
||||||
if (
|
if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() ||
|
||||||
(browser === 'Safari') ||
|
platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isOperaBrowser() ||
|
||||||
(browser === 'Chrome') || (browser === 'Chrome Mobile') ||
|
platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isEdgeMobileBrowser() ||
|
||||||
(browser === 'Firefox') || (browser === 'Firefox Mobile') ||
|
platform.isSafariBrowser() || platform.isAndroidBrowser() || platform.isElectron() || platform.isSamsungBrowser()
|
||||||
(browser === 'Opera') || (browser === 'Opera Mobile') ||
|
|
||||||
(browser === 'Android Browser') || (browser === 'Electron') ||
|
|
||||||
(browser === 'Samsung Internet Mobile') || (browser === 'Samsung Internet')
|
|
||||||
) {
|
) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -370,22 +366,8 @@ export class OpenVidu {
|
||||||
* Checks if the browser supports screen-sharing. Desktop Chrome, Firefox and Opera support screen-sharing
|
* 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
|
* @returns 1 if the browser supports screen-sharing, 0 otherwise
|
||||||
*/
|
*/
|
||||||
checkScreenSharingCapabilities(): number {
|
checkScreenSharingCapabilities(): boolean {
|
||||||
const browser = platform.name;
|
return platform.canScreenShare();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -398,7 +380,7 @@ export class OpenVidu {
|
||||||
const devices: Device[] = [];
|
const devices: Device[] = [];
|
||||||
|
|
||||||
// Ionic Android devices
|
// 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[]) => {
|
cordova.plugins.EnumerateDevicesPlugin.getEnumerateDevices().then((pluginDevices: Device[]) => {
|
||||||
let pluginAudioDevices: Device[] = [];
|
let pluginAudioDevices: Device[] = [];
|
||||||
let videoDevices: Device[] = [];
|
let videoDevices: Device[] = [];
|
||||||
|
|
@ -590,10 +572,10 @@ export class OpenVidu {
|
||||||
// Video is deviceId or screen sharing
|
// Video is deviceId or screen sharing
|
||||||
if (options.videoSource === 'screen' ||
|
if (options.videoSource === 'screen' ||
|
||||||
options.videoSource === 'window' ||
|
options.videoSource === 'window' ||
|
||||||
(platform.name === 'Electron' && options.videoSource.startsWith('screen:'))) {
|
(platform.isElectron() && options.videoSource.startsWith('screen:'))) {
|
||||||
// Video is screen sharing
|
// Video is screen sharing
|
||||||
mustAskForAudioTrackLater = !myConstraints.audioTrack && (options.audioSource !== null && options.audioSource !== false);
|
mustAskForAudioTrackLater = !myConstraints.audioTrack && (options.audioSource !== null && options.audioSource !== false);
|
||||||
if (navigator.mediaDevices['getDisplayMedia'] && platform.name !== 'Electron') {
|
if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
|
||||||
// getDisplayMedia supported
|
// getDisplayMedia supported
|
||||||
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
||||||
.then(mediaStream => {
|
.then(mediaStream => {
|
||||||
|
|
@ -663,6 +645,7 @@ export class OpenVidu {
|
||||||
* - `iceServers`: set custom STUN/TURN servers to be used by OpenVidu Browser
|
* - `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)
|
* - `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
|
* - `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.
|
* Call this method to override previous values at any moment.
|
||||||
*/
|
*/
|
||||||
|
|
@ -763,9 +746,8 @@ export class OpenVidu {
|
||||||
startWs(onConnectSucces: (error: Error) => void): void {
|
startWs(onConnectSucces: (error: Error) => void): void {
|
||||||
const config = {
|
const config = {
|
||||||
heartbeat: 5000,
|
heartbeat: 5000,
|
||||||
sendCloseMessage: false,
|
|
||||||
ws: {
|
ws: {
|
||||||
uri: this.wsUri,
|
uri: this.wsUri + '?sessionId=' + this.session.sessionId,
|
||||||
onconnected: onConnectSucces,
|
onconnected: onConnectSucces,
|
||||||
ondisconnect: this.disconnectCallback.bind(this),
|
ondisconnect: this.disconnectCallback.bind(this),
|
||||||
onreconnecting: this.reconnectingCallback.bind(this),
|
onreconnecting: this.reconnectingCallback.bind(this),
|
||||||
|
|
@ -782,6 +764,8 @@ export class OpenVidu {
|
||||||
recordingStopped: this.session.onRecordingStopped.bind(this.session),
|
recordingStopped: this.session.onRecordingStopped.bind(this.session),
|
||||||
sendMessage: this.session.onNewMessage.bind(this.session),
|
sendMessage: this.session.onNewMessage.bind(this.session),
|
||||||
streamPropertyChanged: this.session.onStreamPropertyChanged.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),
|
filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session),
|
||||||
iceCandidate: this.session.recvIceCandidate.bind(this.session),
|
iceCandidate: this.session.recvIceCandidate.bind(this.session),
|
||||||
mediaError: this.session.onMediaError.bind(this.session)
|
mediaError: this.session.onMediaError.bind(this.session)
|
||||||
|
|
@ -899,12 +883,12 @@ export class OpenVidu {
|
||||||
// Screen sharing
|
// Screen sharing
|
||||||
|
|
||||||
if (!this.checkScreenSharingCapabilities()) {
|
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);
|
logger.error(error);
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (platform.name === 'Electron') {
|
if (platform.isElectron()) {
|
||||||
const prefix = "screen:";
|
const prefix = "screen:";
|
||||||
const videoSourceString: string = videoSource;
|
const videoSourceString: string = videoSource;
|
||||||
const electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length);
|
const electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length);
|
||||||
|
|
@ -918,7 +902,7 @@ export class OpenVidu {
|
||||||
|
|
||||||
} else {
|
} 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()
|
// Custom screen sharing extension for Chrome (and Opera) and no support for MediaDevices.getDisplayMedia()
|
||||||
|
|
||||||
|
|
@ -957,7 +941,7 @@ export class OpenVidu {
|
||||||
resolve(myConstraints);
|
resolve(myConstraints);
|
||||||
} else {
|
} else {
|
||||||
// Default screen sharing extension for Chrome/Opera, or is Firefox < 66
|
// 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) => {
|
screenSharingAuto.getScreenId(firefoxString, (error, sourceId, screenConstraints) => {
|
||||||
if (!!error) {
|
if (!!error) {
|
||||||
|
|
@ -1029,17 +1013,25 @@ export class OpenVidu {
|
||||||
private reconnectedCallback(): void {
|
private reconnectedCallback(): void {
|
||||||
logger.warn('Websocket reconnected');
|
logger.warn('Websocket reconnected');
|
||||||
if (this.isRoomAvailable()) {
|
if (this.isRoomAvailable()) {
|
||||||
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
|
if (!!this.session.connection) {
|
||||||
if (!!error) {
|
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
|
||||||
logger.error(error);
|
if (!!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');
|
logger.error(error);
|
||||||
this.session.onLostConnection("networkDisconnect");
|
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.jsonRpcClient.close(4101, "Reconnection fault");
|
this.session.onLostConnection("networkDisconnect");
|
||||||
} else {
|
this.jsonRpcClient.close(4101, "Reconnection fault");
|
||||||
this.jsonRpcClient.resetPing();
|
} else {
|
||||||
this.session.onRecoveredConnection();
|
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 {
|
} else {
|
||||||
alert('Connection error. Please reload page.');
|
alert('Connection error. Please reload page.');
|
||||||
}
|
}
|
||||||
|
|
@ -1057,21 +1049,7 @@ export class OpenVidu {
|
||||||
private isScreenShare(videoSource: string) {
|
private isScreenShare(videoSource: string) {
|
||||||
return videoSource === 'screen' ||
|
return videoSource === 'screen' ||
|
||||||
videoSource === 'window' ||
|
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 { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
||||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||||
|
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
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
|
* 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
|
// TODO: CLEAN 2.15.0 LEGACY CODE
|
||||||
// THIS LINE:
|
// 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:
|
// 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.properties = properties;
|
||||||
this.openvidu = openvidu;
|
this.openvidu = openvidu;
|
||||||
|
|
||||||
|
|
@ -130,7 +156,7 @@ export class Publisher extends StreamManager {
|
||||||
*/
|
*/
|
||||||
publishAudio(value: boolean): void {
|
publishAudio(value: boolean): void {
|
||||||
if (this.stream.audioActive !== value) {
|
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) => {
|
affectedMediaStream.getAudioTracks().forEach((track) => {
|
||||||
track.enabled = value;
|
track.enabled = value;
|
||||||
});
|
});
|
||||||
|
|
@ -149,6 +175,7 @@ export class Publisher extends StreamManager {
|
||||||
} else {
|
} else {
|
||||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'audioActive', value, !value, 'publishAudio')]);
|
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.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 {
|
publishVideo(value: boolean): void {
|
||||||
if (this.stream.videoActive !== value) {
|
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) => {
|
affectedMediaStream.getVideoTracks().forEach((track) => {
|
||||||
track.enabled = value;
|
track.enabled = value;
|
||||||
});
|
});
|
||||||
|
|
@ -196,6 +223,7 @@ export class Publisher extends StreamManager {
|
||||||
} else {
|
} else {
|
||||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoActive', value, !value, 'publishVideo')]);
|
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.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> {
|
replaceTrack(track: MediaStreamTrack): Promise<any> {
|
||||||
|
|
||||||
const replaceMediaStreamTrack = () => {
|
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;
|
let removedTrack: MediaStreamTrack;
|
||||||
if (track.kind === 'video') {
|
if (track.kind === 'video') {
|
||||||
removedTrack = mediaStream.getVideoTracks()[0];
|
removedTrack = mediaStream.getVideoTracks()[0];
|
||||||
|
|
@ -315,6 +343,7 @@ export class Publisher extends StreamManager {
|
||||||
mediaStream.removeTrack(removedTrack);
|
mediaStream.removeTrack(removedTrack);
|
||||||
removedTrack.stop();
|
removedTrack.stop();
|
||||||
mediaStream.addTrack(track);
|
mediaStream.addTrack(track);
|
||||||
|
this.session.sendVideoData(this.stream.streamManager, 5, true, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
@ -404,7 +433,7 @@ export class Publisher extends StreamManager {
|
||||||
if (this.stream.isSendVideo()) {
|
if (this.stream.isSendVideo()) {
|
||||||
if (!this.stream.isSendScreen()) {
|
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
|
// 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
|
// 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)
|
// Orientation must be checked for mobile devices (width and height are reversed)
|
||||||
const { width, height } = this.getVideoDimensions(mediaStream);
|
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
|
// Mobile portrait mode
|
||||||
this.stream.videoDimensions = {
|
this.stream.videoDimensions = {
|
||||||
width: height || 0,
|
width: height || 0,
|
||||||
|
|
@ -464,8 +493,8 @@ export class Publisher extends StreamManager {
|
||||||
};
|
};
|
||||||
this.screenShareResizeInterval = setInterval(() => {
|
this.screenShareResizeInterval = setInterval(() => {
|
||||||
const firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
|
const firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
|
||||||
const newWidth = (platform.name === 'Chrome' || platform.name === 'Opera') ? this.videoReference.videoWidth : firefoxSettings.width;
|
const newWidth = (platform.isChromeBrowser() || platform.isOperaBrowser()) ? this.videoReference.videoWidth : firefoxSettings.width;
|
||||||
const newHeight = (platform.name === 'Chrome' || platform.name === 'Opera') ? this.videoReference.videoHeight : firefoxSettings.height;
|
const newHeight = (platform.isChromeBrowser() || platform.isOperaBrowser()) ? this.videoReference.videoHeight : firefoxSettings.height;
|
||||||
if (this.stream.isLocalStreamPublished &&
|
if (this.stream.isLocalStreamPublished &&
|
||||||
(newWidth !== this.stream.videoDimensions.width ||
|
(newWidth !== this.stream.videoDimensions.width ||
|
||||||
newHeight !== this.stream.videoDimensions.height)) {
|
newHeight !== this.stream.videoDimensions.height)) {
|
||||||
|
|
@ -488,6 +517,7 @@ export class Publisher extends StreamManager {
|
||||||
} else {
|
} else {
|
||||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoDimensions', this.stream.videoDimensions, oldValue, 'screenResized')]);
|
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.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();
|
startTime = Date.now();
|
||||||
this.setPermissionDialogTimer(timeForDialogEvent);
|
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 })
|
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
||||||
.then(mediaStream => {
|
.then(mediaStream => {
|
||||||
this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
||||||
|
|
@ -683,7 +713,7 @@ export class Publisher extends StreamManager {
|
||||||
initializeVideoReference(mediaStream: MediaStream) {
|
initializeVideoReference(mediaStream: MediaStream) {
|
||||||
this.videoReference = document.createElement('video');
|
this.videoReference = document.createElement('video');
|
||||||
|
|
||||||
if (platform.name === 'Safari') {
|
if (platform.isSafariBrowser()) {
|
||||||
this.videoReference.setAttribute('playsinline', 'true');
|
this.videoReference.setAttribute('playsinline', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ import { Capabilities } from '../OpenViduInternal/Interfaces/Public/Capabilities
|
||||||
import { EventDispatcher } from './EventDispatcher';
|
import { EventDispatcher } from './EventDispatcher';
|
||||||
import { SignalOptions } from '../OpenViduInternal/Interfaces/Public/SignalOptions';
|
import { SignalOptions } from '../OpenViduInternal/Interfaces/Public/SignalOptions';
|
||||||
import { SubscriberProperties } from '../OpenViduInternal/Interfaces/Public/SubscriberProperties';
|
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 { ObjMap } from '../OpenViduInternal/Interfaces/Private/ObjMap';
|
||||||
import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions';
|
import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions';
|
||||||
import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent';
|
import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent';
|
||||||
|
|
@ -37,17 +38,23 @@ import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisc
|
||||||
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
|
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
|
||||||
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
||||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
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 { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||||
|
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
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.
|
* 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.
|
* 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]])
|
* - connectionCreated ([[ConnectionEvent]])
|
||||||
* - connectionDestroyed ([[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]])
|
* - sessionDisconnected ([[SessionDisconnectedEvent]])
|
||||||
* - streamCreated ([[StreamEvent]])
|
* - streamCreated ([[StreamEvent]])
|
||||||
* - streamDestroyed ([[StreamEvent]])
|
* - streamDestroyed ([[StreamEvent]])
|
||||||
|
|
@ -66,9 +74,9 @@ const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||||
* - signal ([[SignalEvent]])
|
* - signal ([[SignalEvent]])
|
||||||
* - recordingStarted ([[RecordingEvent]])
|
* - recordingStarted ([[RecordingEvent]])
|
||||||
* - recordingStopped ([[RecordingEvent]])
|
* - recordingStopped ([[RecordingEvent]])
|
||||||
|
* - networkQualityLevelChanged ([[NetworkQualityLevelChangedEvent]])
|
||||||
* - reconnecting
|
* - reconnecting
|
||||||
* - reconnected
|
* - reconnected
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
export class Session extends EventDispatcher {
|
export class Session extends EventDispatcher {
|
||||||
|
|
||||||
|
|
@ -88,7 +96,7 @@ export class Session extends EventDispatcher {
|
||||||
streamManagers: StreamManager[] = [];
|
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
|
* This object is only defined after [[Session.connect]] has been successfully resolved
|
||||||
*/
|
*/
|
||||||
capabilities: Capabilities;
|
capabilities: Capabilities;
|
||||||
|
|
@ -127,15 +135,23 @@ export class Session extends EventDispatcher {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
stopSpeakingEventsEnabledOnce = false;
|
stopSpeakingEventsEnabledOnce = false;
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
private videoDataInterval: NodeJS.Timeout;
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
private videoDataTimeout: NodeJS.Timeout;
|
||||||
|
|
||||||
|
|
||||||
// TODO: CLEAN 2.15.0 LEGACY CODE
|
// TODO: CLEAN 2.15.0 LEGACY CODE
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
isFirstIonicIosSubscriber = true;
|
isFirstIonicIosSubscriber = true;
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
countDownForIonicIosSubscribersActive = true;
|
countDownForIonicIosSubscribersActive = true;
|
||||||
// END LEGACY CODE
|
// END LEGACY CODE
|
||||||
|
|
@ -146,6 +162,7 @@ export class Session extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
constructor(openvidu: OpenVidu) {
|
constructor(openvidu: OpenVidu) {
|
||||||
super();
|
super();
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
this.openvidu = openvidu;
|
this.openvidu = openvidu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +214,7 @@ export class Session extends EventDispatcher {
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
} else {
|
} 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);
|
this.connection.addStream(publisher.stream);
|
||||||
publisher.stream.publish()
|
publisher.stream.publish()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
this.sendVideoData(publisher, 8, true, 5);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
@ -395,6 +413,7 @@ export class Session extends EventDispatcher {
|
||||||
publisher.reestablishStreamPlayingEvent();
|
publisher.reestablishStreamPlayingEvent();
|
||||||
publisher.stream.publish()
|
publisher.stream.publish()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
this.sendVideoData(publisher, 8, true, 5);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
@ -596,7 +615,7 @@ export class Session extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* See [[EventDispatcher.on]]
|
* 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);
|
super.onAux(type, "Event '" + type + "' triggered by 'Session'", handler);
|
||||||
|
|
||||||
|
|
@ -628,7 +647,7 @@ export class Session extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* See [[EventDispatcher.once]]
|
* 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);
|
super.onceAux(type, "Event '" + type + "' triggered once by 'Session'", handler);
|
||||||
|
|
||||||
|
|
@ -660,7 +679,7 @@ export class Session extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* See [[EventDispatcher.off]]
|
* 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);
|
super.off(type, handler);
|
||||||
|
|
||||||
|
|
@ -699,7 +718,7 @@ export class Session extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
onParticipantJoined(response: ConnectionOptions): void {
|
onParticipantJoined(response: RemoteConnectionOptions): void {
|
||||||
// Connection shouldn't exist
|
// Connection shouldn't exist
|
||||||
this.getConnection(response.id, '')
|
this.getConnection(response.id, '')
|
||||||
|
|
||||||
|
|
@ -751,9 +770,10 @@ export class Session extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
onParticipantPublished(response: ConnectionOptions): void {
|
onParticipantPublished(response: RemoteConnectionOptions): void {
|
||||||
|
|
||||||
const afterConnectionFound = (connection) => {
|
const afterConnectionFound = (connection) => {
|
||||||
|
|
||||||
this.remoteConnections[connection.connectionId] = connection;
|
this.remoteConnections[connection.connectionId] = connection;
|
||||||
|
|
||||||
if (!this.remoteStreamsCreated[connection.stream.streamId]) {
|
if (!this.remoteStreamsCreated[connection.stream.streamId]) {
|
||||||
|
|
@ -777,7 +797,7 @@ export class Session extends EventDispatcher {
|
||||||
// Update existing Connection
|
// Update existing Connection
|
||||||
connection = con;
|
connection = con;
|
||||||
response.metadata = con.data;
|
response.metadata = con.data;
|
||||||
connection.options = response;
|
connection.remoteOptions = response;
|
||||||
connection.initRemoteStreams(response.streams);
|
connection.initRemoteStreams(response.streams);
|
||||||
afterConnectionFound(connection);
|
afterConnectionFound(connection);
|
||||||
})
|
})
|
||||||
|
|
@ -801,12 +821,12 @@ export class Session extends EventDispatcher {
|
||||||
|
|
||||||
.then(connection => {
|
.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]);
|
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||||
streamEvent.callDefaultBehavior();
|
streamEvent.callDefaultBehavior();
|
||||||
|
|
||||||
// Deleting the remote stream
|
// Deleting the remote stream
|
||||||
const streamId: string = connection.stream.streamId;
|
const streamId: string = connection.stream!.streamId;
|
||||||
delete this.remoteStreamsCreated[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
|
* @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)
|
this.getConnection(msg.senderConnectionId, 'Connection not found for connectionId ' + msg.senderConnectionId + ' owning endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate)
|
||||||
.then(connection => {
|
.then(connection => {
|
||||||
const stream = connection.stream;
|
const stream: Stream = connection.stream!;
|
||||||
stream.getWebRtcPeer().addIceCandidate(candidate).catch(error => {
|
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);
|
+ ' stream of endpoint ' + msg.endpointName + ': ' + error);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
@ -989,7 +1047,7 @@ export class Session extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
onLostConnection(reason: string): void {
|
onLostConnection(reason: string): void {
|
||||||
logger.warn('Lost connection in Session ' + this.sessionId);
|
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);
|
this.leave(true, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1042,8 +1100,8 @@ export class Session extends EventDispatcher {
|
||||||
this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId)
|
this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId)
|
||||||
.then(connection => {
|
.then(connection => {
|
||||||
logger.info('Filter event dispatched');
|
logger.info('Filter event dispatched');
|
||||||
const stream: Stream = connection.stream;
|
const stream: Stream = connection.stream!;
|
||||||
stream.filter.handlers[response.eventType](new FilterEvent(stream.filter, response.eventType, response.data));
|
stream.filter!.handlers[response.eventType](new FilterEvent(stream.filter!, response.eventType, response.data));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1086,6 +1144,7 @@ export class Session extends EventDispatcher {
|
||||||
|
|
||||||
forced = !!forced;
|
forced = !!forced;
|
||||||
logger.info('Leaving Session (forced=' + forced + ')');
|
logger.info('Leaving Session (forced=' + forced + ')');
|
||||||
|
this.stopVideoDataIntervals();
|
||||||
|
|
||||||
if (!!this.connection) {
|
if (!!this.connection) {
|
||||||
if (!this.connection.disposed && !forced) {
|
if (!this.connection.disposed && !forced) {
|
||||||
|
|
@ -1119,7 +1178,7 @@ export class Session extends EventDispatcher {
|
||||||
const joinParams = {
|
const joinParams = {
|
||||||
token: (!!token) ? token : '',
|
token: (!!token) ? token : '',
|
||||||
session: this.sessionId,
|
session: this.sessionId,
|
||||||
platform: !!platform.description ? platform.description : 'unknown',
|
platform: !!platform.getDescription() ? platform.getDescription() : 'unknown',
|
||||||
metadata: !!this.options.metadata ? this.options.metadata : '',
|
metadata: !!this.options.metadata ? this.options.metadata : '',
|
||||||
secret: this.openvidu.getSecret(),
|
secret: this.openvidu.getSecret(),
|
||||||
recorder: this.openvidu.getRecorder()
|
recorder: this.openvidu.getRecorder()
|
||||||
|
|
@ -1127,6 +1186,63 @@ export class Session extends EventDispatcher {
|
||||||
return joinParams;
|
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 */
|
/* Private methods */
|
||||||
|
|
||||||
|
|
@ -1139,35 +1255,33 @@ export class Session extends EventDispatcher {
|
||||||
|
|
||||||
const joinParams = this.initializeParams(token);
|
const joinParams = this.initializeParams(token);
|
||||||
|
|
||||||
this.openvidu.sendRequest('joinRoom', joinParams, (error, response) => {
|
this.openvidu.sendRequest('joinRoom', joinParams, (error, response: LocalConnectionOptions) => {
|
||||||
if (!!error) {
|
if (!!error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Initialize capabilities object with the role
|
this.processJoinRoomResponse(response);
|
||||||
this.capabilities = {
|
|
||||||
subscribe: true,
|
|
||||||
publish: this.openvidu.role !== 'SUBSCRIBER',
|
|
||||||
forceUnpublish: this.openvidu.role === 'MODERATOR',
|
|
||||||
forceDisconnect: this.openvidu.role === 'MODERATOR'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize local Connection object with values returned by openvidu-server
|
// 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.openvidu.openviduServerVersion = response.openviduServerVersion;
|
||||||
this.connection.connectionId = response.id;
|
=======
|
||||||
this.connection.creationTime = response.createdAt;
|
this.connection = new Connection(this, response);
|
||||||
this.connection.data = response.metadata;
|
>>>>>>> master
|
||||||
this.connection.rpcSessionId = response.sessionId;
|
|
||||||
|
|
||||||
// Initialize remote Connections with value returned by openvidu-server
|
// Initialize remote Connections with value returned by openvidu-server
|
||||||
const events = {
|
const events = {
|
||||||
connections: new Array<Connection>(),
|
connections: new Array<Connection>(),
|
||||||
streams: new Array<Stream>()
|
streams: new Array<Stream>()
|
||||||
};
|
};
|
||||||
const existingParticipants: ConnectionOptions[] = response.value;
|
const existingParticipants: RemoteConnectionOptions[] = response.value;
|
||||||
existingParticipants.forEach(participant => {
|
existingParticipants.forEach((remoteConnectionOptions: RemoteConnectionOptions) => {
|
||||||
const connection = new Connection(this, participant);
|
const connection = new Connection(this, remoteConnectionOptions);
|
||||||
this.remoteConnections[connection.connectionId] = connection;
|
this.remoteConnections[connection.connectionId] = connection;
|
||||||
events.connections.push(connection);
|
events.connections.push(connection);
|
||||||
if (!!connection.stream) {
|
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 {
|
private stringClientMetadata(metadata: any): string {
|
||||||
if (typeof metadata !== 'string') {
|
if (typeof metadata !== 'string') {
|
||||||
return JSON.stringify(metadata);
|
return JSON.stringify(metadata);
|
||||||
|
|
@ -1272,12 +1391,7 @@ export class Session extends EventDispatcher {
|
||||||
this.sessionId = <string>queryParams['sessionId'];
|
this.sessionId = <string>queryParams['sessionId'];
|
||||||
const secret = queryParams['secret'];
|
const secret = queryParams['secret'];
|
||||||
const recorder = queryParams['recorder'];
|
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 webrtcStatsInterval = queryParams['webrtcStatsInterval'];
|
||||||
const openviduServerVersion = queryParams['version'];
|
|
||||||
|
|
||||||
if (!!secret) {
|
if (!!secret) {
|
||||||
this.openvidu.secret = secret;
|
this.openvidu.secret = secret;
|
||||||
|
|
@ -1285,31 +1399,9 @@ export class Session extends EventDispatcher {
|
||||||
if (!!recorder) {
|
if (!!recorder) {
|
||||||
this.openvidu.recorder = true;
|
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) {
|
if (!!webrtcStatsInterval) {
|
||||||
this.openvidu.webrtcStatsInterval = +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.wsUri = 'wss://' + url.host + '/openvidu';
|
||||||
this.openvidu.httpUri = 'https://' + url.host;
|
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 { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
|
||||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||||
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
import hark = require('hark');
|
import hark = require('hark');
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
let platform: PlatformUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents each one of the media streams available in OpenVidu Server for certain session.
|
* 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.
|
* - `"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]]).
|
* - `"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/)).
|
* - `"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
|
* If [[hasVideo]] is false, this property is undefined
|
||||||
*/
|
*/
|
||||||
typeOfVideo?: string;
|
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
|
* [[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.
|
* 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 webRtcPeer: WebRtcPeer;
|
||||||
protected mediaStream: MediaStream;
|
protected mediaStream?: MediaStream;
|
||||||
private webRtcStats: WebRtcStats;
|
private webRtcStats: WebRtcStats;
|
||||||
|
|
||||||
private isSubscribeToRemote = false;
|
private isSubscribeToRemote = false;
|
||||||
|
|
@ -203,7 +206,7 @@ export class Stream extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
localMediaStreamWhenSubscribedToRemote: MediaStream;
|
localMediaStreamWhenSubscribedToRemote?: MediaStream;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -212,7 +215,7 @@ export class Stream extends EventDispatcher {
|
||||||
constructor(session: Session, options: InboundStreamOptions | OutboundStreamOptions | {}) {
|
constructor(session: Session, options: InboundStreamOptions | OutboundStreamOptions | {}) {
|
||||||
|
|
||||||
super();
|
super();
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
|
||||||
if (options.hasOwnProperty('id')) {
|
if (options.hasOwnProperty('id')) {
|
||||||
|
|
@ -262,7 +265,7 @@ export class Stream extends EventDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ee.on('mediastream-updated', () => {
|
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 + ']');
|
logger.debug('Video srcObject [' + this.mediaStream + '] updated in stream [' + this.streamId + ']');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +326,7 @@ export class Stream extends EventDispatcher {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info('Filter successfully applied on Stream ' + this.streamId);
|
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 = new Filter(type, options);
|
||||||
this.filter.stream = this;
|
this.filter.stream = this;
|
||||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter, oldValue, 'applyFilter')]);
|
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter, oldValue, 'applyFilter')]);
|
||||||
|
|
@ -356,10 +359,10 @@ export class Stream extends EventDispatcher {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info('Filter successfully removed from Stream ' + this.streamId);
|
logger.info('Filter successfully removed from Stream ' + this.streamId);
|
||||||
const oldValue = this.filter;
|
const oldValue = this.filter!;
|
||||||
delete this.filter;
|
delete this.filter;
|
||||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, 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')]);
|
this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.streamManager, this, 'filter', this.filter!, oldValue, 'applyFilter')]);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +385,7 @@ export class Stream extends EventDispatcher {
|
||||||
* @returns Native MediaStream Web API object
|
* @returns Native MediaStream Web API object
|
||||||
*/
|
*/
|
||||||
getMediaStream(): MediaStream {
|
getMediaStream(): MediaStream {
|
||||||
return this.mediaStream;
|
return this.mediaStream!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hidden methods */
|
/* Hidden methods */
|
||||||
|
|
@ -537,7 +540,7 @@ export class Stream extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
isSendScreen(): boolean {
|
isSendScreen(): boolean {
|
||||||
let screen = this.outboundStreamOpts.publisherProperties.videoSource === 'screen';
|
let screen = this.outboundStreamOpts.publisherProperties.videoSource === 'screen';
|
||||||
if (platform.name === 'Electron') {
|
if (platform.isElectron()) {
|
||||||
screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' &&
|
screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' &&
|
||||||
this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:');
|
this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:');
|
||||||
}
|
}
|
||||||
|
|
@ -776,7 +779,7 @@ export class Stream extends EventDispatcher {
|
||||||
if (!this.getWebRtcPeer() || !this.getRTCPeerConnection()) {
|
if (!this.getWebRtcPeer() || !this.getRTCPeerConnection()) {
|
||||||
return false;
|
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');
|
logger.warn('OpenVidu Browser advanced configuration option "forceMediaReconnectionAfterNetworkDrop" is enabled. Publisher stream ' + this.streamId + 'will force a reconnection');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1022,8 +1025,8 @@ export class Stream extends EventDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initHarkEvents(): void {
|
private initHarkEvents(): void {
|
||||||
if (!!this.mediaStream.getAudioTracks()[0]) {
|
if (!!this.mediaStream!.getAudioTracks()[0]) {
|
||||||
// Hark events can only be set if audio track is available
|
// Hark events can only be set if audio track is available
|
||||||
if (this.streamManager.remote) {
|
if (this.streamManager.remote) {
|
||||||
// publisherStartSpeaking/publisherStopSpeaking is only defined for remote streams
|
// 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);
|
(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 { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
|
||||||
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||||
|
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
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.
|
* 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
|
* 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
|
* @hidden
|
||||||
*/
|
*/
|
||||||
firstVideoElement: StreamManagerVideo;
|
firstVideoElement?: StreamManagerVideo;
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
|
@ -101,7 +106,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
constructor(stream: Stream, targetElement?: HTMLElement | string) {
|
constructor(stream: Stream, targetElement?: HTMLElement | string) {
|
||||||
super();
|
super();
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.stream.streamManager = this;
|
this.stream.streamManager = this;
|
||||||
this.remote = !this.stream.isLocal();
|
this.remote = !this.stream.isLocal();
|
||||||
|
|
@ -121,7 +126,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
id: '',
|
id: '',
|
||||||
canplayListenerAdded: false
|
canplayListenerAdded: false
|
||||||
};
|
};
|
||||||
if (platform.name === 'Safari') {
|
if (platform.isSafariBrowser()) {
|
||||||
this.firstVideoElement.video.setAttribute('playsinline', 'true');
|
this.firstVideoElement.video.setAttribute('playsinline', 'true');
|
||||||
}
|
}
|
||||||
this.targetElement = targEl;
|
this.targetElement = targEl;
|
||||||
|
|
@ -379,7 +384,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
video.autoplay = true;
|
video.autoplay = true;
|
||||||
video.controls = false;
|
video.controls = false;
|
||||||
|
|
||||||
if (platform.name === 'Safari') {
|
if (platform.isSafariBrowser()) {
|
||||||
video.setAttribute('playsinline', 'true');
|
video.setAttribute('playsinline', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,7 +468,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
updateMediaStream(mediaStream: MediaStream) {
|
updateMediaStream(mediaStream: MediaStream) {
|
||||||
this.videos.forEach(streamManagerVideo => {
|
this.videos.forEach(streamManagerVideo => {
|
||||||
streamManagerVideo.video.srcObject = mediaStream;
|
streamManagerVideo.video.srcObject = mediaStream;
|
||||||
if (platform['isIonicIos']) {
|
if (platform.isIonicIos()) {
|
||||||
// iOS Ionic. LIMITATION: must reinsert the video in the DOM for
|
// iOS Ionic. LIMITATION: must reinsert the video in the DOM for
|
||||||
// the media stream to be updated
|
// the media stream to be updated
|
||||||
const vParent = streamManagerVideo.video.parentElement;
|
const vParent = streamManagerVideo.video.parentElement;
|
||||||
|
|
@ -506,7 +511,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
private mirrorVideo(video): void {
|
private mirrorVideo(video): void {
|
||||||
if (!platform['isIonicIos']) {
|
if (!platform.isIonicIos()) {
|
||||||
video.style.transform = 'rotateY(180deg)';
|
video.style.transform = 'rotateY(180deg)';
|
||||||
video.style.webkitTransform = '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 { Event } from './Event';
|
||||||
import { Stream } from '../../OpenVidu/Stream';
|
|
||||||
import { Filter } from '../../OpenVidu/Filter';
|
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
|
// Dispose and delete all remote Connections
|
||||||
for (const connectionId in session.remoteConnections) {
|
for (const connectionId in session.remoteConnections) {
|
||||||
if (!!session.remoteConnections[connectionId].stream) {
|
if (!!session.remoteConnections[connectionId].stream) {
|
||||||
session.remoteConnections[connectionId].stream.disposeWebRtcPeer();
|
session.remoteConnections[connectionId].stream!.disposeWebRtcPeer();
|
||||||
session.remoteConnections[connectionId].stream.disposeMediaStream();
|
session.remoteConnections[connectionId].stream!.disposeMediaStream();
|
||||||
if (session.remoteConnections[connectionId].stream.streamManager) {
|
if (session.remoteConnections[connectionId].stream!.streamManager) {
|
||||||
session.remoteConnections[connectionId].stream.streamManager.removeAllVideos();
|
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();
|
session.remoteConnections[connectionId].dispose();
|
||||||
}
|
}
|
||||||
delete session.remoteConnections[connectionId];
|
delete session.remoteConnections[connectionId];
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,8 @@ export class StreamEvent extends Event {
|
||||||
|
|
||||||
// Delete StreamOptionsServer from remote Connection
|
// Delete StreamOptionsServer from remote Connection
|
||||||
const remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
|
const remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId];
|
||||||
if (!!remoteConnection && !!remoteConnection.options) {
|
if (!!remoteConnection && !!remoteConnection.remoteOptions) {
|
||||||
const streamOptionsServer = remoteConnection.options.streams;
|
const streamOptionsServer = remoteConnection.remoteOptions.streams;
|
||||||
for (let i = streamOptionsServer.length - 1; i >= 0; --i) {
|
for (let i = streamOptionsServer.length - 1; i >= 0; --i) {
|
||||||
if (streamOptionsServer[i].id === this.stream.streamId) {
|
if (streamOptionsServer[i].id === this.stream.streamId) {
|
||||||
streamOptionsServer.splice(i, 1);
|
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';
|
import { StreamOptionsServer } from './StreamOptionsServer';
|
||||||
|
|
||||||
export interface ConnectionOptions {
|
export interface RemoteConnectionOptions {
|
||||||
id: string;
|
id: string;
|
||||||
createdAt: number;
|
createdAt: number;
|
||||||
metadata: string;
|
metadata: string;
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
var RpcBuilder = require('../');
|
var RpcBuilder = require('../');
|
||||||
var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
|
var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
|
||||||
|
var OpenViduLogger = require('../../../Logger/OpenViduLogger').OpenViduLogger;
|
||||||
|
|
||||||
Date.now = Date.now || function () {
|
Date.now = Date.now || function () {
|
||||||
return +new Date;
|
return +new Date;
|
||||||
|
|
@ -28,12 +29,11 @@ var RECONNECTING = 'RECONNECTING';
|
||||||
var CONNECTED = 'CONNECTED';
|
var CONNECTED = 'CONNECTED';
|
||||||
var DISCONNECTED = 'DISCONNECTED';
|
var DISCONNECTED = 'DISCONNECTED';
|
||||||
|
|
||||||
var Logger = console;
|
var Logger = OpenViduLogger.getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* heartbeat: interval in ms for each heartbeat message,
|
* heartbeat: interval in ms for each heartbeat message,
|
||||||
* sendCloseMessage : true / false, before closing the connection, it sends a closeSession message
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* ws : {
|
* ws : {
|
||||||
* uri : URI to conntect to,
|
* uri : URI to conntect to,
|
||||||
|
|
@ -250,25 +250,13 @@ function JsonRpcClient(configuration) {
|
||||||
|
|
||||||
this.close = function (code, reason) {
|
this.close = function (code, reason) {
|
||||||
Logger.debug("Closing with code: " + code + " because: " + reason);
|
Logger.debug("Closing with code: " + code + " because: " + reason);
|
||||||
|
|
||||||
if (pingInterval != undefined) {
|
if (pingInterval != undefined) {
|
||||||
Logger.debug("Clearing ping interval");
|
Logger.debug("Clearing ping interval");
|
||||||
clearInterval(pingInterval);
|
clearInterval(pingInterval);
|
||||||
}
|
}
|
||||||
pingPongStarted = false;
|
pingPongStarted = false;
|
||||||
enabledPings = false;
|
enabledPings = false;
|
||||||
|
ws.close(code, reason);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is only for testing
|
// This method is only for testing
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
getScreenId(function (error, sourceId, screen_constraints) {
|
getScreenId(function (error, sourceId, screen_constraints) {
|
||||||
// error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome'
|
// error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome'
|
||||||
// sourceId == null || 'string' || 'firefox'
|
// sourceId == null || 'string' || 'firefox'
|
||||||
|
|
||||||
if(microsoftEdge) {
|
if(microsoftEdge) {
|
||||||
navigator.getDisplayMedia(screen_constraints).then(onSuccess, onFailure);
|
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 freeice = require('freeice');
|
||||||
import uuid = require('uuid');
|
import uuid = require('uuid');
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../Utils/Platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
let platform: PlatformUtils;
|
||||||
|
|
||||||
|
|
||||||
export interface WebRtcPeerConfiguration {
|
export interface WebRtcPeerConfiguration {
|
||||||
|
|
@ -50,6 +55,7 @@ export class WebRtcPeer {
|
||||||
private candidategatheringdone = false;
|
private candidategatheringdone = false;
|
||||||
|
|
||||||
constructor(protected configuration: WebRtcPeerConfiguration) {
|
constructor(protected configuration: WebRtcPeerConfiguration) {
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
|
this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice();
|
||||||
|
|
||||||
this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
|
this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
|
||||||
|
|
@ -139,8 +145,7 @@ export class WebRtcPeer {
|
||||||
|
|
||||||
logger.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints));
|
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
|
// 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) {
|
if (offerAudio) {
|
||||||
this.pc.addTransceiver('audio', {
|
this.pc.addTransceiver('audio', {
|
||||||
|
|
@ -280,8 +285,35 @@ export class WebRtcPeer {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @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> {
|
async setRemoteDescription(sdp: RTCSessionDescriptionInit): Promise<void> {
|
||||||
return this.pc.setRemoteDescription(sdp);
|
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';
|
configuration.mode = 'sendrecv';
|
||||||
super(configuration);
|
super(configuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,16 @@
|
||||||
// tslint:disable:no-string-literal
|
// tslint:disable:no-string-literal
|
||||||
|
|
||||||
import { Stream } from '../../OpenVidu/Stream';
|
import { Stream } from '../../OpenVidu/Stream';
|
||||||
import platform = require('platform');
|
|
||||||
import { OpenViduLogger } from '../Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../Logger/OpenViduLogger';
|
||||||
|
import { PlatformUtils } from '../Utils/Platform';
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
const logger: OpenViduLogger = OpenViduLogger.getInstance();
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
let platform: PlatformUtils;
|
||||||
|
|
||||||
export class WebRtcStats {
|
export class WebRtcStats {
|
||||||
|
|
||||||
|
|
@ -60,7 +63,9 @@ export class WebRtcStats {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private stream: Stream) { }
|
constructor(private stream: Stream) {
|
||||||
|
platform = PlatformUtils.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
public isEnabled(): boolean {
|
public isEnabled(): boolean {
|
||||||
return this.webRtcStatsEnabled;
|
return this.webRtcStatsEnabled;
|
||||||
|
|
@ -103,7 +108,7 @@ export class WebRtcStats {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.getStatsAgnostic(this.stream.getRTCPeerConnection(),
|
this.getStatsAgnostic(this.stream.getRTCPeerConnection(),
|
||||||
(stats) => {
|
(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;
|
let localCandidateId, remoteCandidateId, googCandidatePair;
|
||||||
const localCandidates = {};
|
const localCandidates = {};
|
||||||
const remoteCandidates = {};
|
const remoteCandidates = {};
|
||||||
|
|
@ -181,7 +186,7 @@ export class WebRtcStats {
|
||||||
|
|
||||||
const f = (stats) => {
|
const f = (stats) => {
|
||||||
|
|
||||||
if (platform.name!.indexOf('Firefox') !== -1) {
|
if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) {
|
||||||
stats.forEach((stat) => {
|
stats.forEach((stat) => {
|
||||||
|
|
||||||
let json = {};
|
let json = {};
|
||||||
|
|
@ -278,7 +283,7 @@ export class WebRtcStats {
|
||||||
sendPost(JSON.stringify(json));
|
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)) {
|
for (const key of Object.keys(stats)) {
|
||||||
const stat = stats[key];
|
const stat = stats[key];
|
||||||
if (stat.type === 'ssrc') {
|
if (stat.type === 'ssrc') {
|
||||||
|
|
@ -377,7 +382,7 @@ export class WebRtcStats {
|
||||||
logger.log(response);
|
logger.log(response);
|
||||||
const standardReport = {};
|
const standardReport = {};
|
||||||
|
|
||||||
if (platform.name!.indexOf('Firefox') !== -1) {
|
if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) {
|
||||||
Object.keys(response).forEach(key => {
|
Object.keys(response).forEach(key => {
|
||||||
logger.log(response[key]);
|
logger.log(response[key]);
|
||||||
});
|
});
|
||||||
|
|
@ -400,13 +405,13 @@ export class WebRtcStats {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getStatsAgnostic(pc, successCb, failureCb) {
|
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
|
// getStats takes args in different order in Chrome and Firefox
|
||||||
return pc.getStats(null).then(response => {
|
return pc.getStats(null).then(response => {
|
||||||
const report = this.standardizeReport(response);
|
const report = this.standardizeReport(response);
|
||||||
successCb(report);
|
successCb(report);
|
||||||
}).catch(failureCb);
|
}).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
|
// In Chrome, the first two arguments are reversed
|
||||||
return pc.getStats((response) => {
|
return pc.getStats((response) => {
|
||||||
const report = this.standardizeReport(response);
|
const report = this.standardizeReport(response);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ export { StreamEvent } from './OpenViduInternal/Events/StreamEvent';
|
||||||
export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent';
|
export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent';
|
||||||
export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent';
|
export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent';
|
||||||
export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent';
|
export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||||
|
export { ConnectionPropertyChangedEvent } from './OpenViduInternal/Events/ConnectionPropertyChangedEvent';
|
||||||
export { FilterEvent } from './OpenViduInternal/Events/FilterEvent';
|
export { FilterEvent } from './OpenViduInternal/Events/FilterEvent';
|
||||||
|
export { NetworkQualityLevelChangedEvent } from './OpenViduInternal/Events/NetworkQualityLevelChangedEvent';
|
||||||
|
|
||||||
export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities';
|
export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities';
|
||||||
export { Device } from './OpenViduInternal/Interfaces/Public/Device';
|
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),
|
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_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),
|
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;
|
private int value;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,15 @@ public class ProtocolElements {
|
||||||
public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue";
|
public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue";
|
||||||
public static final String STREAMPROPERTYCHANGED_REASON_PARAM = "reason";
|
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_METHOD = "forceDisconnect";
|
||||||
public static final String FORCEDISCONNECT_CONNECTIONID_PARAM = "connectionId";
|
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_STREAM_PARAM = "stream";
|
||||||
public static final String RECONNECTSTREAM_SDPSTRING_PARAM = "sdpString";
|
public static final String RECONNECTSTREAM_SDPSTRING_PARAM = "sdpString";
|
||||||
|
|
||||||
|
public static final String VIDEODATA_METHOD = "videoData";
|
||||||
|
|
||||||
// ---------------------------- SERVER RESPONSES & EVENTS -----------------
|
// ---------------------------- SERVER RESPONSES & EVENTS -----------------
|
||||||
|
|
||||||
public static final String PARTICIPANTJOINED_METHOD = "participantJoined";
|
public static final String PARTICIPANTJOINED_METHOD = "participantJoined";
|
||||||
public static final String PARTICIPANTJOINED_USER_PARAM = "id";
|
public static final String PARTICIPANTJOINED_USER_PARAM = "id";
|
||||||
public static final String PARTICIPANTJOINED_CREATEDAT_PARAM = "createdAt";
|
public static final String PARTICIPANTJOINED_CREATEDAT_PARAM = "createdAt";
|
||||||
public static final String PARTICIPANTJOINED_METADATA_PARAM = "metadata";
|
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_METHOD = "participantLeft";
|
||||||
public static final String PARTICIPANTLEFT_NAME_PARAM = "connectionId";
|
public static final String PARTICIPANTLEFT_NAME_PARAM = "connectionId";
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>openvidu-java-client</artifactId>
|
<artifactId>openvidu-java-client</artifactId>
|
||||||
<version>2.15.1</version>
|
<version>2.16.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>OpenVidu Java Client</name>
|
<name>OpenVidu Java Client</name>
|
||||||
|
|
|
||||||
|
|
@ -18,77 +18,194 @@
|
||||||
package io.openvidu.java.client;
|
package io.openvidu.java.client;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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 {
|
public class Connection {
|
||||||
|
|
||||||
private String connectionId;
|
private String connectionId;
|
||||||
private long createdAt;
|
private String status;
|
||||||
private OpenViduRole role;
|
private Long createdAt;
|
||||||
private String token;
|
private Long activeAt;
|
||||||
private String location;
|
private String location;
|
||||||
private String platform;
|
private String platform;
|
||||||
private String serverData;
|
|
||||||
private String clientData;
|
private String clientData;
|
||||||
|
private ConnectionProperties connectionProperties;
|
||||||
|
private String token;
|
||||||
|
|
||||||
protected Map<String, Publisher> publishers;
|
protected Map<String, Publisher> publishers = new ConcurrentHashMap<>();
|
||||||
protected List<String> subscribers;
|
protected List<String> subscribers = new ArrayList<>();
|
||||||
|
|
||||||
protected Connection(String connectionId, long createdAt, OpenViduRole role, String token, String location,
|
protected Connection(JsonObject json) {
|
||||||
String platform, String serverData, String clientData, Map<String, Publisher> publishers,
|
this.resetWithJson(json);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the identifier of the connection. You can call
|
* Returns the identifier of the Connection. You can call methods
|
||||||
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} passing this
|
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} or
|
||||||
* property as parameter
|
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}
|
||||||
|
* passing this property as parameter
|
||||||
*/
|
*/
|
||||||
public String getConnectionId() {
|
public String getConnectionId() {
|
||||||
return connectionId;
|
return connectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp when this connection was established, in UTC milliseconds (ms since
|
* Returns the status of the Connection. Can be:
|
||||||
* Jan 1, 1970, 00:00:00 UTC)
|
* <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;
|
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() {
|
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() {
|
public String getToken() {
|
||||||
return token;
|
return this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display:
|
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||||
* inline-block; background-color: rgb(0, 136, 170); color: white; font-weight:
|
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||||
* bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size:
|
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||||
* 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
|
* 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:
|
* Returns the geo location of the connection, with the following format:
|
||||||
* <code>"CITY, COUNTRY"</code> (<code>"unknown"</code> if it wasn't possible to
|
* <code>"CITY, COUNTRY"</code> (<code>"unknown"</code> if it wasn't possible to
|
||||||
|
|
@ -106,20 +223,11 @@ public class Connection {
|
||||||
return platform;
|
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
|
* Returns the data associated to the connection on the client-side. This value
|
||||||
* is set with second parameter of method
|
* is set with second parameter of method <a href=
|
||||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect" target
|
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect"
|
||||||
* ="_blank">Session.connect</a> in OpenVidu Browser
|
* target ="_blank">Session.connect</a> in OpenVidu Browser
|
||||||
*/
|
*/
|
||||||
public String getClientData() {
|
public String getClientData() {
|
||||||
return clientData;
|
return clientData;
|
||||||
|
|
@ -147,8 +255,171 @@ public class Connection {
|
||||||
return this.subscribers;
|
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) {
|
protected void setSubscribers(List<String> subscribers) {
|
||||||
this.subscribers = 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;
|
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()}
|
* 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
|
* Defines the maximum number of Kbps that the Connection will be able to
|
||||||
* able to receive from Kurento Media Server. 0 means unconstrained. Giving a
|
* receive from Kurento Media Server per media stream. 0 means unconstrained.
|
||||||
* value to this property will override the global configuration set in <a
|
* Giving a value to this property will override the global configuration set in
|
||||||
* href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||||
* <code>OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH</code>) for every incoming
|
* <code>OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH</code>) for every incoming
|
||||||
* stream of the user owning the token. <br>
|
* 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
|
* Defines the minimum number of Kbps that the Connection will try to receive
|
||||||
* to receive from Kurento Media Server. 0 means unconstrained. Giving a value
|
* from Kurento Media Server per media stream. 0 means unconstrained. Giving a
|
||||||
* to this property will override the global configuration set in <a href=
|
* value to this property will override the global configuration set in
|
||||||
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||||
* <code>OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH</code>) for every incoming
|
* <code>OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH</code>) for every incoming
|
||||||
* stream of the user owning the token.
|
* 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
|
* Defines the maximum number of Kbps that the Connection will be able to send
|
||||||
* able to send to Kurento Media Server. 0 means unconstrained. Giving a value
|
* to Kurento Media Server per media stream. 0 means unconstrained. Giving a
|
||||||
* to this property will override the global configuration set in <a href=
|
* value to this property will override the global configuration set in
|
||||||
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||||
* <code>OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH</code>) for every outgoing
|
* <code>OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH</code>) for every outgoing
|
||||||
* stream of the user owning the token. <br>
|
* 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
|
* Defines the minimum number of Kbps that the Connection will try to send to
|
||||||
* to send to Kurento Media Server. 0 means unconstrained. Giving a value to
|
* Kurento Media Server per media stream. 0 means unconstrained. Giving a value
|
||||||
* this property will override the global configuration set in <a href=
|
* to this property will override the global configuration set in
|
||||||
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||||
* target="_blank">OpenVidu Server configuration</a> (parameter
|
* target="_blank">OpenVidu Server configuration</a> (parameter
|
||||||
* <code>OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH</code>) for every outgoing
|
* <code>OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH</code>) for every outgoing
|
||||||
* stream of the user owning the token.
|
* 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
|
* Defines the names of the filters the Connection will be able to apply to its
|
||||||
* apply. See
|
* published streams. See
|
||||||
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/" target= "_blank">Voice and
|
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/"
|
||||||
* video filters</a>
|
* target= "_blank">Voice and video filters</a>.
|
||||||
*/
|
*/
|
||||||
public String[] getAllowedFilters() {
|
public String[] getAllowedFilters() {
|
||||||
return allowedFilters;
|
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.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
|
|
@ -70,16 +69,19 @@ public class OpenVidu {
|
||||||
protected HttpClient httpClient;
|
protected HttpClient httpClient;
|
||||||
protected Map<String, Session> activeSessions = new ConcurrentHashMap<>();
|
protected Map<String, Session> activeSessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
protected final static String API_SESSIONS = "api/sessions";
|
protected final static String API_PATH = "openvidu/api";
|
||||||
protected final static String API_TOKENS = "api/tokens";
|
protected final static String API_SESSIONS = API_PATH + "/sessions";
|
||||||
protected final static String API_RECORDINGS = "api/recordings";
|
protected final static String API_TOKENS = API_PATH + "/tokens";
|
||||||
protected final static String API_RECORDINGS_START = "/start";
|
protected final static String API_RECORDINGS = API_PATH + "/recordings";
|
||||||
protected final static String API_RECORDINGS_STOP = "/stop";
|
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
|
* @param hostname URL where your instance of OpenVidu Server is up an running.
|
||||||
* Server is up an running
|
* It must be the full URL (e.g.
|
||||||
* @param secret Secret used on OpenVidu Server initialization
|
* <code>https://12.34.56.78:1234/</code>)
|
||||||
|
*
|
||||||
|
* @param secret Secret used on OpenVidu Server initialization
|
||||||
*/
|
*/
|
||||||
public OpenVidu(String hostname, String secret) {
|
public OpenVidu(String hostname, String secret) {
|
||||||
|
|
||||||
|
|
@ -192,16 +194,19 @@ public class OpenVidu {
|
||||||
public Recording startRecording(String sessionId, RecordingProperties properties)
|
public Recording startRecording(String sessionId, RecordingProperties properties)
|
||||||
throws OpenViduJavaClientException, OpenViduHttpException {
|
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();
|
JsonObject json = new JsonObject();
|
||||||
json.addProperty("session", sessionId);
|
json.addProperty("session", sessionId);
|
||||||
json.addProperty("name", properties.name());
|
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("hasAudio", properties.hasAudio());
|
||||||
json.addProperty("hasVideo", properties.hasVideo());
|
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()) {
|
&& properties.hasVideo()) {
|
||||||
json.addProperty("resolution", properties.resolution());
|
json.addProperty("resolution", properties.resolution());
|
||||||
json.addProperty("recordingLayout",
|
json.addProperty("recordingLayout",
|
||||||
|
|
@ -236,8 +241,9 @@ public class OpenVidu {
|
||||||
if (activeSession != null) {
|
if (activeSession != null) {
|
||||||
activeSession.setIsBeingRecorded(true);
|
activeSession.setIsBeingRecorded(true);
|
||||||
} else {
|
} else {
|
||||||
log.warn("No active session found for sessionId '" + r.getSessionId()
|
log.warn(
|
||||||
+ "'. This instance of OpenVidu Java Client didn't create this session");
|
"No active session found for sessionId '{}'. This instance of OpenVidu Java Client didn't create this session",
|
||||||
|
r.getSessionId());
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -352,7 +358,7 @@ public class OpenVidu {
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public Recording stopRecording(String recordingId) throws OpenViduJavaClientException, OpenViduHttpException {
|
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;
|
HttpResponse response;
|
||||||
try {
|
try {
|
||||||
response = this.httpClient.execute(request);
|
response = this.httpClient.execute(request);
|
||||||
|
|
@ -368,8 +374,9 @@ public class OpenVidu {
|
||||||
if (activeSession != null) {
|
if (activeSession != null) {
|
||||||
activeSession.setIsBeingRecorded(false);
|
activeSession.setIsBeingRecorded(false);
|
||||||
} else {
|
} else {
|
||||||
log.warn("No active session found for sessionId '" + r.getSessionId()
|
log.warn(
|
||||||
+ "'. This instance of OpenVidu Java Client didn't create this session");
|
"No active session found for sessionId '{}'. This instance of OpenVidu Java Client didn't create this session",
|
||||||
|
r.getSessionId());
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -492,6 +499,10 @@ public class OpenVidu {
|
||||||
* since the last time method {@link io.openvidu.java.client.OpenVidu#fetch()}
|
* since the last time method {@link io.openvidu.java.client.OpenVidu#fetch()}
|
||||||
* was called</strong>. Exceptions to this rule are:
|
* was called</strong>. Exceptions to this rule are:
|
||||||
* <ul>
|
* <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
|
* <li>Calling {@link io.openvidu.java.client.Session#fetch()} updates that
|
||||||
* specific Session status</li>
|
* specific Session status</li>
|
||||||
* <li>Calling {@link io.openvidu.java.client.Session#close()} automatically
|
* <li>Calling {@link io.openvidu.java.client.Session#close()} automatically
|
||||||
|
|
@ -531,7 +542,7 @@ public class OpenVidu {
|
||||||
* @throws OpenViduJavaClientException
|
* @throws OpenViduJavaClientException
|
||||||
*/
|
*/
|
||||||
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
|
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;
|
HttpResponse response;
|
||||||
try {
|
try {
|
||||||
|
|
@ -543,44 +554,55 @@ public class OpenVidu {
|
||||||
try {
|
try {
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
||||||
|
|
||||||
JsonObject jsonSessions = httpResponseToJson(response);
|
JsonObject jsonSessions = httpResponseToJson(response);
|
||||||
JsonArray jsonArraySessions = jsonSessions.get("content").getAsJsonArray();
|
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
|
// Boolean to store if any Session has changed
|
||||||
final boolean[] hasChanged = { false };
|
final boolean[] hasChanged = { false };
|
||||||
jsonArraySessions.forEach(session -> {
|
|
||||||
String sessionId = (session.getAsJsonObject()).get("sessionId").getAsString();
|
// 1. Set to store fetched sessionIds and later remove closed ones
|
||||||
fetchedSessionIds.add(sessionId);
|
Set<String> fetchedSessionIds = new HashSet<>();
|
||||||
this.activeSessions.computeIfPresent(sessionId, (sId, s) -> {
|
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();
|
String beforeJSON = s.toJson();
|
||||||
s = s.resetSessionWithJson(session.getAsJsonObject());
|
s = s.resetWithJson(sessionJson);
|
||||||
String afterJSON = s.toJson();
|
String afterJSON = s.toJson();
|
||||||
boolean changed = !beforeJSON.equals(afterJSON);
|
boolean changed = !beforeJSON.equals(afterJSON);
|
||||||
hasChanged[0] = hasChanged[0] || changed;
|
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;
|
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;
|
hasChanged[0] = true;
|
||||||
return new Session(this, session.getAsJsonObject());
|
return sessionObj;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove closed sessions from activeSessions map
|
// 4. Remove closed sessions from local collection
|
||||||
this.activeSessions = this.activeSessions.entrySet().stream().filter(entry -> {
|
this.activeSessions.entrySet().removeIf(entry -> {
|
||||||
if (fetchedSessionIds.contains(entry.getKey())) {
|
if (fetchedSessionIds.contains(entry.getKey())) {
|
||||||
return true;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
log.info("Removing closed session {}", entry.getKey());
|
log.info("Removing closed session {}", entry.getKey());
|
||||||
hasChanged[0] = true;
|
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());
|
log.info("Active sessions info fetched: {}", this.activeSessions.keySet());
|
||||||
return hasChanged[0];
|
return hasChanged[0];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new OpenViduHttpException(statusCode);
|
throw new OpenViduHttpException(statusCode);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,15 @@
|
||||||
|
|
||||||
package io.openvidu.java.client;
|
package io.openvidu.java.client;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link io.openvidu.java.client.Connection#getPublishers()}.
|
* See {@link io.openvidu.java.client.Connection#getPublishers()}.
|
||||||
*
|
*
|
||||||
* <br>
|
* <br>
|
||||||
* This is a backend representation of a published media stream (see
|
* This is a backend representation of a published media stream (see <a href=
|
||||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target="_blank"> OpenVidu
|
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||||
* Browser Stream class</a>).
|
* target="_blank"> OpenVidu Browser Stream class</a>).
|
||||||
*/
|
*/
|
||||||
public class Publisher {
|
public class Publisher {
|
||||||
|
|
||||||
|
|
@ -40,36 +39,18 @@ public class Publisher {
|
||||||
private String typeOfVideo;
|
private String typeOfVideo;
|
||||||
private String videoDimensions;
|
private String videoDimensions;
|
||||||
|
|
||||||
protected Publisher(String streamId, long createdAt, boolean hasAudio, boolean hasVideo, JsonElement audioActive,
|
protected Publisher(JsonObject json) {
|
||||||
JsonElement videoActive, JsonElement frameRate, JsonElement typeOfVideo, JsonElement videoDimensions) {
|
this.resetWithJson(json);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the unique identifier of the
|
* Returns the unique identifier of the <a href=
|
||||||
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
|
||||||
* "_blank">Stream</a> associated to this Publisher. Each Publisher is paired
|
* target= "_blank">Stream</a> associated to this Publisher. Each Publisher is
|
||||||
* with only one Stream, so you can identify each Publisher by its
|
* 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=
|
* <a href=
|
||||||
* "_blank"><code>Stream.streamId</code></a>
|
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html#streamid"
|
||||||
|
* target= "_blank"><code>Stream.streamId</code></a>
|
||||||
*/
|
*/
|
||||||
public String getStreamId() {
|
public String getStreamId() {
|
||||||
return streamId;
|
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=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public boolean hasVideo() {
|
||||||
return this.hasVideo;
|
return this.hasVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public boolean hasAudio() {
|
||||||
return this.hasAudio;
|
return this.hasAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public Boolean isAudioActive() {
|
||||||
return this.audioActive;
|
return this.audioActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public Boolean isVideoActive() {
|
||||||
return this.videoActive;
|
return this.videoActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public Integer getFrameRate() {
|
||||||
return this.frameRate;
|
return this.frameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public String getTypeOfVideo() {
|
||||||
return this.typeOfVideo;
|
return this.typeOfVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
|
* See properties of <a href=
|
||||||
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
|
* "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() {
|
public String getVideoDimensions() {
|
||||||
return this.videoDimensions;
|
return this.videoDimensions;
|
||||||
|
|
@ -152,4 +147,32 @@ public class Publisher {
|
||||||
return json;
|
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,
|
stopped,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recording has finished OK and is available for download through OpenVidu
|
* The recording has finished being processed and is available for download
|
||||||
* Server recordings endpoint:
|
* through property {@link Recording#getUrl}
|
||||||
* https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION}
|
|
||||||
*/
|
*/
|
||||||
ready,
|
ready,
|
||||||
|
|
||||||
|
|
@ -75,27 +74,25 @@ public class Recording {
|
||||||
* Record each stream individually
|
* Record each stream individually
|
||||||
*/
|
*/
|
||||||
INDIVIDUAL,
|
INDIVIDUAL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Works the same way as COMPOSED mode, but the necessary recorder
|
* Works the same way as COMPOSED mode, but the necessary recorder service
|
||||||
* service module will start some time in advance and won't be terminated
|
* module will start some time in advance and won't be terminated once a
|
||||||
* once a specific session recording has ended. This module will remain
|
* specific session recording has ended. This module will remain up and running
|
||||||
* up and running as long as the session remains active.<br><br>
|
* as long as the session remains active.<br>
|
||||||
|
* <br>
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li><strong>Pros vs COMPOSED</strong>: the process of starting the recording
|
||||||
* <strong>Pros vs COMPOSED</strong>: the process of starting the recording will be noticeably
|
* will be noticeably faster. This can be very useful in use cases where a
|
||||||
* faster. This can be very useful in use cases where a session needs to be
|
* session needs to be recorded multiple times over time, when a better response
|
||||||
* recorded multiple times over time, when a better response time is usually
|
* time is usually desirable.</li>
|
||||||
* desirable.
|
* <li><strong>Cons vs COMPOSED</strong>: for every session initialized with
|
||||||
* </li>
|
* COMPOSED_QUICK_START recording output mode, extra CPU power will be required
|
||||||
* <li>
|
* in OpenVidu Server. The recording module will be continuously rendering all
|
||||||
* <strong>Cons vs COMPOSED</strong>: for every session initialized with COMPOSED_QUICK_START
|
* of the streams being published to the session even when the session is not
|
||||||
* recording output mode, extra CPU power will be required in OpenVidu Server.
|
* being recorded. And that is for every session configured with
|
||||||
* The recording module will be continuously rendering all of the streams being
|
* COMPOSED_QUICK_START.</li>
|
||||||
* 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>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
COMPOSED_QUICK_START;
|
COMPOSED_QUICK_START;
|
||||||
|
|
@ -129,7 +126,8 @@ public class Recording {
|
||||||
OutputMode outputMode = OutputMode.valueOf(json.get("outputMode").getAsString());
|
OutputMode outputMode = OutputMode.valueOf(json.get("outputMode").getAsString());
|
||||||
RecordingProperties.Builder builder = new RecordingProperties.Builder().name(json.get("name").getAsString())
|
RecordingProperties.Builder builder = new RecordingProperties.Builder().name(json.get("name").getAsString())
|
||||||
.outputMode(outputMode).hasAudio(hasAudio).hasVideo(hasVideo);
|
.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.resolution(json.get("resolution").getAsString());
|
||||||
builder.recordingLayout(RecordingLayout.valueOf(json.get("recordingLayout").getAsString()));
|
builder.recordingLayout(RecordingLayout.valueOf(json.get("recordingLayout").getAsString()));
|
||||||
JsonElement customLayout = json.get("customLayout");
|
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
|
* URL of the recording. You can access the file from there. It is
|
||||||
* <code>null</code> until recording reaches "ready" or "failed" status. If
|
* <code>null</code> until recording reaches "ready" or "failed" status. If
|
||||||
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/" target=
|
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
|
||||||
* "_blank">OpenVidu Server configuration</a> property
|
* target= "_blank">OpenVidu Server configuration</a> property
|
||||||
* <code>OPENVIDU_RECORDING_PUBLIC_ACCESS</code> is false, this path will be
|
* <code>OPENVIDU_RECORDING_PUBLIC_ACCESS</code> is false, this path will be
|
||||||
* secured with OpenVidu credentials
|
* secured with OpenVidu credentials
|
||||||
*/
|
*/
|
||||||
|
|
@ -230,7 +228,8 @@ public class Recording {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolution of the video file. Only defined if OutputMode of the Recording is
|
* 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() {
|
public String getResolution() {
|
||||||
return this.recordingProperties.resolution();
|
return this.recordingProperties.resolution();
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
package io.openvidu.java.client;
|
package io.openvidu.java.client;
|
||||||
|
|
||||||
import io.openvidu.java.client.Recording.OutputMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See
|
* See
|
||||||
* {@link io.openvidu.java.client.OpenVidu#startRecording(String, RecordingProperties)}
|
* {@link io.openvidu.java.client.OpenVidu#startRecording(String, RecordingProperties)}
|
||||||
|
|
@ -33,6 +31,7 @@ public class RecordingProperties {
|
||||||
private boolean hasAudio;
|
private boolean hasAudio;
|
||||||
private boolean hasVideo;
|
private boolean hasVideo;
|
||||||
private long shmSize; // For COMPOSED recording
|
private long shmSize; // For COMPOSED recording
|
||||||
|
private String mediaNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for {@link io.openvidu.java.client.RecordingProperties}
|
* Builder for {@link io.openvidu.java.client.RecordingProperties}
|
||||||
|
|
@ -40,27 +39,21 @@ public class RecordingProperties {
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private Recording.OutputMode outputMode = Recording.OutputMode.COMPOSED;
|
private Recording.OutputMode outputMode;
|
||||||
private RecordingLayout recordingLayout;
|
private RecordingLayout recordingLayout;
|
||||||
private String customLayout;
|
private String customLayout;
|
||||||
private String resolution;
|
private String resolution;
|
||||||
private boolean hasAudio = true;
|
private boolean hasAudio = true;
|
||||||
private boolean hasVideo = true;
|
private boolean hasVideo = true;
|
||||||
private long shmSize = 536870912L;
|
private long shmSize = 536870912L;
|
||||||
|
private String mediaNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for {@link io.openvidu.java.client.RecordingProperties}
|
* Builder for {@link io.openvidu.java.client.RecordingProperties}
|
||||||
*/
|
*/
|
||||||
public RecordingProperties build() {
|
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,
|
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
|
* method to set the relative path to the specific custom layout you want to
|
||||||
* use.<br>
|
* use.<br>
|
||||||
* Will only have effect if
|
* Will only have effect if
|
||||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)
|
||||||
* has been called with value
|
* Builder.outputMode()} has been called with value
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.<br>
|
* OutputMode.COMPOSED} or
|
||||||
* See <a href="https://docs.openvidu.io/en/stable/advanced-features/recording#custom-recording-layouts"
|
* {@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
|
* target="_blank">Custom recording layouts</a> to learn more
|
||||||
*/
|
*/
|
||||||
public RecordingProperties.Builder customLayout(String path) {
|
public RecordingProperties.Builder customLayout(String path) {
|
||||||
|
|
@ -119,13 +115,15 @@ public class RecordingProperties {
|
||||||
* format "WIDTHxHEIGHT", being both WIDTH and HEIGHT the number of pixels
|
* format "WIDTHxHEIGHT", being both WIDTH and HEIGHT the number of pixels
|
||||||
* between 100 and 1999.<br>
|
* between 100 and 1999.<br>
|
||||||
* Will only have effect if
|
* Will only have effect if
|
||||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)
|
||||||
* has been called with value
|
* Builder.outputMode()} has been called with value
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}. For
|
* OutputMode.COMPOSED} or
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START
|
||||||
* individual video files will have the native resolution of the published
|
* OutputMode.COMPOSED_QUICK_START}. For
|
||||||
* stream
|
* {@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) {
|
public RecordingProperties.Builder resolution(String resolution) {
|
||||||
this.resolution = 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
|
* 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) {
|
public RecordingProperties.Builder hasAudio(boolean hasAudio) {
|
||||||
this.hasAudio = 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
|
* 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) {
|
public RecordingProperties.Builder hasVideo(boolean hasVideo) {
|
||||||
this.hasVideo = hasVideo;
|
this.hasVideo = hasVideo;
|
||||||
|
|
@ -160,10 +160,26 @@ public class RecordingProperties {
|
||||||
return this;
|
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,
|
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.name = name;
|
||||||
this.outputMode = outputMode;
|
this.outputMode = outputMode;
|
||||||
this.recordingLayout = layout;
|
this.recordingLayout = layout;
|
||||||
|
|
@ -172,6 +188,7 @@ public class RecordingProperties {
|
||||||
this.hasAudio = hasAudio;
|
this.hasAudio = hasAudio;
|
||||||
this.hasVideo = hasVideo;
|
this.hasVideo = hasVideo;
|
||||||
this.shmSize = shmSize;
|
this.shmSize = shmSize;
|
||||||
|
this.mediaNode = mediaNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -185,12 +202,12 @@ public class RecordingProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the mode of recording: {@link Recording.OutputMode#COMPOSED} or
|
* Defines the mode of recording: {@link Recording.OutputMode#COMPOSED} or
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} for a
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} for
|
||||||
* single archive in a grid layout or {@link Recording.OutputMode#INDIVIDUAL}
|
* a single archive in a grid layout or {@link Recording.OutputMode#INDIVIDUAL}
|
||||||
* for one archive for each stream.<br>
|
* for one archive for each stream.<br>
|
||||||
* <br>
|
* <br>
|
||||||
*
|
*
|
||||||
* Default to {@link Recording.OutputMode#COMPOSED}
|
* Default to {@link Recording.OutputMode#COMPOSED OutputMode.COMPOSED}
|
||||||
*/
|
*/
|
||||||
public Recording.OutputMode outputMode() {
|
public Recording.OutputMode outputMode() {
|
||||||
return this.outputMode;
|
return this.outputMode;
|
||||||
|
|
@ -199,12 +216,14 @@ public class RecordingProperties {
|
||||||
/**
|
/**
|
||||||
* Defines the layout to be used in the recording.<br>
|
* Defines the layout to be used in the recording.<br>
|
||||||
* Will only have effect if
|
* Will only have effect if
|
||||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)
|
||||||
* has been called with value {@link Recording.OutputMode#COMPOSED} or
|
* Builder.outputMode()} has been called with value
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.<br>
|
* {@link Recording.OutputMode#COMPOSED OutputMode.COMPOSED} or
|
||||||
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START
|
||||||
|
* OutputMode.COMPOSED_QUICK_START}.<br>
|
||||||
* <br>
|
* <br>
|
||||||
*
|
*
|
||||||
* Default to {@link RecordingLayout#BEST_FIT}
|
* Default to {@link RecordingLayout#BEST_FIT RecordingLayout.BEST_FIT}
|
||||||
*/
|
*/
|
||||||
public RecordingLayout recordingLayout() {
|
public RecordingLayout recordingLayout() {
|
||||||
return this.recordingLayout;
|
return this.recordingLayout;
|
||||||
|
|
@ -214,7 +233,8 @@ public class RecordingProperties {
|
||||||
* If {@link io.openvidu.java.client.RecordingProperties#recordingLayout()} is
|
* If {@link io.openvidu.java.client.RecordingProperties#recordingLayout()} is
|
||||||
* set to {@link io.openvidu.java.client.RecordingLayout#CUSTOM}, this property
|
* 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>
|
* 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
|
* target="_blank">Custom recording layouts</a> to learn more
|
||||||
*/
|
*/
|
||||||
public String customLayout() {
|
public String customLayout() {
|
||||||
|
|
@ -227,8 +247,8 @@ public class RecordingProperties {
|
||||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
* {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
|
||||||
* has been called with value
|
* has been called with value
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or
|
* {@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#COMPOSED_QUICK_START}.
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
|
* For {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
|
||||||
* individual video files will have the native resolution of the published
|
* individual video files will have the native resolution of the published
|
||||||
* stream.<br>
|
* stream.<br>
|
||||||
* <br>
|
* <br>
|
||||||
|
|
@ -241,7 +261,7 @@ public class RecordingProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines whether to record audio or not. Cannot be set to false at the same
|
* 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>
|
* <br>
|
||||||
*
|
*
|
||||||
* Default to true
|
* 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
|
* 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>
|
* <br>
|
||||||
*
|
*
|
||||||
* Default to true
|
* Default to true
|
||||||
|
|
@ -273,4 +293,18 @@ public class RecordingProperties {
|
||||||
return this.shmSize;
|
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.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -34,6 +35,7 @@ import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpDelete;
|
import org.apache.http.client.methods.HttpDelete;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
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.client.methods.HttpPost;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
@ -48,7 +50,7 @@ public class Session {
|
||||||
private long createdAt;
|
private long createdAt;
|
||||||
private OpenVidu openVidu;
|
private OpenVidu openVidu;
|
||||||
private SessionProperties properties;
|
private SessionProperties properties;
|
||||||
private Map<String, Connection> activeConnections = new ConcurrentHashMap<>();
|
private Map<String, Connection> connections = new ConcurrentHashMap<>();
|
||||||
private boolean recording = false;
|
private boolean recording = false;
|
||||||
|
|
||||||
protected Session(OpenVidu openVidu) throws OpenViduJavaClientException, OpenViduHttpException {
|
protected Session(OpenVidu openVidu) throws OpenViduJavaClientException, OpenViduHttpException {
|
||||||
|
|
@ -66,11 +68,11 @@ public class Session {
|
||||||
|
|
||||||
protected Session(OpenVidu openVidu, JsonObject json) {
|
protected Session(OpenVidu openVidu, JsonObject json) {
|
||||||
this.openVidu = openVidu;
|
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
|
* @return The sessionId
|
||||||
*/
|
*/
|
||||||
|
|
@ -80,78 +82,49 @@ public class Session {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp when this session was created, in UTC milliseconds (ms since Jan 1,
|
* 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() {
|
public long createdAt() {
|
||||||
return this.createdAt;
|
return this.createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a new token associated to Session object with default values for
|
* @deprecated Use {@link Session#createConnection() Session.createConnection()}
|
||||||
* {@link io.openvidu.java.client.TokenOptions}. This always translates into a
|
* instead to get a {@link io.openvidu.java.client.Connection}
|
||||||
* new request to OpenVidu Server
|
* object.
|
||||||
|
*
|
||||||
|
* @return The generated token String
|
||||||
*
|
*
|
||||||
* @return The generated token
|
|
||||||
*
|
|
||||||
* @throws OpenViduJavaClientException
|
* @throws OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String generateToken() throws OpenViduJavaClientException, OpenViduHttpException {
|
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
|
* @deprecated Use
|
||||||
* <code>tokenOptions</code>. This always translates into a new request to
|
* {@link Session#createConnection(io.openvidu.java.client.ConnectionProperties)
|
||||||
* OpenVidu Server
|
* 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 OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String generateToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException {
|
public String generateToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException {
|
||||||
|
|
||||||
if (!this.hasSessionId()) {
|
if (!this.hasSessionId()) {
|
||||||
this.getSessionId();
|
this.getSessionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpPost request = new HttpPost(this.openVidu.hostname + OpenVidu.API_TOKENS);
|
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;
|
StringEntity params;
|
||||||
try {
|
try {
|
||||||
params = new StringEntity(json.toString());
|
params = new StringEntity(tokenOptions.toJsonObject(sessionId).toString());
|
||||||
} catch (UnsupportedEncodingException e1) {
|
} catch (UnsupportedEncodingException e1) {
|
||||||
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
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
|
* Gracefully closes the Session: unpublishes all streams and evicts every
|
||||||
* participant
|
* participant.
|
||||||
*
|
*
|
||||||
* @throws OpenViduJavaClientException
|
* @throws OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
|
@ -217,22 +259,25 @@ public class Session {
|
||||||
* connections to the Session
|
* connections to the Session
|
||||||
* ({@link io.openvidu.java.client.Session#getActiveConnections()}) and use
|
* ({@link io.openvidu.java.client.Session#getActiveConnections()}) and use
|
||||||
* those values to call
|
* those values to call
|
||||||
* {@link io.openvidu.java.client.Session#forceDisconnect(Connection)} or
|
* {@link io.openvidu.java.client.Session#forceDisconnect(Connection)},
|
||||||
* {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)}. <br>
|
* {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} or
|
||||||
*
|
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}.<br>
|
||||||
* To update every Session object owned by OpenVidu object, call
|
* <br>
|
||||||
* {@link io.openvidu.java.client.OpenVidu#fetch()}
|
*
|
||||||
*
|
* 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,
|
* @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
|
* false if not. This applies to any property or sub-property of the
|
||||||
* object
|
* object.
|
||||||
*
|
*
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
* @throws OpenViduJavaClientException
|
* @throws OpenViduJavaClientException
|
||||||
*/
|
*/
|
||||||
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
|
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
|
||||||
String beforeJSON = this.toJson();
|
final String beforeJSON = this.toJson();
|
||||||
HttpGet request = new HttpGet(this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId);
|
HttpGet request = new HttpGet(
|
||||||
|
this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "?pendingConnections=true");
|
||||||
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
HttpResponse response;
|
HttpResponse response;
|
||||||
|
|
@ -245,8 +290,8 @@ public class Session {
|
||||||
try {
|
try {
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
|
||||||
this.resetSessionWithJson(httpResponseToJson(response));
|
this.resetWithJson(httpResponseToJson(response));
|
||||||
String afterJSON = this.toJson();
|
final String afterJSON = this.toJson();
|
||||||
boolean hasChanged = !beforeJSON.equals(afterJSON);
|
boolean hasChanged = !beforeJSON.equals(afterJSON);
|
||||||
log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged);
|
log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged);
|
||||||
return hasChanged;
|
return hasChanged;
|
||||||
|
|
@ -259,16 +304,31 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces the user represented by <code>connection</code> to leave the session.
|
* Removes the Connection from the Session. This can translate into a forced
|
||||||
* OpenVidu Browser will trigger the proper events on the client-side
|
* eviction of a user from the Session if the Connection had status
|
||||||
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
|
* <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
|
* <code>sessionDisconnected</code>) with reason set to
|
||||||
* "forceDisconnectByServer" <br>
|
* <code>"forceDisconnectByServer"</code>. <br>
|
||||||
*
|
* <br>
|
||||||
* You can get <code>connection</code> parameter with
|
*
|
||||||
* {@link io.openvidu.java.client.Session#fetch()} and then
|
* In the second case, the token of the Connection will be invalidated and no
|
||||||
* {@link io.openvidu.java.client.Session#getActiveConnections()}
|
* 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 OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
|
@ -277,17 +337,13 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces the user with Connection <code>connectionId</code> to leave the
|
* Same as {@link io.openvidu.java.client.Session#forceDisconnect(Connection)
|
||||||
* session. OpenVidu Browser will trigger the proper events on the client-side
|
* forceDisconnect(ConnectionProperties)} but providing the
|
||||||
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
|
* {@link io.openvidu.java.client.Connection#getConnectionId() connectionId}
|
||||||
* <code>sessionDisconnected</code>) with reason set to
|
* instead of the Connection object.
|
||||||
* "forceDisconnectByServer" <br>
|
*
|
||||||
*
|
* @param connectionId The identifier of the Connection object to remove
|
||||||
* 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)
|
|
||||||
*
|
|
||||||
* @throws OpenViduJavaClientException
|
* @throws OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
|
@ -307,13 +363,13 @@ public class Session {
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
|
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
|
||||||
// Remove connection from activeConnections map
|
// 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
|
// Remove every Publisher of the closed connection from every subscriber list of
|
||||||
// other connections
|
// other connections
|
||||||
if (connectionClosed != null) {
|
if (connectionClosed != null) {
|
||||||
for (Publisher publisher : connectionClosed.getPublishers()) {
|
for (Publisher publisher : connectionClosed.getPublishers()) {
|
||||||
String streamId = publisher.getStreamId();
|
String streamId = publisher.getStreamId();
|
||||||
for (Connection connection : this.activeConnections.values()) {
|
for (Connection connection : this.connections.values()) {
|
||||||
connection.setSubscribers(connection.getSubscribers().stream()
|
connection.setSubscribers(connection.getSubscribers().stream()
|
||||||
.filter(subscriber -> !streamId.equals(subscriber)).collect(Collectors.toList()));
|
.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
|
* Forces some Connection to unpublish a Stream. OpenVidu Browser will trigger
|
||||||
* proper events on the client-side (<code>streamDestroyed</code>) with reason
|
* the proper events in the client-side (<code>streamDestroyed</code>) with
|
||||||
* set to "forceUnpublishByServer".<br>
|
* reason set to <code>"forceUnpublishByServer"</code>. <br>
|
||||||
*
|
* <br>
|
||||||
|
*
|
||||||
* You can get <code>publisher</code> parameter with
|
* You can get <code>publisher</code> parameter with
|
||||||
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
|
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
|
||||||
* each Connection you can call
|
* each Connection you can call
|
||||||
* {@link io.openvidu.java.client.Connection#getPublishers()}. Remember to call
|
* {@link io.openvidu.java.client.Connection#getPublishers()}. Remember to call
|
||||||
* {@link io.openvidu.java.client.Session#fetch()} before to fetch the current
|
* {@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 OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
|
@ -353,19 +420,13 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
|
* Same as {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)
|
||||||
* proper events on the client-side (<code>streamDestroyed</code>) with reason
|
* forceUnpublish(Publisher)} but providing the
|
||||||
* set to "forceUnpublishByServer". <br>
|
* {@link io.openvidu.java.client.Publisher#getStreamId() streamId} instead of
|
||||||
*
|
* the Publisher object.
|
||||||
* You can get <code>streamId</code> parameter with
|
*
|
||||||
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
|
* @param streamId The identifier of the Publisher object to remove
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* @throws OpenViduJavaClientException
|
* @throws OpenViduJavaClientException
|
||||||
* @throws OpenViduHttpException
|
* @throws OpenViduHttpException
|
||||||
*/
|
*/
|
||||||
|
|
@ -384,7 +445,7 @@ public class Session {
|
||||||
try {
|
try {
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
|
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
|
// Try to remove the Publisher from the Connection publishers collection
|
||||||
if (connection.publishers.remove(streamId) != null) {
|
if (connection.publishers.remove(streamId) != null) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -402,44 +463,194 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of active connections to the session. <strong>This value
|
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank"
|
||||||
* will remain unchanged since the last time method
|
* style="display: inline-block; background-color: rgb(0, 136, 170); color:
|
||||||
* {@link io.openvidu.java.client.Session#fetch()} was called</strong>.
|
* white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius:
|
||||||
* Exceptions to this rule are:
|
* 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>
|
* <ul>
|
||||||
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
|
* <li>{@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole)
|
||||||
* updates each affected Connection status</li>
|
* ConnectionProperties.Builder.role(OpenViduRole)}</li>
|
||||||
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
|
* <li>{@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean)
|
||||||
* updates each affected Connection status</li>
|
* ConnectionProperties.Builder.record(boolean)}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <br>
|
* <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
|
* This method automatically updates the properties of the local affected
|
||||||
* {@link io.openvidu.java.client.Session#getActiveConnections()}
|
* 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() {
|
public Connection updateConnection(String connectionId, ConnectionProperties connectionProperties)
|
||||||
return new ArrayList<>(this.activeConnections.values());
|
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() {
|
public boolean isBeingRecorded() {
|
||||||
return this.recording;
|
return this.recording;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the properties defining the session
|
* Returns the properties defining the session.
|
||||||
*/
|
*/
|
||||||
public SessionProperties getProperties() {
|
public SessionProperties getProperties() {
|
||||||
return this.properties;
|
return this.properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasSessionId() {
|
private boolean hasSessionId() {
|
||||||
return (this.sessionId != null && !this.sessionId.isEmpty());
|
return (this.sessionId != null && !this.sessionId.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
@ -450,27 +661,9 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpPost request = new HttpPost(this.openVidu.hostname + OpenVidu.API_SESSIONS);
|
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;
|
StringEntity params = null;
|
||||||
try {
|
try {
|
||||||
params = new StringEntity(json.toString());
|
params = new StringEntity(properties.toJson().toString());
|
||||||
} catch (UnsupportedEncodingException e1) {
|
} catch (UnsupportedEncodingException e1) {
|
||||||
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
|
||||||
}
|
}
|
||||||
|
|
@ -490,19 +683,24 @@ public class Session {
|
||||||
JsonObject responseJson = httpResponseToJson(response);
|
JsonObject responseJson = httpResponseToJson(response);
|
||||||
this.sessionId = responseJson.get("id").getAsString();
|
this.sessionId = responseJson.get("id").getAsString();
|
||||||
this.createdAt = responseJson.get("createdAt").getAsLong();
|
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());
|
VideoCodec forcedVideoCodec = VideoCodec.valueOf(responseJson.get("forcedVideoCodec").getAsString());
|
||||||
Boolean allowTranscoding = responseJson.get("allowTranscoding").getAsBoolean();
|
Boolean allowTranscoding = responseJson.get("allowTranscoding").getAsBoolean();
|
||||||
|
|
||||||
SessionProperties responseProperties = new SessionProperties.Builder()
|
SessionProperties responseProperties = new SessionProperties.Builder()
|
||||||
.mediaMode(properties.mediaMode())
|
.customSessionId(properties.customSessionId())
|
||||||
.recordingMode(properties.recordingMode())
|
.mediaMode(properties.mediaMode())
|
||||||
.defaultOutputMode(properties.defaultOutputMode())
|
.recordingMode(properties.recordingMode())
|
||||||
.defaultRecordingLayout(properties.defaultRecordingLayout())
|
.defaultOutputMode(properties.defaultOutputMode())
|
||||||
.defaultCustomLayout(properties.defaultCustomLayout())
|
.defaultRecordingLayout(properties.defaultRecordingLayout())
|
||||||
.forcedVideoCodec(forcedVideoCodec)
|
.defaultCustomLayout(properties.defaultCustomLayout())
|
||||||
.allowTranscoding(allowTranscoding)
|
.mediaNode(properties.mediaNode())
|
||||||
.build();
|
.forcedVideoCodec(forcedVideoCodec)
|
||||||
|
.allowTranscoding(allowTranscoding)
|
||||||
|
.build();
|
||||||
|
|
||||||
this.properties = responseProperties;
|
this.properties = responseProperties;
|
||||||
log.info("Session '{}' created", this.sessionId);
|
log.info("Session '{}' created", this.sessionId);
|
||||||
} else if (statusCode == org.apache.http.HttpStatus.SC_CONFLICT) {
|
} else if (statusCode == org.apache.http.HttpStatus.SC_CONFLICT) {
|
||||||
|
|
@ -530,7 +728,7 @@ public class Session {
|
||||||
this.recording = recording;
|
this.recording = recording;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Session resetSessionWithJson(JsonObject json) {
|
protected Session resetWithJson(JsonObject json) {
|
||||||
this.sessionId = json.get("sessionId").getAsString();
|
this.sessionId = json.get("sessionId").getAsString();
|
||||||
this.createdAt = json.get("createdAt").getAsLong();
|
this.createdAt = json.get("createdAt").getAsLong();
|
||||||
this.recording = json.get("recording").getAsBoolean();
|
this.recording = json.get("recording").getAsBoolean();
|
||||||
|
|
@ -544,50 +742,44 @@ public class Session {
|
||||||
if (json.has("defaultCustomLayout")) {
|
if (json.has("defaultCustomLayout")) {
|
||||||
builder.defaultCustomLayout(json.get("defaultCustomLayout").getAsString());
|
builder.defaultCustomLayout(json.get("defaultCustomLayout").getAsString());
|
||||||
}
|
}
|
||||||
|
if (json.has("customSessionId")) {
|
||||||
|
builder.customSessionId(json.get("customSessionId").getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
if (json.has("forcedVideoCodec")) {
|
if (json.has("forcedVideoCodec")) {
|
||||||
builder.forcedVideoCodec(VideoCodec.valueOf(json.get("forcedVideoCodec").getAsString()));
|
builder.forcedVideoCodec(VideoCodec.valueOf(json.get("forcedVideoCodec").getAsString()));
|
||||||
}
|
}
|
||||||
if (json.has("allowTranscoding")) {
|
if (json.has("allowTranscoding")) {
|
||||||
builder.allowTranscoding(json.get("allowTranscoding").getAsBoolean());
|
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();
|
this.properties = builder.build();
|
||||||
JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray();
|
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<>();
|
// 1. Set to store fetched connections and later remove closed ones
|
||||||
JsonArray jsonArrayPublishers = con.get("publishers").getAsJsonArray();
|
Set<String> fetchedConnectionIds = new HashSet<>();
|
||||||
jsonArrayPublishers.forEach(publisher -> {
|
jsonArrayConnections.forEach(connectionJsonElement -> {
|
||||||
JsonObject pubJson = publisher.getAsJsonObject();
|
|
||||||
JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject();
|
JsonObject connectionJson = connectionJsonElement.getAsJsonObject();
|
||||||
Publisher pub = new Publisher(pubJson.get("streamId").getAsString(),
|
Connection connectionObj = new Connection(connectionJson);
|
||||||
pubJson.get("createdAt").getAsLong(), mediaOptions.get("hasAudio").getAsBoolean(),
|
String id = connectionObj.getConnectionId();
|
||||||
mediaOptions.get("hasVideo").getAsBoolean(), mediaOptions.get("audioActive"),
|
fetchedConnectionIds.add(id);
|
||||||
mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"),
|
|
||||||
mediaOptions.get("videoDimensions"));
|
// 2. Update existing Connection
|
||||||
publishers.put(pub.getStreamId(), pub);
|
this.connections.computeIfPresent(id, (cId, c) -> {
|
||||||
|
c = c.resetWithJson(connectionJson);
|
||||||
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
List<String> subscribers = new ArrayList<>();
|
// 3. Add new Connection
|
||||||
JsonArray jsonArraySubscribers = con.get("subscribers").getAsJsonArray();
|
this.connections.computeIfAbsent(id, cId -> {
|
||||||
jsonArraySubscribers.forEach(subscriber -> {
|
return connectionObj;
|
||||||
subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -609,26 +801,10 @@ public class Session {
|
||||||
json.addProperty("allowTranscoding", this.properties.isTranscodingAllowed());
|
json.addProperty("allowTranscoding", this.properties.isTranscodingAllowed());
|
||||||
}
|
}
|
||||||
JsonObject connections = new JsonObject();
|
JsonObject connections = new JsonObject();
|
||||||
connections.addProperty("numberOfElements", this.getActiveConnections().size());
|
connections.addProperty("numberOfElements", this.getConnections().size());
|
||||||
JsonArray jsonArrayConnections = new JsonArray();
|
JsonArray jsonArrayConnections = new JsonArray();
|
||||||
this.getActiveConnections().forEach(con -> {
|
this.getConnections().forEach(con -> {
|
||||||
JsonObject c = new JsonObject();
|
jsonArrayConnections.add(con.toJson());
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
connections.add("content", jsonArrayConnections);
|
connections.add("content", jsonArrayConnections);
|
||||||
json.add("connections", connections);
|
json.add("connections", connections);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package io.openvidu.java.client;
|
package io.openvidu.java.client;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import io.openvidu.java.client.Recording.OutputMode;
|
import io.openvidu.java.client.Recording.OutputMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -30,6 +32,7 @@ public class SessionProperties {
|
||||||
private RecordingLayout defaultRecordingLayout;
|
private RecordingLayout defaultRecordingLayout;
|
||||||
private String defaultCustomLayout;
|
private String defaultCustomLayout;
|
||||||
private String customSessionId;
|
private String customSessionId;
|
||||||
|
private String mediaNode;
|
||||||
private VideoCodec forcedVideoCodec;
|
private VideoCodec forcedVideoCodec;
|
||||||
private Boolean allowTranscoding;
|
private Boolean allowTranscoding;
|
||||||
|
|
||||||
|
|
@ -44,6 +47,7 @@ public class SessionProperties {
|
||||||
private RecordingLayout defaultRecordingLayout = RecordingLayout.BEST_FIT;
|
private RecordingLayout defaultRecordingLayout = RecordingLayout.BEST_FIT;
|
||||||
private String defaultCustomLayout = "";
|
private String defaultCustomLayout = "";
|
||||||
private String customSessionId = "";
|
private String customSessionId = "";
|
||||||
|
private String mediaNode;
|
||||||
private VideoCodec forcedVideoCodec;
|
private VideoCodec forcedVideoCodec;
|
||||||
private Boolean allowTranscoding;
|
private Boolean allowTranscoding;
|
||||||
|
|
||||||
|
|
@ -53,7 +57,7 @@ public class SessionProperties {
|
||||||
*/
|
*/
|
||||||
public SessionProperties build() {
|
public SessionProperties build() {
|
||||||
return new SessionProperties(this.mediaMode, this.recordingMode, this.defaultOutputMode,
|
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);
|
this.forcedVideoCodec, this.allowTranscoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +66,7 @@ public class SessionProperties {
|
||||||
* your clients: routed through OpenVidu Media Node
|
* your clients: routed through OpenVidu Media Node
|
||||||
* (<code>MediaMode.ROUTED</code>) or attempting direct p2p connections
|
* (<code>MediaMode.ROUTED</code>) or attempting direct p2p connections
|
||||||
* (<code>MediaMode.RELAYED</code>, <i>not available yet</i>)
|
* (<code>MediaMode.RELAYED</code>, <i>not available yet</i>)
|
||||||
*
|
*
|
||||||
* Default value is <code>MediaMode.ROUTED</code>
|
* Default value is <code>MediaMode.ROUTED</code>
|
||||||
*/
|
*/
|
||||||
public SessionProperties.Builder mediaMode(MediaMode mediaMode) {
|
public SessionProperties.Builder mediaMode(MediaMode mediaMode) {
|
||||||
|
|
@ -120,11 +124,11 @@ public class SessionProperties {
|
||||||
* {@link io.openvidu.java.client.RecordingProperties.Builder#customLayout(String)}
|
* {@link io.openvidu.java.client.RecordingProperties.Builder#customLayout(String)}
|
||||||
* with any other value.<br>
|
* with any other value.<br>
|
||||||
* <br>
|
* <br>
|
||||||
*
|
*
|
||||||
* Custom layouts are only applicable to recordings with OutputMode
|
* 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} (or
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) and
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START})
|
||||||
* RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
* and RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
||||||
*/
|
*/
|
||||||
public SessionProperties.Builder defaultCustomLayout(String path) {
|
public SessionProperties.Builder defaultCustomLayout(String path) {
|
||||||
this.defaultCustomLayout = path;
|
this.defaultCustomLayout = path;
|
||||||
|
|
@ -142,20 +146,55 @@ public class SessionProperties {
|
||||||
this.customSessionId = customSessionId;
|
this.customSessionId = customSessionId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this method to define which video codec do you want to be forcibly used for this session.
|
* 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.
|
* 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.
|
* 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) {
|
public SessionProperties.Builder forcedVideoCodec(VideoCodec forcedVideoCodec) {
|
||||||
this.forcedVideoCodec = forcedVideoCodec;
|
this.forcedVideoCodec = forcedVideoCodec;
|
||||||
return this;
|
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
|
* 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.
|
* when {@link #forcedVideoCodec(VideoCodec)} is not compatible with the browser/client.
|
||||||
|
|
@ -174,11 +213,11 @@ public class SessionProperties {
|
||||||
this.defaultRecordingLayout = RecordingLayout.BEST_FIT;
|
this.defaultRecordingLayout = RecordingLayout.BEST_FIT;
|
||||||
this.defaultCustomLayout = "";
|
this.defaultCustomLayout = "";
|
||||||
this.customSessionId = "";
|
this.customSessionId = "";
|
||||||
this.allowTranscoding = false;
|
this.mediaNode = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private SessionProperties(MediaMode mediaMode, RecordingMode recordingMode, OutputMode outputMode,
|
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) {
|
VideoCodec forcedVideoCodec, Boolean allowTranscoding) {
|
||||||
this.mediaMode = mediaMode;
|
this.mediaMode = mediaMode;
|
||||||
this.recordingMode = recordingMode;
|
this.recordingMode = recordingMode;
|
||||||
|
|
@ -186,6 +225,7 @@ public class SessionProperties {
|
||||||
this.defaultRecordingLayout = layout;
|
this.defaultRecordingLayout = layout;
|
||||||
this.defaultCustomLayout = defaultCustomLayout;
|
this.defaultCustomLayout = defaultCustomLayout;
|
||||||
this.customSessionId = customSessionId;
|
this.customSessionId = customSessionId;
|
||||||
|
this.mediaNode = mediaNode;
|
||||||
this.forcedVideoCodec = forcedVideoCodec;
|
this.forcedVideoCodec = forcedVideoCodec;
|
||||||
this.allowTranscoding = allowTranscoding;
|
this.allowTranscoding = allowTranscoding;
|
||||||
}
|
}
|
||||||
|
|
@ -244,8 +284,8 @@ public class SessionProperties {
|
||||||
* with any other value.<br>
|
* with any other value.<br>
|
||||||
* Custom layouts are only applicable to recordings with OutputMode
|
* 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} (or
|
||||||
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) and
|
* {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START})
|
||||||
* RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
* and RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM}
|
||||||
*/
|
*/
|
||||||
public String defaultCustomLayout() {
|
public String defaultCustomLayout() {
|
||||||
return this.defaultCustomLayout;
|
return this.defaultCustomLayout;
|
||||||
|
|
@ -261,14 +301,14 @@ public class SessionProperties {
|
||||||
public String customSessionId() {
|
public String customSessionId() {
|
||||||
return this.customSessionId;
|
return this.customSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines which video codec is being forced to be used in the browser/client
|
* Defines which video codec is being forced to be used in the browser/client
|
||||||
*/
|
*/
|
||||||
public VideoCodec forcedVideoCodec() {
|
public VideoCodec forcedVideoCodec() {
|
||||||
return this.forcedVideoCodec;
|
return this.forcedVideoCodec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines if transcoding is allowed or not when {@link #forcedVideoCodec}
|
* Defines if transcoding is allowed or not when {@link #forcedVideoCodec}
|
||||||
* is not a compatible codec with the browser/client.
|
* is not a compatible codec with the browser/client.
|
||||||
|
|
@ -277,4 +317,54 @@ public class SessionProperties {
|
||||||
return this.allowTranscoding;
|
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;
|
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 {
|
public class TokenOptions {
|
||||||
|
|
||||||
private String data;
|
|
||||||
private OpenViduRole role;
|
private OpenViduRole role;
|
||||||
|
private String data;
|
||||||
private KurentoOptions kurentoOptions;
|
private KurentoOptions kurentoOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @deprecated Use {@link io.openvidu.java.client.ConnectionProperties.Builder
|
||||||
* Builder for {@link io.openvidu.java.client.TokenOptions}
|
* ConnectionProperties.Builder} instead
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private String data = "";
|
|
||||||
private OpenViduRole role = OpenViduRole.PUBLISHER;
|
private OpenViduRole role = OpenViduRole.PUBLISHER;
|
||||||
|
private String data;
|
||||||
private KurentoOptions kurentoOptions;
|
private KurentoOptions kurentoOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for {@link io.openvidu.java.client.TokenOptions}
|
* Builder for {@link io.openvidu.java.client.TokenOptions}.
|
||||||
*/
|
*/
|
||||||
public TokenOptions build() {
|
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;
|
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}
|
* 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) {
|
public Builder kurentoOptions(KurentoOptions kurentoOptions) {
|
||||||
this.kurentoOptions = kurentoOptions;
|
this.kurentoOptions = kurentoOptions;
|
||||||
|
|
@ -90,26 +93,26 @@ public class TokenOptions {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TokenOptions(String data, OpenViduRole role, KurentoOptions kurentoOptions) {
|
TokenOptions(OpenViduRole role, String data, KurentoOptions kurentoOptions) {
|
||||||
this.data = data;
|
|
||||||
this.role = role;
|
this.role = role;
|
||||||
|
this.data = data;
|
||||||
this.kurentoOptions = kurentoOptions;
|
this.kurentoOptions = kurentoOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the secure (server-side) metadata assigned to this token
|
* Returns the role assigned to this token.
|
||||||
*/
|
|
||||||
public String getData() {
|
|
||||||
return this.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the role assigned to this token
|
|
||||||
*/
|
*/
|
||||||
public OpenViduRole getRole() {
|
public OpenViduRole getRole() {
|
||||||
return this.role;
|
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
|
* Returns the Kurento options assigned to this token
|
||||||
*/
|
*/
|
||||||
|
|
@ -117,4 +120,23 @@ public class TokenOptions {
|
||||||
return this.kurentoOptions;
|
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/
|
/lib/
|
||||||
|
|
||||||
docs/
|
docs/
|
||||||
lib/
|
lib/
|
||||||
|
|
||||||
|
*.tgz
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ module.exports = {
|
||||||
externalPattern: "node_modules",
|
externalPattern: "node_modules",
|
||||||
excludeExternals: true,
|
excludeExternals: true,
|
||||||
excludePrivate: true,
|
excludePrivate: true,
|
||||||
|
excludeProtected: true,
|
||||||
excludeNotExported: true,
|
excludeNotExported: true,
|
||||||
theme: "default",
|
theme: "default",
|
||||||
readme: "none",
|
readme: "none",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,24 +1,24 @@
|
||||||
{
|
{
|
||||||
"author": "OpenVidu",
|
"author": "OpenVidu",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.19.2",
|
"axios": "0.21.1",
|
||||||
"buffer": "5.6.0"
|
"buffer": "6.0.2"
|
||||||
},
|
},
|
||||||
"description": "OpenVidu Node Client",
|
"description": "OpenVidu Node Client",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "14.0.13",
|
"@types/node": "14.14.7",
|
||||||
"grunt": "1.1.0",
|
"grunt": "1.3.0",
|
||||||
"grunt-cli": "1.3.2",
|
"grunt-cli": "1.3.2",
|
||||||
"grunt-contrib-copy": "1.0.0",
|
"grunt-contrib-copy": "1.0.0",
|
||||||
"grunt-contrib-sass": "1.0.0",
|
"grunt-contrib-sass": "2.0.0",
|
||||||
"grunt-contrib-uglify": "4.0.1",
|
"grunt-contrib-uglify": "5.0.0",
|
||||||
"grunt-contrib-watch": "1.1.0",
|
"grunt-contrib-watch": "1.1.0",
|
||||||
"grunt-postcss": "0.9.0",
|
"grunt-postcss": "0.9.0",
|
||||||
"grunt-string-replace": "1.3.1",
|
"grunt-string-replace": "1.3.1",
|
||||||
"grunt-ts": "6.0.0-beta.22",
|
"grunt-ts": "6.0.0-beta.22",
|
||||||
"ts-node": "8.10.2",
|
"ts-node": "9.0.0",
|
||||||
"tslint": "6.1.1",
|
"tslint": "6.1.3",
|
||||||
"typedoc": "0.17.7",
|
"typedoc": "0.19.2",
|
||||||
"typescript": "3.8.3"
|
"typescript": "3.8.3"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|
@ -33,5 +33,5 @@
|
||||||
"docs": "./generate-docs.sh"
|
"docs": "./generate-docs.sh"
|
||||||
},
|
},
|
||||||
"typings": "lib/index.d.ts",
|
"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 { Publisher } from './Publisher';
|
||||||
|
import { ConnectionProperties } from './ConnectionProperties';
|
||||||
|
import { OpenViduRole } from './OpenViduRole';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See [[Session.activeConnections]]
|
* See [[Session.connections]]
|
||||||
*/
|
*/
|
||||||
export class Connection {
|
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;
|
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;
|
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;
|
activeAt: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Token associated to the connection
|
|
||||||
*/
|
|
||||||
token: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <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>
|
||||||
* 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;
|
location: string;
|
||||||
|
|
||||||
|
|
@ -55,16 +65,22 @@ export class Connection {
|
||||||
platform: string;
|
platform: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]]
|
* Data associated to the Connection on the client-side. This value is set with second parameter of method
|
||||||
*/
|
|
||||||
serverData: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* [Session.connect](/en/stable/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser
|
||||||
*/
|
*/
|
||||||
clientData: string;
|
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
|
* 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
|
* 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[] = [];
|
subscribers: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden deprecated. Inside ConnectionProperties
|
||||||
|
*/
|
||||||
|
role?: OpenViduRole;
|
||||||
|
/**
|
||||||
|
* @hidden deprecated. Inside ConnectionProperties
|
||||||
|
*/
|
||||||
|
serverData?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
constructor(connectionId: string, createdAt: number, role: OpenViduRole, token: string, location: string, platform: string, serverData: string, clientData: string,
|
constructor(json) {
|
||||||
publishers: Publisher[], subscribers: string[]) {
|
this.resetWithJson(json);
|
||||||
this.connectionId = connectionId;
|
}
|
||||||
this.createdAt = createdAt;
|
|
||||||
this.role = role;
|
/**
|
||||||
this.token = token;
|
* @hidden
|
||||||
this.location = location;
|
*/
|
||||||
this.platform = platform;
|
resetWithJson(json): Connection {
|
||||||
this.serverData = serverData;
|
|
||||||
this.clientData = clientData;
|
this.connectionId = json.connectionId;
|
||||||
this.publishers = publishers;
|
this.status = json.status;
|
||||||
this.subscribers = subscribers;
|
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 {
|
equalTo(other: Connection): boolean {
|
||||||
let equals: boolean = (
|
let equals: boolean = (
|
||||||
this.connectionId === other.connectionId &&
|
this.connectionId === other.connectionId &&
|
||||||
|
this.status === other.status &&
|
||||||
this.createdAt === other.createdAt &&
|
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.token === other.token &&
|
||||||
this.location === other.location &&
|
this.location === other.location &&
|
||||||
this.platform === other.platform &&
|
this.platform === other.platform &&
|
||||||
this.serverData === other.serverData &&
|
|
||||||
this.clientData === other.clientData &&
|
this.clientData === other.clientData &&
|
||||||
this.subscribers.length === other.subscribers.length &&
|
this.subscribers.length === other.subscribers.length &&
|
||||||
this.publishers.length === other.publishers.length);
|
this.publishers.length === other.publishers.length);
|
||||||
if (equals) {
|
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) {
|
if (equals) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (equals && i < this.publishers.length) {
|
while (equals && i < this.publishers.length) {
|
||||||
|
|
@ -125,4 +247,18 @@ export class Connection {
|
||||||
return false;
|
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 axios from 'axios';
|
||||||
import { Connection } from './Connection';
|
import { Connection } from './Connection';
|
||||||
import { Publisher } from './Publisher';
|
|
||||||
import { Recording } from './Recording';
|
import { Recording } from './Recording';
|
||||||
import { RecordingProperties } from './RecordingProperties';
|
import { RecordingProperties } from './RecordingProperties';
|
||||||
import { Session } from './Session';
|
import { Session } from './Session';
|
||||||
import { SessionProperties } from './SessionProperties';
|
import { SessionProperties } from './SessionProperties';
|
||||||
import { RecordingLayout } from './RecordingLayout';
|
import { RecordingLayout } from './RecordingLayout';
|
||||||
import { RecordingMode } from 'RecordingMode';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
|
@ -47,29 +45,36 @@ export class OpenVidu {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
static readonly API_RECORDINGS: string = '/api/recordings';
|
static readonly API_PATH: string = '/openvidu/api';
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
static readonly API_RECORDINGS_START: string = '/start';
|
static readonly API_SESSIONS = OpenVidu.API_PATH + '/sessions';
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
static readonly API_RECORDINGS_STOP: string = '/stop';
|
static readonly API_TOKENS = OpenVidu.API_PATH + '/tokens';
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
static readonly API_SESSIONS = '/api/sessions';
|
static readonly API_RECORDINGS: string = OpenVidu.API_PATH + '/recordings';
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @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]]
|
* Array of active sessions. **This value will remain unchanged since the last time method [[OpenVidu.fetch]]
|
||||||
* was called**. Exceptions to this rule are:
|
* 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.fetch]] updates that specific Session status
|
||||||
* - Calling [[Session.close]] automatically removes the Session from the list of active Sessions
|
* - 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
|
* - Calling [[Session.forceDisconnect]] automatically updates the inner affected connections for that specific Session
|
||||||
|
|
@ -83,16 +88,18 @@ export class OpenVidu {
|
||||||
activeSessions: Session[] = [];
|
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
|
* @param secret Secret used on OpenVidu Server initialization
|
||||||
*/
|
*/
|
||||||
constructor(private urlOpenViduServer: string, secret: string) {
|
constructor(private hostname: string, secret: string) {
|
||||||
this.setHostnameAndPort();
|
this.setHostnameAndPort();
|
||||||
this.basicAuth = this.getBasicAuth(secret);
|
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.
|
* @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 = {
|
data = {
|
||||||
session: sessionId,
|
session: sessionId,
|
||||||
name: !!properties.name ? properties.name : '',
|
name: !!properties.name ? properties.name : '',
|
||||||
outputMode: !!properties.outputMode ? properties.outputMode : Recording.OutputMode.COMPOSED,
|
outputMode: properties.outputMode,
|
||||||
hasAudio: !!(properties.hasAudio),
|
hasAudio: properties.hasAudio != null ? properties.hasAudio : null,
|
||||||
hasVideo: !!(properties.hasVideo)
|
hasVideo: properties.hasVideo != null ? properties.hasVideo : null,
|
||||||
|
shmSize: properties.shmSize,
|
||||||
|
mediaNode: properties.mediaNode
|
||||||
};
|
};
|
||||||
if (data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]
|
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.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START])) {
|
||||||
data.resolution = !!properties.resolution ? properties.resolution : '1920x1080';
|
data.resolution = properties.resolution;
|
||||||
data.recordingLayout = !!properties.recordingLayout ? properties.recordingLayout : RecordingLayout.BEST_FIT;
|
data.recordingLayout = !!properties.recordingLayout ? properties.recordingLayout : '';
|
||||||
if (data.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
|
if (data.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
|
||||||
data.customLayout = !!properties.customLayout ? properties.customLayout : '';
|
data.customLayout = !!properties.customLayout ? properties.customLayout : '';
|
||||||
}
|
}
|
||||||
|
|
@ -156,20 +165,18 @@ export class OpenVidu {
|
||||||
} else {
|
} else {
|
||||||
data = JSON.stringify({
|
data = JSON.stringify({
|
||||||
session: sessionId,
|
session: sessionId,
|
||||||
name: param2,
|
name: param2
|
||||||
outputMode: Recording.OutputMode.COMPOSED
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data = JSON.stringify({
|
data = JSON.stringify({
|
||||||
session: sessionId,
|
session: sessionId,
|
||||||
name: '',
|
name: ''
|
||||||
outputMode: Recording.OutputMode.COMPOSED
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
axios.post(
|
axios.post(
|
||||||
this.host + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_START,
|
this.host + OpenVidu.API_RECORDINGS_START,
|
||||||
data,
|
data,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -223,7 +230,7 @@ export class OpenVidu {
|
||||||
return new Promise<Recording>((resolve, reject) => {
|
return new Promise<Recording>((resolve, reject) => {
|
||||||
|
|
||||||
axios.post(
|
axios.post(
|
||||||
this.host + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId,
|
this.host + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId,
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -412,7 +419,7 @@ export class OpenVidu {
|
||||||
public fetch(): Promise<boolean> {
|
public fetch(): Promise<boolean> {
|
||||||
return new Promise<boolean>((resolve, reject) => {
|
return new Promise<boolean>((resolve, reject) => {
|
||||||
axios.get(
|
axios.get(
|
||||||
this.host + OpenVidu.API_SESSIONS,
|
this.host + OpenVidu.API_SESSIONS + '?pendingConnections=true',
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: this.basicAuth
|
Authorization: this.basicAuth
|
||||||
|
|
@ -422,47 +429,44 @@ export class OpenVidu {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status === 200) {
|
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
|
// Boolean to store if any Session has changed
|
||||||
let hasChanged = false;
|
let hasChanged = false;
|
||||||
|
|
||||||
res.data.content.forEach(session => {
|
// 1. Array to store fetched sessionIds and later remove closed ones
|
||||||
fetchedSessionIds.push(session.sessionId);
|
const fetchedSessionIds: string[] = [];
|
||||||
let sessionIndex = -1;
|
res.data.content.forEach(jsonSession => {
|
||||||
let storedSession = this.activeSessions.find((s, index) => {
|
|
||||||
if (s.sessionId === session.sessionId) {
|
const fetchedSession: Session = new Session(this, jsonSession);
|
||||||
sessionIndex = index;
|
fetchedSessionIds.push(fetchedSession.sessionId);
|
||||||
return true;
|
let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId);
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!!storedSession) {
|
if (!!storedSession) {
|
||||||
const fetchedSession: Session = new Session(this).resetSessionWithJson(session);
|
|
||||||
|
// 2. Update existing Session
|
||||||
const changed: boolean = !storedSession.equalTo(fetchedSession);
|
const changed: boolean = !storedSession.equalTo(fetchedSession);
|
||||||
if (changed) {
|
storedSession.resetWithJson(jsonSession);
|
||||||
storedSession = fetchedSession;
|
|
||||||
this.activeSessions[sessionIndex] = storedSession;
|
|
||||||
}
|
|
||||||
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
||||||
hasChanged = hasChanged || changed;
|
hasChanged = hasChanged || changed;
|
||||||
|
|
||||||
} else {
|
} 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;
|
hasChanged = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Remove closed sessions from activeSessions array
|
|
||||||
this.activeSessions = this.activeSessions.filter(session => {
|
// 4. Remove closed sessions from local collection
|
||||||
if (fetchedSessionIds.includes(session.sessionId)) {
|
for (var i = this.activeSessions.length - 1; i >= 0; --i) {
|
||||||
return true;
|
let sessionId = this.activeSessions[i].sessionId;
|
||||||
} else {
|
if (!fetchedSessionIds.includes(sessionId)) {
|
||||||
console.log("Removing closed session '" + session.sessionId + "'");
|
console.log("Removing closed session '" + sessionId + "'");
|
||||||
hasChanged = true;
|
hasChanged = true;
|
||||||
return false;
|
this.activeSessions.splice(i, 1);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
||||||
resolve(hasChanged);
|
resolve(hasChanged);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -498,26 +502,9 @@ export class OpenVidu {
|
||||||
const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => {
|
const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => {
|
||||||
const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId);
|
const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId);
|
||||||
if (!!connectionExtended) {
|
if (!!connectionExtended) {
|
||||||
const publisherArray = [];
|
|
||||||
connection.publishers.forEach(pub => {
|
connection.publishers.forEach(pub => {
|
||||||
const publisherExtended = connectionExtended.publishers.find(p => p.streamId === pub.streamId);
|
const publisherExtended = connectionExtended.publishers.find(p => p.streamId === pub.streamId);
|
||||||
const pubAux = {};
|
pub['webRtc'] = {
|
||||||
// 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'] = {
|
|
||||||
kms: {
|
kms: {
|
||||||
events: publisherExtended.events,
|
events: publisherExtended.events,
|
||||||
localCandidate: publisherExtended.localCandidate,
|
localCandidate: publisherExtended.localCandidate,
|
||||||
|
|
@ -529,11 +516,10 @@ export class OpenVidu {
|
||||||
remoteSdp: publisherExtended.remoteSdp
|
remoteSdp: publisherExtended.remoteSdp
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
newPublisher['localCandidatePair'] = parseRemoteCandidatePair(newPublisher['webRtc'].kms.remoteCandidate);
|
pub['localCandidatePair'] = parseRemoteCandidatePair(pub['webRtc'].kms.remoteCandidate);
|
||||||
if (!!publisherExtended.serverStats) {
|
if (!!publisherExtended.serverStats) {
|
||||||
newPublisher['webRtc'].kms.serverStats = publisherExtended.serverStats;
|
pub['webRtc'].kms.serverStats = publisherExtended.serverStats;
|
||||||
}
|
}
|
||||||
publisherArray.push(newPublisher);
|
|
||||||
});
|
});
|
||||||
const subscriberArray = [];
|
const subscriberArray = [];
|
||||||
connection.subscribers.forEach(sub => {
|
connection.subscribers.forEach(sub => {
|
||||||
|
|
@ -562,7 +548,6 @@ export class OpenVidu {
|
||||||
}
|
}
|
||||||
subscriberArray.push(subAux);
|
subscriberArray.push(subAux);
|
||||||
});
|
});
|
||||||
connection.publishers = publisherArray;
|
|
||||||
connection.subscribers = subscriberArray;
|
connection.subscribers = subscriberArray;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -594,68 +579,64 @@ export class OpenVidu {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
|
||||||
// Array to store fetched sessionIds and later remove closed sessions
|
|
||||||
const fetchedSessionIds: string[] = [];
|
|
||||||
// Global changes
|
// Global changes
|
||||||
let globalChanges = false;
|
let globalChanges = false;
|
||||||
// Collection of sessionIds telling whether each one of them has changed or not
|
// Collection of sessionIds telling whether each one of them has changed or not
|
||||||
const sessionChanges: ObjMap<boolean> = {};
|
const sessionChanges: ObjMap<boolean> = {};
|
||||||
|
|
||||||
res.data.content.forEach(session => {
|
// 1. Array to store fetched sessionIds and later remove closed ones
|
||||||
fetchedSessionIds.push(session.sessionId);
|
const fetchedSessionIds: string[] = [];
|
||||||
let sessionIndex = -1;
|
res.data.content.forEach(jsonSession => {
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
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);
|
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)
|
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++) {
|
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.resetWithJson(jsonSession);
|
||||||
storedSession = fetchedSession;
|
storedSession.connections.forEach(connection => {
|
||||||
this.activeSessions[sessionIndex] = storedSession;
|
addWebRtcStatsToConnections(connection, jsonSession.connections.content);
|
||||||
}
|
});
|
||||||
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
||||||
sessionChanges[storedSession.sessionId] = changed;
|
sessionChanges[storedSession.sessionId] = changed;
|
||||||
globalChanges = globalChanges || changed;
|
globalChanges = globalChanges || changed;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const newSession = new Session(this, session);
|
|
||||||
newSession.activeConnections.forEach(connection => {
|
// 3. Add new Session
|
||||||
addWebRtcStatsToConnections(connection, session.connections.content);
|
this.activeSessions.push(fetchedSession);
|
||||||
});
|
console.log("New session '" + fetchedSession.sessionId + "' info fetched");
|
||||||
this.activeSessions.push(newSession);
|
sessionChanges[fetchedSession.sessionId] = true;
|
||||||
console.log("New session '" + session.sessionId + "' info fetched");
|
|
||||||
sessionChanges[session.sessionId] = true;
|
|
||||||
globalChanges = true;
|
globalChanges = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Remove closed sessions from activeSessions array
|
|
||||||
this.activeSessions = this.activeSessions.filter(session => {
|
// 4. Remove closed sessions from local collection
|
||||||
if (fetchedSessionIds.includes(session.sessionId)) {
|
for (var i = this.activeSessions.length - 1; i >= 0; --i) {
|
||||||
return true;
|
let sessionId = this.activeSessions[i].sessionId;
|
||||||
} else {
|
if (!fetchedSessionIds.includes(sessionId)) {
|
||||||
console.log("Removing closed session '" + session.sessionId + "'");
|
console.log("Removing closed session '" + sessionId + "'");
|
||||||
sessionChanges[session.sessionId] = true;
|
sessionChanges[sessionId] = true;
|
||||||
globalChanges = true;
|
globalChanges = true;
|
||||||
return false;
|
this.activeSessions.splice(i, 1);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
||||||
resolve({ changes: globalChanges, sessionChanges });
|
resolve({ changes: globalChanges, sessionChanges });
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -687,7 +668,7 @@ export class OpenVidu {
|
||||||
private setHostnameAndPort(): void {
|
private setHostnameAndPort(): void {
|
||||||
let url: URL;
|
let url: URL;
|
||||||
try {
|
try {
|
||||||
url = new URL(this.urlOpenViduServer);
|
url = new URL(this.hostname);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('URL format incorrect', error);
|
console.error('URL format incorrect', error);
|
||||||
throw new Error('URL format incorrect: ' + error);
|
throw new Error('URL format incorrect: ' + error);
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,13 @@ export class Publisher {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
constructor(json) {
|
constructor(json) {
|
||||||
|
this.resetWithJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
resetWithJson(json): Publisher {
|
||||||
this.streamId = json.streamId;
|
this.streamId = json.streamId;
|
||||||
this.createdAt = json.createdAt;
|
this.createdAt = json.createdAt;
|
||||||
this.hasAudio = json.mediaOptions.hasAudio;
|
this.hasAudio = json.mediaOptions.hasAudio;
|
||||||
|
|
@ -83,6 +90,7 @@ export class Publisher {
|
||||||
this.frameRate = json.mediaOptions.frameRate;
|
this.frameRate = json.mediaOptions.frameRate;
|
||||||
this.typeOfVideo = json.mediaOptions.typeOfVideo;
|
this.typeOfVideo = json.mediaOptions.typeOfVideo;
|
||||||
this.videoDimensions = json.mediaOptions.videoDimensions;
|
this.videoDimensions = json.mediaOptions.videoDimensions;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ export class Recording {
|
||||||
hasVideo: !!json['hasVideo']
|
hasVideo: !!json['hasVideo']
|
||||||
};
|
};
|
||||||
if (this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]
|
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.resolution = !!(json['resolution']) ? json['resolution'] : '1920x1080';
|
||||||
this.properties.recordingLayout = !!(json['recordingLayout']) ? json['recordingLayout'] : RecordingLayout.BEST_FIT;
|
this.properties.recordingLayout = !!(json['recordingLayout']) ? json['recordingLayout'] : RecordingLayout.BEST_FIT;
|
||||||
if (this.properties.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
|
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
|
* 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',
|
starting = 'starting',
|
||||||
|
|
||||||
|
|
@ -113,21 +113,20 @@ export namespace Recording {
|
||||||
started = 'started',
|
started = 'started',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recording has stopped and is being processed. At some point it will reach
|
* The recording has stopped and is being processed. At some point it will reach
|
||||||
* "ready" status
|
* "ready" status
|
||||||
*/
|
*/
|
||||||
stopped = 'stopped',
|
stopped = 'stopped',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recording has finished OK and is available for download through OpenVidu
|
* The recording has finished being processed and is available for download through
|
||||||
* Server recordings endpoint:
|
* property [[Recording.url]]
|
||||||
* https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION}
|
|
||||||
*/
|
*/
|
||||||
ready = 'ready',
|
ready = 'ready',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recording has failed. This status may be reached from "starting",
|
* The recording has failed. This status may be reached from "starting",
|
||||||
* "started" and "stopped" status
|
* "started" and "stopped" status
|
||||||
*/
|
*/
|
||||||
failed = 'failed'
|
failed = 'failed'
|
||||||
}
|
}
|
||||||
|
|
@ -141,24 +140,24 @@ export namespace Recording {
|
||||||
* Record all streams in a grid layout in a single archive
|
* Record all streams in a grid layout in a single archive
|
||||||
*/
|
*/
|
||||||
COMPOSED = 'COMPOSED',
|
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.
|
* Works the same way as COMPOSED mode, but the necessary recorder
|
||||||
* The recording module will be continuously rendering all of the streams being
|
* service module will start some time in advance and won't be terminated
|
||||||
* published to the session even when the session is not being recorded. And that
|
* once a specific session recording has ended. This module will remain
|
||||||
* is for every session configured with COMPOSED_QUICK_START.
|
* 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',
|
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]]
|
* Whether or not to record video. Cannot be set to false at the same time as [[RecordingProperties.hasAudio]]
|
||||||
*/
|
*/
|
||||||
hasVideo?: boolean;
|
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 { Connection } from './Connection';
|
||||||
|
import { ConnectionProperties } from './ConnectionProperties';
|
||||||
import { MediaMode } from './MediaMode';
|
import { MediaMode } from './MediaMode';
|
||||||
import { OpenVidu } from './OpenVidu';
|
import { OpenVidu } from './OpenVidu';
|
||||||
import { OpenViduRole } from './OpenViduRole';
|
|
||||||
import { Publisher } from './Publisher';
|
import { Publisher } from './Publisher';
|
||||||
import { Recording } from './Recording';
|
import { Recording } from './Recording';
|
||||||
import { RecordingLayout } from './RecordingLayout';
|
import { RecordingLayout } from './RecordingLayout';
|
||||||
|
|
@ -28,7 +28,6 @@ import { SessionProperties } from './SessionProperties';
|
||||||
import { TokenOptions } from './TokenOptions';
|
import { TokenOptions } from './TokenOptions';
|
||||||
import { VideoCodec } from './VideoCodec';
|
import { VideoCodec } from './VideoCodec';
|
||||||
|
|
||||||
|
|
||||||
export class Session {
|
export class Session {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -47,14 +46,26 @@ export class Session {
|
||||||
properties: SessionProperties;
|
properties: SessionProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of active connections to the session. This property always initialize as an empty array and
|
* 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]] was called**. Exceptions to this rule are:
|
* **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.createConnection]] automatically adds the new Connection object to the local collection.
|
||||||
* - Calling [[Session.forceDisconnect]] automatically updates each affected Connection status
|
* - 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
|
* To get the array of Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]]
|
||||||
* property [[activeConnections]]
|
* 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[] = [];
|
activeConnections: Connection[] = [];
|
||||||
|
|
||||||
|
|
@ -71,7 +82,7 @@ export class Session {
|
||||||
// Defined parameter
|
// Defined parameter
|
||||||
if (!!propertiesOrJson.sessionId) {
|
if (!!propertiesOrJson.sessionId) {
|
||||||
// Parameter is a JSON representation of Session ('sessionId' property always defined)
|
// Parameter is a JSON representation of Session ('sessionId' property always defined)
|
||||||
this.resetSessionWithJson(propertiesOrJson);
|
this.resetWithJson(propertiesOrJson);
|
||||||
} else {
|
} else {
|
||||||
// Parameter is a SessionProperties object
|
// Parameter is a SessionProperties object
|
||||||
this.properties = propertiesOrJson;
|
this.properties = propertiesOrJson;
|
||||||
|
|
@ -84,32 +95,23 @@ export class Session {
|
||||||
this.properties.recordingMode = !!this.properties.recordingMode ? this.properties.recordingMode : RecordingMode.MANUAL;
|
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.defaultOutputMode = !!this.properties.defaultOutputMode ? this.properties.defaultOutputMode : Recording.OutputMode.COMPOSED;
|
||||||
this.properties.defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
|
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 : undefined;
|
||||||
this.properties.forcedVideoCodec = !!this.properties.forcedVideoCodec ? this.properties.forcedVideoCodec : null;
|
this.properties.allowTranscoding = this.properties.allowTranscoding != null ? this.properties.allowTranscoding : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the unique identifier of the Session
|
* @deprecated Use [[Session.createConnection]] instead to get a [[Connection]] object.
|
||||||
*/
|
|
||||||
public getSessionId(): string {
|
|
||||||
return this.sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a new token associated to Session 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> {
|
public generateToken(tokenOptions?: TokenOptions): Promise<string> {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
|
||||||
const data = JSON.stringify({
|
const data = JSON.stringify({
|
||||||
session: this.sessionId,
|
session: this.sessionId,
|
||||||
role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : OpenViduRole.PUBLISHER,
|
role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : null,
|
||||||
data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : '',
|
data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : null,
|
||||||
kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : {},
|
kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : null
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.post(
|
axios.post(
|
||||||
this.ov.host + OpenVidu.API_TOKENS,
|
this.ov.host + OpenVidu.API_TOKENS,
|
||||||
data,
|
data,
|
||||||
|
|
@ -123,26 +125,57 @@ export class Session {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
// SUCCESS response from openvidu-server. Resolve token
|
// SUCCESS response from openvidu-server. Resolve token
|
||||||
resolve(res.data.id);
|
resolve(res.data.token);
|
||||||
} else {
|
} else {
|
||||||
// ERROR response from openvidu-server. Resolve HTTP status
|
// ERROR response from openvidu-server. Resolve HTTP status
|
||||||
reject(new Error(res.status.toString()));
|
reject(new Error(res.status.toString()));
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.response) {
|
this.handleError(error, reject);
|
||||||
// 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
|
* Creates a new Connection object associated to Session object and configured with
|
||||||
console.error(error.request);
|
* `connectionProperties`. Each user connecting to the Session requires a Connection.
|
||||||
reject(new Error(error.request));
|
* The token string value to send to the client side is available at [[Connection.token]].
|
||||||
} else {
|
*
|
||||||
// Something happened in setting up the request that triggered an Error
|
* @returns A Promise that is resolved to the generated [[Connection]] object if success and rejected with an Error object if not
|
||||||
console.error('Error', error.message);
|
*/
|
||||||
reject(new Error(error.message));
|
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()));
|
reject(new Error(res.status.toString()));
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.response) {
|
this.handleError(error, reject);
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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.activeConnections]]) and use those values to call [[Session.forceDisconnect]] or [[Session.forceUnpublish]].
|
* 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.
|
* @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
|
* 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) => {
|
return new Promise<boolean>((resolve, reject) => {
|
||||||
const beforeJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
|
const beforeJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
|
||||||
axios.get(
|
axios.get(
|
||||||
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId,
|
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '?pendingConnections=true',
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': this.ov.basicAuth,
|
'Authorization': this.ov.basicAuth,
|
||||||
|
|
@ -216,7 +237,7 @@ export class Session {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
// SUCCESS response from openvidu-server
|
// SUCCESS response from openvidu-server
|
||||||
this.resetSessionWithJson(res.data);
|
this.resetWithJson(res.data);
|
||||||
const afterJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
|
const afterJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
|
||||||
const hasChanged: boolean = !(beforeJSON === afterJSON);
|
const hasChanged: boolean = !(beforeJSON === afterJSON);
|
||||||
console.log("Session info fetched for session '" + this.sessionId + "'. Any change: " + hasChanged);
|
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()));
|
reject(new Error(res.status.toString()));
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.response) {
|
this.handleError(error, reject);
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces the user with Connection `connectionId` to leave the session. OpenVidu Browser will trigger the proper events on the client-side
|
* Removes the Connection from the Session. This can translate into a forced eviction of a user from the Session if the
|
||||||
* (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`
|
* 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).
|
* In the first case, OpenVidu Browser will trigger the proper events in the client-side (`streamDestroyed`, `connectionDestroyed`,
|
||||||
* Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server
|
* `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> {
|
public forceDisconnect(connection: string | Connection): Promise<any> {
|
||||||
return new Promise<any>((resolve, reject) => {
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
|
@ -267,9 +282,9 @@ export class Session {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status === 204) {
|
if (res.status === 204) {
|
||||||
// SUCCESS response from openvidu-server
|
// SUCCESS response from openvidu-server
|
||||||
// Remove connection from activeConnections array
|
// Remove connection from connections array
|
||||||
let connectionClosed;
|
let connectionClosed;
|
||||||
this.activeConnections = this.activeConnections.filter(con => {
|
this.connections = this.connections.filter(con => {
|
||||||
if (con.connectionId !== connectionId) {
|
if (con.connectionId !== connectionId) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -280,7 +295,7 @@ export class Session {
|
||||||
// Remove every Publisher of the closed connection from every subscriber list of other connections
|
// Remove every Publisher of the closed connection from every subscriber list of other connections
|
||||||
if (!!connectionClosed) {
|
if (!!connectionClosed) {
|
||||||
connectionClosed.publishers.forEach(publisher => {
|
connectionClosed.publishers.forEach(publisher => {
|
||||||
this.activeConnections.forEach(con => {
|
this.connections.forEach(con => {
|
||||||
con.subscribers = con.subscribers.filter(subscriber => {
|
con.subscribers = con.subscribers.filter(subscriber => {
|
||||||
// tslint:disable:no-string-literal
|
// tslint:disable:no-string-literal
|
||||||
if (!!subscriber['streamId']) {
|
if (!!subscriber['streamId']) {
|
||||||
|
|
@ -295,8 +310,9 @@ export class Session {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} 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");
|
console.log("Connection '" + connectionId + "' closed");
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -305,30 +321,22 @@ export class Session {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (error.response) {
|
this.handleError(error, reject);
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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"`.
|
* 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).
|
* 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
|
* @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 => {
|
.then(res => {
|
||||||
if (res.status === 204) {
|
if (res.status === 204) {
|
||||||
// SUCCESS response from openvidu-server
|
// SUCCESS response from openvidu-server
|
||||||
this.activeConnections.forEach(connection => {
|
this.connections.forEach(connection => {
|
||||||
// Try to remove the Publisher from the Connection publishers collection
|
// Try to remove the Publisher from the Connection publishers collection
|
||||||
connection.publishers = connection.publishers.filter(pub => pub.streamId !== streamId);
|
connection.publishers = connection.publishers.filter(pub => pub.streamId !== streamId);
|
||||||
// Try to remove the Publisher from the Connection subscribers collection
|
// Try to remove the Publisher from the Connection subscribers collection
|
||||||
|
|
@ -363,6 +371,7 @@ export class Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.updateActiveConnectionsArray();
|
||||||
console.log("Stream '" + streamId + "' unpublished");
|
console.log("Stream '" + streamId + "' unpublished");
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -370,24 +379,79 @@ export class Session {
|
||||||
reject(new Error(res.status.toString()));
|
reject(new Error(res.status.toString()));
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.response) {
|
this.handleError(error, reject);
|
||||||
// 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 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
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
|
@ -399,18 +463,17 @@ export class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mediaMode = !!this.properties.mediaMode ? this.properties.mediaMode : MediaMode.ROUTED;
|
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 defaultOutputMode = !!this.properties.defaultOutputMode ? this.properties.defaultOutputMode : Recording.OutputMode.COMPOSED;
|
||||||
const defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
|
const defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
|
||||||
const defaultCustomLayout = !!this.properties.defaultCustomLayout ? this.properties.defaultCustomLayout : '';
|
const defaultCustomLayout = !!this.properties.defaultCustomLayout ? this.properties.defaultCustomLayout : '';
|
||||||
const customSessionId = !!this.properties.customSessionId ? this.properties.customSessionId : '';
|
const customSessionId = !!this.properties.customSessionId ? this.properties.customSessionId : '';
|
||||||
const forcedVideoCodec = !!this.properties.forcedVideoCodec ? this.properties.forcedVideoCodec : null;
|
const mediaNode = !!this.properties.mediaNode ? this.properties.mediaNode : undefined;
|
||||||
const allowTranscoding = !!this.properties.allowTranscoding ? this.properties.allowTranscoding : null;
|
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,
|
const data = JSON.stringify({mediaMode, recordingMode, defaultOutputMode, defaultRecordingLayout, defaultCustomLayout,
|
||||||
customSessionId, forcedVideoCodec, allowTranscoding
|
customSessionId, mediaNode, forcedVideoCodec, allowTranscoding});
|
||||||
});
|
|
||||||
|
|
||||||
axios.post(
|
axios.post(
|
||||||
this.ov.host + OpenVidu.API_SESSIONS,
|
this.ov.host + OpenVidu.API_SESSIONS,
|
||||||
|
|
@ -431,7 +494,9 @@ export class Session {
|
||||||
this.properties.recordingMode = recordingMode;
|
this.properties.recordingMode = recordingMode;
|
||||||
this.properties.defaultOutputMode = defaultOutputMode;
|
this.properties.defaultOutputMode = defaultOutputMode;
|
||||||
this.properties.defaultRecordingLayout = defaultRecordingLayout;
|
this.properties.defaultRecordingLayout = defaultRecordingLayout;
|
||||||
|
this.properties.defaultCustomLayout = defaultCustomLayout;
|
||||||
this.properties.customSessionId = customSessionId;
|
this.properties.customSessionId = customSessionId;
|
||||||
|
this.properties.mediaNode = mediaNode;
|
||||||
this.properties.forcedVideoCodec = res.data.forcedVideoCodec;
|
this.properties.forcedVideoCodec = res.data.forcedVideoCodec;
|
||||||
this.properties.allowTranscoding = res.data.allowTranscoding;
|
this.properties.allowTranscoding = res.data.allowTranscoding;
|
||||||
resolve(this.sessionId);
|
resolve(this.sessionId);
|
||||||
|
|
@ -467,58 +532,67 @@ export class Session {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
public resetSessionWithJson(json): Session {
|
public resetWithJson(json): Session {
|
||||||
this.sessionId = json.sessionId;
|
this.sessionId = json.sessionId;
|
||||||
this.createdAt = json.createdAt;
|
this.createdAt = json.createdAt;
|
||||||
this.recording = json.recording;
|
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 = {
|
this.properties = {
|
||||||
|
customSessionId: json.customSessionId,
|
||||||
mediaMode: json.mediaMode,
|
mediaMode: json.mediaMode,
|
||||||
recordingMode: json.recordingMode,
|
recordingMode: json.recordingMode,
|
||||||
defaultOutputMode: json.defaultOutputMode,
|
defaultOutputMode: json.defaultOutputMode,
|
||||||
defaultRecordingLayout: json.defaultRecordingLayout,
|
defaultRecordingLayout: json.defaultRecordingLayout,
|
||||||
forcedVideoCodec: !!json.forcedVideoCodec ? json.forcedVideoCodec : null,
|
defaultCustomLayout: json.defaultCustomLayout,
|
||||||
allowTranscoding: !!json.allowTranscoding ? json.allowTranscoding : null
|
forcedVideoCodec: json.forcedVideoCodec,
|
||||||
|
allowTranscoding: json.allowTranscoding
|
||||||
};
|
};
|
||||||
if (!!customSessionId) {
|
if (json.defaultRecordingLayout == null) {
|
||||||
this.properties.customSessionId = customSessionId;
|
delete this.properties.defaultRecordingLayout;
|
||||||
} else if (!!json.customSessionId) {
|
|
||||||
this.properties.customSessionId = json.customSessionId;
|
|
||||||
}
|
}
|
||||||
if (!!defaultCustomLayout) {
|
if (json.customSessionId == null) {
|
||||||
this.properties.defaultCustomLayout = defaultCustomLayout;
|
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 = [];
|
// 1. Array to store fetched connections and later remove closed ones
|
||||||
json.connections.content.forEach(connection => {
|
const fetchedConnectionIds: string[] = [];
|
||||||
const publishers: Publisher[] = [];
|
json.connections.content.forEach(jsonConnection => {
|
||||||
connection.publishers.forEach(publisher => {
|
|
||||||
publishers.push(new Publisher(publisher));
|
const connectionObj: Connection = new Connection(jsonConnection);
|
||||||
});
|
fetchedConnectionIds.push(connectionObj.connectionId);
|
||||||
const subscribers: string[] = [];
|
let storedConnection = this.connections.find(c => c.connectionId === connectionObj.connectionId);
|
||||||
connection.subscribers.forEach(subscriber => {
|
|
||||||
subscribers.push(subscriber.streamId);
|
if (!!storedConnection) {
|
||||||
});
|
// 2. Update existing Connection
|
||||||
this.activeConnections.push(
|
storedConnection.resetWithJson(jsonConnection);
|
||||||
new Connection(
|
} else {
|
||||||
connection.connectionId,
|
// 3. Add new Connection
|
||||||
connection.createdAt,
|
this.connections.push(connectionObj);
|
||||||
connection.role,
|
}
|
||||||
connection.token,
|
|
||||||
connection.location,
|
|
||||||
connection.platform,
|
|
||||||
connection.serverData,
|
|
||||||
connection.clientData,
|
|
||||||
publishers,
|
|
||||||
subscribers));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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
|
// 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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -530,13 +604,13 @@ export class Session {
|
||||||
this.sessionId === other.sessionId &&
|
this.sessionId === other.sessionId &&
|
||||||
this.createdAt === other.createdAt &&
|
this.createdAt === other.createdAt &&
|
||||||
this.recording === other.recording &&
|
this.recording === other.recording &&
|
||||||
this.activeConnections.length === other.activeConnections.length &&
|
this.connections.length === other.connections.length &&
|
||||||
JSON.stringify(this.properties) === JSON.stringify(other.properties)
|
JSON.stringify(this.properties) === JSON.stringify(other.properties)
|
||||||
);
|
);
|
||||||
if (equals) {
|
if (equals) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (equals && i < this.activeConnections.length) {
|
while (equals && i < this.connections.length) {
|
||||||
equals = this.activeConnections[i].equalTo(other.activeConnections[i]);
|
equals = this.connections[i].equalTo(other.connections[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return equals;
|
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.
|
* If this parameter is undefined or an empty string, OpenVidu Server will generate a random sessionId for you.
|
||||||
*/
|
*/
|
||||||
customSessionId?: string;
|
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.
|
* 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.
|
* 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.
|
* 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
|
* It defines if you want to allow transcoding in the media server or not
|
||||||
* when [[forcedVideoCodec]] is not compatible with the browser/client.
|
* when [[forcedVideoCodec]] is not compatible with the browser/client.
|
||||||
*/
|
*/
|
||||||
allowTranscoding?: boolean;
|
allowTranscoding?: boolean;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,17 @@
|
||||||
import { OpenViduRole } from './OpenViduRole';
|
import { OpenViduRole } from './OpenViduRole';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See [[Session.generateToken]]
|
* @deprecated Use [[ConnectionProperties]] instead
|
||||||
*/
|
*/
|
||||||
export interface TokenOptions {
|
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.
|
* 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.
|
* - 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;
|
data?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The role assigned to this token
|
|
||||||
*/
|
|
||||||
role?: OpenViduRole;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **WARNING**: experimental option. This interface may change in the near future
|
* **WARNING**: experimental option. This interface may change in the near future
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ export * from './OpenViduRole';
|
||||||
export * from './Session';
|
export * from './Session';
|
||||||
export * from './SessionProperties';
|
export * from './SessionProperties';
|
||||||
export * from './TokenOptions';
|
export * from './TokenOptions';
|
||||||
|
export * from './ConnectionProperties';
|
||||||
|
export * from './ConnectionType';
|
||||||
export * from './MediaMode';
|
export * from './MediaMode';
|
||||||
export * from './RecordingLayout';
|
export * from './RecordingLayout';
|
||||||
export * from './RecordingMode';
|
export * from './RecordingMode';
|
||||||
|
|
|
||||||
|
|
@ -44,18 +44,18 @@ Parameters:
|
||||||
# OpenVidu configuration
|
# OpenVidu configuration
|
||||||
|
|
||||||
OpenViduSecret:
|
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
|
Type: String
|
||||||
AllowedPattern: ^((?!")(?! ).)+$
|
AllowedPattern: ^[a-zA-Z0-9_-]+$
|
||||||
NoEcho: true
|
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
|
# EC2 Instance configuration
|
||||||
|
|
||||||
InstanceType:
|
InstanceType:
|
||||||
Description: "Specifies the EC2 instance type for your OpenVidu instance"
|
Description: "Specifies the EC2 instance type for your OpenVidu instance"
|
||||||
Type: String
|
Type: String
|
||||||
Default: t2.xlarge
|
Default: c5.xlarge
|
||||||
AllowedValues:
|
AllowedValues:
|
||||||
- t2.large
|
- t2.large
|
||||||
- t2.xlarge
|
- t2.xlarge
|
||||||
|
|
@ -115,10 +115,12 @@ Parameters:
|
||||||
- false
|
- false
|
||||||
Default: true
|
Default: true
|
||||||
|
|
||||||
|
#start_mappings
|
||||||
Mappings:
|
Mappings:
|
||||||
OVAMIMAP:
|
OVAMIMAP:
|
||||||
eu-west-1:
|
eu-west-1:
|
||||||
AMI: OV_AMI_ID
|
AMI: OV_AMI_ID
|
||||||
|
#end_mappings
|
||||||
|
|
||||||
Metadata:
|
Metadata:
|
||||||
'AWS::CloudFormation::Interface':
|
'AWS::CloudFormation::Interface':
|
||||||
|
|
@ -272,6 +274,10 @@ Resources:
|
||||||
|
|
||||||
# Restart all services
|
# Restart all services
|
||||||
pushd /opt/openvidu
|
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
|
docker-compose up -d
|
||||||
popd
|
popd
|
||||||
mode: "000755"
|
mode: "000755"
|
||||||
|
|
@ -293,6 +299,8 @@ Resources:
|
||||||
|
|
||||||
cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenviduServer
|
cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenviduServer
|
||||||
|
|
||||||
|
export HOME="/root"
|
||||||
|
|
||||||
# Replace .env variables
|
# Replace .env variables
|
||||||
/usr/local/bin/feedGroupVars.sh || { echo "[Openvidu] Parameters incorrect/insufficient"; exit 1; }
|
/usr/local/bin/feedGroupVars.sh || { echo "[Openvidu] Parameters incorrect/insufficient"; exit 1; }
|
||||||
|
|
||||||
|
|
@ -306,6 +314,10 @@ Resources:
|
||||||
|
|
||||||
# Start openvidu application
|
# Start openvidu application
|
||||||
pushd /opt/openvidu
|
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
|
docker-compose up -d
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
|
@ -327,10 +339,9 @@ Resources:
|
||||||
BlockDeviceMappings:
|
BlockDeviceMappings:
|
||||||
- DeviceName: /dev/sda1
|
- DeviceName: /dev/sda1
|
||||||
Ebs:
|
Ebs:
|
||||||
VolumeType: io1
|
VolumeType: gp2
|
||||||
Iops: 200
|
|
||||||
DeleteOnTermination: true
|
DeleteOnTermination: true
|
||||||
VolumeSize: 100
|
VolumeSize: 200
|
||||||
|
|
||||||
MyEIP:
|
MyEIP:
|
||||||
Type: 'AWS::EC2::EIPAssociation'
|
Type: 'AWS::EC2::EIPAssociation'
|
||||||
|
|
@ -373,11 +384,11 @@ Resources:
|
||||||
CidrIp: 0.0.0.0/0
|
CidrIp: 0.0.0.0/0
|
||||||
- IpProtocol: udp
|
- IpProtocol: udp
|
||||||
FromPort: 40000
|
FromPort: 40000
|
||||||
ToPort: 65535
|
ToPort: 57000
|
||||||
CidrIp: 0.0.0.0/0
|
CidrIp: 0.0.0.0/0
|
||||||
- IpProtocol: tcp
|
- IpProtocol: tcp
|
||||||
FromPort: 40000
|
FromPort: 40000
|
||||||
ToPort: 65535
|
ToPort: 57000
|
||||||
CidrIp: 0.0.0.0/0
|
CidrIp: 0.0.0.0/0
|
||||||
|
|
||||||
Outputs:
|
Outputs:
|
||||||
|
|
|
||||||
|
|
@ -141,5 +141,5 @@ Resources:
|
||||||
Type: AWS::CloudFormation::WaitCondition
|
Type: AWS::CloudFormation::WaitCondition
|
||||||
CreationPolicy:
|
CreationPolicy:
|
||||||
ResourceSignal:
|
ResourceSignal:
|
||||||
Timeout: PT10M
|
Timeout: PT20M
|
||||||
Count: 1
|
Count: 1
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -eu -o pipefail
|
set -eu -o pipefail
|
||||||
|
|
||||||
CF_OVP_TARGET=${CF_OVP_TARGET:-nomarket}
|
|
||||||
CF_RELEASE=${CF_RELEASE:-false}
|
CF_RELEASE=${CF_RELEASE:-false}
|
||||||
|
AWS_KEY_NAME=${AWS_KEY_NAME:-}
|
||||||
|
|
||||||
if [[ $CF_RELEASE == "true" ]]; then
|
if [[ $CF_RELEASE == "true" ]]; then
|
||||||
git checkout v$OPENVIDU_VERSION
|
git checkout v$OPENVIDU_VERSION
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
export AWS_DEFAULT_REGION=eu-west-1
|
||||||
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
|
|
||||||
|
|
||||||
DATESTAMP=$(date +%s)
|
DATESTAMP=$(date +%s)
|
||||||
TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
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
|
# Get Latest Ubuntu AMI id from specified region
|
||||||
# Parameters
|
# Parameters
|
||||||
# $1 Aws region
|
# $1 Aws region
|
||||||
|
|
||||||
getUbuntuAmiId() {
|
getUbuntuAmiId() {
|
||||||
local AMI_ID=$(
|
local AMI_ID=$(
|
||||||
aws --region ${1} ec2 describe-images \
|
aws --region ${1} ec2 describe-images \
|
||||||
--filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64* \
|
--filters "Name=name,Values=*ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*" \
|
||||||
--query 'Images[*].[ImageId,CreationDate]' \
|
--query "sort_by(Images, &CreationDate)" \
|
||||||
--output text \
|
| jq -r 'del(.[] | select(.ImageOwnerAlias != null)) | .[-1].ImageId'
|
||||||
| sort -k2 -r | head -n1 | cut -d$'\t' -f1
|
|
||||||
)
|
)
|
||||||
echo $AMI_ID
|
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
|
# Update installation script
|
||||||
if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then
|
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
|
aws s3 cp ../docker-compose/install_openvidu.sh s3://aws.openvidu.io/install_openvidu_$OPENVIDU_VERSION.sh --acl public-read
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -85,11 +90,34 @@ echo "Cleaning up"
|
||||||
aws cloudformation delete-stack --stack-name openvidu-ce-${DATESTAMP}
|
aws cloudformation delete-stack --stack-name openvidu-ce-${DATESTAMP}
|
||||||
|
|
||||||
# Wait for the instance
|
# 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
|
# Updating the template
|
||||||
sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" CF-OpenVidu.yaml.template > CF-OpenVidu-${OPENVIDU_VERSION}.yaml
|
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
|
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 $TEMPJSON
|
||||||
rm cfn-mkt-ov-ce-ami.yaml
|
rm cfn-mkt-ov-ce-ami.yaml
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,12 @@ set -eu -o pipefail
|
||||||
#
|
#
|
||||||
# Input parameters:
|
# Input parameters:
|
||||||
#
|
#
|
||||||
# OV_AMI_NAME OpenVidu AMI Name
|
# OV_AMI_NAME OpenVidu AMI Name
|
||||||
# OV_AMI_ID OpenVidu AMI ID
|
# 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
|
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"
|
echo "Making original AMI public"
|
||||||
aws ec2 wait image-exists --image-ids ${OV_AMI_ID}
|
aws ec2 wait image-exists --image-ids ${OV_AMI_ID}
|
||||||
|
|
@ -71,13 +69,54 @@ do
|
||||||
ITER=$(expr $ITER + 1)
|
ITER=$(expr $ITER + 1)
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Print and generate replicated AMIS
|
||||||
|
REPLICATED_AMIS_FILE="replicated_amis.yaml"
|
||||||
echo "OV IDs"
|
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
|
ITER=0
|
||||||
for i in "${AMI_IDS[@]}"
|
for i in "${AMI_IDS[@]}"
|
||||||
do
|
do
|
||||||
AMI_ID=${AMI_IDS[$ITER]}
|
AMI_ID=${AMI_IDS[$ITER]}
|
||||||
REGION=${REGIONS[$ITER]}
|
REGION=${REGIONS[$ITER]}
|
||||||
echo " ${REGION}:"
|
if [[ ${ITER} -eq 0 ]]; then
|
||||||
echo " AMI: ${AMI_ID}"
|
AMI_LIST="${REGION}:${AMI_ID}"
|
||||||
|
else
|
||||||
|
AMI_LIST="${AMI_LIST},${REGION}:${AMI_ID}"
|
||||||
|
fi
|
||||||
ITER=$(expr $ITER + 1)
|
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
|
# SDKs, REST clients and browsers will have to connect to this port
|
||||||
# HTTPS_PORT=443
|
# 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
|
# Access restrictions
|
||||||
# In this section you will be able to restrict the IPs from which you can access to
|
# In this section you will be able to restrict the IPs from which you can access to
|
||||||
# Openvidu API and the Administration Panel
|
# Openvidu API and the Administration Panel
|
||||||
|
|
@ -110,6 +126,15 @@ OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH=1000
|
||||||
# 0 means unconstrained
|
# 0 means unconstrained
|
||||||
OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH=300
|
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
|
# true to enable OpenVidu Webhook service. false' otherwise
|
||||||
# Values: true | false
|
# Values: true | false
|
||||||
OPENVIDU_WEBHOOK=false
|
OPENVIDU_WEBHOOK=false
|
||||||
|
|
@ -138,10 +163,10 @@ OPENVIDU_SESSIONS_GARBAGE_INTERVAL=900
|
||||||
OPENVIDU_SESSIONS_GARBAGE_THRESHOLD=3600
|
OPENVIDU_SESSIONS_GARBAGE_THRESHOLD=3600
|
||||||
|
|
||||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_ALLOW_TRANSCODING=true
|
# 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
|
# 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
|
# OPENVIDU_ALLOW_TRANSCODING=false
|
||||||
|
|
||||||
# Call Detail Record enabled
|
# Call Detail Record enabled
|
||||||
|
|
@ -154,16 +179,16 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
|
||||||
|
|
||||||
# Kurento Media Server image
|
# 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
|
# 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
|
# Kurento Media Server Level logs
|
||||||
# -------------------------------
|
# -------------------------------
|
||||||
# Uncomment the next line and define this variable to change
|
# Uncomment the next line and define this variable to change
|
||||||
# the verbosity level of the logs of KMS
|
# the verbosity level of the logs of KMS
|
||||||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
# 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
|
# Openvidu Server Level logs
|
||||||
# --------------------------
|
# --------------------------
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@ services:
|
||||||
#
|
#
|
||||||
# Default Application
|
# Default Application
|
||||||
#
|
#
|
||||||
# Openvidu-Call Version: 2.15.0
|
# Openvidu-Call Version: 2.16.0
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
app:
|
app:
|
||||||
image: openvidu/openvidu-call:2.15.0
|
image: openvidu/openvidu-call:2.16.0
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -21,3 +21,6 @@ services:
|
||||||
- OPENVIDU_URL=http://localhost:5443
|
- OPENVIDU_URL=http://localhost:5443
|
||||||
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||||
- CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE}
|
- 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
|
# Application based on OpenVidu should be specified in
|
||||||
# docker-compose.override.yml file
|
# 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
|
# This file will be overridden when update OpenVidu Platform
|
||||||
#
|
#
|
||||||
# Openvidu Version: 2.15.0
|
# Openvidu Version: 2.16.0
|
||||||
#
|
#
|
||||||
# Installation Mode: On Premises
|
# Installation Mode: On Premises
|
||||||
#
|
#
|
||||||
|
|
@ -22,10 +22,10 @@ version: '3.1'
|
||||||
services:
|
services:
|
||||||
|
|
||||||
openvidu-server:
|
openvidu-server:
|
||||||
image: openvidu/openvidu-server:2.15.0
|
image: openvidu/openvidu-server:2.17.0-dev2
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
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:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||||
|
|
@ -39,9 +39,13 @@ services:
|
||||||
- KMS_URIS=["ws://localhost:8888/kurento"]
|
- KMS_URIS=["ws://localhost:8888/kurento"]
|
||||||
- COTURN_REDIS_IP=127.0.0.1
|
- COTURN_REDIS_IP=127.0.0.1
|
||||||
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||||
|
- COTURN_IP=${COTURN_IP:-auto-ipv4}
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||||
|
|
||||||
kms:
|
kms:
|
||||||
image: ${KMS_IMAGE:-kurento/kurento-media-server:6.14.0}
|
image: ${KMS_IMAGE:-kurento/kurento-media-server:6.15.0}
|
||||||
restart: always
|
restart: always
|
||||||
network_mode: host
|
network_mode: host
|
||||||
ulimits:
|
ulimits:
|
||||||
|
|
@ -49,20 +53,29 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/openvidu/kms-crashes:/opt/openvidu/kms-crashes
|
- /opt/openvidu/kms-crashes:/opt/openvidu/kms-crashes
|
||||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||||
|
- /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs
|
||||||
environment:
|
environment:
|
||||||
- KMS_MIN_PORT=40000
|
- KMS_MIN_PORT=40000
|
||||||
- KMS_MAX_PORT=57000
|
- 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:
|
redis:
|
||||||
image: openvidu/openvidu-redis:1.0.0
|
image: openvidu/openvidu-redis:2.0.0-dev2
|
||||||
restart: always
|
restart: always
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||||
|
|
||||||
coturn:
|
coturn:
|
||||||
image: openvidu/openvidu-coturn:1.0.0
|
image: openvidu/openvidu-coturn:3.0.0-dev2
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -72,14 +85,19 @@ services:
|
||||||
- DB_PASSWORD=${OPENVIDU_SECRET}
|
- DB_PASSWORD=${OPENVIDU_SECRET}
|
||||||
- MIN_PORT=57001
|
- MIN_PORT=57001
|
||||||
- MAX_PORT=65535
|
- MAX_PORT=65535
|
||||||
|
- ENABLE_COTURN_LOGS=true
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
image: openvidu/openvidu-proxy:3.0.0
|
image: openvidu/openvidu-proxy:5.0.0-dev2
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
network_mode: host
|
||||||
volumes:
|
volumes:
|
||||||
- ./certificates:/etc/letsencrypt
|
- ./certificates:/etc/letsencrypt
|
||||||
- ./owncert:/owncert
|
- ./owncert:/owncert
|
||||||
|
- ./custom-nginx-vhosts:/etc/nginx/vhost.d/
|
||||||
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout
|
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout
|
||||||
environment:
|
environment:
|
||||||
- DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP}
|
- DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP}
|
||||||
|
|
@ -91,3 +109,10 @@ services:
|
||||||
- ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-}
|
- ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-}
|
||||||
- PROXY_MODE=CE
|
- PROXY_MODE=CE
|
||||||
- WITH_APP=true
|
- 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
|
# Global variables
|
||||||
OPENVIDU_FOLDER=openvidu
|
OPENVIDU_FOLDER=openvidu
|
||||||
OPENVIDU_VERSION=master
|
OPENVIDU_VERSION=master
|
||||||
|
OPENVIDU_UPGRADABLE_VERSION="2.16"
|
||||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${OPENVIDU_VERSION}
|
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${OPENVIDU_VERSION}
|
||||||
|
|
||||||
fatal_error() {
|
fatal_error() {
|
||||||
|
|
@ -42,10 +43,6 @@ new_ov_installation() {
|
||||||
--output "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
--output "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||||
printf '\n - 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
|
# Add execution permissions
|
||||||
printf "\n => Adding permission to 'openvidu' program..."
|
printf "\n => Adding permission to 'openvidu' program..."
|
||||||
chmod +x "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error while 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'..."
|
printf "\n => Creating folder 'owncert'..."
|
||||||
mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the 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
|
# Ready to use
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|
@ -105,10 +106,13 @@ upgrade_ov() {
|
||||||
|
|
||||||
# Uppgrade Openvidu
|
# Uppgrade Openvidu
|
||||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
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
|
# 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.
|
# 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 ======================================='
|
printf '\n ======================================='
|
||||||
|
|
@ -146,10 +150,6 @@ upgrade_ov() {
|
||||||
--output "${TMP_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
--output "${TMP_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||||
printf '\n - 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
|
# Dowloading new images and stoped actual Openvidu
|
||||||
printf '\n => Dowloading new images...'
|
printf '\n => Dowloading new images...'
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|
@ -187,12 +187,14 @@ upgrade_ov() {
|
||||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
mv "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||||
printf '\n - 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'"
|
cp "${OPENVIDU_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'"
|
||||||
printf '\n - .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
|
# Move tmp files to Openvidu
|
||||||
printf '\n => Updating files:'
|
printf '\n => Updating files:'
|
||||||
|
|
||||||
|
|
@ -213,9 +215,6 @@ upgrade_ov() {
|
||||||
mv "${TMP_FOLDER}/openvidu" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'openvidu'"
|
mv "${TMP_FOLDER}/openvidu" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'openvidu'"
|
||||||
printf '\n - 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"
|
printf "\n => Deleting 'tmp' folder"
|
||||||
rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder"
|
rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder"
|
||||||
|
|
||||||
|
|
@ -249,7 +248,9 @@ upgrade_ov() {
|
||||||
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 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 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'
|
||||||
printf '\n'
|
printf '\n'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,16 @@ generate_report() {
|
||||||
printf '\n'
|
printf '\n'
|
||||||
done
|
done
|
||||||
|
|
||||||
|
printf '\n'
|
||||||
|
printf "\n ---------------------------------------"
|
||||||
|
printf "\n KMS"
|
||||||
|
printf "\n ---------------------------------------"
|
||||||
|
printf '\n'
|
||||||
|
kurento_logs
|
||||||
|
printf "\n ---------------------------------------"
|
||||||
|
printf '\n'
|
||||||
|
printf '\n'
|
||||||
|
|
||||||
printf "\n ======================================="
|
printf "\n ======================================="
|
||||||
printf "\n = CONTAINER ENVS VARIABLES ="
|
printf "\n = CONTAINER ENVS VARIABLES ="
|
||||||
printf "\n ======================================="
|
printf "\n ======================================="
|
||||||
|
|
@ -189,7 +199,8 @@ usage() {
|
||||||
printf "\n\tstart\t\t\tStart all services"
|
printf "\n\tstart\t\t\tStart all services"
|
||||||
printf "\n\tstop\t\t\tStop all services"
|
printf "\n\tstop\t\t\tStop all services"
|
||||||
printf "\n\trestart\t\t\tRestart all stoped and running 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\t\t\tUpgrade to the lastest Openvidu version"
|
||||||
printf "\n\tupgrade [version]\tUpgrade to the specific Openvidu version"
|
printf "\n\tupgrade [version]\tUpgrade to the specific Openvidu version"
|
||||||
printf "\n\tversion\t\t\tShow version of Openvidu Server"
|
printf "\n\tversion\t\t\tShow version of Openvidu Server"
|
||||||
|
|
@ -198,6 +209,14 @@ usage() {
|
||||||
printf "\n"
|
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
|
case $1 in
|
||||||
start)
|
start)
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
@ -215,7 +234,18 @@ case $1 in
|
||||||
;;
|
;;
|
||||||
|
|
||||||
logs)
|
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)
|
upgrade)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
global:
|
global:
|
||||||
owner: openvidu@gmail.com
|
owner: info@openvidu.io
|
||||||
qsname: openvidu-ce
|
qsname: openvidu-ce
|
||||||
regions:
|
regions:
|
||||||
- us-east-1
|
- us-east-1
|
||||||
|
|
|
||||||
|
|
@ -142,5 +142,5 @@ Resources:
|
||||||
Type: AWS::CloudFormation::WaitCondition
|
Type: AWS::CloudFormation::WaitCondition
|
||||||
CreationPolicy:
|
CreationPolicy:
|
||||||
ResourceSignal:
|
ResourceSignal:
|
||||||
Timeout: PT10M
|
Timeout: PT20M
|
||||||
Count: 1
|
Count: 1
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,12 @@ Resources:
|
||||||
Tags:
|
Tags:
|
||||||
- Key: Name
|
- Key: Name
|
||||||
Value: !Ref AWS::StackName
|
Value: !Ref AWS::StackName
|
||||||
|
BlockDeviceMappings:
|
||||||
|
- DeviceName: /dev/sda1
|
||||||
|
Ebs:
|
||||||
|
VolumeType: gp2
|
||||||
|
DeleteOnTermination: true
|
||||||
|
VolumeSize: 10
|
||||||
UserData:
|
UserData:
|
||||||
"Fn::Base64":
|
"Fn::Base64":
|
||||||
!Sub |
|
!Sub |
|
||||||
|
|
@ -138,5 +144,5 @@ Resources:
|
||||||
Type: AWS::CloudFormation::WaitCondition
|
Type: AWS::CloudFormation::WaitCondition
|
||||||
CreationPolicy:
|
CreationPolicy:
|
||||||
ResourceSignal:
|
ResourceSignal:
|
||||||
Timeout: PT10M
|
Timeout: PT20M
|
||||||
Count: 1
|
Count: 1
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,22 @@ Parameters:
|
||||||
LetsEncryptEmail:
|
LetsEncryptEmail:
|
||||||
Description: "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications"
|
Description: "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications"
|
||||||
Type: String
|
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
|
# OpenVidu Configuration
|
||||||
|
|
||||||
|
|
@ -52,39 +68,51 @@ Parameters:
|
||||||
ConstraintDescription: OpenVidu Pro License is mandatory
|
ConstraintDescription: OpenVidu Pro License is mandatory
|
||||||
|
|
||||||
OpenViduSecret:
|
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
|
Type: String
|
||||||
AllowedPattern: ^((?!")(?! ).)+$
|
AllowedPattern: ^[a-zA-Z0-9_-]+$
|
||||||
NoEcho: true
|
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:
|
MediaNodesStartNumber:
|
||||||
Description: "How many Media Nodes do you want on startup (EC2 instances will be launched)"
|
Description: "How many Media Nodes do you want on startup (EC2 instances will be launched)"
|
||||||
Type: Number
|
Type: Number
|
||||||
Default: 1
|
Default: 1
|
||||||
|
|
||||||
# Kibana configuration
|
# Elasticsearch configuration
|
||||||
|
ElasticsearchUser:
|
||||||
KibanaUser:
|
Description: "Username for Elasticsearch and Kibana"
|
||||||
Description: "Username for Kibana Dashboard"
|
|
||||||
Type: String
|
Type: String
|
||||||
AllowedPattern: ^((?!")(?! ).)+$
|
AllowedPattern: ^((?!")(?! ).)+$
|
||||||
ConstraintDescription: Kibana user is mandatory (no whitespaces or quotations allowed)
|
ConstraintDescription: Elasticsearch user is mandatory (no whitespaces or quotations allowed)
|
||||||
Default: kibanaadmin
|
Default: elasticadmin
|
||||||
|
|
||||||
KibanaPassword:
|
ElasticsearchPassword:
|
||||||
Description: "Password for Kibana Dashboard"
|
Description: "Password for Elasticsearch and Kibana"
|
||||||
Type: String
|
Type: String
|
||||||
AllowedPattern: ^((?!")(?! ).)+$
|
AllowedPattern: ^((?!")(?! ).)+$
|
||||||
NoEcho: true
|
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
|
# EC2 Instance configuration
|
||||||
|
|
||||||
AwsInstanceTypeOV:
|
AwsInstanceTypeOV:
|
||||||
Description: "Specifies the EC2 instance type for your OpenVidu Server Pro Node"
|
Description: "Specifies the EC2 instance type for your OpenVidu Server Pro Node"
|
||||||
Type: String
|
Type: String
|
||||||
Default: t2.xlarge
|
Default: c5.xlarge
|
||||||
AllowedValues:
|
AllowedValues:
|
||||||
- t2.large
|
- t2.large
|
||||||
- t2.xlarge
|
- t2.xlarge
|
||||||
|
|
@ -124,7 +152,7 @@ Parameters:
|
||||||
AwsInstanceTypeKMS:
|
AwsInstanceTypeKMS:
|
||||||
Description: "Specifies the EC2 instance type for your Media Nodes"
|
Description: "Specifies the EC2 instance type for your Media Nodes"
|
||||||
Type: String
|
Type: String
|
||||||
Default: t2.xlarge
|
Default: c5.xlarge
|
||||||
AllowedValues:
|
AllowedValues:
|
||||||
- t2.large
|
- t2.large
|
||||||
- t2.xlarge
|
- t2.xlarge
|
||||||
|
|
@ -186,6 +214,7 @@ Parameters:
|
||||||
- false
|
- false
|
||||||
Default: true
|
Default: true
|
||||||
|
|
||||||
|
#start_mappings
|
||||||
Mappings:
|
Mappings:
|
||||||
OVAMIMAP:
|
OVAMIMAP:
|
||||||
eu-west-1:
|
eu-west-1:
|
||||||
|
|
@ -194,6 +223,7 @@ Mappings:
|
||||||
KMSAMIMAP:
|
KMSAMIMAP:
|
||||||
eu-west-1:
|
eu-west-1:
|
||||||
AMI: KMS_AMI_ID
|
AMI: KMS_AMI_ID
|
||||||
|
#end_mappings
|
||||||
|
|
||||||
Metadata:
|
Metadata:
|
||||||
'AWS::CloudFormation::Interface':
|
'AWS::CloudFormation::Interface':
|
||||||
|
|
@ -214,10 +244,17 @@ Metadata:
|
||||||
- OpenViduSecret
|
- OpenViduSecret
|
||||||
- MediaNodesStartNumber
|
- MediaNodesStartNumber
|
||||||
- Label:
|
- Label:
|
||||||
default: Kibana configuration
|
default: OpenVidu Recording Configuration
|
||||||
Parameters:
|
Parameters:
|
||||||
- KibanaUser
|
- Recording
|
||||||
- KibanaPassword
|
- S3RecordingsBucketName
|
||||||
|
- Label:
|
||||||
|
default: Elasticsearch and Kibana configuration
|
||||||
|
Parameters:
|
||||||
|
- ElasticsearchUrl
|
||||||
|
- KibanaUrl
|
||||||
|
- ElasticsearchUser
|
||||||
|
- ElasticsearchPassword
|
||||||
- Label:
|
- Label:
|
||||||
default: EC2 Instance configuration
|
default: EC2 Instance configuration
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
@ -248,6 +285,10 @@ Metadata:
|
||||||
default: "URL to the key file (owncert)"
|
default: "URL to the key file (owncert)"
|
||||||
LetsEncryptEmail:
|
LetsEncryptEmail:
|
||||||
default: "Email for Let's Encrypt (letsencrypt)"
|
default: "Email for Let's Encrypt (letsencrypt)"
|
||||||
|
Recording:
|
||||||
|
default: "OpenVidu Recording"
|
||||||
|
S3RecordingsBucketName:
|
||||||
|
default: "S3 Bucket where recordings will be stored"
|
||||||
# OpenVidu configuration
|
# OpenVidu configuration
|
||||||
OpenViduLicense:
|
OpenViduLicense:
|
||||||
default: "OpenVidu Pro License key"
|
default: "OpenVidu Pro License key"
|
||||||
|
|
@ -256,10 +297,14 @@ Metadata:
|
||||||
OpenViduSecret:
|
OpenViduSecret:
|
||||||
default: "Openvidu Secret"
|
default: "Openvidu Secret"
|
||||||
# Kibana configuration
|
# Kibana configuration
|
||||||
KibanaUser:
|
ElasticsearchUrl:
|
||||||
default: "Kibana username"
|
default: "Elasticsearch URL"
|
||||||
KibanaPassword:
|
KibanaUrl:
|
||||||
default: "Kibana password"
|
default: "Kibana URL"
|
||||||
|
ElasticsearchUser:
|
||||||
|
default: "Elasticsearch and Kibana username"
|
||||||
|
ElasticsearchPassword:
|
||||||
|
default: "Elasticsearch and Kibana password"
|
||||||
# EC2 instance configuration
|
# EC2 instance configuration
|
||||||
AwsInstanceTypeOV:
|
AwsInstanceTypeOV:
|
||||||
default: "Instance type for Openvidu Server Pro Node"
|
default: "Instance type for Openvidu Server Pro Node"
|
||||||
|
|
@ -277,8 +322,22 @@ Metadata:
|
||||||
default: "Deploy OpenVidu Call application"
|
default: "Deploy OpenVidu Call application"
|
||||||
|
|
||||||
Conditions:
|
Conditions:
|
||||||
WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ""] ]
|
WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ''] ]
|
||||||
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
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:
|
Resources:
|
||||||
|
|
||||||
|
|
@ -313,6 +372,45 @@ Resources:
|
||||||
- 'route53:ChangeResourceRecordSets'
|
- 'route53:ChangeResourceRecordSets'
|
||||||
- 'route53:ListHostedZones'
|
- 'route53:ListHostedZones'
|
||||||
Resource: '*'
|
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'] ]
|
RoleName: !Join [ "-", [ OpenViduManageEC2Role, !Ref 'AWS::StackName', !Ref 'AWS::Region'] ]
|
||||||
|
|
||||||
OpenviduInstancesProfile:
|
OpenviduInstancesProfile:
|
||||||
|
|
@ -325,6 +423,21 @@ Resources:
|
||||||
DependsOn:
|
DependsOn:
|
||||||
- OpenViduManageEC2Role
|
- 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:
|
OpenViduServer:
|
||||||
Type: AWS::EC2::Instance
|
Type: AWS::EC2::Instance
|
||||||
Metadata:
|
Metadata:
|
||||||
|
|
@ -383,9 +496,15 @@ Resources:
|
||||||
sed -i "s/CERTIFICATE_TYPE=selfsigned/CERTIFICATE_TYPE=${WhichCert}/" $WORKINGDIR/.env
|
sed -i "s/CERTIFICATE_TYPE=selfsigned/CERTIFICATE_TYPE=${WhichCert}/" $WORKINGDIR/.env
|
||||||
sed -i "s/LETSENCRYPT_EMAIL=user@example.com/LETSENCRYPT_EMAIL=${LetsEncryptEmail}/" $WORKINGDIR/.env
|
sed -i "s/LETSENCRYPT_EMAIL=user@example.com/LETSENCRYPT_EMAIL=${LetsEncryptEmail}/" $WORKINGDIR/.env
|
||||||
|
|
||||||
# Replace Kibana Conf
|
# Replace Elastic Search Conf
|
||||||
sed -i "s/KIBANA_USER=kibanaadmin/KIBANA_USER=${KibanaUser}/" $WORKINGDIR/.env
|
if [[ ! -z "${ElasticsearchUrl}" ]]; then
|
||||||
sed -i "s/KIBANA_PASSWORD=/KIBANA_PASSWORD=${KibanaPassword}/" $WORKINGDIR/.env
|
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
|
# Replace vars AWS
|
||||||
sed -i "s/#AWS_DEFAULT_REGION=/AWS_DEFAULT_REGION=${AWS::Region}/" $WORKINGDIR/.env
|
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_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_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_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
|
# Get security group id of kms and use it as env variable
|
||||||
SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh)
|
SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh)
|
||||||
|
|
@ -405,7 +526,20 @@ Resources:
|
||||||
sed -i "s/WITH_APP=true/WITH_APP=false/" $WORKINGDIR/docker-compose.yml
|
sed -i "s/WITH_APP=true/WITH_APP=false/" $WORKINGDIR/docker-compose.yml
|
||||||
rm $WORKINGDIR/docker-compose.override.yml
|
rm $WORKINGDIR/docker-compose.override.yml
|
||||||
fi
|
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]
|
- 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"
|
mode: "000755"
|
||||||
owner: "root"
|
owner: "root"
|
||||||
group: "root"
|
group: "root"
|
||||||
|
|
@ -421,7 +555,7 @@ Resources:
|
||||||
'/usr/local/bin/getSecurityGroupKms.sh':
|
'/usr/local/bin/getSecurityGroupKms.sh':
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash -x
|
#!/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} \
|
--region ${AWS::Region} \
|
||||||
--output text \
|
--output text \
|
||||||
--filters "Name=tag:aws:cloudformation:logical-id,Values=KMSSecurityGroup" \
|
--filters "Name=tag:aws:cloudformation:logical-id,Values=KMSSecurityGroup" \
|
||||||
|
|
@ -433,7 +567,7 @@ Resources:
|
||||||
'/usr/local/bin/getSecurityGroupOpenVidu.sh':
|
'/usr/local/bin/getSecurityGroupOpenVidu.sh':
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash -x
|
#!/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} \
|
--region ${AWS::Region} \
|
||||||
--output text \
|
--output text \
|
||||||
--filters "Name=tag:aws:cloudformation:logical-id,Values=OpenViduSecurityGroup" \
|
--filters "Name=tag:aws:cloudformation:logical-id,Values=OpenViduSecurityGroup" \
|
||||||
|
|
@ -445,7 +579,7 @@ Resources:
|
||||||
'/usr/local/bin/getCidrBlocKSubnet.sh':
|
'/usr/local/bin/getCidrBlocKSubnet.sh':
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash -x
|
#!/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} \
|
--region ${AWS::Region} \
|
||||||
--output text \
|
--output text \
|
||||||
--filters "Name=subnet-id,Values=${OpenViduSubnet}" \
|
--filters "Name=subnet-id,Values=${OpenViduSubnet}" \
|
||||||
|
|
@ -454,25 +588,25 @@ Resources:
|
||||||
owner: "root"
|
owner: "root"
|
||||||
group: "root"
|
group: "root"
|
||||||
'/usr/local/bin/create_security_group_rules.sh':
|
'/usr/local/bin/create_security_group_rules.sh':
|
||||||
content: !Sub |
|
content: |
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh)
|
SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh)
|
||||||
SECGRPIDOV=$(/usr/local/bin/getSecurityGroupOpenVidu.sh)
|
SECGRPIDOV=$(/usr/local/bin/getSecurityGroupOpenVidu.sh)
|
||||||
SUBNET_CIDR=$(/usr/local/bin/getCidrBlocKSubnet.sh)
|
SUBNET_CIDR=$(/usr/local/bin/getCidrBlocKSubnet.sh)
|
||||||
|
|
||||||
# Create Security group rules OpenVidu
|
# 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:AWS_DOCKER_TAG 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 9200 --cidr $SUBNET_CIDR
|
||||||
|
|
||||||
# Create security group rules for KMS
|
# 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:AWS_DOCKER_TAG 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 3000 --cidr $SUBNET_CIDR
|
||||||
|
|
||||||
mode: "000755"
|
mode: "000755"
|
||||||
owner: "root"
|
owner: "root"
|
||||||
group: "root"
|
group: "root"
|
||||||
'/usr/local/bin/restartPRO.sh':
|
'/usr/local/bin/restartPRO.sh':
|
||||||
content: !Sub |
|
content: |
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
WORKINGDIR=/opt/openvidu
|
WORKINGDIR=/opt/openvidu
|
||||||
|
|
||||||
|
|
@ -484,7 +618,8 @@ Resources:
|
||||||
|
|
||||||
# Restart all services
|
# Restart all services
|
||||||
pushd /opt/openvidu
|
pushd /opt/openvidu
|
||||||
docker-compose up -d
|
export FOLLOW_OPENVIDU_LOGS=false
|
||||||
|
./openvidu start
|
||||||
popd
|
popd
|
||||||
mode: "000755"
|
mode: "000755"
|
||||||
owner: "root"
|
owner: "root"
|
||||||
|
|
@ -509,6 +644,8 @@ Resources:
|
||||||
|
|
||||||
cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenViduServer
|
cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenViduServer
|
||||||
|
|
||||||
|
export HOME="/root"
|
||||||
|
|
||||||
# Replace .env variables
|
# Replace .env variables
|
||||||
/usr/local/bin/feedGroupVars.sh || { echo "[Openvidu] Parameters incorrect/insufficient"; exit 1; }
|
/usr/local/bin/feedGroupVars.sh || { echo "[Openvidu] Parameters incorrect/insufficient"; exit 1; }
|
||||||
|
|
||||||
|
|
@ -525,7 +662,8 @@ Resources:
|
||||||
|
|
||||||
# Start openvidu application
|
# Start openvidu application
|
||||||
pushd /opt/openvidu
|
pushd /opt/openvidu
|
||||||
docker-compose up -d
|
export FOLLOW_OPENVIDU_LOGS=false
|
||||||
|
./openvidu start
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# Wait for the app
|
# Wait for the app
|
||||||
|
|
@ -537,10 +675,9 @@ Resources:
|
||||||
BlockDeviceMappings:
|
BlockDeviceMappings:
|
||||||
- DeviceName: /dev/sda1
|
- DeviceName: /dev/sda1
|
||||||
Ebs:
|
Ebs:
|
||||||
VolumeType: io1
|
VolumeType: gp2
|
||||||
Iops: 200
|
|
||||||
DeleteOnTermination: true
|
DeleteOnTermination: true
|
||||||
VolumeSize: 50
|
VolumeSize: 200
|
||||||
|
|
||||||
KMSSecurityGroup:
|
KMSSecurityGroup:
|
||||||
Type: 'AWS::EC2::SecurityGroup'
|
Type: 'AWS::EC2::SecurityGroup'
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
#!/bin/bash -x
|
#!/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
|
if [[ $CF_RELEASE == "true" ]]; then
|
||||||
export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID}
|
git checkout v$OPENVIDU_PRO_VERSION
|
||||||
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
|
fi
|
||||||
|
|
||||||
if [ "${OPENVIDU_PRO_IS_SNAPSHOT}" == "true" ]; then
|
export AWS_DEFAULT_REGION=eu-west-1
|
||||||
OPENVIDU_PRO_VERSION=${OPENVIDU_PRO_VERSION}-SNAPSHOT
|
|
||||||
fi
|
|
||||||
|
|
||||||
DATESTAMP=$(date +%s)
|
DATESTAMP=$(date +%s)
|
||||||
TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
||||||
|
|
@ -23,10 +19,9 @@ TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json)
|
||||||
getUbuntuAmiId() {
|
getUbuntuAmiId() {
|
||||||
local AMI_ID=$(
|
local AMI_ID=$(
|
||||||
aws --region ${1} ec2 describe-images \
|
aws --region ${1} ec2 describe-images \
|
||||||
--filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64* \
|
--filters "Name=name,Values=*ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*" \
|
||||||
--query 'Images[*].[ImageId,CreationDate]' \
|
--query "sort_by(Images, &CreationDate)" \
|
||||||
--output text \
|
| jq -r 'del(.[] | select(.ImageOwnerAlias != null)) | .[-1].ImageId'
|
||||||
| sort -k2 -r | head -n1 | cut -d$'\t' -f1
|
|
||||||
)
|
)
|
||||||
echo $AMI_ID
|
echo $AMI_ID
|
||||||
}
|
}
|
||||||
|
|
@ -61,12 +56,22 @@ sed -i "s/AMIUSEAST1/${AMIUSEAST1}/g" cfn-mkt-kms-ami.yaml
|
||||||
## KMS AMI
|
## KMS AMI
|
||||||
|
|
||||||
# Copy template to S3
|
# Copy template to S3
|
||||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io
|
||||||
aws s3 cp cfn-mkt-kms-ami.yaml s3://naeva-openvidu-pro
|
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml
|
||||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/naeva-openvidu-pro/cfn-mkt-kms-ami.yaml
|
|
||||||
else
|
# Update installation script
|
||||||
aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io
|
if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then
|
||||||
TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml
|
# 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
|
fi
|
||||||
|
|
||||||
aws cloudformation create-stack \
|
aws cloudformation create-stack \
|
||||||
|
|
@ -94,12 +99,22 @@ aws cloudformation delete-stack --stack-name kms-${DATESTAMP}
|
||||||
## OpenVidu AMI
|
## OpenVidu AMI
|
||||||
|
|
||||||
# Copy template to S3
|
# 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
|
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
|
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
|
fi
|
||||||
|
|
||||||
aws cloudformation create-stack \
|
aws cloudformation create-stack \
|
||||||
|
|
@ -125,15 +140,35 @@ echo "Cleaning up"
|
||||||
aws cloudformation delete-stack --stack-name openvidu-${DATESTAMP}
|
aws cloudformation delete-stack --stack-name openvidu-${DATESTAMP}
|
||||||
|
|
||||||
# Wait for the instance
|
# 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
|
# Updating the template
|
||||||
if [ ${CF_OVP_TARGET} == "market" ]; then
|
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 "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-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
||||||
sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-mkt-openvidu-server-pro-${OPENVIDU_PRO_VERSION}.yaml
|
sed -i "s/AWS_DOCKER_TAG/${AWS_DOCKER_TAG}/g" cfn-openvidu-server-pro-no-market-${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
|
# Update CF template
|
||||||
sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml
|
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
|
fi
|
||||||
|
|
||||||
rm $TEMPJSON
|
rm $TEMPJSON
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,24 @@
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -eu -o pipefail
|
set -eu -o pipefail
|
||||||
|
|
||||||
|
# Process AMI_LIST
|
||||||
|
AMI_LIST=($(echo "$AMI_LIST" | tr ',' '\n'))
|
||||||
|
|
||||||
# Remove the list of AMIs in each region
|
# Remove the list of AMIs in each region
|
||||||
|
for line in "${AMI_LIST[@]}"
|
||||||
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}
|
|
||||||
do
|
do
|
||||||
REGION=$(echo ${line} | cut -d":" -f1)
|
REGION=$(echo "${line}" | cut -d":" -f1)
|
||||||
AMI_ID=$(echo ${line} | cut -d":" -f2)
|
AMI_ID=$(echo "${line}" | cut -d":" -f2)
|
||||||
export AWS_DEFAULT_REGION=${REGION}
|
export AWS_DEFAULT_REGION=${REGION}
|
||||||
aws ec2 deregister-image --image-id $AMI_ID
|
|
||||||
sleep 1
|
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
|
done
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash -x
|
#!/bin/bash
|
||||||
set -eu -o pipefail
|
set -eu -o pipefail
|
||||||
|
|
||||||
# Replicate AMIs in all regions
|
# Replicate AMIs in all regions
|
||||||
|
|
@ -10,12 +10,11 @@ set -eu -o pipefail
|
||||||
#
|
#
|
||||||
# OV_AMI_NAME OpenVidu AMI Name
|
# OV_AMI_NAME OpenVidu AMI Name
|
||||||
# OV_AMI_ID OpenVidu AMI ID
|
# 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
|
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"
|
echo "Making original AMIs public"
|
||||||
|
|
||||||
|
|
@ -96,26 +95,82 @@ do
|
||||||
ITER=$(expr $ITER + 1)
|
ITER=$(expr $ITER + 1)
|
||||||
done
|
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
|
ITER=0
|
||||||
for i in "${OPENVIDU_SERVER_PRO_AMI_IDS[@]}"
|
for i in "${OPENVIDU_SERVER_PRO_AMI_IDS[@]}"
|
||||||
do
|
do
|
||||||
AMI_ID=${OPENVIDU_SERVER_PRO_AMI_IDS[$ITER]}
|
AMI_ID=${OPENVIDU_SERVER_PRO_AMI_IDS[$ITER]}
|
||||||
REGION=${REGIONS[$ITER]}
|
REGION=${REGIONS[$ITER]}
|
||||||
echo " ${REGION}:"
|
if [[ ${ITER} -eq 0 ]]; then
|
||||||
echo " AMI: ${AMI_ID}"
|
AMI_LIST="${REGION}:${AMI_ID}"
|
||||||
|
else
|
||||||
|
AMI_LIST="${AMI_LIST},${REGION}:${AMI_ID}"
|
||||||
|
fi
|
||||||
ITER=$(expr $ITER + 1)
|
ITER=$(expr $ITER + 1)
|
||||||
done
|
done
|
||||||
|
echo "AMI_LIST_OV: ${AMI_LIST}"
|
||||||
|
|
||||||
echo
|
# Print AMI_LIST for delete_amis.sh
|
||||||
echo "Media Node AMI IDs"
|
AMI_LIST=""
|
||||||
ITER=0
|
ITER=0
|
||||||
for i in "${MEDIA_NODE_AMI_IDS[@]}"
|
for i in "${MEDIA_NODE_AMI_IDS[@]}"
|
||||||
do
|
do
|
||||||
AMI_ID=${MEDIA_NODE_AMI_IDS[$ITER]}
|
AMI_ID=${MEDIA_NODE_AMI_IDS[$ITER]}
|
||||||
REGION=${REGIONS[$ITER]}
|
REGION=${REGIONS[$ITER]}
|
||||||
echo " ${REGION}:"
|
if [[ ${ITER} -eq 0 ]]; then
|
||||||
echo " AMI: ${AMI_ID}"
|
AMI_LIST="${REGION}:${AMI_ID}"
|
||||||
|
else
|
||||||
|
AMI_LIST="${AMI_LIST},${REGION}:${AMI_ID}"
|
||||||
|
fi
|
||||||
ITER=$(expr $ITER + 1)
|
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
|
mkdir -p /opt/openvidu/beats
|
||||||
echo "Copying beat config files"
|
echo "Copying beat config files"
|
||||||
cp /beats/filebeat.yml /opt/openvidu/beats/filebeat.yml
|
cp /beats/filebeat.yml /opt/openvidu/beats/filebeat.yml
|
||||||
cp /beats/metricbeat-elasticsearch.yml /opt/openvidu/beats/metricbeat-elasticsearch.yml
|
cp /beats/metricbeat-elasticsearch.yml /opt/openvidu/beats/metricbeat-elasticsearch.yml
|
||||||
cp /beats/metricbeat-openvidu.yml /opt/openvidu/beats/metricbeat-openvidu.yml
|
|
||||||
|
|
@ -5,6 +5,14 @@ filebeat.inputs:
|
||||||
multiline.pattern: '^\d*:\d*:\d*'
|
multiline.pattern: '^\d*:\d*:\d*'
|
||||||
multiline.negate: true
|
multiline.negate: true
|
||||||
multiline.match: after
|
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:
|
processors:
|
||||||
- add_docker_metadata:
|
- add_docker_metadata:
|
||||||
|
|
@ -19,23 +27,21 @@ processors:
|
||||||
- add_fields:
|
- add_fields:
|
||||||
fields:
|
fields:
|
||||||
ip: ${MEDIA_NODE_IP}
|
ip: ${MEDIA_NODE_IP}
|
||||||
|
cluster-id: ${CLUSTER_ID}
|
||||||
|
|
||||||
output:
|
output:
|
||||||
elasticsearch:
|
elasticsearch:
|
||||||
hosts: ["${OPENVIDU_SERVER_PRO_IP}:9200"]
|
|
||||||
indices:
|
indices:
|
||||||
- index: "filebeat-kurento-%{+yyyy.MM.dd}"
|
- index: "filebeat-kurento-%{+yyyy.MM.dd}"
|
||||||
when.or:
|
when.or:
|
||||||
- contains:
|
- equals:
|
||||||
container.image.name: kurento/kurento-media-server
|
kurento-media-server: true
|
||||||
pipelines:
|
pipelines:
|
||||||
- pipeline: kurento-pipeline
|
- pipeline: kurento-pipeline
|
||||||
when.or:
|
when.or:
|
||||||
- contains:
|
- equals:
|
||||||
container.image.name: kurento/kurento-media-server
|
kurento-media-server: true
|
||||||
|
|
||||||
logging.json: true
|
logging.json: true
|
||||||
logging.metrics.enabled: false
|
logging.metrics.enabled: false
|
||||||
setup.ilm.enabled: true
|
setup.ilm.enabled: false
|
||||||
setup.ilm.policy_name: "openvidu_cleanup_policy"
|
|
||||||
|
|
@ -1,14 +1,34 @@
|
||||||
output:
|
|
||||||
elasticsearch:
|
|
||||||
hosts: ["${OPENVIDU_SERVER_PRO_IP}:9200"]
|
|
||||||
metricbeat.modules:
|
metricbeat.modules:
|
||||||
- module: system
|
- module: system
|
||||||
metricsets: [cpu]
|
metricsets:
|
||||||
enabled: true
|
- cpu
|
||||||
period: ${OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL}s
|
#- 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: ['.*']
|
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]
|
cpu.metrics: [normalized_percentages]
|
||||||
fields: {ip: "${MEDIA_NODE_IP}"}
|
fields: {ip: "${MEDIA_NODE_IP}", cluster-id: "${CLUSTER_ID}"}
|
||||||
pipeline:
|
pipeline:
|
||||||
queue.mem.events: 0
|
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.
|
# 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
|
# Installation Mode: On Premises
|
||||||
#
|
#
|
||||||
|
|
@ -16,20 +16,24 @@ version: '3.1'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
media-node-controller:
|
media-node-controller:
|
||||||
image: openvidu/media-node-controller:1.0.0
|
image: openvidu/media-node-controller:3.0.0-dev4
|
||||||
restart: always
|
restart: always
|
||||||
ulimits:
|
ulimits:
|
||||||
core: -1
|
core: -1
|
||||||
entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh']
|
entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh']
|
||||||
environment:
|
environment:
|
||||||
- KMS_IMAGE=${KMS_IMAGE:-kurento/kurento-media-server:6.14.0}
|
- KMS_IMAGE=kurento/kurento-media-server:6.15.0
|
||||||
- KMS_DEBUG_LEVEL=${KMS_DEBUG_LEVEL:-}
|
- METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0
|
||||||
- METRICBEAT_IMAGE=${METRICBEAT_IMAGE:-docker.elastic.co/beats/metricbeat:7.8.0}
|
- FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0
|
||||||
- FILEBEAT_IMAGE=${FILEBEAT_IMAGE:-docker.elastic.co/beats/filebeat:7.8.0}
|
- OPENVIDU_RECORDING_IMAGE=openvidu/openvidu-recording:2.17.0-dev1
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/openvidu/recordings:/opt/openvidu/recordings
|
- /opt/openvidu/recordings:/opt/openvidu/recordings
|
||||||
- /opt/openvidu/beats:/opt/openvidu/beats
|
- /opt/openvidu/beats:/opt/openvidu/beats
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs
|
||||||
- ./beats:/beats
|
- ./beats:/beats
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "100M"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,16 @@
|
||||||
|
|
||||||
MEDIA_NODE_FOLDER=kms
|
MEDIA_NODE_FOLDER=kms
|
||||||
MEDIA_NODE_VERSION=master
|
MEDIA_NODE_VERSION=master
|
||||||
|
OPENVIDU_UPGRADABLE_VERSION="2.16"
|
||||||
BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats
|
BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats
|
||||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${MEDIA_NODE_VERSION}
|
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() {
|
fatal_error() {
|
||||||
printf "\n =======¡ERROR!======="
|
printf "\n =======¡ERROR!======="
|
||||||
printf "\n %s" "$1"
|
printf "\n %s" "$1"
|
||||||
|
|
@ -11,6 +19,27 @@ fatal_error() {
|
||||||
exit 0
|
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() {
|
new_media_node_installation() {
|
||||||
printf '\n'
|
printf '\n'
|
||||||
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'"
|
--output "${MEDIA_NODE_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||||
printf '\n - 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 \
|
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'"
|
--output "${MEDIA_NODE_FOLDER}/media_node" || fatal_error "Error when downloading the file 'media_node'"
|
||||||
printf '\n - 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'"
|
--output "${BEATS_FOLDER}/metricbeat-elasticsearch.yml" || fatal_error "Error when downloading the file 'metricbeat-elasticsearch.yml'"
|
||||||
printf '\n - 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 \
|
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'"
|
--output "${BEATS_FOLDER}/copy_config_files.sh" || fatal_error "Error when downloading the file 'copy_config_files.sh'"
|
||||||
printf '\n - copy_config_files.sh'
|
printf '\n - copy_config_files.sh'
|
||||||
|
|
@ -68,12 +89,14 @@ new_media_node_installation() {
|
||||||
# Pull images
|
# Pull images
|
||||||
printf "\n => Pulling images...\n"
|
printf "\n => Pulling images...\n"
|
||||||
cd "${MEDIA_NODE_FOLDER}" || fatal_error "Error when moving to '${MEDIA_NODE_FOLDER}' folder"
|
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/')
|
KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | cut -d"=" -f2)
|
||||||
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | cut -d"=" -f2)
|
||||||
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
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 $KMS_IMAGE || fatal "Error while pulling docker image: $KMS_IMAGE"
|
||||||
docker pull $METRICBEAT_IMAGE || fatal "Error while pulling docker image: $METRICBEAT_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 $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
|
docker-compose pull | true
|
||||||
|
|
||||||
# Ready to use
|
# Ready to use
|
||||||
|
|
@ -81,16 +104,28 @@ new_media_node_installation() {
|
||||||
printf '\n ======================================='
|
printf '\n ======================================='
|
||||||
printf "\n Media Node successfully installed."
|
printf "\n Media Node successfully installed."
|
||||||
printf '\n ======================================='
|
printf '\n ======================================='
|
||||||
printf "\n"
|
printf '\n'
|
||||||
printf '\n 1. Go to kms folder:'
|
printf '\n 1. Go to kms folder:'
|
||||||
printf '\n $ cd kms'
|
printf '\n $ cd kms'
|
||||||
printf "\n"
|
printf '\n'
|
||||||
printf '\n 2. Start Media Node Controller'
|
printf '\n 2. Start Media Node Controller'
|
||||||
printf '\n $ ./media_node start'
|
printf '\n $ ./media_node start'
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf "\n For more information, check:"
|
printf '\n 3. This will run a service at port 3000 which OpenVidu will use to deploy necessary containers.'
|
||||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions"
|
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'
|
||||||
|
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'
|
printf '\n'
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
@ -123,10 +158,13 @@ upgrade_media_node() {
|
||||||
|
|
||||||
# Uppgrade Media Node
|
# Uppgrade Media Node
|
||||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${MEDIA_NODE_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
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
|
# 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.
|
# 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 ======================================='
|
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'"
|
--output "${TMP_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||||
printf '\n - 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 \
|
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'"
|
--output "${TMP_FOLDER}/media_node" || fatal_error "Error when downloading the file 'media_node'"
|
||||||
printf '\n - 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'"
|
--output "${TMP_FOLDER}/metricbeat-elasticsearch.yml" || fatal_error "Error when downloading the file 'metricbeat-elasticsearch.yml'"
|
||||||
printf '\n - 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 \
|
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'"
|
--output "${TMP_FOLDER}/copy_config_files.sh" || fatal_error "Error when downloading the file 'copy_config_files.sh'"
|
||||||
printf '\n - 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 => Moving to 'tmp' folder..."
|
||||||
printf '\n'
|
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
|
# Pull images
|
||||||
printf "\n => Pulling images...\n"
|
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 | cut -d"=" -f2)
|
||||||
KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | sed 's/\(^.*KMS_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | cut -d"=" -f2)
|
||||||
METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | cut -d"=" -f2)
|
||||||
FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/')
|
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 $KMS_IMAGE || fatal "Error while pulling docker image: $KMS_IMAGE"
|
||||||
docker pull $METRICBEAT_IMAGE || fatal "Error while pulling docker image: $METRICBEAT_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 $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
|
docker-compose pull | true
|
||||||
|
|
||||||
printf '\n => Stoping Media Node...'
|
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'"
|
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/media_node" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||||
printf '\n - media_node'
|
printf '\n - media_node'
|
||||||
|
|
||||||
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/readme.md" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'readme.md'"
|
mv "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'beats' folder"
|
||||||
printf '\n - readme.md'
|
printf '\n - beats'
|
||||||
|
|
||||||
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'
|
|
||||||
|
|
||||||
# Move tmp files to Openvidu
|
# Move tmp files to Openvidu
|
||||||
printf '\n => Updating files:'
|
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'"
|
mv "${TMP_FOLDER}/docker-compose.yml" "${MEDIA_NODE_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'docker-compose.yml'"
|
||||||
printf '\n - 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'"
|
mv "${TMP_FOLDER}/media_node" "${MEDIA_NODE_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'media_node'"
|
||||||
printf '\n - 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'"
|
mv "${TMP_FOLDER}/metricbeat-elasticsearch.yml" "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" || fatal_error "Error while updating 'metricbeat-elasticsearch.yml'"
|
||||||
printf '\n - 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'"
|
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'
|
printf '\n - copy_config_files.sh'
|
||||||
|
|
||||||
|
|
@ -275,17 +301,27 @@ upgrade_media_node() {
|
||||||
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 1. A new file 'docker-compose.yml' has been created with the new OpenVidu %s services" "${OPENVIDU_VERSION}"
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf "\n 2. The previous file '.env' remains intact, but a new file '.env-%s' has been created." "${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 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'
|
||||||
printf '\n 3. Start new version of Media Node'
|
printf '\n 3. Start new version of Media Node'
|
||||||
printf '\n $ ./media_node start'
|
printf '\n $ ./media_node start'
|
||||||
printf '\n'
|
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 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'
|
|
||||||
printf '\n'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check docker and docker-compose installation
|
# Check docker and docker-compose installation
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,41 @@
|
||||||
#!/bin/bash
|
#!/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_media_node() {
|
||||||
UPGRADE_SCRIPT_URL="https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/install_media_node_OVVERSION.sh"
|
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})
|
HTTP_STATUS=$(curl -s -o /dev/null -I -w "%{http_code}" ${UPGRADE_SCRIPT_URL//OVVERSION/$1})
|
||||||
|
|
@ -140,6 +176,16 @@ generate_report() {
|
||||||
printf '\n'
|
printf '\n'
|
||||||
done
|
done
|
||||||
|
|
||||||
|
printf '\n'
|
||||||
|
printf "\n ---------------------------------------"
|
||||||
|
printf "\n KMS"
|
||||||
|
printf "\n ---------------------------------------"
|
||||||
|
printf '\n'
|
||||||
|
kurento_logs
|
||||||
|
printf "\n ---------------------------------------"
|
||||||
|
printf '\n'
|
||||||
|
printf '\n'
|
||||||
|
|
||||||
printf "\n ======================================="
|
printf "\n ======================================="
|
||||||
printf "\n = CONTAINER ENVS VARIABLES ="
|
printf "\n = CONTAINER ENVS VARIABLES ="
|
||||||
printf "\n ======================================="
|
printf "\n ======================================="
|
||||||
|
|
@ -170,7 +216,8 @@ usage() {
|
||||||
printf "\n\tstart\t\t\tStart media node service"
|
printf "\n\tstart\t\t\tStart media node service"
|
||||||
printf "\n\tstop\t\t\tStop media node service"
|
printf "\n\tstop\t\t\tStop media node service"
|
||||||
printf "\n\trestart\t\t\tRestart 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\t\t\tUpgrade to the lastest Media Node version"
|
||||||
printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version"
|
printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version"
|
||||||
printf "\n\tversion\t\t\tShow version of Media Node"
|
printf "\n\tversion\t\t\tShow version of Media Node"
|
||||||
|
|
@ -179,15 +226,6 @@ usage() {
|
||||||
printf "\n"
|
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
|
case $1 in
|
||||||
|
|
||||||
start)
|
start)
|
||||||
|
|
@ -208,7 +246,18 @@ case $1 in
|
||||||
;;
|
;;
|
||||||
|
|
||||||
logs)
|
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)
|
upgrade)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,22 @@ LETSENCRYPT_EMAIL=user@example.com
|
||||||
# SDKs, REST clients and browsers will have to connect to this port
|
# SDKs, REST clients and browsers will have to connect to this port
|
||||||
# HTTPS_PORT=443
|
# 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
|
# Access restrictions
|
||||||
# In this section you will be able to restrict the IPs from which you can access to
|
# In this section you will be able to restrict the IPs from which you can access to
|
||||||
# Openvidu API and the Administration Panel
|
# Openvidu API and the Administration Panel
|
||||||
|
|
@ -71,6 +87,12 @@ OPENVIDU_PRO_CLUSTER_MODE=manual
|
||||||
# Possibles values: aws, on_premise
|
# Possibles values: aws, on_premise
|
||||||
OPENVIDU_PRO_CLUSTER_ENVIRONMENT=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.
|
# 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 too many Media Nodes after that, they will be dropped until this number is reached.
|
||||||
# If there are not enough, more will be launched.
|
# If there are not enough, more will be launched.
|
||||||
|
|
@ -85,7 +107,6 @@ OPENVIDU_PRO_CLUSTER_ENVIRONMENT=on_premise
|
||||||
# Type: number >= 0
|
# Type: number >= 0
|
||||||
# OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL=
|
# OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL=
|
||||||
|
|
||||||
|
|
||||||
# Whether to enable or disable autoscaling. With autoscaling the number of Media Nodes will
|
# Whether to enable or disable autoscaling. With autoscaling the number of Media Nodes will
|
||||||
# be automatically adjusted according to existing load
|
# be automatically adjusted according to existing load
|
||||||
# Values: true | false
|
# Values: true | false
|
||||||
|
|
@ -119,13 +140,55 @@ OPENVIDU_PRO_CLUSTER_AUTOSCALING=false
|
||||||
# (and therefore distribution of load) among all available Media Nodes
|
# (and therefore distribution of load) among all available Media Nodes
|
||||||
OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams
|
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
|
# Max days until delete indexes in state of rollover on Elasticsearch
|
||||||
# Type number >= 0
|
# Type number >= 0
|
||||||
|
# Default Value is 15
|
||||||
# OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE=
|
# OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE=
|
||||||
|
|
||||||
# Private IP of OpenVidu Server Pro
|
# If you have an external Elasticsearch and Kibana already running, put here the url to elasticsearch and kibana services.
|
||||||
# For example 192.168.1.101
|
# It is very important that both url have the port specified in the url.
|
||||||
# OPENVIDU_PRO_PRIVATE_IP=
|
# 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
|
# Whether to enable recording module or not
|
||||||
OPENVIDU_RECORDING=false
|
OPENVIDU_RECORDING=false
|
||||||
|
|
@ -178,12 +241,14 @@ OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH=1000
|
||||||
# 0 means unconstrained
|
# 0 means unconstrained
|
||||||
OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH=300
|
OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH=300
|
||||||
|
|
||||||
# All sessions of OpenVidu will try to force this codec. If OPENVIDU_ALLOW_TRANSCODING=true
|
# 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
|
# when a codec can not be forced, transcoding will be allowed
|
||||||
# OPENVIDU_FORCED_CODEC=VP8
|
# Default value is VP8
|
||||||
|
# OPENVIDU_STREAMS_FORCED_VIDEO_CODEC=VP8
|
||||||
|
|
||||||
# Allow transcoding if codec specified in OPENVIDU_FORCED_CODEC can not be applied
|
# Allow transcoding if codec specified in OPENVIDU_STREAMS_FORCED_VIDEO_CODEC can not be applied
|
||||||
# OPENVIDU_ALLOW_TRANSCODING=false
|
# Default value is false
|
||||||
|
# OPENVIDU_STREAMS_ALLOW_TRANSCODING=false
|
||||||
|
|
||||||
# true to enable OpenVidu Webhook service. false' otherwise
|
# true to enable OpenVidu Webhook service. false' otherwise
|
||||||
# Values: true | false
|
# Values: true | false
|
||||||
|
|
@ -227,17 +292,44 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
|
||||||
# RECOMENDED VALUES: INFO for normal logs DEBUG for more verbose logs
|
# RECOMENDED VALUES: INFO for normal logs DEBUG for more verbose logs
|
||||||
# OV_CE_DEBUG_LEVEL=INFO
|
# OV_CE_DEBUG_LEVEL=INFO
|
||||||
|
|
||||||
# Java Options
|
# OpenVidu Java Options
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Uncomment the next line and define this to add options to java command
|
# 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
|
# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058
|
||||||
# JAVA_OPTIONS=-Xms2048m -Xmx4096m
|
# JAVA_OPTIONS=-Xms2048m -Xmx4096m
|
||||||
|
|
||||||
# Kibana And ElasticSearch Configuration
|
# ElasticSearch Java Options
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Kibana dashboard configuration (Credentials)
|
# Uncomment the next line and define this to add options to java command of Elasticsearch
|
||||||
KIBANA_USER=kibanaadmin
|
# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058
|
||||||
KIBANA_PASSWORD=
|
# 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
|
# Cloudformation configuration
|
||||||
# --------------------------
|
# --------------------------
|
||||||
|
|
@ -250,3 +342,5 @@ KIBANA_PASSWORD=
|
||||||
#AWS_SECURITY_GROUP=
|
#AWS_SECURITY_GROUP=
|
||||||
#AWS_STACK_ID=
|
#AWS_STACK_ID=
|
||||||
#AWS_STACK_NAME=
|
#AWS_STACK_NAME=
|
||||||
|
#AWS_CLI_DOCKER_TAG=
|
||||||
|
#AWS_VOLUME_SIZE=
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,36 @@ processors:
|
||||||
fields: ["message"]
|
fields: ["message"]
|
||||||
target: "json"
|
target: "json"
|
||||||
overwrite_keys: true
|
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:
|
output:
|
||||||
elasticsearch:
|
elasticsearch:
|
||||||
hosts: ["elasticsearch:9200"]
|
hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
|
||||||
indices:
|
indices:
|
||||||
- index: "filebeat-redis-%{+yyyy.MM.dd}"
|
- index: "filebeat-redis-%{+yyyy.MM.dd}"
|
||||||
when.or:
|
when.or:
|
||||||
- contains:
|
- contains:
|
||||||
container.image.name: openvidu/openvidu-redis
|
container.image.name: openvidu/openvidu-redis
|
||||||
- index: "filebeat-coturn-%{+yyyy.MM.dd}"
|
- index: "filebeat-nginx-%{+yyyy.MM.dd}"
|
||||||
when.or:
|
when.or:
|
||||||
- contains:
|
- contains:
|
||||||
container.image.name: openvidu/openvidu-coturn
|
container.image.name: openvidu/openvidu-proxy
|
||||||
|
|
||||||
|
|
||||||
logging.json: true
|
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)
|
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 \
|
--output text \
|
||||||
--filters "Name=instance-state-name,Values=running" \
|
--filters "Name=instance-state-name,Values=running" \
|
||||||
"Name=tag:ov-cluster-member,Values=kms" \
|
"Name=tag:ov-cluster-member,Values=kms" \
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,4 @@ DEBUG=${DEBUG:-false}
|
||||||
ID=$1
|
ID=$1
|
||||||
[ -z "${ID}" ] && { echo "Must provide instance ID"; exit 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")
|
"UnauthorizedOperation")
|
||||||
MSG_COD=$(cat ${ERROUTPUT} | awk -F: '{ print $3 }')
|
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
|
echo -e "Unauthorized " $(cat ${MSG_DEC}) >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -35,16 +35,17 @@ exit_on_error () {
|
||||||
esac
|
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 \
|
--image-id ${AWS_IMAGE_ID} --count 1 \
|
||||||
--instance-type ${AWS_INSTANCE_TYPE} \
|
--instance-type ${AWS_INSTANCE_TYPE} \
|
||||||
--key-name ${AWS_KEY_NAME} \
|
--key-name ${AWS_KEY_NAME} \
|
||||||
--subnet-id ${AWS_SUBNET_ID} \
|
--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}'}]" \
|
--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}" \
|
--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}
|
--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
|
# Generating the output
|
||||||
KMS_IP=$(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .NetworkInterfaces[0] | .PrivateIpAddress')
|
KMS_IP=$(cat ${OUTPUT} | jq --raw-output ' .Instances[] | .NetworkInterfaces[0] | .PrivateIpAddress')
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@ services:
|
||||||
#
|
#
|
||||||
# Default Application
|
# Default Application
|
||||||
#
|
#
|
||||||
# Openvidu-Call Version: 2.15.0
|
# Openvidu-Call Version: 2.16.0
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
app:
|
app:
|
||||||
image: openvidu/openvidu-call:2.15.0
|
image: openvidu/openvidu-call:2.16.0
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -21,3 +21,6 @@ services:
|
||||||
- OPENVIDU_URL=http://localhost:5443
|
- OPENVIDU_URL=http://localhost:5443
|
||||||
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
- OPENVIDU_SECRET=${OPENVIDU_SECRET}
|
||||||
- CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE}
|
- 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
|
# Application based on OpenVidu should be specified in
|
||||||
# docker-compose.override.yml file
|
# 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
|
# This file will be overridden when update OpenVidu Platform
|
||||||
#
|
#
|
||||||
# Openvidu Version: 2.15.1
|
# Openvidu Version: 2.16.0
|
||||||
#
|
#
|
||||||
# Installation Mode: On Premises
|
# Installation Mode: On Premises
|
||||||
#
|
#
|
||||||
|
|
@ -22,10 +22,10 @@ version: '3.1'
|
||||||
services:
|
services:
|
||||||
|
|
||||||
openvidu-server:
|
openvidu-server:
|
||||||
image: openvidu/openvidu-server-pro:2.15.1
|
image: openvidu/openvidu-server-pro:2.17.0-dev5
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
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:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
- ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH}
|
||||||
|
|
@ -41,21 +41,28 @@ services:
|
||||||
- KMS_URIS=[]
|
- KMS_URIS=[]
|
||||||
- COTURN_REDIS_IP=127.0.0.1
|
- COTURN_REDIS_IP=127.0.0.1
|
||||||
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
- COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||||
|
- COTURN_IP=${COTURN_IP:-auto-ipv4}
|
||||||
- OPENVIDU_PRO_CLUSTER=true
|
- OPENVIDU_PRO_CLUSTER=true
|
||||||
- OPENVIDU_PRO_KIBANA_HOST=http://127.0.0.1/kibana
|
- OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
|
||||||
- OPENVIDU_PRO_ELASTICSEARCH_HOST=http://127.0.0.1:9200
|
- OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
|
||||||
- WAIT_KIBANA_URL=http://127.0.0.1:5601/api/status
|
- WAIT_KIBANA_URL=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
|
||||||
- DOTENV_PATH=${PWD}
|
- DOTENV_PATH=${PWD}
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: openvidu/openvidu-redis:1.0.0
|
image: openvidu/openvidu-redis:2.0.0-dev2
|
||||||
restart: always
|
restart: always
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
- REDIS_PASSWORD=${OPENVIDU_SECRET}
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||||
|
|
||||||
coturn:
|
coturn:
|
||||||
image: openvidu/openvidu-coturn:1.0.0
|
image: openvidu/openvidu-coturn:3.0.0-dev2
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -63,17 +70,22 @@ services:
|
||||||
- TURN_LISTEN_PORT=3478
|
- TURN_LISTEN_PORT=3478
|
||||||
- DB_NAME=0
|
- DB_NAME=0
|
||||||
- DB_PASSWORD=${OPENVIDU_SECRET}
|
- DB_PASSWORD=${OPENVIDU_SECRET}
|
||||||
- MIN_PORT=57001
|
- MIN_PORT=40000
|
||||||
- MAX_PORT=65535
|
- 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:
|
nginx:
|
||||||
image: openvidu/openvidu-proxy:3.0.0
|
image: openvidu/openvidu-proxy:5.0.0-dev2
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
network_mode: host
|
network_mode: host
|
||||||
entrypoint: ['/bin/sh', '-c', 'htpasswd -bc /etc/nginx/kibana.htpasswd "${KIBANA_USER}" "${KIBANA_PASSWORD}" && /usr/local/bin/entrypoint.sh']
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./certificates:/etc/letsencrypt
|
- ./certificates:/etc/letsencrypt
|
||||||
- ./owncert:/owncert
|
- ./owncert:/owncert
|
||||||
|
- ./custom-nginx-vhosts:/etc/nginx/vhost.d/
|
||||||
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout
|
- ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout
|
||||||
environment:
|
environment:
|
||||||
- DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP}
|
- DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP}
|
||||||
|
|
@ -85,31 +97,84 @@ services:
|
||||||
- ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-}
|
- ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-}
|
||||||
- PROXY_MODE=PRO
|
- PROXY_MODE=PRO
|
||||||
- WITH_APP=true
|
- 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:
|
elasticsearch:
|
||||||
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
|
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- discovery.type=single-node
|
- discovery.type=single-node
|
||||||
|
- xpack.security.enabled=true
|
||||||
|
- "ES_JAVA_OPTS=${ES_JAVA_OPTS:--Xms2g -Xmx2g}"
|
||||||
ports:
|
ports:
|
||||||
- 9200:9200
|
- 9200:9200
|
||||||
volumes:
|
volumes:
|
||||||
- ./elasticsearch:/usr/share/elasticsearch/data
|
- ./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:
|
kibana:
|
||||||
image: docker.elastic.co/kibana/kibana:7.8.0
|
image: docker.elastic.co/kibana/kibana:7.8.0
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- SERVER_BASEPATH="/kibana"
|
- SERVER_BASEPATH="/kibana"
|
||||||
|
- xpack.security.enabled=true
|
||||||
|
- ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
|
||||||
|
- ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
|
||||||
ports:
|
ports:
|
||||||
- 5601:5601
|
- 5601:5601
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||||
|
|
||||||
filebeat:
|
metricbeat:
|
||||||
image: docker.elastic.co/beats/filebeat:7.8.0
|
image: docker.elastic.co/beats/metricbeat-oss:7.8.0
|
||||||
|
network_mode: host
|
||||||
restart: always
|
restart: always
|
||||||
user: root
|
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:
|
volumes:
|
||||||
- ./beats/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
|
- ./beats/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
|
||||||
- /var/lib/docker:/var/lib/docker:ro
|
- /var/lib/docker:/var/lib/docker:ro
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /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
|
# Global variables
|
||||||
OPENVIDU_FOLDER=openvidu
|
OPENVIDU_FOLDER=openvidu
|
||||||
OPENVIDU_VERSION=master
|
OPENVIDU_VERSION=master
|
||||||
|
OPENVIDU_UPGRADABLE_VERSION="2.16"
|
||||||
AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws
|
AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws
|
||||||
ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch
|
ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch
|
||||||
BEATS_FOLDER=${OPENVIDU_FOLDER}/beats
|
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'"
|
--output "${BEATS_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
||||||
printf '\n - 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 \
|
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'"
|
--output "${OPENVIDU_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||||
printf '\n - .env'
|
printf '\n - .env'
|
||||||
|
|
@ -95,6 +100,10 @@ new_ov_installation() {
|
||||||
printf "\n => Creating folder 'owncert'..."
|
printf "\n => Creating folder 'owncert'..."
|
||||||
mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the 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
|
# Ready to use
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|
@ -105,13 +114,15 @@ new_ov_installation() {
|
||||||
printf '\n 1. Go to openvidu folder:'
|
printf '\n 1. Go to openvidu folder:'
|
||||||
printf '\n $ cd openvidu'
|
printf '\n $ cd openvidu'
|
||||||
printf '\n'
|
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 $ nano .env'
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf '\n 3. Start OpenVidu'
|
printf '\n 3. Start OpenVidu'
|
||||||
printf '\n $ ./openvidu start'
|
printf '\n $ ./openvidu start'
|
||||||
printf '\n'
|
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 For more information, check:"
|
||||||
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions"
|
printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions"
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|
@ -147,10 +158,13 @@ upgrade_ov() {
|
||||||
|
|
||||||
# Uppgrade Openvidu
|
# Uppgrade Openvidu
|
||||||
OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }')
|
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
|
# 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.
|
# 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 ======================================='
|
printf '\n ======================================='
|
||||||
|
|
@ -188,6 +202,10 @@ upgrade_ov() {
|
||||||
--output "${TMP_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
--output "${TMP_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'"
|
||||||
printf '\n - 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 \
|
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'"
|
--output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||||
printf '\n - .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'"
|
mv "${OPENVIDU_PREVIOUS_FOLDER}/openvidu" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'openvidu'"
|
||||||
printf '\n - 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'"
|
mv "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'cluster/aws'"
|
||||||
printf '\n - 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'"
|
cp "${OPENVIDU_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'"
|
||||||
printf '\n - .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
|
# Move tmp files to Openvidu
|
||||||
printf '\n => Updating files:'
|
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'"
|
mv "${TMP_FOLDER}/filebeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/filebeat.yml" || fatal_error "Error while updating 'filebeat.yml'"
|
||||||
printf '\n - 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"
|
printf "\n => Deleting 'tmp' folder"
|
||||||
rm -rf "${TMP_FOLDER}" || fatal_error "Error 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"
|
[ ! -z "${OLD_MODE}" ] && sed -i -r "s/Installation Mode:.+/Installation Mode: ${OLD_MODE}/" "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml"
|
||||||
|
|
||||||
# In Aws, update AMI ID
|
# In Aws, update AMI ID
|
||||||
CHECK_AWS=$(curl -s -o /dev/null -w "%{http_code}" http://169.254.169.254)
|
AWS_REGION=$(grep -E "AWS_DEFAULT_REGION=.*$" "${OPENVIDU_PREVIOUS_FOLDER}/.env" | cut -d'=' -f2)
|
||||||
if [[ ${CHECK_AWS} == "200" ]]; then
|
if [[ ! -z ${AWS_REGION} ]]; 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"
|
|
||||||
NEW_AMI_ID=$(curl https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_VERSION//v}.yaml --silent |
|
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' |
|
sed -n -e '/KMSAMIMAP:/,/Metadata:/ p' |
|
||||||
grep -A 1 ${AWS_REGION} | grep AMI | tr -d " " | cut -d":" -f2)
|
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"
|
[[ -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"
|
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
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Ready to use
|
# Ready to use
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ generate_report() {
|
||||||
printf '\n'
|
printf '\n'
|
||||||
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'
|
||||||
printf '\n ========= docker-compose.yml =========='
|
printf '\n ========= docker-compose.yml =========='
|
||||||
|
|
@ -183,6 +183,42 @@ generate_report() {
|
||||||
printf "\n"
|
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() {
|
usage() {
|
||||||
printf "Usage: \n\t openvidu [command]"
|
printf "Usage: \n\t openvidu [command]"
|
||||||
printf "\n\nAvailable Commands:"
|
printf "\n\nAvailable Commands:"
|
||||||
|
|
@ -198,11 +234,15 @@ usage() {
|
||||||
printf "\n"
|
printf "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[ -z "${FOLLOW_OPENVIDU_LOGS}" ]] && FOLLOW_OPENVIDU_LOGS=true
|
||||||
|
|
||||||
case $1 in
|
case $1 in
|
||||||
|
|
||||||
start)
|
start)
|
||||||
docker-compose up -d
|
start_openvidu
|
||||||
docker-compose logs -f openvidu-server
|
if [[ "${FOLLOW_OPENVIDU_LOGS}" == "true" ]]; then
|
||||||
|
docker-compose logs -f openvidu-server
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
stop)
|
stop)
|
||||||
|
|
@ -211,8 +251,10 @@ case $1 in
|
||||||
|
|
||||||
restart)
|
restart)
|
||||||
docker-compose down
|
docker-compose down
|
||||||
docker-compose up -d
|
start_openvidu
|
||||||
docker-compose logs -f openvidu-server
|
if [[ "${FOLLOW_OPENVIDU_LOGS}" == "true" ]]; then
|
||||||
|
docker-compose logs -f openvidu-server
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
logs)
|
logs)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
global:
|
global:
|
||||||
owner: openvidu@gmail.com
|
owner: info@openvidu.io
|
||||||
qsname: openvidu-pro-clustering
|
qsname: openvidu-pro-clustering
|
||||||
regions:
|
regions:
|
||||||
- us-east-1
|
- us-east-1
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
FROM ubuntu:16.04
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y coturn curl
|
&& apt-get install -y coturn curl dnsutils
|
||||||
|
|
||||||
COPY ./configuration-files.sh /tmp/
|
COPY ./configuration-files.sh /tmp/
|
||||||
COPY ./entrypoint.sh /usr/local/bin
|
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/entrypoint.sh \
|
||||||
&& chmod +x /usr/local/bin/discover_my_public_ip.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