mirror of https://github.com/OpenVidu/openvidu.git
openvidu-browser: restrict updated values of VB to background image URL
parent
34be4d8c13
commit
5826032020
|
@ -92,39 +92,67 @@ export class Filter {
|
|||
execMethod(method: string, params: Object): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
logger.info('Executing filter method to stream ' + this.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";
|
||||
logger.error(errorMsg);
|
||||
return reject(errorMsg);
|
||||
}
|
||||
} else {
|
||||
stringParams = <string>params;
|
||||
}
|
||||
this.stream.session.openvidu.sendRequest(
|
||||
'execFilterMethod',
|
||||
{ streamId: this.stream.streamId, method, params: stringParams },
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
logger.error('Error executing filter method for Stream ' + this.stream.streamId, error);
|
||||
if (error.code === 401) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to execute a filter method"));
|
||||
} else {
|
||||
return reject(error);
|
||||
}
|
||||
} else {
|
||||
logger.info('Filter method successfully executed on Stream ' + this.stream.streamId);
|
||||
const oldValue = (<any>Object).assign({}, this.stream.filter);
|
||||
this.stream.filter!.lastExecMethod = { method, params: JSON.parse(stringParams) };
|
||||
this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.session, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||
this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||
return resolve();
|
||||
|
||||
if (this.type.startsWith('VB:')) {
|
||||
|
||||
if (typeof params === 'string') {
|
||||
try {
|
||||
params = JSON.parse(params);
|
||||
} catch (error) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'Wrong params syntax: ' + error));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (method === 'update') {
|
||||
if (!this.stream.virtualBackgroundSinkElements?.VB) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'There is no Virtual Background filter applied'));
|
||||
} else {
|
||||
try {
|
||||
this.stream.virtualBackgroundSinkElements.VB.updateValues(params);
|
||||
} catch (error) {
|
||||
reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'Error updating values on Virtual Background filter: ' + error));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, `Unknown Virtual Background method "${method}"`));
|
||||
}
|
||||
} else {
|
||||
|
||||
let stringParams;
|
||||
if (typeof params !== 'string') {
|
||||
try {
|
||||
stringParams = JSON.stringify(params);
|
||||
} catch (error) {
|
||||
const errorMsg = "'params' property must be a JSON formatted object";
|
||||
logger.error(errorMsg);
|
||||
return reject(errorMsg);
|
||||
}
|
||||
} else {
|
||||
stringParams = <string>params;
|
||||
}
|
||||
|
||||
this.stream.session.openvidu.sendRequest(
|
||||
'execFilterMethod',
|
||||
{ streamId: this.stream.streamId, method, params: stringParams },
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
logger.error('Error executing filter method for Stream ' + this.stream.streamId, error);
|
||||
if (error.code === 401) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to execute a filter method"));
|
||||
} else {
|
||||
return reject(error);
|
||||
}
|
||||
} else {
|
||||
logger.info('Filter method successfully executed on Stream ' + this.stream.streamId);
|
||||
const oldValue = (<any>Object).assign({}, this.stream.filter);
|
||||
this.stream.filter!.lastExecMethod = { method, params: JSON.parse(stringParams) };
|
||||
this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.session, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||
this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]);
|
||||
return resolve();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@ import { Publisher } from './Publisher';
|
|||
import { Session } from './Session';
|
||||
import { StreamManager } from './StreamManager';
|
||||
import { Subscriber } from './Subscriber';
|
||||
import { VirtualBackgroundOptions } from '../OpenViduInternal/Interfaces/Public/VirtualBackgroundOptions';
|
||||
import { VirtualBackgroundImageOptions } from '../OpenViduInternal/Interfaces/Public/VirtualBackgroundImageOptions';
|
||||
import { VirtualBackgroundChromaOptions } from '../OpenViduInternal/Interfaces/Public/VirtualBackgroundChromaOptions';
|
||||
import { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions';
|
||||
import { OutboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/OutboundStreamOptions';
|
||||
import { WebRtcPeer, WebRtcPeerSendonly, WebRtcPeerRecvonly, WebRtcPeerSendrecv, WebRtcPeerConfiguration } from '../OpenViduInternal/WebRtcPeer/WebRtcPeer';
|
||||
|
@ -157,8 +154,11 @@ export class Stream {
|
|||
|
||||
private isSubscribeToRemote = false;
|
||||
|
||||
private virtualBackgroundSourceElements: { videoClone: HTMLVideoElement, mediaStreamClone: MediaStream };
|
||||
private virtualBackgroundSinkElements: { VB: any, video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
||||
private virtualBackgroundSourceElements?: { videoClone: HTMLVideoElement, mediaStreamClone: MediaStream };
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
virtualBackgroundSinkElements?: { VB: any, video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
|
@ -346,13 +346,16 @@ export class Stream {
|
|||
return reject(this.session.notConnectedError());
|
||||
}
|
||||
if (!this.session.openvidu.isAtLeastPro) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.OPENVIDU_EDITION_NOT_SUPPORTED, 'OpenVidu Virtual Background API is available from OpenVidu Pro edition onwards'));
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'OpenVidu Virtual Background API is available from OpenVidu Pro edition onwards'));
|
||||
}
|
||||
if (!this.hasVideo) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.NO_VIDEO_TRACK, 'The Virtual Background filter requires a video track to be applied'));
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'The Virtual Background filter requires a video track to be applied'));
|
||||
}
|
||||
if (!this.mediaStream || this.streamManager.videos.length === 0) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.STREAM_MANAGER_HAS_NO_VIDEO_ELEMENT, 'The StreamManager requires some video element to be attached to it in order to apply a Virtual Background filter'));
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'The StreamManager requires some video element to be attached to it in order to apply a Virtual Background filter'));
|
||||
}
|
||||
if (!!this.virtualBackgroundSinkElements && !!this.virtualBackgroundSourceElements) {
|
||||
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'There is already a Virtual Background filter applied to Stream ' + this.streamId));
|
||||
}
|
||||
|
||||
logger.info('Applying Virtual Background to stream ' + this.streamId);
|
||||
|
@ -379,25 +382,17 @@ export class Stream {
|
|||
openviduServerUrl: new URL(this.session.openvidu.httpUri),
|
||||
inputVideo: videoClone,
|
||||
inputResolution: '160x96',
|
||||
outputFramerate: 30
|
||||
outputFramerate: 24
|
||||
});
|
||||
|
||||
|
||||
let response: { video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
||||
switch (type) {
|
||||
case 'VB:blur': {
|
||||
const optionsVB = options as VirtualBackgroundOptions;
|
||||
response = await VB.backgroundBlur(optionsVB);
|
||||
response = await VB.backgroundBlur(options);
|
||||
break;
|
||||
}
|
||||
case 'VB:image': {
|
||||
const optionsVB = options as VirtualBackgroundImageOptions;
|
||||
response = await VB.backgroundImage(optionsVB);
|
||||
break;
|
||||
}
|
||||
case 'VB:chroma': {
|
||||
const optionsVB = options as VirtualBackgroundChromaOptions;
|
||||
response = await VB.backgroundChroma(optionsVB);
|
||||
response = await VB.backgroundImage(options);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -417,7 +412,11 @@ export class Stream {
|
|||
resolveApplyFilter(undefined);
|
||||
|
||||
} catch (error) {
|
||||
resolveApplyFilter(error);
|
||||
if (error.name === OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR) {
|
||||
resolveApplyFilter(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, error.message));
|
||||
} else {
|
||||
resolveApplyFilter(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,8 +426,12 @@ export class Stream {
|
|||
script.type = "text/javascript";
|
||||
script.src = this.session.openvidu.httpUri + '/virtual-background/openvidu-virtual-background.js';
|
||||
script.onload = async () => {
|
||||
await afterScriptLoaded();
|
||||
resolve(new Filter(type, options));
|
||||
try {
|
||||
await afterScriptLoaded();
|
||||
resolve(new Filter(type, options));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
} else {
|
||||
|
@ -496,20 +499,23 @@ export class Stream {
|
|||
|
||||
try {
|
||||
|
||||
this.virtualBackgroundSinkElements.VB.cleanUp();
|
||||
const parent = this.virtualBackgroundSourceElements.videoClone.parentElement;
|
||||
this.virtualBackgroundSourceElements.videoClone.remove();
|
||||
this.virtualBackgroundSinkElements!.VB.cleanUp();
|
||||
const parent = this.virtualBackgroundSourceElements!.videoClone.parentElement;
|
||||
this.virtualBackgroundSourceElements!.videoClone.remove();
|
||||
if (parent!.children.length === 0) {
|
||||
// @ts-ignore
|
||||
VirtualBackground.VirtualBackground.removeHiddenContainer();
|
||||
}
|
||||
|
||||
if (this.streamManager.remote) {
|
||||
await this.streamManager.replaceTrackInMediaStream(this.virtualBackgroundSourceElements.mediaStreamClone.getVideoTracks()[0]);
|
||||
await this.streamManager.replaceTrackInMediaStream(this.virtualBackgroundSourceElements!.mediaStreamClone.getVideoTracks()[0]);
|
||||
} else {
|
||||
await (this.streamManager as Publisher).replaceTrack(this.virtualBackgroundSourceElements.mediaStreamClone.getVideoTracks()[0]);
|
||||
await (this.streamManager as Publisher).replaceTrack(this.virtualBackgroundSourceElements!.mediaStreamClone.getVideoTracks()[0]);
|
||||
}
|
||||
|
||||
delete this.virtualBackgroundSinkElements;
|
||||
delete this.virtualBackgroundSourceElements;
|
||||
|
||||
return resolveRemoveFilter(undefined);
|
||||
|
||||
} catch (error) {
|
||||
|
|
|
@ -108,19 +108,9 @@ export enum OpenViduErrorName {
|
|||
OPENVIDU_NOT_CONNECTED = 'OPENVIDU_NOT_CONNECTED',
|
||||
|
||||
/**
|
||||
* The action performed is not supported for this OpenVidu edition.
|
||||
* Error related to [Virtual Background](/en/stable/advanced-features/virtual-background/)
|
||||
*/
|
||||
OPENVIDU_EDITION_NOT_SUPPORTED = 'OPENVIDU_EDITION_NOT_SUPPORTED',
|
||||
|
||||
/**
|
||||
* The action performed requires a video track to be present.
|
||||
*/
|
||||
NO_VIDEO_TRACK = 'NO_VIDEO_TRACK',
|
||||
|
||||
/**
|
||||
* The action performed requires some video element to be attached to the [[StreamManager]].
|
||||
*/
|
||||
STREAM_MANAGER_HAS_NO_VIDEO_ELEMENT = 'STREAM_MANAGER_HAS_NO_VIDEO_ELEMENT',
|
||||
VIRTUAL_BACKGROUND_ERROR = 'VIRTUAL_BACKGROUND_ERROR',
|
||||
|
||||
/**
|
||||
* Generic error
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2022 OpenVidu (https://openvidu.io)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
import { VirtualBackgroundImageOptions } from './VirtualBackgroundImageOptions';
|
||||
|
||||
/**
|
||||
* Options to apply to a Virtual Background Image filter. See [[Stream.applyFilter]]
|
||||
*/
|
||||
export interface VirtualBackgroundChromaOptions extends VirtualBackgroundImageOptions {
|
||||
/**
|
||||
* H component (Hue) range for the HSV chroma color. A pixel color must be inside this range to be replaced by the chroma filter
|
||||
*/
|
||||
chromaHRange: [number, number];
|
||||
/**
|
||||
* S component (Saturation) range for the HSV chroma color. A pixel color must be inside this range to be replaced by the chroma filter
|
||||
*/
|
||||
chromaSRange: [number, number];
|
||||
/**
|
||||
* V component (Value) range for the HSV chroma color. A pixel color must be inside this range to be replaced by the chroma filter
|
||||
*/
|
||||
chromaVRange: [number, number];
|
||||
/**
|
||||
* Whether to automatically detect the most probable chroma color or not
|
||||
*/
|
||||
chromaAuto: boolean;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2022 OpenVidu (https://openvidu.io)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
import { VirtualBackgroundOptions } from './VirtualBackgroundOptions';
|
||||
|
||||
/**
|
||||
* Options to apply to a Virtual Background Image filter. See [[Stream.applyFilter]]
|
||||
*/
|
||||
export interface VirtualBackgroundImageOptions extends VirtualBackgroundOptions {
|
||||
/**
|
||||
* URL to the image asset to be used as background
|
||||
*/
|
||||
url: string;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2022 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options to apply to a Virtual Background filter. See [[Stream.applyFilter]]
|
||||
*/
|
||||
export interface VirtualBackgroundOptions {
|
||||
/**
|
||||
* Radius of the effect. Higher values mean less defined edges but a smoother transition between the person's mask and
|
||||
* the background. Number between [0, 1] with 2 decimals
|
||||
*/
|
||||
maskRadius?: number;
|
||||
|
||||
/**
|
||||
* Amplitude of the space between the person's mask and the background. Higher values mean the effect will be applied
|
||||
* more tightly to the person's mask, but this may cause loss of pixel information of the person. Lower values mean the
|
||||
* effect will be applied further from the person's mask, granting a full view of the person but at the cost of the accuracy
|
||||
* of the person's mask. Number between [0, 1] with 2 decimals
|
||||
*/
|
||||
backgroundCoverage?: number;
|
||||
|
||||
/**
|
||||
* Blends the background with the person's mask with a light effect. Higher values mean a more aggressive light blending
|
||||
* Number between [0, 1] with 2 decimals
|
||||
*/
|
||||
lightWrapping?: number;
|
||||
}
|
Loading…
Reference in New Issue