mirror of https://github.com/OpenVidu/openvidu.git
Merge branch 'master' into participant-event-role
commit
23ade52816
|
@ -1,8 +1,9 @@
|
|||
name: openvidu-angular E2E
|
||||
name: openvidu-components-angular E2E
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'openvidu-components-angular/**'
|
||||
- 'openvidu-browser/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
@ -23,6 +24,16 @@ jobs:
|
|||
run: docker run -d --shm-size="2g" --network host selenium/standalone-chrome:latest
|
||||
- name: Run openvidu-server-kms
|
||||
run: docker run -p 4443:4443 --rm -d -e OPENVIDU_SECRET=MY_SECRET openvidu/openvidu-server-kms:latest
|
||||
- name: Build openvidu-browser
|
||||
run: |
|
||||
cd openvidu-browser
|
||||
npm install
|
||||
npm run build && npm pack
|
||||
mv openvidu-browser-*.tgz ../openvidu-components-angular
|
||||
- name: Install openvidu-browser
|
||||
run: |
|
||||
cd openvidu-components-angular
|
||||
npm install openvidu-browser-*.tgz
|
||||
- name: Install dependencies
|
||||
run: npm install --prefix openvidu-components-angular
|
||||
- name: Build openvidu-angular
|
||||
|
@ -31,11 +42,11 @@ jobs:
|
|||
run: npm run webcomponent:build --prefix openvidu-components-angular
|
||||
- name: Build openvidu-angular-testapp
|
||||
run: npm run build --prefix openvidu-components-angular
|
||||
- name: Run Angular Testapp
|
||||
- name: Serve openvidu-angular-testapp
|
||||
run: npm run start-prod --prefix openvidu-components-angular &
|
||||
- name: Run Angular E2E
|
||||
- name: Run openvidu-angular E2E
|
||||
run: npm run lib:e2e-ci --prefix openvidu-components-angular
|
||||
- name: Run Webcomponent Testapp
|
||||
- name: Serve Webcomponent Testapp
|
||||
run: npm run webcomponent:serve-testapp --prefix openvidu-components-angular &
|
||||
- name: Run Webcomponent E2E
|
||||
run: npm run webcomponent:e2e-ci --prefix openvidu-components-angular
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "openvidu-browser",
|
||||
"version": "2.21.0",
|
||||
"version": "2.22.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "openvidu-browser",
|
||||
"version": "2.21.0",
|
||||
"version": "2.22.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"events": "3.3.0",
|
||||
|
|
|
@ -53,5 +53,5 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"version": "2.21.0"
|
||||
"version": "2.22.0"
|
||||
}
|
|
@ -635,7 +635,7 @@ export class OpenVidu {
|
|||
if (attempts > MAX_ATTEMPTS) {
|
||||
clearTimeout(repeatUntilChangeOrMaxAttempts);
|
||||
}
|
||||
publisher.getVideoDimensions(publisher.stream.getMediaStream()).then(newDimensions => {
|
||||
publisher.getVideoDimensions().then(newDimensions => {
|
||||
if (newDimensions.width !== oldWidth || newDimensions.height !== oldHeight) {
|
||||
clearTimeout(repeatUntilChangeOrMaxAttempts);
|
||||
this.sendVideoDimensionsChangedEvent(publisher, reason, oldWidth, oldHeight, newDimensions.width, newDimensions.height);
|
||||
|
|
|
@ -168,7 +168,9 @@ export class Publisher extends StreamManager {
|
|||
* useful if the Publisher was unpublished freeing the hardware resource, and openvidu-browser is not able to successfully re-create the video track as it was before unpublishing. In this way previous track settings will be ignored and this MediaStreamTrack
|
||||
* will be used instead.
|
||||
*/
|
||||
publishVideo<T extends boolean>(enabled: T, resource?: T extends false ? boolean : MediaStreamTrack): void {
|
||||
publishVideo<T extends boolean>(enabled: T, resource?: T extends false ? boolean : MediaStreamTrack): Promise<void> {
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
if (this.stream.videoActive !== enabled) {
|
||||
|
||||
|
@ -184,27 +186,43 @@ export class Publisher extends StreamManager {
|
|||
}
|
||||
});
|
||||
|
||||
// There is a Virtual Background filter applied that must be removed in case the hardware must be freed
|
||||
if (!enabled && resource === true && !!this.stream.filter && this.stream.filter.type.startsWith('VB:')) {
|
||||
this.stream.lastVBFilter = this.stream.filter; // Save the filter to be re-applied in case of unmute
|
||||
await this.stream.removeFilterAux(true);
|
||||
}
|
||||
|
||||
if (mustRestartMediaStream) {
|
||||
const oldVideoTrack = affectedMediaStream.getVideoTracks()[0];
|
||||
affectedMediaStream.removeTrack(oldVideoTrack);
|
||||
|
||||
const replaceVideoTrack = (tr: MediaStreamTrack) => {
|
||||
const replaceVideoTrack = async (tr: MediaStreamTrack) => {
|
||||
affectedMediaStream.addTrack(tr);
|
||||
if (this.stream.isLocalStreamPublished) {
|
||||
this.replaceTrackInRtcRtpSender(tr);
|
||||
await this.replaceTrackInRtcRtpSender(tr);
|
||||
}
|
||||
if (!!this.stream.lastVBFilter) {
|
||||
setTimeout(async () => {
|
||||
let options = this.stream.lastVBFilter!.options;
|
||||
const lastExecMethod = this.stream.lastVBFilter!.lastExecMethod;
|
||||
if (!!lastExecMethod && lastExecMethod.method === 'update') {
|
||||
options = Object.assign({}, options, lastExecMethod.params);
|
||||
}
|
||||
await this.stream.applyFilter(this.stream.lastVBFilter!.type, options);
|
||||
delete this.stream.lastVBFilter;
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!!resource && resource instanceof MediaStreamTrack) {
|
||||
replaceVideoTrack(resource);
|
||||
await replaceVideoTrack(resource);
|
||||
} else {
|
||||
navigator.mediaDevices.getUserMedia({ audio: false, video: this.stream.lastVideoTrackConstraints })
|
||||
.then(mediaStream => {
|
||||
replaceVideoTrack(mediaStream.getVideoTracks()[0]);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
try {
|
||||
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: this.stream.lastVideoTrackConstraints });
|
||||
await replaceVideoTrack(mediaStream.getVideoTracks()[0]);
|
||||
} catch (error) {
|
||||
return reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +247,9 @@ export class Publisher extends StreamManager {
|
|||
}
|
||||
this.stream.videoActive = enabled;
|
||||
logger.info("'Publisher' has " + (enabled ? 'published' : 'unpublished') + ' its video stream');
|
||||
return resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -329,27 +349,7 @@ export class Publisher extends StreamManager {
|
|||
* @returns A Promise (to which you can optionally subscribe to) that is resolved if the track was successfully replaced and rejected with an Error object in other case
|
||||
*/
|
||||
async replaceTrack(track: MediaStreamTrack): Promise<void> {
|
||||
// Set field "enabled" of the new track to the previous value
|
||||
const trackOriginalEnabledValue: boolean = track.enabled;
|
||||
if (track.kind === 'video') {
|
||||
track.enabled = this.stream.videoActive;
|
||||
} else if (track.kind === 'audio') {
|
||||
track.enabled = this.stream.audioActive;
|
||||
}
|
||||
try {
|
||||
if (this.stream.isLocalStreamPublished) {
|
||||
// Only if the Publisher has been published is necessary to call native Web API RTCRtpSender.replaceTrack
|
||||
// If it has not been published yet, replacing it on the MediaStream object is enough
|
||||
await this.replaceTrackInMediaStream(track);
|
||||
return await this.replaceTrackInRtcRtpSender(track);
|
||||
} else {
|
||||
// Publisher not published. Simply replace the track on the local MediaStream
|
||||
return await this.replaceTrackInMediaStream(track);
|
||||
}
|
||||
} catch (error) {
|
||||
track.enabled = trackOriginalEnabledValue;
|
||||
throw error;
|
||||
}
|
||||
return this.replaceTrackAux(track, true);
|
||||
}
|
||||
|
||||
/* Hidden methods */
|
||||
|
@ -438,7 +438,7 @@ export class Publisher extends StreamManager {
|
|||
|
||||
if (this.stream.isSendVideo()) {
|
||||
// Has video track
|
||||
this.getVideoDimensions(mediaStream).then(dimensions => {
|
||||
this.getVideoDimensions().then(dimensions => {
|
||||
this.stream.videoDimensions = {
|
||||
width: dimensions.width,
|
||||
height: dimensions.height
|
||||
|
@ -636,6 +636,33 @@ export class Publisher extends StreamManager {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
async replaceTrackAux(track: MediaStreamTrack, updateLastConstraints: boolean): Promise<void> {
|
||||
// Set field "enabled" of the new track to the previous value
|
||||
const trackOriginalEnabledValue: boolean = track.enabled;
|
||||
if (track.kind === 'video') {
|
||||
track.enabled = this.stream.videoActive;
|
||||
} else if (track.kind === 'audio') {
|
||||
track.enabled = this.stream.audioActive;
|
||||
}
|
||||
try {
|
||||
if (this.stream.isLocalStreamPublished) {
|
||||
// Only if the Publisher has been published is necessary to call native Web API RTCRtpSender.replaceTrack
|
||||
// If it has not been published yet, replacing it on the MediaStream object is enough
|
||||
await this.replaceTrackInMediaStream(track, updateLastConstraints);
|
||||
return await this.replaceTrackInRtcRtpSender(track);
|
||||
} else {
|
||||
// Publisher not published. Simply replace the track on the local MediaStream
|
||||
return await this.replaceTrackInMediaStream(track, updateLastConstraints);
|
||||
}
|
||||
} catch (error) {
|
||||
track.enabled = trackOriginalEnabledValue;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*
|
||||
|
@ -643,7 +670,7 @@ export class Publisher extends StreamManager {
|
|||
* and then try to use MediaStreamTrack.getSettingsMethod(). If not available, then we
|
||||
* use the HTMLVideoElement properties videoWidth and videoHeight
|
||||
*/
|
||||
getVideoDimensions(mediaStream: MediaStream): Promise<{ width: number, height: number }> {
|
||||
getVideoDimensions(): Promise<{ width: number, height: number }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
// Ionic iOS and Safari iOS supposedly require the video element to actually exist inside the DOM
|
||||
|
@ -729,19 +756,21 @@ export class Publisher extends StreamManager {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
async replaceTrackInMediaStream(track: MediaStreamTrack): Promise<void> {
|
||||
async replaceTrackInMediaStream(track: MediaStreamTrack, updateLastConstraints: boolean): Promise<void> {
|
||||
const mediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream();
|
||||
let removedTrack: MediaStreamTrack;
|
||||
if (track.kind === 'video') {
|
||||
removedTrack = mediaStream.getVideoTracks()[0];
|
||||
if (updateLastConstraints) {
|
||||
this.stream.lastVideoTrackConstraints = track.getConstraints();
|
||||
}
|
||||
} else {
|
||||
removedTrack = mediaStream.getAudioTracks()[0];
|
||||
}
|
||||
mediaStream.removeTrack(removedTrack);
|
||||
removedTrack.stop();
|
||||
mediaStream.addTrack(track);
|
||||
if (track.kind === 'video' && this.stream.isLocalStreamPublished) {
|
||||
if (track.kind === 'video' && this.stream.isLocalStreamPublished && updateLastConstraints) {
|
||||
this.openvidu.sendNewVideoDimensionsIfRequired(this, 'trackReplaced', 50, 30);
|
||||
this.session.sendVideoData(this.stream.streamManager, 5, true, 5);
|
||||
}
|
||||
|
|
|
@ -232,6 +232,10 @@ export class Stream {
|
|||
* @hidden
|
||||
*/
|
||||
lastVideoTrackConstraints: MediaTrackConstraints | boolean | undefined;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
lastVBFilter?: Filter;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -421,9 +425,9 @@ export class Stream {
|
|||
videoClone.style.display = 'none';
|
||||
|
||||
if (this.streamManager.remote) {
|
||||
this.streamManager.replaceTrackInMediaStream((this.virtualBackgroundSinkElements.video.srcObject as MediaStream).getVideoTracks()[0]);
|
||||
this.streamManager.replaceTrackInMediaStream((this.virtualBackgroundSinkElements.video.srcObject as MediaStream).getVideoTracks()[0], false);
|
||||
} else {
|
||||
(this.streamManager as Publisher).replaceTrack((this.virtualBackgroundSinkElements.video.srcObject as MediaStream).getVideoTracks()[0]);
|
||||
(this.streamManager as Publisher).replaceTrackAux((this.virtualBackgroundSinkElements.video.srcObject as MediaStream).getVideoTracks()[0], false);
|
||||
}
|
||||
|
||||
resolveApplyFilter(undefined, false);
|
||||
|
@ -553,9 +557,9 @@ export class Stream {
|
|||
const mediaStreamClone = this.virtualBackgroundSourceElements!.mediaStreamClone;
|
||||
if (!isDisposing) {
|
||||
if (this.streamManager.remote) {
|
||||
await this.streamManager.replaceTrackInMediaStream(mediaStreamClone.getVideoTracks()[0]);
|
||||
await this.streamManager.replaceTrackInMediaStream(mediaStreamClone.getVideoTracks()[0], false);
|
||||
} else {
|
||||
await (this.streamManager as Publisher).replaceTrack(mediaStreamClone.getVideoTracks()[0]);
|
||||
await (this.streamManager as Publisher).replaceTrackAux(mediaStreamClone.getVideoTracks()[0], false);
|
||||
}
|
||||
} else {
|
||||
mediaStreamClone.getTracks().forEach((track) => track.stop());
|
||||
|
|
|
@ -529,7 +529,7 @@ export abstract class StreamManager extends EventDispatcher {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
abstract replaceTrackInMediaStream(track: MediaStreamTrack): Promise<void>;
|
||||
abstract replaceTrackInMediaStream(track: MediaStreamTrack, updateLastConstraints: boolean): Promise<void>;
|
||||
|
||||
/* Private methods */
|
||||
|
||||
|
|
|
@ -78,12 +78,14 @@ export class Subscriber extends StreamManager {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
async replaceTrackInMediaStream(track: MediaStreamTrack): Promise<void> {
|
||||
async replaceTrackInMediaStream(track: MediaStreamTrack, updateLastConstraints: boolean): Promise<void> {
|
||||
const mediaStream: MediaStream = this.stream.getMediaStream();
|
||||
let removedTrack: MediaStreamTrack;
|
||||
if (track.kind === 'video') {
|
||||
removedTrack = mediaStream.getVideoTracks()[0];
|
||||
if (updateLastConstraints) {
|
||||
this.stream.lastVideoTrackConstraints = track.getConstraints();
|
||||
}
|
||||
} else {
|
||||
removedTrack = mediaStream.getAudioTracks()[0];
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -50,9 +50,9 @@
|
|||
"@types/chai": "4.3.0",
|
||||
"@types/mocha": "9.1.0",
|
||||
"@types/node": "16.11.6",
|
||||
"@types/selenium-webdriver": "4.0.18",
|
||||
"@types/selenium-webdriver": "4.0.20",
|
||||
"chai": "4.3.6",
|
||||
"chromedriver": "99.0.0",
|
||||
"chromedriver": "101.0.0",
|
||||
"codelyzer": "6.0.2",
|
||||
"concat": "^1.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
|
@ -70,7 +70,7 @@
|
|||
"karma-notify-reporter": "1.3.0",
|
||||
"mocha": "9.2.2",
|
||||
"ng-packagr": "13.0.3",
|
||||
"selenium-webdriver": "4.1.1",
|
||||
"selenium-webdriver": "4.1.2",
|
||||
"ts-node": "10.4.0",
|
||||
"tslint": "6.1.3",
|
||||
"typescript": "4.4.4",
|
||||
|
|
|
@ -1,28 +1,3 @@
|
|||
#activities-container {
|
||||
margin: 20px;
|
||||
background-color: var(--ov-panel-background);
|
||||
border-radius: var(--ov-panel-radius);
|
||||
max-height: calc(100% - 40px);
|
||||
min-height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.header-container {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-container h3 {
|
||||
margin-left: 5px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header-container button {
|
||||
margin-left: auto;
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
}
|
||||
|
||||
.activities-body-container {
|
||||
display: block !important;
|
||||
overflow-y: auto;
|
||||
|
@ -40,7 +15,6 @@
|
|||
margin: auto;
|
||||
}
|
||||
|
||||
|
||||
.activity-subtitle {
|
||||
font-style: italic;
|
||||
font-size: 11px !important;
|
||||
|
@ -49,7 +23,7 @@
|
|||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.activity-action-buttons{
|
||||
.activity-action-buttons {
|
||||
align-self: flex-start;
|
||||
margin-top: 15px;
|
||||
font-weight: 600;
|
||||
|
@ -63,7 +37,8 @@
|
|||
padding: 0px 10px !important;
|
||||
}
|
||||
|
||||
::ng-deep .mat-list-base .mat-list-item .mat-list-item-content, .mat-list-base .mat-list-option .mat-list-item-content {
|
||||
::ng-deep .mat-list-base .mat-list-item .mat-list-item-content,
|
||||
.mat-list-base .mat-list-option .mat-list-item-content {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="panel" id="activities-container" fxLayout="column" fxLayoutAlign="space-evenly none">
|
||||
<div class="header-container" fxFlex="55px" fxLayoutAlign="start center">
|
||||
<h3>Activities</h3>
|
||||
<button mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<div class="panel-container" id="activities-container" fxLayout="column" fxLayoutAlign="space-evenly none">
|
||||
<div class="panel-header-container" fxFlex="55px" fxLayoutAlign="start center">
|
||||
<h3 class="panel-title">Activities</h3>
|
||||
<button class="panel-close-button" mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ import { PanelService } from '../../../services/panel/panel.service';
|
|||
@Component({
|
||||
selector: 'ov-activities-panel',
|
||||
templateUrl: './activities-panel.component.html',
|
||||
styleUrls: ['./activities-panel.component.css']
|
||||
styleUrls: ['../panel.component.css','./activities-panel.component.css']
|
||||
})
|
||||
export class ActivitiesPanelComponent implements OnInit {
|
||||
constructor(private panelService: PanelService) {}
|
||||
|
|
|
@ -1,28 +1,3 @@
|
|||
#background-effects-container {
|
||||
margin: 20px;
|
||||
background-color: var(--ov-panel-background);
|
||||
border-radius: var(--ov-panel-radius);
|
||||
max-height: calc(100% - 40px);
|
||||
min-height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.header-container {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-container h3 {
|
||||
margin-left: 5px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header-container button {
|
||||
margin-left: auto;
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
}
|
||||
|
||||
.effects-container {
|
||||
display: block !important;
|
||||
overflow-y: auto;
|
||||
|
@ -70,21 +45,3 @@
|
|||
::ng-deep .mat-slider-vertical .mat-slider-track-wrapper {
|
||||
width: 10px !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #a7a7a7;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #7c7c7c;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--ov-light-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="panel" id="background-effects-container" fxLayout="column" fxLayoutAlign="space-evenly none">
|
||||
<div class="header-container" fxFlex="55px" fxLayoutAlign="start center">
|
||||
<h3>Background effects</h3>
|
||||
<button mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<div class="panel-container" id="background-effects-container" fxLayout="column" fxLayoutAlign="space-evenly none">
|
||||
<div class="panel-header-container" fxFlex="55px" fxLayoutAlign="start center">
|
||||
<h3 class="panel-title">Background effects</h3>
|
||||
<button class="panel-close-button" mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@ import { VirtualBackgroundService } from '../../../services/virtual-background/v
|
|||
@Component({
|
||||
selector: 'ov-background-effects-panel',
|
||||
templateUrl: './background-effects-panel.component.html',
|
||||
styleUrls: ['./background-effects-panel.component.css'],
|
||||
styleUrls: ['../panel.component.css','./background-effects-panel.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class BackgroundEffectsPanelComponent implements OnInit {
|
||||
|
@ -19,7 +19,7 @@ export class BackgroundEffectsPanelComponent implements OnInit {
|
|||
private backgrounds: BackgroundEffect[];
|
||||
private backgroundSubs: Subscription;
|
||||
|
||||
constructor(private panelService: PanelService, private backgroundService: VirtualBackgroundService, private cd: ChangeDetectorRef) {}
|
||||
constructor(private panelService: PanelService, private backgroundService: VirtualBackgroundService, private cd: ChangeDetectorRef) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.subscribeToBackgroundSelected();
|
||||
|
@ -29,7 +29,7 @@ export class BackgroundEffectsPanelComponent implements OnInit {
|
|||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if(this.backgroundSubs) this.backgroundSubs.unsubscribe();
|
||||
if (this.backgroundSubs) this.backgroundSubs.unsubscribe();
|
||||
}
|
||||
subscribeToBackgroundSelected() {
|
||||
this.backgroundSubs = this.backgroundService.backgroundSelectedObs.subscribe((id) => {
|
||||
|
@ -43,13 +43,11 @@ export class BackgroundEffectsPanelComponent implements OnInit {
|
|||
}
|
||||
|
||||
async applyBackground(effect: BackgroundEffect) {
|
||||
|
||||
if(effect.type === EffectType.NONE){
|
||||
if (effect.type === EffectType.NONE) {
|
||||
await this.removeBackground();
|
||||
} else {
|
||||
await this.backgroundService.applyBackground(effect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async removeBackground() {
|
||||
|
|
|
@ -1,28 +1,4 @@
|
|||
#chat-container {
|
||||
margin: 20px;
|
||||
background-color: var(--ov-panel-background);
|
||||
border-radius: var(--ov-panel-radius);
|
||||
max-height: calc(100% - 40px);
|
||||
min-height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.header-container {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-container h3 {
|
||||
margin-left: 5px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.header-container button {
|
||||
margin-left: auto;
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
}
|
||||
|
||||
.text-container{
|
||||
.text-container {
|
||||
/* padding: 5px; */
|
||||
background-color: var(--ov-light-color);
|
||||
color: var(--ov-panel-text-color);
|
||||
|
@ -33,7 +9,6 @@
|
|||
|
||||
.text-info {
|
||||
margin: 3px;
|
||||
|
||||
}
|
||||
|
||||
.messages-container {
|
||||
|
@ -68,32 +43,31 @@
|
|||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
font-family: 'Roboto','RobotoDraft',Helvetica,Arial,sans-serif;
|
||||
font-family: 'Roboto', 'RobotoDraft', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.message {
|
||||
.message {
|
||||
position: relative;
|
||||
padding: 3px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-detail {
|
||||
.msg-detail {
|
||||
width: 95%;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-detail p {
|
||||
.msg-detail p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.nickname-container p {
|
||||
.nickname-container p {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: var(--ov-panel-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.msg-content {
|
||||
.msg-content {
|
||||
position: relative;
|
||||
border-radius: var(--ov-panel-radius);
|
||||
padding: 8px;
|
||||
|
@ -102,12 +76,11 @@
|
|||
max-width: 95%;
|
||||
font-size: 13px;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
#send-btn {
|
||||
#send-btn {
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Start message from other user */
|
||||
|
||||
|
@ -119,30 +92,18 @@
|
|||
float: left;
|
||||
}
|
||||
|
||||
/* End message from other user */
|
||||
|
||||
/* End message from other user */
|
||||
/* Start my messages */
|
||||
|
||||
/* Start my messages */
|
||||
|
||||
.message.right .msg-detail .nickname-container {
|
||||
.message.right .msg-detail .nickname-container {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.message.right .msg-detail .msg-content {
|
||||
.message.right .msg-detail .msg-content {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* End my messages */
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #6b6b6b;
|
||||
}
|
||||
|
||||
::ng-deep a:-webkit-any-link {
|
||||
::ng-deep a:-webkit-any-link {
|
||||
color: #1a73e8;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<div id="chat-container" fxLayout="column" fxLayoutAlign="space-evenly none" >
|
||||
<div class="header-container" fxFlex="55px" fxLayoutAlign="start center">
|
||||
<h3>Chat</h3>
|
||||
<button mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<div class="panel-container" id="chat-container" fxLayout="column" fxLayoutAlign="space-evenly none" >
|
||||
<div class="panel-header-container" fxFlex="55px" fxLayoutAlign="start center">
|
||||
<h3 class="panel-title">Chat</h3>
|
||||
<button class="panel-close-button" mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -41,7 +41,7 @@ import { PanelService } from '../../../services/panel/panel.service';
|
|||
@Component({
|
||||
selector: 'ov-chat-panel',
|
||||
templateUrl: './chat-panel.component.html',
|
||||
styleUrls: ['./chat-panel.component.css'],
|
||||
styleUrls: ['../panel.component.css','./chat-panel.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ChatPanelComponent implements OnInit, AfterViewInit {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
.panel-container {
|
||||
margin: 20px;
|
||||
background-color: var(--ov-panel-background);
|
||||
border-radius: var(--ov-panel-radius);
|
||||
max-height: calc(100% - 40px);
|
||||
min-height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.panel-header-container {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
margin-left: 5px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.panel-close-button {
|
||||
margin-left: auto;
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #a7a7a7;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #7c7c7c;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--ov-light-color);
|
||||
border-radius: 4px;
|
||||
}
|
|
@ -1,28 +1,5 @@
|
|||
.participants-container {
|
||||
margin: 20px;
|
||||
background-color: var(--ov-panel-background);
|
||||
border-radius: var(--ov-panel-radius);
|
||||
max-height: calc(100% - 40px);
|
||||
min-height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.header-container {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-container h3 {
|
||||
margin-left: 5px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.header-container button {
|
||||
margin-left: auto;
|
||||
border-radius: var(--ov-buttons-radius);
|
||||
}
|
||||
|
||||
.local-participant-container, .remote-participants-container {
|
||||
.local-participant-container,
|
||||
.remote-participants-container {
|
||||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
|
@ -32,7 +9,7 @@
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.message-container{
|
||||
.message-container {
|
||||
padding: 5px;
|
||||
background-color: var(--ov-light-color);
|
||||
color: var(--ov-panel-text-color);
|
||||
|
@ -41,7 +18,6 @@
|
|||
font-size: 12px;
|
||||
}
|
||||
|
||||
.message-container p{
|
||||
.message-container p {
|
||||
margin: 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="participants-container" id="participants-container">
|
||||
<div class="header-container">
|
||||
<h3>Participants</h3>
|
||||
<button mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<div class="panel-container" id="participants-container">
|
||||
<div class="panel-header-container">
|
||||
<h3 class="panel-title">Participants</h3>
|
||||
<button class="panel-close-button" mat-icon-button matTooltip="Close" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -41,7 +41,7 @@ import { Subscription } from 'rxjs';
|
|||
@Component({
|
||||
selector: 'ov-participants-panel',
|
||||
templateUrl: './participants-panel.component.html',
|
||||
styleUrls: ['./participants-panel.component.css'],
|
||||
styleUrls: ['../../panel.component.css','./participants-panel.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ParticipantsPanelComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<ng-template #stream let-stream>
|
||||
<button
|
||||
*ngIf="!isMinimal && showBackgroundEffectsButton"
|
||||
[disabled]="isVideoMuted"
|
||||
mat-icon-button
|
||||
id="background-effects-btn"
|
||||
(click)="toggleBackgroundEffects()"
|
||||
|
@ -72,7 +73,7 @@
|
|||
<button
|
||||
mat-icon-button
|
||||
id="camera-button"
|
||||
[disabled]="!hasVideoDevices"
|
||||
[disabled]="!hasVideoDevices || videoMuteChanging"
|
||||
[class.warn-btn]="isVideoMuted"
|
||||
(click)="toggleCam()"
|
||||
>
|
||||
|
|
|
@ -20,6 +20,7 @@ import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
|||
import { PanelService } from '../../services/panel/panel.service';
|
||||
import { ParticipantService } from '../../services/participant/participant.service';
|
||||
import { StorageService } from '../../services/storage/storage.service';
|
||||
import { VirtualBackgroundService } from '../../services/virtual-background/virtual-background.service';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
@ -37,6 +38,7 @@ export class PreJoinComponent implements OnInit, OnDestroy {
|
|||
microphoneSelected: CustomDevice;
|
||||
isVideoMuted: boolean;
|
||||
isAudioMuted: boolean;
|
||||
videoMuteChanging: boolean;
|
||||
localParticipant: ParticipantAbstractModel;
|
||||
windowSize: number;
|
||||
hasVideoDevices: boolean;
|
||||
|
@ -72,7 +74,8 @@ export class PreJoinComponent implements OnInit, OnDestroy {
|
|||
private participantService: ParticipantService,
|
||||
protected panelService: PanelService,
|
||||
private libService: OpenViduAngularConfigService,
|
||||
private storageSrv: StorageService
|
||||
private storageSrv: StorageService,
|
||||
private backgroundService: VirtualBackgroundService
|
||||
) {
|
||||
this.log = this.loggerSrv.get('PreJoinComponent');
|
||||
}
|
||||
|
@ -95,17 +98,12 @@ export class PreJoinComponent implements OnInit, OnDestroy {
|
|||
this.isLoading = false;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.localParticipantSubscription) {
|
||||
this.localParticipantSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.screenShareStateSubscription) {
|
||||
this.screenShareStateSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
async ngOnDestroy() {
|
||||
if (this.localParticipantSubscription) this.localParticipantSubscription.unsubscribe();
|
||||
if (this.screenShareStateSubscription) this.screenShareStateSubscription.unsubscribe();
|
||||
if (this.backgroundEffectsButtonSub) this.backgroundEffectsButtonSub.unsubscribe();
|
||||
if (this.minimalSub) this.minimalSub.unsubscribe();
|
||||
this.panelService.closePanel();
|
||||
}
|
||||
|
||||
async onCameraSelected(event: any) {
|
||||
|
@ -118,7 +116,16 @@ export class PreJoinComponent implements OnInit, OnDestroy {
|
|||
// await this.openviduService.replaceTrack(VideoType.CAMERA, pp);
|
||||
// TODO: Remove this when replaceTrack issue is fixed
|
||||
const pp: PublisherProperties = { videoSource, audioSource: this.microphoneSelected.device, mirror };
|
||||
|
||||
// Reapply Virtual Background to new Publisher if necessary
|
||||
const backgroundSelected = this.backgroundService.backgroundSelected.getValue();
|
||||
if (this.backgroundService.isBackgroundApplied()) {
|
||||
await this.backgroundService.removeBackground();
|
||||
}
|
||||
await this.openviduService.republishTrack(pp);
|
||||
if (this.backgroundService.isBackgroundApplied()) {
|
||||
await this.backgroundService.applyBackground(this.backgroundService.backgrounds.find(b => b.id === backgroundSelected));
|
||||
}
|
||||
|
||||
this.deviceSrv.setCameraSelected(videoSource);
|
||||
this.cameraSelected = this.deviceSrv.getCameraSelected();
|
||||
|
@ -142,10 +149,15 @@ export class PreJoinComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
async toggleCam() {
|
||||
this.videoMuteChanging = true;
|
||||
const publish = this.isVideoMuted;
|
||||
await this.openviduService.publishVideo(publish);
|
||||
this.isVideoMuted = !this.isVideoMuted;
|
||||
this.storageSrv.setVideoMuted(this.isVideoMuted);
|
||||
if (this.isVideoMuted && this.panelService.isExternalPanelOpened()) {
|
||||
this.panelService.togglePanel(PanelType.BACKGROUND_EFFECTS);
|
||||
}
|
||||
this.videoMuteChanging = false;
|
||||
}
|
||||
|
||||
toggleMic() {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
id="camera-btn"
|
||||
mat-icon-button
|
||||
(click)="toggleCamera()"
|
||||
[disabled]="isConnectionLost || !hasVideoDevices"
|
||||
[disabled]="isConnectionLost || !hasVideoDevices || videoMuteChanging"
|
||||
[class.warn-btn]="!isWebcamVideoActive"
|
||||
>
|
||||
<mat-icon *ngIf="isWebcamVideoActive" matTooltip="Mute your cam" id="videocam">videocam</mat-icon>
|
||||
|
@ -93,7 +93,13 @@
|
|||
</button> -->
|
||||
|
||||
<!-- Virtual background button -->
|
||||
<button *ngIf="!isMinimal && showBackgroundEffectsButton" mat-menu-item id="virtual-bg-btn" (click)="toggleBackgroundEffects()">
|
||||
<button
|
||||
*ngIf="!isMinimal && showBackgroundEffectsButton"
|
||||
[disabled]="!isWebcamVideoActive"
|
||||
mat-menu-item
|
||||
id="virtual-bg-btn"
|
||||
(click)="toggleBackgroundEffects()"
|
||||
>
|
||||
<mat-icon>auto_awesome</mat-icon>
|
||||
<span>Background effects</span>
|
||||
</button>
|
||||
|
|
|
@ -277,6 +277,10 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
* @ignore
|
||||
*/
|
||||
showSessionName: boolean = true;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
videoMuteChanging: boolean = false;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
|
@ -395,15 +399,19 @@ export class ToolbarComponent implements OnInit, OnDestroy {
|
|||
* @ignore
|
||||
*/
|
||||
async toggleCamera() {
|
||||
this.videoMuteChanging = true;
|
||||
this.onCameraButtonClicked.emit();
|
||||
|
||||
try {
|
||||
const publishVideo = !this.participantService.isMyVideoActive();
|
||||
if(this.panelService.isExternalPanelOpened() && !publishVideo) {
|
||||
this.panelService.togglePanel(PanelType.BACKGROUND_EFFECTS);
|
||||
}
|
||||
await this.openviduService.publishVideo(publishVideo);
|
||||
} catch (error) {
|
||||
this.log.e('There was an error toggling camera:', error.code, error.message);
|
||||
this.actionService.openDialog('There was an error toggling camera', error?.error || error?.message);
|
||||
}
|
||||
this.videoMuteChanging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,162 +0,0 @@
|
|||
<!-- Modal -->
|
||||
<div class="modal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content cardContainer">
|
||||
<!-- Modal Header -->
|
||||
<div class="modal-header card-header">
|
||||
<div class="headerLogo">
|
||||
<img id="header_img" alt="OpenVidu Logo" src="assets/images/openvidu_logo.png" />
|
||||
</div>
|
||||
<h3 class="headerTitle" *ngIf="sessionId">{{ sessionId }}</h3>
|
||||
|
||||
<button mat-mini-fab (click)="close()" class="closeButton" id="closeButton">
|
||||
<mat-icon matTooltip="Close">close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Modal body -->
|
||||
<div class="modal-body" #bodyCard>
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-6 col-md-6 col-lg-6 leftSection">
|
||||
<div class="spinner-container" *ngIf="isLoading">
|
||||
<mat-spinner [diameter]="50"></mat-spinner>
|
||||
</div>
|
||||
<div class="videoContainer" *ngIf="!isLoading">
|
||||
<div *ngFor="let stream of localParticipant | streams">
|
||||
<!-- Only webcam video will be shown if webcamera is available -->
|
||||
<ov-video
|
||||
*ngIf="(stream.type === 'CAMERA' && hasVideoDevices) || stream.type === 'SCREEN'"
|
||||
[streamManager]="stream.streamManager"
|
||||
[ngClass]="{ ovVideoSmall: localParticipant.streams.size > 1 && stream.type === 'CAMERA' }"
|
||||
></ov-video>
|
||||
<div class="cameraMessageContainer" *ngIf="stream.type === 'CAMERA' && !hasVideoDevices">
|
||||
<span *ngIf="!hasVideoDevices && !hasAudioDevices">Oops! Camera and microphone are not available</span>
|
||||
<span *ngIf="!hasVideoDevices && hasAudioDevices">Oops! Camera is not available</span>
|
||||
<span *ngIf="hasVideoDevices && !hasAudioDevices">Oops! Microphone is not available</span>
|
||||
</div>
|
||||
<div id="audio-wave-container" *ngIf="stream.type === 'CAMERA'">
|
||||
<ov-audio-wave [streamManager]="stream.streamManager"></ov-audio-wave>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-md-6 col-lg-6 rightSection">
|
||||
<!-- Devices section / Camera-->
|
||||
<div fxLayout="row" fxFill id="devicesSection" *ngIf="hasVideoDevices">
|
||||
<div fxLayout fxFlex>
|
||||
<div class="one" fxFlex="20" fxLayoutAlign="center center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
(click)="toggleCam()"
|
||||
class="deviceButton"
|
||||
id="configCardCameraButton"
|
||||
[class.warn-btn]="isVideoMuted"
|
||||
>
|
||||
<mat-icon *ngIf="!isVideoMuted" matTooltip="Camera Enabled">videocam</mat-icon>
|
||||
<mat-icon *ngIf="isVideoMuted" matTooltip="Camera Disabled">videocam_off</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="two" fxFlex="80" fxLayoutAlign="center center">
|
||||
<mat-form-field class="alternate-theme">
|
||||
<mat-label>Camera Options</mat-label>
|
||||
<mat-select [disabled]="isVideoMuted" (selectionChange)="onCameraSelected($event)">
|
||||
<mat-option *ngFor="let camera of cameras" [value]="camera.device">
|
||||
{{ camera.label }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Devices section / Microphone-->
|
||||
<div fxLayout="row" fxFill id="devicesSection" *ngIf="hasAudioDevices">
|
||||
<div fxLayout fxFlex>
|
||||
<div class="one" fxFlex="20" fxLayoutAlign="center center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
(click)="toggleMic()"
|
||||
class="deviceButton"
|
||||
id="configCardMicrophoneButton"
|
||||
[class.warn-btn]="isAudioMuted"
|
||||
>
|
||||
<mat-icon *ngIf="!isAudioMuted" matTooltip="Microphone Enabled">mic</mat-icon>
|
||||
<mat-icon *ngIf="isAudioMuted" matTooltip="Microphone Disabled">mic_off</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="two" fxFlex="80" fxLayoutAlign="center center">
|
||||
<mat-form-field class="alternate-theme">
|
||||
<mat-label>Microphone Options</mat-label>
|
||||
<mat-select [disabled]="isAudioMuted" (selectionChange)="onMicrophoneSelected($event)">
|
||||
<mat-option *ngFor="let microphone of microphones" [value]="microphone.device">
|
||||
{{ microphone.label }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Devices section / ScreenShare-->
|
||||
<div fxLayout="row" fxFill id="devicesSection">
|
||||
<div fxLayout fxFlex>
|
||||
<div class="one" fxFlex="20" fxLayoutAlign="center center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
(click)="toggleScreenShare()"
|
||||
class="deviceButton"
|
||||
id="configCardScreenButton"
|
||||
[class.active-btn]="screenShareEnabled"
|
||||
>
|
||||
<mat-icon *ngIf="!screenShareEnabled" matTooltip="Enable screen share">screen_share</mat-icon>
|
||||
<mat-icon *ngIf="screenShareEnabled" matTooltip="Disable screen share">screen_share</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="two" fxFlex="80" fxLayoutAlign="center center">
|
||||
<mat-form-field class="alternate-theme">
|
||||
<input matInput disabled placeholder="Screen" [ngModel]="screenShareEnabled ? 'Screen' : 'None'" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Devices section / Nickname-->
|
||||
<div fxLayout="row" fxFill id="devicesSection">
|
||||
<div fxLayout fxFlex>
|
||||
<div class="one" fxFlex="20" fxLayoutAlign="center center">
|
||||
<button mat-mini-fab class="deviceButton" disabled>
|
||||
<mat-icon matTooltip="Nickname">person</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="two" fxFlex="80" fxLayoutAlign="center center">
|
||||
<form id="nicknameForm" class="alternate-theme">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="Nickname"
|
||||
[formControl]="nicknameFormControl"
|
||||
[errorStateMatcher]="matcher"
|
||||
(keypress)="eventKeyPress($event)"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<mat-error *ngIf="nicknameFormControl.hasError('required')">
|
||||
Nickname is <strong>required</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="nicknameFormControl.hasError('maxlength')">
|
||||
Nickname is <strong>too long!</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal footer -->
|
||||
<div class="modal-footer" style="justify-content: center">
|
||||
<button mat-flat-button (click)="joinSession()" form="nicknameForm" id="joinButton">JOIN</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,47 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ActionService } from '../../services/action/action.service';
|
||||
import { ActionServiceMock } from '../../services/action/action.service.mock';
|
||||
import { DeviceService } from '../../services/device/device.service';
|
||||
|
||||
import { DeviceServiceMock } from '../../services/device/device.service.mock';
|
||||
import { LocalUserService } from '../../services/local-user/local-user.service';
|
||||
import { LocalUserServiceMock } from '../../services/local-user/local-user.service.mock';
|
||||
import { LoggerService } from '../../services/logger/logger.service';
|
||||
import { LoggerServiceMock } from '../../services/logger/logger.service.mock';
|
||||
import { StorageService } from '../../services/storage/storage.service';
|
||||
import { WebrtcService } from '../../services/webrtc/webrtc.service';
|
||||
import { StorageServiceMock } from '../../services/storage/storage.service.mock';
|
||||
|
||||
import { WebrtcServiceMock } from '../../services/webrtc/webrtc.service.mock';
|
||||
|
||||
import { UserSettingsComponent } from './user-settings.component';
|
||||
|
||||
describe('UserSettingsComponent', () => {
|
||||
let component: UserSettingsComponent;
|
||||
let fixture: ComponentFixture<UserSettingsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ UserSettingsComponent ],
|
||||
providers: [
|
||||
{ provide: LoggerService, useClass: LoggerServiceMock },
|
||||
{ provide: ActionService, useClass: ActionServiceMock },
|
||||
{ provide: LocalUserService, useClass: LocalUserServiceMock },
|
||||
{ provide: WebrtcService, useClass: WebrtcServiceMock },
|
||||
{ provide: DeviceService, useClass: DeviceServiceMock },
|
||||
{ provide: StorageService, useClass: StorageServiceMock }
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UserSettingsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,321 +0,0 @@
|
|||
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { FormControl, Validators } from '@angular/forms';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { OpenViduErrorName } from 'openvidu-browser/lib/OpenViduInternal/Enums/OpenViduError';
|
||||
import { Publisher, PublisherProperties } from 'openvidu-browser';
|
||||
|
||||
import { ILogger } from '../../models/logger.model';
|
||||
import { CustomDevice } from '../../models/device.model';
|
||||
import { ScreenType, VideoType } from '../../models/video-type.model';
|
||||
|
||||
import { NicknameMatcher } from '../../matchers/nickname.matcher';
|
||||
|
||||
import { DeviceService } from '../../services/device/device.service';
|
||||
import { LoggerService } from '../../services/logger/logger.service';
|
||||
import { StorageService } from '../../services/storage/storage.service';
|
||||
import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
||||
import { ActionService } from '../../services/action/action.service';
|
||||
import { ParticipantService } from '../../services/participant/participant.service';
|
||||
import { ParticipantAbstractModel } from '../../models/participant.model';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ov-user-settings',
|
||||
templateUrl: './user-settings.component.html',
|
||||
styleUrls: ['./user-settings.component.css'],
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class UserSettingsComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('bodyCard') bodyCard: ElementRef;
|
||||
|
||||
@Input() sessionId: string;
|
||||
@Output() onJoinClicked = new EventEmitter<any>();
|
||||
@Output() onCloseClicked = new EventEmitter<any>();
|
||||
|
||||
cameras: CustomDevice[];
|
||||
microphones: CustomDevice[];
|
||||
cameraSelected: CustomDevice;
|
||||
microphoneSelected: CustomDevice;
|
||||
isVideoMuted: boolean;
|
||||
isAudioMuted: boolean;
|
||||
screenShareEnabled: boolean;
|
||||
localParticipant: ParticipantAbstractModel;
|
||||
columns: number;
|
||||
|
||||
nicknameFormControl = new FormControl('', [Validators.maxLength(20), Validators.required]);
|
||||
matcher = new NicknameMatcher();
|
||||
hasVideoDevices: boolean;
|
||||
hasAudioDevices: boolean;
|
||||
isLoading = true;
|
||||
private log: ILogger;
|
||||
private localParticipantSubscription: Subscription;
|
||||
private screenShareStateSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private actionService: ActionService,
|
||||
private deviceSrv: DeviceService,
|
||||
private loggerSrv: LoggerService,
|
||||
private openviduService: OpenViduService,
|
||||
private participantService: ParticipantService,
|
||||
private storageSrv: StorageService
|
||||
) {
|
||||
this.log = this.loggerSrv.get('UserSettingsComponent');
|
||||
}
|
||||
|
||||
@HostListener('window:beforeunload')
|
||||
beforeunloadHandler() {
|
||||
this.close();
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.deviceSrv.initializeDevices();
|
||||
|
||||
this.subscribeToLocalParticipantEvents();
|
||||
this.openviduService.initialize();
|
||||
const nickname = this.storageSrv.getNickname() || this.generateRandomNickname();
|
||||
this.nicknameFormControl.setValue(nickname);
|
||||
this.columns = window.innerWidth > 900 ? 2 : 1;
|
||||
this.setDevicesInfo();
|
||||
if (this.hasAudioDevices || this.hasVideoDevices) {
|
||||
await this.initwebcamPublisher();
|
||||
}
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.localParticipantSubscription) {
|
||||
this.localParticipantSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.screenShareStateSubscription) {
|
||||
this.screenShareStateSubscription.unsubscribe();
|
||||
}
|
||||
this.deviceSrv.clear();
|
||||
}
|
||||
|
||||
async onCameraSelected(event: any) {
|
||||
const videoSource = event?.value;
|
||||
// Is New deviceId different from the old one?
|
||||
if (this.deviceSrv.needUpdateVideoTrack(videoSource)) {
|
||||
const mirror = this.deviceSrv.cameraNeedsMirror(videoSource);
|
||||
//TODO: Uncomment this when replaceTrack issue is fixed
|
||||
// const pp: PublisherProperties = { videoSource, audioSource: false, mirror };
|
||||
// await this.openviduService.replaceTrack(VideoType.CAMERA, pp);
|
||||
// TODO: Remove this when replaceTrack issue is fixed
|
||||
const pp: PublisherProperties = { videoSource, audioSource: this.microphoneSelected.device, mirror };
|
||||
await this.openviduService.republishTrack(pp);
|
||||
|
||||
|
||||
this.cameraSelected = videoSource;
|
||||
this.deviceSrv.setCameraSelected(this.cameraSelected);
|
||||
}
|
||||
if (this.isVideoMuted) {
|
||||
// Publish Webcam video
|
||||
this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), true);
|
||||
this.isVideoMuted = false;
|
||||
}
|
||||
}
|
||||
|
||||
async onMicrophoneSelected(event: any) {
|
||||
const audioSource = event?.value;
|
||||
// Is New deviceId different than older?
|
||||
if (this.deviceSrv.needUpdateAudioTrack(audioSource)) {
|
||||
//TODO: Uncomment this when replaceTrack issue is fixed
|
||||
// const pp: PublisherProperties = { audioSource, videoSource: false };
|
||||
// await this.openviduService.replaceTrack(VideoType.CAMERA, pp);
|
||||
// TODO: Remove this when replaceTrack issue is fixed
|
||||
const mirror = this.deviceSrv.cameraNeedsMirror(this.cameraSelected.device);
|
||||
const pp: PublisherProperties = { videoSource: this.cameraSelected.device, audioSource, mirror };
|
||||
await this.openviduService.republishTrack(pp);
|
||||
|
||||
this.microphoneSelected = audioSource;
|
||||
this.deviceSrv.setMicSelected(this.microphoneSelected);
|
||||
}
|
||||
if (this.isAudioMuted) {
|
||||
// Enable microphone
|
||||
this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), true);
|
||||
this.isAudioMuted = true;
|
||||
}
|
||||
}
|
||||
|
||||
toggleCam() {
|
||||
|
||||
const publish = this.isVideoMuted;
|
||||
this.openviduService.publishVideo(this.participantService.getMyCameraPublisher(), publish);
|
||||
|
||||
if (this.participantService.haveICameraAndScreenActive()) {
|
||||
// Cam will not published, disable webcam with screensharing active
|
||||
this.participantService.disableWebcamUser();
|
||||
this.openviduService.publishAudio(this.participantService.getMyScreenPublisher(), publish);
|
||||
} else if (this.participantService.isOnlyMyScreenActive()) {
|
||||
// Cam will be published, enable webcam
|
||||
this.participantService.enableWebcamUser();
|
||||
}
|
||||
|
||||
this.isVideoMuted = !this.isVideoMuted;
|
||||
this.storageSrv.setVideoMuted(this.isVideoMuted);
|
||||
}
|
||||
|
||||
async toggleScreenShare() {
|
||||
// Disabling screenShare
|
||||
if (this.participantService.haveICameraAndScreenActive()) {
|
||||
this.participantService.disableScreenUser();
|
||||
return;
|
||||
}
|
||||
|
||||
// Enabling screenShare
|
||||
if (this.participantService.isOnlyMyCameraActive()) {
|
||||
const willThereBeWebcam = this.participantService.isMyCameraActive() && this.participantService.hasCameraVideoActive();
|
||||
const hasAudio = willThereBeWebcam ? false : this.hasAudioDevices && this.isAudioMuted;
|
||||
const properties: PublisherProperties = {
|
||||
videoSource: ScreenType.SCREEN,
|
||||
audioSource: this.hasAudioDevices ? undefined : null,
|
||||
publishVideo: true,
|
||||
publishAudio: hasAudio,
|
||||
mirror: false
|
||||
};
|
||||
const screenPublisher = await this.openviduService.initPublisher(undefined, properties);
|
||||
|
||||
screenPublisher.on('accessAllowed', (event) => {
|
||||
screenPublisher.stream
|
||||
.getMediaStream()
|
||||
.getVideoTracks()[0]
|
||||
.addEventListener('ended', () => {
|
||||
this.log.d('Clicked native stop button. Stopping screen sharing');
|
||||
this.toggleScreenShare();
|
||||
});
|
||||
this.participantService.activeMyScreenShare(screenPublisher);
|
||||
if (!this.participantService.hasCameraVideoActive()) {
|
||||
this.participantService.disableWebcamUser();
|
||||
}
|
||||
});
|
||||
|
||||
screenPublisher.on('accessDenied', (error: any) => {
|
||||
if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {
|
||||
this.actionService.openDialog('Error sharing screen', 'Your browser does not support screen sharing');
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Disabling screnShare and enabling webcam
|
||||
this.participantService.enableWebcamUser();
|
||||
this.participantService.disableScreenUser();
|
||||
}
|
||||
|
||||
toggleMic() {
|
||||
const publish = this.isAudioMuted;
|
||||
this.openviduService.publishAudio(this.participantService.getMyCameraPublisher(), publish);
|
||||
this.isAudioMuted = !this.isAudioMuted;
|
||||
this.storageSrv.setAudioMuted(this.isAudioMuted);
|
||||
}
|
||||
|
||||
eventKeyPress(event) {
|
||||
if (event && event.keyCode === 13 && this.nicknameFormControl.valid) {
|
||||
this.joinSession();
|
||||
}
|
||||
}
|
||||
|
||||
onResize(event) {
|
||||
this.columns = event.target.innerWidth > 900 ? 2 : 1;
|
||||
}
|
||||
|
||||
joinSession() {
|
||||
if (this.nicknameFormControl.valid) {
|
||||
const nickname = this.nicknameFormControl.value;
|
||||
this.participantService.setMyNickname(nickname);
|
||||
this.storageSrv.setNickname(nickname);
|
||||
return this.onJoinClicked.emit();
|
||||
}
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.onCloseClicked.emit();
|
||||
}
|
||||
|
||||
private setDevicesInfo() {
|
||||
this.hasVideoDevices = this.deviceSrv.hasVideoDeviceAvailable();
|
||||
this.hasAudioDevices = this.deviceSrv.hasAudioDeviceAvailable();
|
||||
this.microphones = this.deviceSrv.getMicrophones();
|
||||
this.cameras = this.deviceSrv.getCameras();
|
||||
this.cameraSelected = this.deviceSrv.getCameraSelected();
|
||||
this.microphoneSelected = this.deviceSrv.getMicrophoneSelected();
|
||||
|
||||
this.isVideoMuted = this.deviceSrv.isVideoMuted();
|
||||
this.isAudioMuted = this.deviceSrv.isAudioMuted();
|
||||
}
|
||||
|
||||
private scrollToBottom(): void {
|
||||
try {
|
||||
this.bodyCard.nativeElement.scrollTop = this.bodyCard.nativeElement.scrollHeight;
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
private subscribeToLocalParticipantEvents() {
|
||||
this.localParticipantSubscription = this.participantService.localParticipantObs.subscribe((p) => {
|
||||
this.localParticipant = p;
|
||||
this.screenShareEnabled = p.isScreenActive();
|
||||
});
|
||||
}
|
||||
|
||||
private async initwebcamPublisher() {
|
||||
const publisher = await this.openviduService.initDefaultPublisher(undefined);
|
||||
if (publisher) {
|
||||
// this.handlePublisherSuccess(publisher);
|
||||
this.handlePublisherError(publisher);
|
||||
}
|
||||
}
|
||||
|
||||
//? After test in Chrome and Firefox, the devices always have labels.
|
||||
//? It's not longer needed
|
||||
// private handlePublisherSuccess(publisher: Publisher) {
|
||||
// publisher.once('accessAllowed', async () => {
|
||||
// if (this.deviceSrv.areEmptyLabels()) {
|
||||
// await this.deviceSrv.forceUpdate();
|
||||
// if (this.hasAudioDevices) {
|
||||
// const audioLabel = publisher?.stream?.getMediaStream()?.getAudioTracks()[0]?.label;
|
||||
// this.deviceSrv.setMicSelected(audioLabel);
|
||||
// }
|
||||
|
||||
// if (this.hasVideoDevices) {
|
||||
// const videoLabel = publisher?.stream?.getMediaStream()?.getVideoTracks()[0]?.label;
|
||||
// this.deviceSrv.setCameraSelected(videoLabel);
|
||||
// }
|
||||
// this.setDevicesInfo();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
private handlePublisherError(publisher: Publisher) {
|
||||
publisher.once('accessDenied', (e: any) => {
|
||||
let message: string;
|
||||
if (e.name === OpenViduErrorName.DEVICE_ALREADY_IN_USE) {
|
||||
this.log.w('Video device already in use. Disabling video device...');
|
||||
// Allow access to the room with only mic if camera device is already in use
|
||||
this.hasVideoDevices = false;
|
||||
this.deviceSrv.disableVideoDevices();
|
||||
return this.initwebcamPublisher();
|
||||
}
|
||||
if (e.name === OpenViduErrorName.DEVICE_ACCESS_DENIED) {
|
||||
message = 'Access to media devices was not allowed.';
|
||||
this.hasVideoDevices = false;
|
||||
this.hasAudioDevices = false;
|
||||
this.deviceSrv.disableVideoDevices();
|
||||
this.deviceSrv.disableAudioDevices();
|
||||
return this.initwebcamPublisher();
|
||||
} else if (e.name === OpenViduErrorName.NO_INPUT_SOURCE_SET) {
|
||||
message = 'No video or audio devices have been found. Please, connect at least one.';
|
||||
}
|
||||
this.actionService.openDialog(e.name.replace(/_/g, ' '), message, true);
|
||||
this.log.e(e.message);
|
||||
});
|
||||
}
|
||||
|
||||
private generateRandomNickname(): string {
|
||||
return 'OpenVidu_User' + Math.floor(Math.random() * 100);
|
||||
}
|
||||
}
|
|
@ -414,11 +414,11 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
|||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
async ngOnDestroy() {
|
||||
if (this.prejoinSub) this.prejoinSub.unsubscribe();
|
||||
if (this.participantNameSub) this.participantNameSub.unsubscribe();
|
||||
this.deviceSrv.clear();
|
||||
this.openviduService.clear();
|
||||
await this.openviduService.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,6 @@ import { CommonModule } from '@angular/common';
|
|||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
// import { UserSettingsComponent } from './components/user-settings/user-settings.component';
|
||||
import { ToolbarComponent } from './components/toolbar/toolbar.component';
|
||||
import { VideoComponent } from './components/video/video.component';
|
||||
import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component';
|
||||
|
@ -70,7 +69,6 @@ import { RecordingActivityComponent } from './components/panel/activities-panel/
|
|||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
// UserSettingsComponent,
|
||||
VideoComponent,
|
||||
ToolbarComponent,
|
||||
ChatPanelComponent,
|
||||
|
@ -140,7 +138,6 @@ import { RecordingActivityComponent } from './components/panel/activities-panel/
|
|||
],
|
||||
exports: [
|
||||
VideoconferenceComponent,
|
||||
// UserSettingsComponent,
|
||||
ToolbarComponent,
|
||||
PanelComponent,
|
||||
ParticipantsPanelComponent,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Connection, OpenVidu, Publisher, PublisherProperties, Session, SignalOptions } from 'openvidu-browser';
|
||||
import { Connection, OpenVidu, Publisher, PublisherProperties, Session, SignalOptions, Stream } from 'openvidu-browser';
|
||||
|
||||
import { LoggerService } from '../logger/logger.service';
|
||||
|
||||
|
@ -84,11 +84,11 @@ export class OpenViduService {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
clear() {
|
||||
async clear() {
|
||||
this.videoSource = undefined;
|
||||
this.audioSource = undefined;
|
||||
this.stopTracks(this.participantService.getMyCameraPublisher()?.stream?.getMediaStream());
|
||||
this.stopTracks(this.participantService.getMyScreenPublisher()?.stream?.getMediaStream());
|
||||
await this.participantService.getMyCameraPublisher()?.stream?.disposeMediaStream();
|
||||
await this.participantService.getMyScreenPublisher()?.stream?.disposeMediaStream();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,7 +261,7 @@ export class OpenViduService {
|
|||
|
||||
// Disabling webcam
|
||||
if (this.participantService.haveICameraAndScreenActive()) {
|
||||
this.publishVideoAux(this.participantService.getMyCameraPublisher(), publish);
|
||||
await this.publishVideoAux(this.participantService.getMyCameraPublisher(), publish);
|
||||
this.participantService.disableWebcamStream();
|
||||
this.unpublish(this.participantService.getMyCameraPublisher());
|
||||
this.publishAudioAux(this.participantService.getMyScreenPublisher(), publishAudio);
|
||||
|
@ -273,22 +273,22 @@ export class OpenViduService {
|
|||
await this.connectSession(this.getWebcamSession(), this.tokenService.getWebcamToken());
|
||||
}
|
||||
await this.publish(this.participantService.getMyCameraPublisher());
|
||||
this.publishVideoAux(this.participantService.getMyCameraPublisher(), true);
|
||||
await this.publishVideoAux(this.participantService.getMyCameraPublisher(), true);
|
||||
this.publishAudioAux(this.participantService.getMyScreenPublisher(), false);
|
||||
this.publishAudioAux(this.participantService.getMyCameraPublisher(), hasAudio);
|
||||
this.participantService.enableWebcamStream();
|
||||
} else {
|
||||
// Muting/unmuting webcam
|
||||
this.publishVideoAux(this.participantService.getMyCameraPublisher(), publish);
|
||||
await this.publishVideoAux(this.participantService.getMyCameraPublisher(), publish);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
private publishVideoAux(publisher: Publisher, publish: boolean): void {
|
||||
private async publishVideoAux(publisher: Publisher, publish: boolean): Promise<void> {
|
||||
if (!!publisher) {
|
||||
publisher.publishVideo(publish, true);
|
||||
await publisher.publishVideo(publish, true);
|
||||
this.participantService.updateLocalParticipant();
|
||||
}
|
||||
}
|
||||
|
@ -592,12 +592,4 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private stopTracks(mediaStream: MediaStream) {
|
||||
if (mediaStream) {
|
||||
mediaStream?.getAudioTracks().forEach((track) => track.stop());
|
||||
mediaStream?.getVideoTracks().forEach((track) => track.stop());
|
||||
// this.webcamMediaStream?.getAudioTracks().forEach((track) => track.stop());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ export class PanelService {
|
|||
return this.isParticipantsOpened;
|
||||
}
|
||||
|
||||
private isExternalPanelOpened(): boolean {
|
||||
isExternalPanelOpened(): boolean {
|
||||
return this.isExternalOpened;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,9 +41,16 @@ export class VirtualBackgroundService {
|
|||
getBackgrounds(): any[] {
|
||||
return this.backgrounds;
|
||||
}
|
||||
|
||||
isBackgroundApplied(): boolean {
|
||||
const bgSelected = this.backgroundSelected.getValue();
|
||||
return !!bgSelected && bgSelected !== 'no_effect';
|
||||
}
|
||||
|
||||
async applyBackground(effect: BackgroundEffect) {
|
||||
if (effect.id !== this.backgroundSelected.getValue()) {
|
||||
const isBackgroundSelected = !!this.backgroundSelected.getValue() && this.backgroundSelected.getValue() !== 'no_effect';
|
||||
const filter = this.participantService.getMyCameraPublisher().stream.filter;
|
||||
const isBackgroundSelected = !!filter && filter.type.startsWith('VB:');
|
||||
let options = { token: this.tokenService.getWebcamToken(), url: '' };
|
||||
if (effect.type === EffectType.IMAGE) {
|
||||
options.url = effect.src;
|
||||
|
@ -60,7 +67,7 @@ export class VirtualBackgroundService {
|
|||
}
|
||||
|
||||
async removeBackground() {
|
||||
if (!!this.backgroundSelected.getValue() && this.backgroundSelected.getValue() !== 'no_effect') {
|
||||
if (!!this.isBackgroundApplied()) {
|
||||
this.backgroundSelected.next('no_effect');
|
||||
await this.participantService.getMyCameraPublisher().stream.removeFilter();
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ export class ToolbarDirectiveComponent implements OnInit {
|
|||
OPENVIDU_SECRET = 'MY_SECRET';
|
||||
publishVideo = true;
|
||||
publishAudio = true;
|
||||
constructor(private restService: RestService, private openviduService: OpenViduService) {}
|
||||
constructor(private restService: RestService, private openviduService: OpenViduService) { }
|
||||
|
||||
ngOnInit(): void {}
|
||||
ngOnInit(): void { }
|
||||
|
||||
async onJoinButtonClicked() {
|
||||
this.tokens = {
|
||||
|
@ -31,13 +31,13 @@ export class ToolbarDirectiveComponent implements OnInit {
|
|||
};
|
||||
}
|
||||
|
||||
toggleVideo() {
|
||||
async toggleVideo(): Promise<void> {
|
||||
this.publishVideo = !this.publishVideo;
|
||||
this.openviduService.publishVideo(this.publishVideo);
|
||||
await this.openviduService.publishVideo(this.publishVideo);
|
||||
}
|
||||
|
||||
toggleAudio() {
|
||||
async toggleAudio(): Promise<void> {
|
||||
this.publishAudio = !this.publishAudio;
|
||||
this.openviduService.publishAudio(this.publishAudio);
|
||||
await this.openviduService.publishAudio(this.publishAudio);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export class ToolbarAdditionalButtonsDirectiveComponent {
|
|||
private restService: RestService,
|
||||
private openviduService: OpenViduService,
|
||||
private participantService: ParticipantService
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async onJoinButtonClicked() {
|
||||
this.tokens = {
|
||||
|
@ -31,13 +31,13 @@ export class ToolbarAdditionalButtonsDirectiveComponent {
|
|||
};
|
||||
}
|
||||
|
||||
toggleVideo() {
|
||||
async toggleVideo() {
|
||||
const publishVideo = !this.participantService.isMyVideoActive();
|
||||
this.openviduService.publishVideo(publishVideo);
|
||||
await this.openviduService.publishVideo(publishVideo);
|
||||
}
|
||||
|
||||
toggleAudio() {
|
||||
async toggleAudio() {
|
||||
const publishAudio = !this.participantService.isMyAudioActive();
|
||||
this.openviduService.publishAudio(publishAudio);
|
||||
await this.openviduService.publishAudio(publishAudio);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</parent>
|
||||
|
||||
<artifactId>openvidu-java-client</artifactId>
|
||||
<version>2.21.1</version>
|
||||
<version>2.22.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>OpenVidu Java Client</name>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "openvidu-node-client",
|
||||
"version": "2.21.0",
|
||||
"version": "2.22.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "openvidu-node-client",
|
||||
"version": "2.21.0",
|
||||
"version": "2.22.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"axios": "0.21.4",
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
"docs": "./generate-docs.sh"
|
||||
},
|
||||
"typings": "lib/index.d.ts",
|
||||
"version": "2.21.0"
|
||||
"version": "2.22.0"
|
||||
}
|
|
@ -9,7 +9,7 @@ services:
|
|||
#
|
||||
# Default Application
|
||||
#
|
||||
# Openvidu-Call Version: 2.21.0
|
||||
# Openvidu-Call Version: 2.22.0
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
app:
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# This file will be overridden when update OpenVidu Platform
|
||||
#
|
||||
# Openvidu Version: 2.21.0
|
||||
# Openvidu Version: 2.22.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Global variables
|
||||
OPENVIDU_FOLDER=openvidu
|
||||
OPENVIDU_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.21"
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.22"
|
||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${OPENVIDU_VERSION}
|
||||
|
||||
# Support docker compose v1 and v2
|
||||
|
|
|
@ -356,6 +356,20 @@ ELASTICSEARCH_PASSWORD=
|
|||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
||||
# KMS_DOCKER_ENV_GST_DEBUG=
|
||||
|
||||
# Coturn deployment in media nodes (Experimental)
|
||||
# --------------------------
|
||||
# OpenVidu PRO/Enterprise includes a default TURN/STUN deployment (Coturn).
|
||||
# By default, Coturn is deployed in master nodes, but if you want to deploy
|
||||
# Coturn in the media nodes, you just need to set OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=true
|
||||
# Default value is OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=false
|
||||
# For Coturn to work, you need at least this ports open:
|
||||
# For master node you need 3478 TCP/UDP open in the master node.
|
||||
# For Media nodes you need 443 TCP/UDP open in media nodes.
|
||||
# More info about Coturn configuration in OpenVidu PRO/ENTERPRISE:
|
||||
# - https://docs.openvidu.io/en/stable/deployment/pro/on-premises/#coturn-configuration
|
||||
OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=false
|
||||
|
||||
|
||||
# Cloudformation configuration
|
||||
# --------------------------
|
||||
# If you're working outside AWS ignore this section
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
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.21.0
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
app:
|
||||
image: openvidu/openvidu-call:2.21.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}"
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# This file will be overridden when update OpenVidu Platform
|
||||
#
|
||||
# Openvidu Version: 2.21.0
|
||||
# Openvidu Version: 2.22.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
@ -64,6 +64,7 @@ services:
|
|||
network_mode: host
|
||||
volumes:
|
||||
- ./:/opt/openvidu
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- SERVER_PORT=4443
|
||||
- SERVER_SSL_ENABLED=false
|
||||
|
@ -81,6 +82,7 @@ services:
|
|||
- RM_S3_CONFIGURATION_BUCKET_REGION=${RM_S3_CONFIGURATION_BUCKET_REGION}
|
||||
- RM_MEDIA_NODES_AUTOSCALING_GROUP_NAME=${RM_MEDIA_NODES_AUTOSCALING_GROUP_NAME}
|
||||
- RM_MASTER_NODES_AUTOSCALING_GROUP_NAME=${RM_MASTER_NODES_AUTOSCALING_GROUP_NAME}
|
||||
- RM_S3_CONFIG_AUTORESTART=${OPENVIDU_ENTERPRISE_S3_CONFIG_AUTORESTART:-true}
|
||||
logging:
|
||||
options:
|
||||
max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Global variables
|
||||
OPENVIDU_FOLDER=openvidu
|
||||
OPENVIDU_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.21"
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.22"
|
||||
AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws
|
||||
ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch
|
||||
BEATS_FOLDER=${OPENVIDU_FOLDER}/beats
|
||||
|
@ -80,10 +80,6 @@ new_ov_installation() {
|
|||
--output "${OPENVIDU_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/enterprise/master-node/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/enterprise/master-node/docker-compose.yml \
|
||||
--output "${OPENVIDU_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'"
|
||||
printf '\n - docker-compose.yml'
|
||||
|
@ -160,286 +156,6 @@ replace_variable_in_new_env_file() {
|
|||
[[ -n "${ENV_VARIABLE_VALUE}" ]] && sed -i "s|#${ENV_VARIABLE_NAME}=|${ENV_VARIABLE_NAME}=${ENV_VARIABLE_VALUE}|" "${OPENVIDU_PREVIOUS_FOLDER}/.env-${OPENVIDU_VERSION}"
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
# Upgrade 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/enterprise/master-node/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/enterprise/master-node/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/enterprise/master-node/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/enterprise/master-node/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/enterprise/master-node/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/enterprise/master-node/.env \
|
||||
--output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'"
|
||||
printf '\n - .env'
|
||||
|
||||
curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/enterprise/master-node/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/enterprise/master-node/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/enterprise/master-node/openvidu \
|
||||
--output "${TMP_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'"
|
||||
printf '\n - openvidu'
|
||||
|
||||
# Downloading new images and stopped actual Openvidu
|
||||
printf '\n => Downloading 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 => Stopping 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 [ -n "${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
|
||||
|
||||
if [ -d "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-locations" ]; then
|
||||
mv "${OPENVIDU_PREVIOUS_FOLDER}/custom-nginx-locations" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous directory 'custom-nginx-locations'"
|
||||
printf '\n - custom-nginx-locations'
|
||||
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 [ -n "${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'
|
||||
|
||||
# Change recording folder with all permissions
|
||||
printf "\n => Adding permission to 'recordings' folder..."
|
||||
mkdir -p "${OPENVIDU_PREVIOUS_FOLDER}/recordings"
|
||||
|
||||
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 }')
|
||||
[ -n "${OLD_MODE}" ] && sed -i -r "s/Installation Mode:.+/Installation Mode: ${OLD_MODE}/" "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml"
|
||||
|
||||
# Update .env variables to new .env-version
|
||||
AWS_REGION=$(get_previous_env_variable AWS_DEFAULT_REGION)
|
||||
if [[ -n ${AWS_REGION} ]]; then
|
||||
|
||||
# Get new AMI ID
|
||||
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"
|
||||
|
||||
# Get previous values
|
||||
PREV_AWS_DEFAULT_REGION=$(get_previous_env_variable AWS_DEFAULT_REGION)
|
||||
PREV_AWS_INSTANCE_TYPE=$(get_previous_env_variable AWS_INSTANCE_TYPE)
|
||||
PREV_AWS_INSTANCE_ID=$(get_previous_env_variable AWS_INSTANCE_ID)
|
||||
PREV_AWS_KEY_NAME=$(get_previous_env_variable AWS_KEY_NAME)
|
||||
PREV_AWS_SUBNET_ID=$(get_previous_env_variable AWS_SUBNET_ID)
|
||||
PREV_AWS_SECURITY_GROUP=$(get_previous_env_variable AWS_SECURITY_GROUP)
|
||||
PREV_AWS_STACK_ID=$(get_previous_env_variable AWS_STACK_ID)
|
||||
PREV_AWS_STACK_NAME=$(get_previous_env_variable AWS_STACK_NAME)
|
||||
PREV_AWS_CLI_DOCKER_TAG=$(get_previous_env_variable AWS_CLI_DOCKER_TAG)
|
||||
PREV_AWS_VOLUME_SIZE=$(get_previous_env_variable AWS_VOLUME_SIZE)
|
||||
|
||||
# Replace variables in new .env-version file
|
||||
replace_variable_in_new_env_file "AWS_DEFAULT_REGION" "${PREV_AWS_DEFAULT_REGION}"
|
||||
replace_variable_in_new_env_file "AWS_INSTANCE_TYPE" "${PREV_AWS_INSTANCE_TYPE}"
|
||||
replace_variable_in_new_env_file "AWS_INSTANCE_ID" "${PREV_AWS_INSTANCE_ID}"
|
||||
replace_variable_in_new_env_file "AWS_KEY_NAME" "${PREV_AWS_KEY_NAME}"
|
||||
replace_variable_in_new_env_file "AWS_SUBNET_ID" "${PREV_AWS_SUBNET_ID}"
|
||||
replace_variable_in_new_env_file "AWS_SECURITY_GROUP" "${PREV_AWS_SECURITY_GROUP}"
|
||||
replace_variable_in_new_env_file "AWS_STACK_ID" "${PREV_AWS_STACK_ID}"
|
||||
replace_variable_in_new_env_file "AWS_STACK_NAME" "${PREV_AWS_STACK_NAME}"
|
||||
replace_variable_in_new_env_file "AWS_CLI_DOCKER_TAG" "${PREV_AWS_CLI_DOCKER_TAG}"
|
||||
replace_variable_in_new_env_file "AWS_VOLUME_SIZE" "${PREV_AWS_VOLUME_SIZE}"
|
||||
|
||||
# Replace new AMI
|
||||
replace_variable_in_new_env_file "AWS_IMAGE_ID" "${NEW_AMI_ID}"
|
||||
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"
|
||||
|
@ -459,7 +175,7 @@ fi
|
|||
|
||||
# Check type of installation
|
||||
if [[ -n "$1" && "$1" == "upgrade" ]]; then
|
||||
upgrade_ov
|
||||
fatal_error "OpenVidu Enterprise HA can't be upgraded manually. Deploy the Cloudformation template of the version '${OPENVIDU_VERSION}' you want to deploy: https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/enterprise/aws/"
|
||||
else
|
||||
new_ov_installation
|
||||
fi
|
||||
|
|
|
@ -207,27 +207,12 @@ is_external_url() {
|
|||
}
|
||||
|
||||
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
|
||||
COTURN_IN_MEDIA_NODES=$(grep -v '^#' .env | grep COTURN_IN_MEDIA_NODES | cut -d '=' -f2)
|
||||
if [[ -z "${COTURN_IN_MEDIA_NODES}" ]]; then
|
||||
COTURN_IN_MEDIA_NODES=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)
|
||||
$(if [ "${COTURN_IN_MEDIA_NODES}" == "true" ]; then echo '--scale coturn=0'; fi)
|
||||
}
|
||||
|
||||
usage() {
|
||||
|
|
|
@ -93,7 +93,7 @@ Resources:
|
|||
|
||||
# Environment variables from docker-compose.yml
|
||||
sed -i "s|MEDIASOUP_IMAGE=openvidu/mediasoup-controller.*|MEDIASOUP_IMAGE=openvidu/mediasoup-controller:master|g" docker-compose.yml
|
||||
sed -i "s|COTURN_IMAGE=openvidu/openvidu-coturn.*|MEDIASOUP_IMAGE=openvidu/openvidu-coturn:master|g" docker-compose.yml
|
||||
sed -i "s|COTURN_IMAGE=openvidu/openvidu-coturn.*|COTURN_IMAGE=openvidu/openvidu-coturn:master|g" docker-compose.yml
|
||||
popd
|
||||
fi
|
||||
|
||||
|
|
|
@ -221,6 +221,14 @@ Parameters:
|
|||
- false
|
||||
Default: true
|
||||
|
||||
CoturnInMediaNodes:
|
||||
Description: "If true, Coturn will be deployed on media nodes. Otherwise it will be deployed in master nodes."
|
||||
Type: String
|
||||
AllowedValues:
|
||||
- true
|
||||
- false
|
||||
Default: false
|
||||
|
||||
#start_mappings
|
||||
Mappings:
|
||||
OVAMIMAP:
|
||||
|
@ -278,6 +286,7 @@ Metadata:
|
|||
default: Other configuration
|
||||
Parameters:
|
||||
- WantToDeployDemos
|
||||
- CoturnInMediaNodes
|
||||
|
||||
ParameterLabels:
|
||||
# SSL certificate configuration
|
||||
|
@ -330,6 +339,8 @@ Metadata:
|
|||
# Other configuration
|
||||
WantToDeployDemos:
|
||||
default: "Deploy OpenVidu Call application"
|
||||
CoturnInMediaNodes:
|
||||
default: "Deploy Coturn in Media Nodes. (Experimental)"
|
||||
|
||||
Conditions:
|
||||
WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ''] ]
|
||||
|
@ -542,6 +553,11 @@ Resources:
|
|||
rm $WORKINGDIR/docker-compose.override.yml
|
||||
fi
|
||||
|
||||
# Deploy Coturn in media nodes
|
||||
if [ "${CoturnInMediaNodes}" == "true" ]; then
|
||||
sed -i "s/OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=false/OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=true/" $WORKINGDIR/.env
|
||||
fi
|
||||
|
||||
# Recording Configuration
|
||||
if [ "${Recording}" != "disabled" ]; then
|
||||
sed -i "s/OPENVIDU_RECORDING=false/OPENVIDU_RECORDING=true/" $WORKINGDIR/.env
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
# This docker-compose file coordinates all services of OpenVidu CE Platform.
|
||||
#
|
||||
# Openvidu Version: 2.21.0
|
||||
# Openvidu Version: 2.22.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
@ -16,18 +16,18 @@ version: '3.1'
|
|||
|
||||
services:
|
||||
media-node-controller:
|
||||
image: openvidu/media-node-controller:6.0.0
|
||||
image: openvidu/media-node-controller:2.22.0
|
||||
restart: always
|
||||
ulimits:
|
||||
core: -1
|
||||
entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh']
|
||||
environment:
|
||||
- KMS_IMAGE=kurento/kurento-media-server:6.16.0
|
||||
- MEDIASOUP_IMAGE=openvidu/mediasoup-controller:2.21.0
|
||||
- MEDIASOUP_IMAGE=openvidu/mediasoup-controller:2.22.0
|
||||
- METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0
|
||||
- FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0
|
||||
- OPENVIDU_RECORDING_IMAGE=openvidu/openvidu-recording:2.19.0
|
||||
- COTURN_IMAGE=openvidu/openvidu-coturn:7.0.0-dev1
|
||||
- COTURN_IMAGE=openvidu/openvidu-coturn:2.22.0
|
||||
- NO_COLOR=true
|
||||
ports:
|
||||
- 3000:3000
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
MEDIA_NODE_FOLDER=kms
|
||||
MEDIA_NODE_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.21"
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.22"
|
||||
BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats
|
||||
OPENVIDU_RECORDINGS_FOLDER="/opt/openvidu/recordings"
|
||||
DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${MEDIA_NODE_VERSION}
|
||||
|
|
|
@ -353,6 +353,19 @@ ELASTICSEARCH_PASSWORD=
|
|||
# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html
|
||||
# KMS_DOCKER_ENV_GST_DEBUG=
|
||||
|
||||
# Coturn deployment in media nodes (Experimental)
|
||||
# --------------------------
|
||||
# OpenVidu PRO/Enterprise includes a default TURN/STUN deployment (Coturn).
|
||||
# By default, Coturn is deployed in master nodes, but if you want to deploy
|
||||
# Coturn in the media nodes, you just need to set OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=true
|
||||
# Default value is OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=false
|
||||
# For Coturn to work, you need at least this ports open:
|
||||
# For master node you need 3478 TCP/UDP open in the master node.
|
||||
# For Media nodes you need 443 TCP/UDP open in media nodes.
|
||||
# More info about Coturn configuration in OpenVidu PRO/ENTERPRISE:
|
||||
# - https://docs.openvidu.io/en/stable/deployment/pro/on-premises/#coturn-configuration
|
||||
OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=false
|
||||
|
||||
# Cloudformation configuration
|
||||
# --------------------------
|
||||
# If you're working outside AWS ignore this section
|
||||
|
|
|
@ -9,7 +9,7 @@ services:
|
|||
#
|
||||
# Default Application
|
||||
#
|
||||
# Openvidu-Call Version: 2.21.0
|
||||
# Openvidu-Call Version: 2.22.0
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
app:
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# This file will be overridden when update OpenVidu Platform
|
||||
#
|
||||
# Openvidu Version: 2.21.0
|
||||
# Openvidu Version: 2.22.0
|
||||
#
|
||||
# Installation Mode: On Premises
|
||||
#
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Global variables
|
||||
OPENVIDU_FOLDER=openvidu
|
||||
OPENVIDU_VERSION=master
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.21"
|
||||
OPENVIDU_UPGRADABLE_VERSION="2.22"
|
||||
AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws
|
||||
ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch
|
||||
BEATS_FOLDER=${OPENVIDU_FOLDER}/beats
|
||||
|
|
|
@ -213,8 +213,12 @@ start_openvidu() {
|
|||
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)
|
||||
COTURN_IN_MEDIA_NODES=$(grep -v '^#' .env | grep COTURN_IN_MEDIA_NODES | cut -d '=' -f2)
|
||||
RUN_LOCAL_ES=true
|
||||
RUN_LOCAL_KIBANA=true
|
||||
if [[ -z "${COTURN_IN_MEDIA_NODES}" ]]; then
|
||||
COTURN_IN_MEDIA_NODES=false
|
||||
fi
|
||||
if is_external_url "${CONFIGURED_ELASTICSEARCH_HOST}"; then
|
||||
printf "Configured external elasticsearch: %s" "${CONFIGURED_ELASTICSEARCH_HOST}"
|
||||
printf "\n"
|
||||
|
@ -227,7 +231,8 @@ start_openvidu() {
|
|||
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)
|
||||
$(if [ "${RUN_LOCAL_KIBANA}" == "false" ]; then echo '--scale kibana=0'; fi) \
|
||||
$(if [ "${COTURN_IN_MEDIA_NODES}" == "true" ]; then echo '--scale coturn=0'; fi)
|
||||
}
|
||||
|
||||
usage() {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<packaging>jar</packaging>
|
||||
|
||||
<name>OpenVidu Server</name>
|
||||
<version>2.21.0</version>
|
||||
<version>2.22.0</version>
|
||||
<description>OpenVidu Server</description>
|
||||
<url>https://openvidu.io</url>
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"@angular/router": "13.3.0",
|
||||
"core-js": "3.21.1",
|
||||
"jquery": "3.6.0",
|
||||
"openvidu-browser": "2.21.0",
|
||||
"openvidu-browser": "2.22.0",
|
||||
"rxjs": "7.5.5",
|
||||
"tslib": "2.3.1",
|
||||
"zone.js": "0.11.5"
|
||||
|
@ -9191,9 +9191,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/openvidu-browser": {
|
||||
"version": "2.21.0",
|
||||
"resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.21.0.tgz",
|
||||
"integrity": "sha512-dQZ8lsvt7zydklG/naHtaWpnhRo5ErTjEkWslmg6e2fjFVy+GmGVrJBeMJrJDM2FrOWv8aH86fRNR+P7eESB9g==",
|
||||
"version": "2.22.0",
|
||||
"resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.22.0.tgz",
|
||||
"integrity": "sha512-fug7V5WZPwEXCF4im6RzhWSbv9nYB4QWMXrEQBEsh7RI1VPQ5Jl2VcindiUeMtN+quLqeTjXSRUh4lfkrTlQSQ==",
|
||||
"dependencies": {
|
||||
"events": "3.3.0",
|
||||
"freeice": "2.2.2",
|
||||
|
@ -14935,7 +14935,8 @@
|
|||
"version": "13.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-13.3.0.tgz",
|
||||
"integrity": "sha512-QbTQWXK2WzYU+aKKVDG0ya7WYT+6rNAUXVt5ov9Nz1SGgDeozpiOx8ZqPWUvnToTY8EoodwWFGCVtkLHXUR+wA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
|
@ -15501,7 +15502,8 @@
|
|||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
|
||||
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "8.2.0",
|
||||
|
@ -16234,7 +16236,8 @@
|
|||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz",
|
||||
"integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"clean-stack": {
|
||||
"version": "2.2.0",
|
||||
|
@ -16317,13 +16320,15 @@
|
|||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz",
|
||||
"integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@angular/core": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz",
|
||||
"integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.6.7",
|
||||
|
@ -16806,7 +16811,8 @@
|
|||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
|
||||
"integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"css-select": {
|
||||
"version": "4.2.1",
|
||||
|
@ -18291,7 +18297,8 @@
|
|||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
|
||||
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
|
@ -19137,7 +19144,8 @@
|
|||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz",
|
||||
"integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"karma-source-map-support": {
|
||||
"version": "1.4.0",
|
||||
|
@ -20071,9 +20079,9 @@
|
|||
}
|
||||
},
|
||||
"openvidu-browser": {
|
||||
"version": "2.21.0",
|
||||
"resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.21.0.tgz",
|
||||
"integrity": "sha512-dQZ8lsvt7zydklG/naHtaWpnhRo5ErTjEkWslmg6e2fjFVy+GmGVrJBeMJrJDM2FrOWv8aH86fRNR+P7eESB9g==",
|
||||
"version": "2.22.0",
|
||||
"resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.22.0.tgz",
|
||||
"integrity": "sha512-fug7V5WZPwEXCF4im6RzhWSbv9nYB4QWMXrEQBEsh7RI1VPQ5Jl2VcindiUeMtN+quLqeTjXSRUh4lfkrTlQSQ==",
|
||||
"requires": {
|
||||
"events": "3.3.0",
|
||||
"freeice": "2.2.2",
|
||||
|
@ -20532,7 +20540,8 @@
|
|||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz",
|
||||
"integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-custom-properties": {
|
||||
"version": "12.1.4",
|
||||
|
@ -20602,13 +20611,15 @@
|
|||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz",
|
||||
"integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-gap-properties": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz",
|
||||
"integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-image-set-function": {
|
||||
"version": "4.0.6",
|
||||
|
@ -20634,7 +20645,8 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz",
|
||||
"integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-lab-function": {
|
||||
"version": "4.1.2",
|
||||
|
@ -20661,19 +20673,22 @@
|
|||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz",
|
||||
"integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-media-minmax": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz",
|
||||
"integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-modules-extract-imports": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
|
||||
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-modules-local-by-default": {
|
||||
"version": "4.0.0",
|
||||
|
@ -20717,13 +20732,15 @@
|
|||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz",
|
||||
"integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-page-break": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz",
|
||||
"integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-place": {
|
||||
"version": "7.0.4",
|
||||
|
@ -20788,7 +20805,8 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz",
|
||||
"integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-selector-not": {
|
||||
"version": "5.0.0",
|
||||
|
@ -21534,7 +21552,8 @@
|
|||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
|
@ -22162,7 +22181,8 @@
|
|||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
|
@ -22690,7 +22710,8 @@
|
|||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
|
@ -22987,7 +23008,8 @@
|
|||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.23",
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"@angular/router": "13.3.0",
|
||||
"core-js": "3.21.1",
|
||||
"jquery": "3.6.0",
|
||||
"openvidu-browser": "2.21.0",
|
||||
"openvidu-browser": "2.22.0",
|
||||
"rxjs": "7.5.5",
|
||||
"tslib": "2.3.1",
|
||||
"zone.js": "0.11.5"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"core-js": "3.4.7",
|
||||
"hammerjs": "2.0.8",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"openvidu-browser": "2.21.0",
|
||||
"openvidu-browser": "2.22.0",
|
||||
"openvidu-node-client": "2.21.0",
|
||||
"rxjs": "6.5.3",
|
||||
"zone.js": "0.10.2"
|
||||
|
@ -45,5 +45,5 @@
|
|||
"start": "ng serve",
|
||||
"test": "ng test"
|
||||
},
|
||||
"version": "2.21.0"
|
||||
"version": "2.22.0"
|
||||
}
|
2
pom.xml
2
pom.xml
|
@ -65,7 +65,7 @@
|
|||
|
||||
<version.webdrivermanager>4.2.2</version.webdrivermanager>
|
||||
|
||||
<version.openvidu.java.client>2.21.1</version.openvidu.java.client>
|
||||
<version.openvidu.java.client>2.22.0</version.openvidu.java.client>
|
||||
<version.openvidu.client>1.1.0</version.openvidu.client>
|
||||
<version.openvidu.test.browsers>1.1.0</version.openvidu.test.browsers>
|
||||
<version.openvidu.test.e2e>1.1.1</version.openvidu.test.e2e>
|
||||
|
|
Loading…
Reference in New Issue