mirror of https://github.com/OpenVidu/openvidu.git
openvidu-testapp: Kurento filters support
parent
65c886930f
commit
7ce6826b62
|
@ -24,6 +24,7 @@ import { SessionApiDialogComponent } from './components/dialogs/session-api-dial
|
||||||
import { EventsDialogComponent } from './components/dialogs/events-dialog/events-dialog.component';
|
import { EventsDialogComponent } from './components/dialogs/events-dialog/events-dialog.component';
|
||||||
import { PublisherPropertiesDialogComponent } from './components/dialogs/publisher-properties-dialog/publisher-properties-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 { 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 { OpenviduRestService } from './services/openvidu-rest.service';
|
||||||
import { OpenviduParamsService } from './services/openvidu-params.service';
|
import { OpenviduParamsService } from './services/openvidu-params.service';
|
||||||
|
@ -46,6 +47,7 @@ import { MuteSubscribersService } from './services/mute-subscribers.service';
|
||||||
LocalRecordingDialogComponent,
|
LocalRecordingDialogComponent,
|
||||||
PublisherPropertiesDialogComponent,
|
PublisherPropertiesDialogComponent,
|
||||||
ScenarioPropertiesDialogComponent,
|
ScenarioPropertiesDialogComponent,
|
||||||
|
FilterDialogComponent,
|
||||||
UsersTableComponent,
|
UsersTableComponent,
|
||||||
TableVideoComponent
|
TableVideoComponent
|
||||||
],
|
],
|
||||||
|
@ -71,7 +73,8 @@ import { MuteSubscribersService } from './services/mute-subscribers.service';
|
||||||
EventsDialogComponent,
|
EventsDialogComponent,
|
||||||
LocalRecordingDialogComponent,
|
LocalRecordingDialogComponent,
|
||||||
PublisherPropertiesDialogComponent,
|
PublisherPropertiesDialogComponent,
|
||||||
ScenarioPropertiesDialogComponent
|
ScenarioPropertiesDialogComponent,
|
||||||
|
FilterDialogComponent
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|
|
@ -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: `
|
||||||
|
<div>
|
||||||
|
<h2 mat-dialog-title>Filter configuration</h2>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<label class="label">Apply filter</label>
|
||||||
|
<button mat-button id="apply-filter-btn" (click)="apply()">Apply</button>
|
||||||
|
<mat-form-field class="inner-text-input">
|
||||||
|
<input matInput id="filter-type-field" placeholder="Type" [(ngModel)]="filterType">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="inner-text-input">
|
||||||
|
<input matInput id="filter-options-field" placeholder="Options" [(ngModel)]="filterOptions">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<label class="label">Exec filter method</label>
|
||||||
|
<button mat-button id="exec-filter-btn" (click)="execMethod()">Exec</button>
|
||||||
|
<mat-form-field class="inner-text-input">
|
||||||
|
<input matInput id="filter-method-field" placeholder="Method" [(ngModel)]="filterMethod">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="inner-text-input">
|
||||||
|
<input matInput id="filter-params-field" placeholder="Params" [(ngModel)]="filterParams">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<label class="label">Remove filter</label>
|
||||||
|
<button mat-button id="remove-filter-btn" (click)="remove()">Remove</button>
|
||||||
|
<mat-form-field *ngIf="!!response" id="response-text-area" appearance="fill">
|
||||||
|
<textarea id="api-response-text-area" [(ngModel)]="response" matInput readonly></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-dialog-content>
|
||||||
|
<mat-dialog-actions>
|
||||||
|
<button mat-button id="close-dialog-btn" [mat-dialog-close]="{session: session}">CLOSE</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
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<FilterDialogComponent>,
|
||||||
|
@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 + ']';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -40,6 +40,13 @@
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input matInput placeholder="Framerate" [(ngModel)]="publisherProperties.frameRate" type="number">
|
<input matInput placeholder="Framerate" [(ngModel)]="publisherProperties.frameRate" type="number">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Filter type" [(ngModel)]="filter.type" type="text">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Filter options" [(ngModel)]="stringOptions" type="text">
|
||||||
|
</mat-form-field>
|
||||||
</mat-dialog-content>
|
</mat-dialog-content>
|
||||||
<mat-dialog-actions>
|
<mat-dialog-actions>
|
||||||
<button mat-button [mat-dialog-close]="initValue">CANCEL</button>
|
<button mat-button [mat-dialog-close]="initValue">CANCEL</button>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, Inject } from '@angular/core';
|
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({
|
@Component({
|
||||||
selector: 'app-publisher-properties-dialog',
|
selector: 'app-publisher-properties-dialog',
|
||||||
|
@ -26,6 +26,9 @@ export class PublisherPropertiesDialogComponent {
|
||||||
audioDevices = [];
|
audioDevices = [];
|
||||||
videoDevices = [];
|
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<PublisherPropertiesDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<PublisherPropertiesDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: PublisherProperties) {
|
@Inject(MAT_DIALOG_DATA) public data: PublisherProperties) {
|
||||||
this.publisherProperties = data;
|
this.publisherProperties = data;
|
||||||
|
@ -72,6 +75,12 @@ export class PublisherPropertiesDialogComponent {
|
||||||
this.publisherProperties.videoSource = undefined;
|
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;
|
return this.publisherProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,12 @@ mat-radio-button:first-child {
|
||||||
padding-bottom: 1.25em;
|
padding-bottom: 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#turn-div mat-radio-button {
|
||||||
|
display: block;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
#manual-turn-div {
|
#manual-turn-div {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
|
@ -1,77 +1,105 @@
|
||||||
<div>
|
<div>
|
||||||
<h2 mat-dialog-title>Session properties</h2>
|
<div fxLayout="row" fxLayoutGap="20px">
|
||||||
<mat-dialog-content>
|
<div>
|
||||||
<mat-form-field>
|
<h2 mat-dialog-title>Session properties</h2>
|
||||||
<mat-select placeholder="MediaMode" [(ngModel)]="sessionProperties.mediaMode">
|
<mat-dialog-content>
|
||||||
<mat-option *ngFor="let enumerator of enumToArray(mediaMode)" [value]="enumerator">
|
<mat-form-field>
|
||||||
{{ enumerator }}
|
<mat-select placeholder="MediaMode" [(ngModel)]="sessionProperties.mediaMode">
|
||||||
</mat-option>
|
<mat-option *ngFor="let enumerator of enumToArray(mediaMode)" [value]="enumerator">
|
||||||
</mat-select>
|
{{ enumerator }}
|
||||||
</mat-form-field>
|
</mat-option>
|
||||||
<mat-form-field>
|
</mat-select>
|
||||||
<mat-select placeholder="RecordingMode" [(ngModel)]="sessionProperties.recordingMode">
|
|
||||||
<mat-option *ngFor="let enumerator of enumToArray(recordingMode)" [value]="enumerator">
|
|
||||||
{{ enumerator }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field>
|
|
||||||
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout">
|
|
||||||
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
|
|
||||||
{{ enumerator }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field *ngIf="this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
|
|
||||||
<input matInput placeholder="DefaultCustomLayout" [(ngModel)]="sessionProperties.defaultCustomLayout">
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field>
|
|
||||||
<input matInput placeholder="CustomSessionId" [(ngModel)]="sessionProperties.customSessionId">
|
|
||||||
</mat-form-field>
|
|
||||||
<label class="label">Turn configuration</label>
|
|
||||||
<div id="turn-div">
|
|
||||||
<mat-radio-group name="Turn configuration" [(ngModel)]="turnConf">
|
|
||||||
<mat-radio-button value="auto">Auto</mat-radio-button>
|
|
||||||
<mat-radio-button value="freeice">Freeice</mat-radio-button>
|
|
||||||
<mat-radio-button value="manual">Manual</mat-radio-button>
|
|
||||||
</mat-radio-group>
|
|
||||||
<div *ngIf="turnConf === 'manual'" id="manual-turn-div">
|
|
||||||
<mat-form-field style="width: 100%">
|
|
||||||
<input matInput placeholder="url" [(ngModel)]="manualTurnConf.urls[0]">
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field style="width: 49%; padding-right: 2px">
|
<mat-form-field>
|
||||||
<input matInput placeholder="user" [(ngModel)]="manualTurnConf.username">
|
<mat-select placeholder="RecordingMode" [(ngModel)]="sessionProperties.recordingMode">
|
||||||
|
<mat-option *ngFor="let enumerator of enumToArray(recordingMode)" [value]="enumerator">
|
||||||
|
{{ enumerator }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field style="width: 49%; padding-left: 2px">
|
<mat-form-field>
|
||||||
<input matInput placeholder="pass" [(ngModel)]="manualTurnConf.credential">
|
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout">
|
||||||
|
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
|
||||||
|
{{ enumerator }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
<mat-form-field *ngIf="this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
|
||||||
|
<input matInput placeholder="DefaultCustomLayout" type="text" [(ngModel)]="sessionProperties.defaultCustomLayout">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="CustomSessionId" type="text" [(ngModel)]="sessionProperties.customSessionId">
|
||||||
|
</mat-form-field>
|
||||||
|
<label class="label">Turn configuration</label>
|
||||||
|
<div id="turn-div">
|
||||||
|
<mat-radio-group name="Turn configuration" [(ngModel)]="turnConf">
|
||||||
|
<mat-radio-button value="auto">Auto</mat-radio-button>
|
||||||
|
<mat-radio-button value="freeice">Freeice</mat-radio-button>
|
||||||
|
<mat-radio-button value="manual">Manual</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
<div *ngIf="turnConf === 'manual'" id="manual-turn-div">
|
||||||
|
<mat-form-field style="width: 100%">
|
||||||
|
<input matInput placeholder="url" type="text" [(ngModel)]="manualTurnConf.urls[0]">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="width: 49%; padding-right: 2px">
|
||||||
|
<input matInput placeholder="user" type="text" [(ngModel)]="manualTurnConf.username">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="width: 49%; padding-left: 2px">
|
||||||
|
<input matInput placeholder="pass" type="text" [(ngModel)]="manualTurnConf.credential">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-dialog-content>
|
||||||
</div>
|
</div>
|
||||||
</mat-dialog-content>
|
<div>
|
||||||
|
<h2 mat-dialog-title>User configuration</h2>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<label class="label">Role</label>
|
||||||
|
<div id="role-div">
|
||||||
|
<mat-radio-group name="Role" [(ngModel)]="tokenOptions.role">
|
||||||
|
<mat-radio-button value="SUBSCRIBER">SUB</mat-radio-button>
|
||||||
|
<mat-radio-button value="PUBLISHER">PUB</mat-radio-button>
|
||||||
|
<mat-radio-button value="MODERATOR">MOD</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
<mat-divider style="margin-bottom: 20px"></mat-divider>
|
<label class="label" style="margin-bottom: 8px">Kurento config</label>
|
||||||
|
<div id="kurento-config-div">
|
||||||
|
<mat-form-field style="width: 39%; margin-right: 5px">
|
||||||
|
<input matInput placeholder="Max recv" type="number" [(ngModel)]="tokenOptions.kurentoOptions.videoMaxRecvBandwidth">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="width: 39%">
|
||||||
|
<input matInput placeholder="Min recv" type="number" [(ngModel)]="tokenOptions.kurentoOptions.videoMinRecvBandwidth">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="width: 39%; margin-right: 5px">
|
||||||
|
<input matInput placeholder="Max send" type="number" [(ngModel)]="tokenOptions.kurentoOptions.videoMaxSendBandwidth">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="width: 39%">
|
||||||
|
<input matInput placeholder="Min send" type="number" [(ngModel)]="tokenOptions.kurentoOptions.videoMinSendBandwidth">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-chip-list *ngIf="filters.length > 0">
|
||||||
|
<mat-chip style="height: 20px" *ngFor="let filterName of filters" (click)="filters.splice(filters.indexOf(filterName, 1))">{{filterName}}</mat-chip>
|
||||||
|
</mat-chip-list>
|
||||||
|
<mat-form-field style="width: 70%">
|
||||||
|
<input matInput placeholder="Allowed filter" type="text" [(ngModel)]="filterName">
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-icon-button style="width: 24px; height: 24px; line-height: 24px;" title="Add allowed filter" (click)="filters.push(filterName); filterName = '';">
|
||||||
|
<mat-icon style="font-size: 18px; line-height: 18px; width: 18px; height: 18px" aria-label="Add allowed filter">add_circle</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2 mat-dialog-title>User configuration</h2>
|
<label class="label">Token</label>
|
||||||
<mat-dialog-content>
|
<div id="custom-token-div">
|
||||||
<label class="label">Role</label>
|
<mat-form-field>
|
||||||
<div id="role-div">
|
<input matInput placeholder="Custom token" type="text" [(ngModel)]="customToken">
|
||||||
<mat-radio-group name="Role" [(ngModel)]="participantRole">
|
</mat-form-field>
|
||||||
<mat-radio-button value="SUBSCRIBER">SUB</mat-radio-button>
|
</div>
|
||||||
<mat-radio-button value="PUBLISHER">PUB</mat-radio-button>
|
</mat-dialog-content>
|
||||||
<mat-radio-button value="MODERATOR">MOD</mat-radio-button>
|
|
||||||
</mat-radio-group>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<label class="label">Token</label>
|
|
||||||
<div id="custom-token-div">
|
|
||||||
<mat-form-field>
|
|
||||||
<input matInput placeholder="Custom token" [(ngModel)]="customToken">
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
</mat-dialog-content>
|
|
||||||
|
|
||||||
<mat-dialog-actions>
|
<mat-dialog-actions>
|
||||||
<button mat-button [mat-dialog-close]="undefined">CANCEL</button>
|
<button mat-button [mat-dialog-close]="undefined">CANCEL</button>
|
||||||
<button mat-button [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, participantRole: participantRole, customToken: customToken}">SAVE</button>
|
<button mat-button [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, tokenOptions: generateTokenOptions(), customToken: customToken}">SAVE</button>
|
||||||
</mat-dialog-actions>
|
</mat-dialog-actions>
|
||||||
</div>
|
</div>
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, Inject } from '@angular/core';
|
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({
|
@Component({
|
||||||
selector: 'app-session-properties-dialog',
|
selector: 'app-session-properties-dialog',
|
||||||
|
@ -13,8 +13,11 @@ export class SessionPropertiesDialogComponent {
|
||||||
sessionProperties: SessionProperties;
|
sessionProperties: SessionProperties;
|
||||||
turnConf: string;
|
turnConf: string;
|
||||||
manualTurnConf: RTCIceServer = {};
|
manualTurnConf: RTCIceServer = {};
|
||||||
participantRole: string;
|
|
||||||
customToken: string;
|
customToken: string;
|
||||||
|
tokenOptions: TokenOptions;
|
||||||
|
|
||||||
|
filterName = 'GStreamerFilter';
|
||||||
|
filters: string[] = [];
|
||||||
|
|
||||||
mediaMode = MediaMode;
|
mediaMode = MediaMode;
|
||||||
recordingMode = RecordingMode;
|
recordingMode = RecordingMode;
|
||||||
|
@ -25,7 +28,7 @@ export class SessionPropertiesDialogComponent {
|
||||||
this.sessionProperties = data.sessionProperties;
|
this.sessionProperties = data.sessionProperties;
|
||||||
this.turnConf = data.turnConf;
|
this.turnConf = data.turnConf;
|
||||||
this.manualTurnConf = data.manualTurnConf;
|
this.manualTurnConf = data.manualTurnConf;
|
||||||
this.participantRole = data.participantRole;
|
this.tokenOptions = data.tokenOptions;
|
||||||
this.customToken = data.customToken;
|
this.customToken = data.customToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,4 +36,9 @@ export class SessionPropertiesDialogComponent {
|
||||||
return Object.keys(enumerator);
|
return Object.keys(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateTokenOptions(): TokenOptions {
|
||||||
|
this.tokenOptions.kurentoOptions.allowedFilters = this.filters;
|
||||||
|
return this.tokenOptions;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
MediaMode,
|
MediaMode,
|
||||||
RecordingMode,
|
RecordingMode,
|
||||||
RecordingLayout,
|
RecordingLayout,
|
||||||
|
TokenOptions,
|
||||||
OpenViduRole
|
OpenViduRole
|
||||||
} from 'openvidu-node-client';
|
} from 'openvidu-node-client';
|
||||||
import { MatDialog, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material';
|
import { MatDialog, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material';
|
||||||
|
@ -113,10 +114,20 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
publisherStopSpeaking: false
|
publisherStopSpeaking: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Session properties dialog
|
||||||
turnConf = 'auto';
|
turnConf = 'auto';
|
||||||
manualTurnConf: RTCIceServer = { urls: [] };
|
manualTurnConf: RTCIceServer = { urls: [] };
|
||||||
participantRole: OpenViduRole = OpenViduRole.PUBLISHER;
|
|
||||||
customToken: string;
|
customToken: string;
|
||||||
|
tokenOptions: TokenOptions = {
|
||||||
|
role: OpenViduRole.PUBLISHER,
|
||||||
|
kurentoOptions: {
|
||||||
|
videoMaxRecvBandwidth: 600,
|
||||||
|
videoMinRecvBandwidth: 300,
|
||||||
|
videoMaxSendBandwidth: 600,
|
||||||
|
videoMinSendBandwidth: 300,
|
||||||
|
allowedFilters: ['GStreamerFilter']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
events: OpenViduEvent[] = [];
|
events: OpenViduEvent[] = [];
|
||||||
|
|
||||||
|
@ -334,7 +345,12 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.session.off('streamPropertyChanged');
|
this.session.off('streamPropertyChanged');
|
||||||
if (this.sessionEvents.streamPropertyChanged) {
|
if (this.sessionEvents.streamPropertyChanged) {
|
||||||
this.session.on('streamPropertyChanged', (event: StreamPropertyChangedEvent) => {
|
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 + ']');
|
this.updateEventList('streamPropertyChanged', event.changedProperty + ' [' + newValue + ']');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -499,10 +515,10 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
sessionProperties: this.sessionProperties,
|
sessionProperties: this.sessionProperties,
|
||||||
turnConf: this.turnConf,
|
turnConf: this.turnConf,
|
||||||
manualTurnConf: this.manualTurnConf,
|
manualTurnConf: this.manualTurnConf,
|
||||||
participantRole: this.participantRole,
|
customToken: this.customToken,
|
||||||
customToken: this.customToken
|
tokenOptions: this.tokenOptions
|
||||||
},
|
},
|
||||||
width: '280px'
|
width: '450px'
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((result) => {
|
dialogRef.afterClosed().subscribe((result) => {
|
||||||
|
@ -513,8 +529,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
}
|
}
|
||||||
this.turnConf = result.turnConf;
|
this.turnConf = result.turnConf;
|
||||||
this.manualTurnConf = result.manualTurnConf;
|
this.manualTurnConf = result.manualTurnConf;
|
||||||
this.participantRole = result.participantRole;
|
|
||||||
this.customToken = result.customToken;
|
this.customToken = result.customToken;
|
||||||
|
this.tokenOptions = result.tokenOptions;
|
||||||
}
|
}
|
||||||
document.getElementById('session-settings-btn-' + this.index).classList.remove('cdk-program-focused');
|
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)
|
return this.OV_NodeClient.createSession(this.sessionProperties)
|
||||||
.then(session_NodeClient => {
|
.then(session_NodeClient => {
|
||||||
this.sessionAPI = 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 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,20 @@
|
||||||
<button class="video-btn pub-btn" title="Publish/Unpublish" (click)="pubUnpub()">
|
<button class="video-btn pub-btn" title="Publish/Unpublish" (click)="pubUnpub()">
|
||||||
<mat-icon aria-label="Publish or unpublish" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
<mat-icon aria-label="Publish or unpublish" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="streamManager.stream.hasVideo && !this.unpublished" class="video-btn pub-video-btn" title="Publish/Unpublish Video" (click)="pubUnpubVideo()">
|
<button *ngIf="streamManager.stream.hasVideo && !this.unpublished" class="video-btn pub-video-btn" title="Publish/Unpublish Video"
|
||||||
|
(click)="pubUnpubVideo()">
|
||||||
<mat-icon aria-label="Publish or unpublish video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
<mat-icon aria-label="Publish or unpublish video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="streamManager.stream.hasAudio && !this.unpublished" class="video-btn pub-audio-btn" title="Publish/Unpublish Audio" (click)="pubUnpubAudio()">
|
<button *ngIf="streamManager.stream.hasAudio && !this.unpublished" class="video-btn pub-audio-btn" title="Publish/Unpublish Audio"
|
||||||
|
(click)="pubUnpubAudio()">
|
||||||
<mat-icon aria-label="Publish or unpublish audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
<mat-icon aria-label="Publish or unpublish audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="!this.unpublished" class="video-btn change-publisher-btn" title="Change publisher" (click)="changePub()">
|
<button *ngIf="!this.unpublished" class="video-btn change-publisher-btn" title="Change publisher" (click)="changePub()">
|
||||||
<mat-icon aria-label="Change publisher" class="mat-icon material-icons" role="img" aria-hidden="true">switch_video</mat-icon>
|
<mat-icon aria-label="Change publisher" class="mat-icon material-icons" role="img" aria-hidden="true">switch_video</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
<button *ngIf="!this.unpublished" class="video-btn filter-btn" title="Filter configuration" (click)="filterConfig()">
|
||||||
|
<mat-icon aria-label="Filter configuration" class="mat-icon material-icons" role="img" aria-hidden="true">filter_vintage</mat-icon>
|
||||||
|
</button>
|
||||||
<button *ngIf="!this.unpublished" class="video-btn rec-btn publisher-rec-btn" title="Record" (click)="record()">
|
<button *ngIf="!this.unpublished" class="video-btn rec-btn publisher-rec-btn" title="Record" (click)="record()">
|
||||||
<mat-icon aria-label="Start/Stop local recording" class="mat-icon material-icons" role="img" aria-hidden="true">
|
<mat-icon aria-label="Start/Stop local recording" class="mat-icon material-icons" role="img" aria-hidden="true">
|
||||||
{{recordIcon}}</mat-icon>
|
{{recordIcon}}</mat-icon>
|
||||||
|
@ -41,10 +46,12 @@
|
||||||
<button class="video-btn sub-btn" title="Subscribe/Unsubscribe" (click)="subUnsub()">
|
<button class="video-btn sub-btn" title="Subscribe/Unsubscribe" (click)="subUnsub()">
|
||||||
<mat-icon aria-label="Subscribe or unsubscribe" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
<mat-icon aria-label="Subscribe or unsubscribe" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="streamManager.stream.hasVideo && !!pubSubVideoIcon" class="video-btn sub-video-btn" title="Subscribe/Unsubscribe Video" (click)="subUnsubVideo()">
|
<button *ngIf="streamManager.stream.hasVideo && !!pubSubVideoIcon" class="video-btn sub-video-btn" title="Subscribe/Unsubscribe Video"
|
||||||
|
(click)="subUnsubVideo()">
|
||||||
<mat-icon aria-label="Subscribe or unsubscribe video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
<mat-icon aria-label="Subscribe or unsubscribe video" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubVideoIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="streamManager.stream.hasAudio && !!pubSubAudioIcon" class="video-btn sub-audio-btn" title="Subscribe/Unsubscribe Audio" (click)="subUnsubAudio()">
|
<button *ngIf="streamManager.stream.hasAudio && !!pubSubAudioIcon" class="video-btn sub-audio-btn" title="Subscribe/Unsubscribe Audio"
|
||||||
|
(click)="subUnsubAudio()">
|
||||||
<mat-icon aria-label="Subscribe or unsubscribe audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
<mat-icon aria-label="Subscribe or unsubscribe audio" class="mat-icon material-icons" role="img" aria-hidden="true">{{pubSubAudioIcon}}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { MuteSubscribersService } from '../../services/mute-subscribers.service'
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog/local-recording-dialog.component';
|
import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog/local-recording-dialog.component';
|
||||||
import { ExtensionDialogComponent } from '../dialogs/extension-dialog/extension-dialog.component';
|
import { ExtensionDialogComponent } from '../dialogs/extension-dialog/extension-dialog.component';
|
||||||
|
import { FilterDialogComponent } from '../dialogs/filter-dialog/filter-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-video',
|
selector: 'app-video',
|
||||||
|
@ -621,4 +622,12 @@ export class VideoComponent implements OnInit, OnDestroy {
|
||||||
this.OV.session.forceDisconnect(this.streamManager.stream.connection);
|
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'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue