openvidu-browser: filter support

pull/87/merge
pabloFuente 2018-07-27 14:32:53 +02:00
parent 95a078b14a
commit ccd8d7a8b9
9 changed files with 188 additions and 3 deletions

View File

@ -129,7 +129,8 @@ export class Connection {
videoActive: opts.videoActive,
typeOfVideo: opts.typeOfVideo,
frameRate: opts.frameRate,
videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined,
filter: !!opts.filter ? opts.filter : {}
};
const stream = new Stream(this.session, streamOptions);

View File

@ -188,7 +188,8 @@ export class OpenVidu {
publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true,
publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true,
resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined
videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined,
filter: properties.filter
};
} else {

View File

@ -492,6 +492,99 @@ export class Session implements EventDispatcher {
});
}
applyFilter(stream: Stream, type: string, options: string): Promise<any> {
return new Promise((resolve, reject) => {
console.info('Applying filter to stream ' + stream.streamId);
this.openvidu.sendRequest(
'applyFilter',
{ streamId: stream.streamId, type, options },
(error, response) => {
if (error) {
console.error('Error applying filter for Stream ' + stream.streamId, error);
if (error.code === 401) {
reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to apply a filter"));
} else {
reject(error);
}
} else {
console.info('Filter successfully applied on Stream ' + stream.streamId);
const oldValue = JSON.parse(JSON.stringify(stream.filter));
stream.filter = { type, options };
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, 'filter', stream.filter, oldValue, 'applyFilter')]);
stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(stream.streamManager, stream, 'filter', stream.filter, oldValue, 'applyFilter')]);
resolve();
}
}
);
});
}
execFilterMethod(stream: Stream, method: string, params: Object): Promise<any> {
return new Promise((resolve, reject) => {
console.info('Executing filter method to stream ' + stream.streamId);
let stringParams;
if (typeof params !== 'string') {
try {
stringParams = JSON.stringify(params);
} catch (error) {
const errorMsg = "'params' property must be a JSON formatted object";
console.error(errorMsg);
reject(errorMsg);
}
} else {
stringParams = <string>params;
}
this.openvidu.sendRequest(
'execFilterMethod',
{ streamId: stream.streamId, method, params: stringParams },
(error, response) => {
if (error) {
console.error('Error executing filter method for Stream ' + stream.streamId, error);
if (error.code === 401) {
reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to execute a filter method"));
} else {
reject(error);
}
} else {
console.info('Filter method successfully executed on Stream ' + stream.streamId);
const oldValue = JSON.parse(JSON.stringify(stream.filter));
stream.filter.lastExecMethod = { method, params: JSON.parse(stringParams) };
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, 'filter', stream.filter, oldValue, 'execFilterMethod')]);
stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(stream.streamManager, stream, 'filter', stream.filter, oldValue, 'execFilterMethod')]);
resolve();
}
}
);
});
}
removeFilter(stream: Stream): Promise<any> {
return new Promise((resolve, reject) => {
console.info('Removing filter of stream ' + stream.streamId);
this.openvidu.sendRequest(
'removeFilter',
{ streamId: stream.streamId },
(error, response) => {
if (error) {
console.error('Error removing filter for Stream ' + stream.streamId, error);
if (error.code === 401) {
reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to remove a filter"));
} else {
reject(error);
}
} else {
console.info('Filter successfully removed from Stream ' + stream.streamId);
const oldValue = JSON.parse(JSON.stringify(stream.filter));
stream.filter = new Object();
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, 'filter', stream.filter, oldValue, 'applyFilter')]);
stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(stream.streamManager, stream, 'filter', stream.filter, oldValue, 'applyFilter')]);
resolve();
}
}
);
});
}
/**
* Sends one signal. `signal` object has the following optional properties:
@ -792,6 +885,10 @@ export class Session implements EventDispatcher {
msg.newValue = JSON.parse(JSON.parse(msg.newValue));
stream.videoDimensions = msg.newValue;
break;
case 'filter':
oldValue = stream.filter;
stream.filter = msg.newValue;
break;
}
this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);

View File

@ -100,6 +100,21 @@ export class Stream {
*/
videoDimensions: { width: number, height: number };
/**
* **WARNING**: experimental option. This interface may change in the near future
*
* Filter applied to the Stream. You can apply filters by calling [[Session.applyFilter]], execute methods of the applied filter with
* [[Session.execFilterMethod]] and remove it with [[Session.removeFilter]]. Be aware that the client calling this methods must have the
* necessary permissions: the token owned by the client must have been initialized with the appropriated `allowedFilters` array.
*/
filter: {
type?: string,
options?: Object,
lastExecMethod?: {
method: string, params: Object
}
} = {};
/**
* @hidden
*/
@ -163,6 +178,12 @@ export class Stream {
this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
this.videoDimensions = this.inboundStreamOpts.videoDimensions;
}
if (!!this.inboundStreamOpts.filter) {
if (!!this.inboundStreamOpts.filter.lastExecMethod && Object.keys(this.inboundStreamOpts.filter.lastExecMethod).length === 0) {
delete this.inboundStreamOpts.filter.lastExecMethod;
}
this.filter = this.inboundStreamOpts.filter;
}
} else {
// OutboundStreamOptions: stream belongs to a Publisher
this.outboundStreamOpts = <OutboundStreamOptions>options;
@ -182,6 +203,9 @@ export class Stream {
this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
}
}
if (!!this.outboundStreamOpts.publisherProperties.filter) {
this.filter = this.outboundStreamOpts.publisherProperties.filter;
}
}
this.ee.on('mediastream-updated', () => {
@ -467,7 +491,8 @@ export class Stream {
videoActive: this.videoActive,
typeOfVideo,
frameRate: !!this.frameRate ? this.frameRate : -1,
videoDimensions: JSON.stringify(this.videoDimensions)
videoDimensions: JSON.stringify(this.videoDimensions),
filter: this.outboundStreamOpts.publisherProperties.filter
}, (error, response) => {
if (error) {
if (error.code === 401) {

View File

@ -16,6 +16,7 @@
*/
import { Connection } from '../../../OpenVidu/Connection';
import { Filter } from '../Public/Filter';
export interface InboundStreamOptions {
id: string;
@ -27,4 +28,5 @@ export interface InboundStreamOptions {
typeOfVideo: string;
frameRate: number;
videoDimensions: { width: number, height: number };
filter: Filter;
}

View File

@ -15,6 +15,8 @@
*
*/
import { Filter } from '../Public/Filter';
export interface StreamOptionsServer {
id: string;
hasAudio: boolean;
@ -24,4 +26,5 @@ export interface StreamOptionsServer {
typeOfVideo: string;
frameRate: number;
videoDimensions: string;
filter: Filter;
}

View File

@ -0,0 +1,47 @@
/*
* (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* **WARNING**: experimental option. This interface may change in the near future. See [[Stream.filter]]
*/
export interface Filter {
/**
* Type of filter applied. This is the name of the remote class identifying the filter to apply in Kurento Media Server.
* For example: `"FaceOverlayFilter"`, `"GStreamerFilter"`. If `undefined` no filter is applied to the Stream
*/
type?: string;
/**
* Parameters used to initialized the filter.
* These correspond to the constructor parameters used in the filter in Kurento Media Server.
* For example: for `filter.type = "GStreamerFilter"` could be `filter.options = "pitch pitch=0.8 tempo=1.0"`
*/
options?: Object;
/**
* Value passed the last time [[Session.execFilterMethod]] or [[Session.forceExecFilterMethod]] were called
* for the Stream owning this filter. If `undefined` those methods have not been called yet.
*
* You can use this value to know the current status of any applied filter
*/
lastExecMethod?: {
method: string,
params: Object
};
}

View File

@ -15,6 +15,7 @@
*
*/
import { Filter } from './Filter';
import { VideoInsertMode } from '../../Enums/VideoInsertMode';
/**
@ -80,4 +81,11 @@ export interface PublisherProperties {
*/
videoSource?: string | MediaStreamTrack | boolean;
/**
* **WARNING**: experimental option. This property may change in the near future
*
* Define a filter to apply in the Publisher's stream
*/
filter?: Filter;
}

View File

@ -25,6 +25,7 @@ export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamProp
export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities';
export { Device } from './OpenViduInternal/Interfaces/Public/Device';
export { EventDispatcher } from './OpenViduInternal/Interfaces/Public/EventDispatcher';
export { Filter } from './OpenViduInternal/Interfaces/Public/Filter';
export { OpenViduAdvancedConfiguration } from './OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
export { PublisherProperties } from './OpenViduInternal/Interfaces/Public/PublisherProperties';
export { SignalOptions } from './OpenViduInternal/Interfaces/Public/SignalOptions';