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> {
|
execMethod(method: string, params: Object): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
logger.info('Executing filter method to stream ' + this.stream.streamId);
|
logger.info('Executing filter method to stream ' + this.stream.streamId);
|
||||||
let stringParams;
|
|
||||||
if (typeof params !== 'string') {
|
if (this.type.startsWith('VB:')) {
|
||||||
try {
|
|
||||||
stringParams = JSON.stringify(params);
|
if (typeof params === 'string') {
|
||||||
} catch (error) {
|
try {
|
||||||
const errorMsg = "'params' property must be a JSON formatted object";
|
params = JSON.parse(params);
|
||||||
logger.error(errorMsg);
|
} catch (error) {
|
||||||
return reject(errorMsg);
|
return reject(new OpenViduError(OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'Wrong params syntax: ' + error));
|
||||||
}
|
|
||||||
} 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 (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 { Session } from './Session';
|
||||||
import { StreamManager } from './StreamManager';
|
import { StreamManager } from './StreamManager';
|
||||||
import { Subscriber } from './Subscriber';
|
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 { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions';
|
||||||
import { OutboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/OutboundStreamOptions';
|
import { OutboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/OutboundStreamOptions';
|
||||||
import { WebRtcPeer, WebRtcPeerSendonly, WebRtcPeerRecvonly, WebRtcPeerSendrecv, WebRtcPeerConfiguration } from '../OpenViduInternal/WebRtcPeer/WebRtcPeer';
|
import { WebRtcPeer, WebRtcPeerSendonly, WebRtcPeerRecvonly, WebRtcPeerSendrecv, WebRtcPeerConfiguration } from '../OpenViduInternal/WebRtcPeer/WebRtcPeer';
|
||||||
|
@ -157,8 +154,11 @@ export class Stream {
|
||||||
|
|
||||||
private isSubscribeToRemote = false;
|
private isSubscribeToRemote = false;
|
||||||
|
|
||||||
private virtualBackgroundSourceElements: { videoClone: HTMLVideoElement, mediaStreamClone: MediaStream };
|
private virtualBackgroundSourceElements?: { videoClone: HTMLVideoElement, mediaStreamClone: MediaStream };
|
||||||
private virtualBackgroundSinkElements: { VB: any, video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
virtualBackgroundSinkElements?: { VB: any, video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
@ -346,13 +346,16 @@ export class Stream {
|
||||||
return reject(this.session.notConnectedError());
|
return reject(this.session.notConnectedError());
|
||||||
}
|
}
|
||||||
if (!this.session.openvidu.isAtLeastPro) {
|
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) {
|
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) {
|
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);
|
logger.info('Applying Virtual Background to stream ' + this.streamId);
|
||||||
|
@ -379,25 +382,17 @@ export class Stream {
|
||||||
openviduServerUrl: new URL(this.session.openvidu.httpUri),
|
openviduServerUrl: new URL(this.session.openvidu.httpUri),
|
||||||
inputVideo: videoClone,
|
inputVideo: videoClone,
|
||||||
inputResolution: '160x96',
|
inputResolution: '160x96',
|
||||||
outputFramerate: 30
|
outputFramerate: 24
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let response: { video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
let response: { video: HTMLVideoElement, canvas: HTMLCanvasElement };
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'VB:blur': {
|
case 'VB:blur': {
|
||||||
const optionsVB = options as VirtualBackgroundOptions;
|
response = await VB.backgroundBlur(options);
|
||||||
response = await VB.backgroundBlur(optionsVB);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'VB:image': {
|
case 'VB:image': {
|
||||||
const optionsVB = options as VirtualBackgroundImageOptions;
|
response = await VB.backgroundImage(options);
|
||||||
response = await VB.backgroundImage(optionsVB);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'VB:chroma': {
|
|
||||||
const optionsVB = options as VirtualBackgroundChromaOptions;
|
|
||||||
response = await VB.backgroundChroma(optionsVB);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -417,7 +412,11 @@ export class Stream {
|
||||||
resolveApplyFilter(undefined);
|
resolveApplyFilter(undefined);
|
||||||
|
|
||||||
} catch (error) {
|
} 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.type = "text/javascript";
|
||||||
script.src = this.session.openvidu.httpUri + '/virtual-background/openvidu-virtual-background.js';
|
script.src = this.session.openvidu.httpUri + '/virtual-background/openvidu-virtual-background.js';
|
||||||
script.onload = async () => {
|
script.onload = async () => {
|
||||||
await afterScriptLoaded();
|
try {
|
||||||
resolve(new Filter(type, options));
|
await afterScriptLoaded();
|
||||||
|
resolve(new Filter(type, options));
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
} else {
|
} else {
|
||||||
|
@ -496,20 +499,23 @@ export class Stream {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
this.virtualBackgroundSinkElements.VB.cleanUp();
|
this.virtualBackgroundSinkElements!.VB.cleanUp();
|
||||||
const parent = this.virtualBackgroundSourceElements.videoClone.parentElement;
|
const parent = this.virtualBackgroundSourceElements!.videoClone.parentElement;
|
||||||
this.virtualBackgroundSourceElements.videoClone.remove();
|
this.virtualBackgroundSourceElements!.videoClone.remove();
|
||||||
if (parent!.children.length === 0) {
|
if (parent!.children.length === 0) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
VirtualBackground.VirtualBackground.removeHiddenContainer();
|
VirtualBackground.VirtualBackground.removeHiddenContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.streamManager.remote) {
|
if (this.streamManager.remote) {
|
||||||
await this.streamManager.replaceTrackInMediaStream(this.virtualBackgroundSourceElements.mediaStreamClone.getVideoTracks()[0]);
|
await this.streamManager.replaceTrackInMediaStream(this.virtualBackgroundSourceElements!.mediaStreamClone.getVideoTracks()[0]);
|
||||||
} else {
|
} 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);
|
return resolveRemoveFilter(undefined);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -108,19 +108,9 @@ export enum OpenViduErrorName {
|
||||||
OPENVIDU_NOT_CONNECTED = 'OPENVIDU_NOT_CONNECTED',
|
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',
|
VIRTUAL_BACKGROUND_ERROR = 'VIRTUAL_BACKGROUND_ERROR',
|
||||||
|
|
||||||
/**
|
|
||||||
* 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',
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic 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