From 7ce6826b622474567fbbc7e1adab84c2626ee917 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 1 Aug 2018 15:12:34 +0200 Subject: [PATCH] openvidu-testapp: Kurento filters support --- openvidu-testapp/src/app/app.module.ts | 5 +- .../filter-dialog/filter-dialog.component.ts | 101 ++++++++++++ ...publisher-properties-dialog.component.html | 7 + .../publisher-properties-dialog.component.ts | 13 +- .../session-properties-dialog.component.css | 6 + .../session-properties-dialog.component.html | 156 +++++++++++------- .../session-properties-dialog.component.ts | 16 +- .../openvidu-instance.component.ts | 30 +++- .../app/components/video/video.component.html | 15 +- .../app/components/video/video.component.ts | 9 + 10 files changed, 276 insertions(+), 82 deletions(-) create mode 100644 openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.ts diff --git a/openvidu-testapp/src/app/app.module.ts b/openvidu-testapp/src/app/app.module.ts index 85da573d..61f3323a 100644 --- a/openvidu-testapp/src/app/app.module.ts +++ b/openvidu-testapp/src/app/app.module.ts @@ -24,6 +24,7 @@ import { SessionApiDialogComponent } from './components/dialogs/session-api-dial import { EventsDialogComponent } from './components/dialogs/events-dialog/events-dialog.component'; import { PublisherPropertiesDialogComponent } from './components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component'; import { ScenarioPropertiesDialogComponent } from './components/dialogs/scenario-properties-dialog/scenario-properties-dialog.component'; +import { FilterDialogComponent } from './components/dialogs/filter-dialog/filter-dialog.component'; import { OpenviduRestService } from './services/openvidu-rest.service'; import { OpenviduParamsService } from './services/openvidu-params.service'; @@ -46,6 +47,7 @@ import { MuteSubscribersService } from './services/mute-subscribers.service'; LocalRecordingDialogComponent, PublisherPropertiesDialogComponent, ScenarioPropertiesDialogComponent, + FilterDialogComponent, UsersTableComponent, TableVideoComponent ], @@ -71,7 +73,8 @@ import { MuteSubscribersService } from './services/mute-subscribers.service'; EventsDialogComponent, LocalRecordingDialogComponent, PublisherPropertiesDialogComponent, - ScenarioPropertiesDialogComponent + ScenarioPropertiesDialogComponent, + FilterDialogComponent ], bootstrap: [AppComponent] }) diff --git a/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.ts new file mode 100644 index 00000000..272567f4 --- /dev/null +++ b/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.ts @@ -0,0 +1,101 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; + +import { Session, Stream } from 'openvidu-browser'; + +@Component({ + selector: 'app-session-api-dialog', + template: ` +
+

Filter configuration

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ `, + styles: [ + '#response-text-area { width: 100%; color: #808080; }', + '#response-text-area textarea { resize: none; }', + 'mat-dialog-content button, mat-divider { margin-bottom: 5px; }', + 'mat-dialog-content button { height: 30px; line-height: 30px; padding-left: 12px; padding-right: 12px; display: inline-flex;}', + '.label { display: block; font-size: 12px; color: rgba(0, 0, 0, 0.54); font-weight: 400; margin-bottom: 5px; margin-top: 13px}', + ] +}) +export class FilterDialogComponent { + + session: Session; + stream: Stream; + + filterType = 'GStreamerFilter'; + filterOptions = '{"command": "pitch pitch=1.2 tempo=1.0"}'; + + filterMethod = 'setElementProperty'; + filterParams = '{"propertyName":"pitch","propertyValue":"0.8"}'; + + response: string; + + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data) { + this.session = data.session; + this.stream = data.stream; + } + + apply() { + console.log('Applying filter'); + this.session.applyFilter(this.stream, this.filterType, JSON.parse(this.filterOptions)) + .then(() => { + this.response = 'Filter applied'; + }) + .catch(error => { + this.response = 'Error [' + error.message + ']'; + }); + } + + execMethod() { + console.log('Executing filter method'); + this.session.execFilterMethod(this.stream, this.filterMethod, this.filterParams) + .then(recording => { + this.response = 'Filter method executed'; + }) + .catch(error => { + this.response = 'Error [' + error.message + ']'; + }); + } + + remove() { + console.log('Removing filter'); + this.session.removeFilter(this.stream) + .then(() => { + this.response = 'Filter removed'; + }) + .catch(error => { + this.response = 'Error [' + error.message + ']'; + }); + } + +} diff --git a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.html index 8ccb84b7..329c842c 100644 --- a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.html @@ -40,6 +40,13 @@ + + + + + + + diff --git a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.ts index a9838f17..85329497 100644 --- a/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/publisher-properties-dialog/publisher-properties-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material'; +import { MatDialogRef, MAT_CHECKBOX_CLICK_ACTION, MAT_DIALOG_DATA } from '@angular/material'; -import { PublisherProperties, OpenVidu } from 'openvidu-browser'; +import { PublisherProperties, OpenVidu, Filter } from 'openvidu-browser'; @Component({ selector: 'app-publisher-properties-dialog', @@ -26,6 +26,9 @@ export class PublisherPropertiesDialogComponent { audioDevices = []; videoDevices = []; + filter: Filter = { type: 'GStreamerFilter', options: { 'command': 'pitch pitch=0.8 tempo=1.0' } }; + stringOptions = "{\"command\":\"pitch pitch=0.8 tempo=1.0\"}"; + constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: PublisherProperties) { this.publisherProperties = data; @@ -72,6 +75,12 @@ export class PublisherPropertiesDialogComponent { this.publisherProperties.videoSource = undefined; } } + try { + this.filter.options = JSON.parse(this.stringOptions); + } catch (e) { + console.error('Invalid JSON object in "Filter options" field'); + } + this.publisherProperties.filter = this.filter; return this.publisherProperties; } diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css index 4728e295..06363071 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css @@ -19,6 +19,12 @@ mat-radio-button:first-child { padding-bottom: 1.25em; } +#turn-div mat-radio-button { + display: block; + margin-left: 0; + margin-bottom: 3px; +} + #manual-turn-div { margin-top: 10px; padding: 5px; diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index 95ebe950..9df17402 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -1,77 +1,105 @@
-

Session properties

- - - - - {{ enumerator }} - - - - - - - {{ enumerator }} - - - - - - - {{ enumerator }} - - - - - - - - - - -
- - Auto - Freeice - Manual - -
- - +
+
+

Session properties

+ + + + + {{ enumerator }} + + - - + + + + {{ enumerator }} + + - - + + + + {{ enumerator }} + + -
+ + + + + + + +
+ + Auto + Freeice + Manual + +
+ + + + + + + + + +
+
+
- +
+

User configuration

+ + +
+ + SUB + PUB + MOD + +
- + +
+ + + + + + + + + + + + + + {{filterName}} + + + + + +
-

User configuration

- - -
- - SUB - PUB - MOD - + +
+ + + +
+
- - -
- - - -
-
+
- +
\ No newline at end of file diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts index 5d2fd9b3..8024ea66 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; -import { MatDialog, MAT_DIALOG_DATA, MatDialogConfig, MatDialogRef } from '@angular/material'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { SessionProperties, MediaMode, RecordingMode, RecordingLayout } from 'openvidu-node-client'; +import { SessionProperties, MediaMode, RecordingMode, RecordingLayout, TokenOptions } from 'openvidu-node-client'; @Component({ selector: 'app-session-properties-dialog', @@ -13,8 +13,11 @@ export class SessionPropertiesDialogComponent { sessionProperties: SessionProperties; turnConf: string; manualTurnConf: RTCIceServer = {}; - participantRole: string; customToken: string; + tokenOptions: TokenOptions; + + filterName = 'GStreamerFilter'; + filters: string[] = []; mediaMode = MediaMode; recordingMode = RecordingMode; @@ -25,7 +28,7 @@ export class SessionPropertiesDialogComponent { this.sessionProperties = data.sessionProperties; this.turnConf = data.turnConf; this.manualTurnConf = data.manualTurnConf; - this.participantRole = data.participantRole; + this.tokenOptions = data.tokenOptions; this.customToken = data.customToken; } @@ -33,4 +36,9 @@ export class SessionPropertiesDialogComponent { return Object.keys(enumerator); } + generateTokenOptions(): TokenOptions { + this.tokenOptions.kurentoOptions.allowedFilters = this.filters; + return this.tokenOptions; + } + } diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 1e78b14c..e97a11d6 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -15,6 +15,7 @@ import { MediaMode, RecordingMode, RecordingLayout, + TokenOptions, OpenViduRole } from 'openvidu-node-client'; import { MatDialog, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material'; @@ -113,10 +114,20 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { publisherStopSpeaking: false }; + // Session properties dialog turnConf = 'auto'; manualTurnConf: RTCIceServer = { urls: [] }; - participantRole: OpenViduRole = OpenViduRole.PUBLISHER; customToken: string; + tokenOptions: TokenOptions = { + role: OpenViduRole.PUBLISHER, + kurentoOptions: { + videoMaxRecvBandwidth: 600, + videoMinRecvBandwidth: 300, + videoMaxSendBandwidth: 600, + videoMinSendBandwidth: 300, + allowedFilters: ['GStreamerFilter'] + } + }; events: OpenViduEvent[] = []; @@ -334,7 +345,12 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.session.off('streamPropertyChanged'); if (this.sessionEvents.streamPropertyChanged) { this.session.on('streamPropertyChanged', (event: StreamPropertyChangedEvent) => { - const newValue = event.changedProperty === 'videoDimensions' ? JSON.stringify(event.newValue) : event.newValue.toString(); + let newValue: string; + if (event.changedProperty === 'filter') { + newValue = !event.newValue ? undefined : event.newValue.toString(); + } else { + newValue = event.changedProperty === 'videoDimensions' ? JSON.stringify(event.newValue) : event.newValue.toString(); + } this.updateEventList('streamPropertyChanged', event.changedProperty + ' [' + newValue + ']'); }); } @@ -499,10 +515,10 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { sessionProperties: this.sessionProperties, turnConf: this.turnConf, manualTurnConf: this.manualTurnConf, - participantRole: this.participantRole, - customToken: this.customToken + customToken: this.customToken, + tokenOptions: this.tokenOptions }, - width: '280px' + width: '450px' }); dialogRef.afterClosed().subscribe((result) => { @@ -513,8 +529,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { } this.turnConf = result.turnConf; this.manualTurnConf = result.manualTurnConf; - this.participantRole = result.participantRole; this.customToken = result.customToken; + this.tokenOptions = result.tokenOptions; } document.getElementById('session-settings-btn-' + this.index).classList.remove('cdk-program-focused'); }); @@ -612,7 +628,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { return this.OV_NodeClient.createSession(this.sessionProperties) .then(session_NodeClient => { this.sessionAPI = session_NodeClient; - return session_NodeClient.generateToken({ role: this.participantRole }); + return session_NodeClient.generateToken({ role: this.tokenOptions.role, kurentoOptions: this.tokenOptions.kurentoOptions }); }); } diff --git a/openvidu-testapp/src/app/components/video/video.component.html b/openvidu-testapp/src/app/components/video/video.component.html index 33e74041..1c2524be 100644 --- a/openvidu-testapp/src/app/components/video/video.component.html +++ b/openvidu-testapp/src/app/components/video/video.component.html @@ -10,15 +10,20 @@ - - + - - diff --git a/openvidu-testapp/src/app/components/video/video.component.ts b/openvidu-testapp/src/app/components/video/video.component.ts index 1fae7b53..7004d568 100644 --- a/openvidu-testapp/src/app/components/video/video.component.ts +++ b/openvidu-testapp/src/app/components/video/video.component.ts @@ -18,6 +18,7 @@ import { MuteSubscribersService } from '../../services/mute-subscribers.service' import { Subscription } from 'rxjs'; import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog/local-recording-dialog.component'; import { ExtensionDialogComponent } from '../dialogs/extension-dialog/extension-dialog.component'; +import { FilterDialogComponent } from '../dialogs/filter-dialog/filter-dialog.component'; @Component({ selector: 'app-video', @@ -621,4 +622,12 @@ export class VideoComponent implements OnInit, OnDestroy { this.OV.session.forceDisconnect(this.streamManager.stream.connection); } + filterConfig() { + this.dialog.open(FilterDialogComponent, { + data: { session: this.streamManager.stream.session, stream: this.streamManager.stream }, + disableClose: true, + width: '250px' + }); + } + }