feat(virtual-background): Desktop share as virtual background
This commit is contained in:
parent
dffe2316d4
commit
99f61ca2cd
|
@ -14,5 +14,6 @@ import '../prejoin/middleware';
|
||||||
import '../remote-control/middleware';
|
import '../remote-control/middleware';
|
||||||
import '../shared-video/middleware';
|
import '../shared-video/middleware';
|
||||||
import '../talk-while-muted/middleware';
|
import '../talk-while-muted/middleware';
|
||||||
|
import '../virtual-background/middleware';
|
||||||
|
|
||||||
import './middlewares.any';
|
import './middlewares.any';
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { JitsiTrackEvents } from '../../base/lib-jitsi-meet';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CLEAR_TIMEOUT,
|
CLEAR_TIMEOUT,
|
||||||
|
@ -16,7 +15,6 @@ import {
|
||||||
export default class JitsiStreamBackgroundEffect {
|
export default class JitsiStreamBackgroundEffect {
|
||||||
_model: Object;
|
_model: Object;
|
||||||
_options: Object;
|
_options: Object;
|
||||||
_screenSharing: Object;
|
|
||||||
_segmentationPixelCount: number;
|
_segmentationPixelCount: number;
|
||||||
_inputVideoElement: HTMLVideoElement;
|
_inputVideoElement: HTMLVideoElement;
|
||||||
_onMaskFrameTimer: Function;
|
_onMaskFrameTimer: Function;
|
||||||
|
@ -39,21 +37,19 @@ export default class JitsiStreamBackgroundEffect {
|
||||||
* @class
|
* @class
|
||||||
* @param {Object} model - Meet model.
|
* @param {Object} model - Meet model.
|
||||||
* @param {Object} options - Segmentation dimensions.
|
* @param {Object} options - Segmentation dimensions.
|
||||||
* @param {Object} screenSharing - Desktop track for displaying desktop share as virtual background.
|
|
||||||
*/
|
*/
|
||||||
constructor(model: Object, options: Object, screenSharing: Object) {
|
constructor(model: Object, options: Object) {
|
||||||
this._options = options;
|
this._options = options;
|
||||||
this._screenSharing = screenSharing;
|
|
||||||
|
|
||||||
if (this._options.virtualBackground.backgroundType === 'image') {
|
if (this._options.virtualBackground.backgroundType === 'image') {
|
||||||
this._virtualImage = document.createElement('img');
|
this._virtualImage = document.createElement('img');
|
||||||
this._virtualImage.crossOrigin = 'anonymous';
|
this._virtualImage.crossOrigin = 'anonymous';
|
||||||
this._virtualImage.src = this._options.virtualBackground.virtualSource;
|
this._virtualImage.src = this._options.virtualBackground.virtualSource;
|
||||||
}
|
}
|
||||||
if (this._options.virtualBackground.backgroundType === 'desktop-share' && this._screenSharing) {
|
if (this._options.virtualBackground.backgroundType === 'desktop-share') {
|
||||||
this._virtualVideo = document.createElement('video');
|
this._virtualVideo = document.createElement('video');
|
||||||
this._virtualVideo.autoplay = true;
|
this._virtualVideo.autoplay = true;
|
||||||
this._virtualVideo.srcObject = this._screenSharing.stream;
|
this._virtualVideo.srcObject = this._options?.virtualBackground?.virtualSource?.stream;
|
||||||
}
|
}
|
||||||
this._model = model;
|
this._model = model;
|
||||||
this._options = options;
|
this._options = options;
|
||||||
|
@ -252,15 +248,6 @@ export default class JitsiStreamBackgroundEffect {
|
||||||
this._inputVideoElement.height = parseInt(height, 10);
|
this._inputVideoElement.height = parseInt(height, 10);
|
||||||
this._inputVideoElement.autoplay = true;
|
this._inputVideoElement.autoplay = true;
|
||||||
this._inputVideoElement.srcObject = stream;
|
this._inputVideoElement.srcObject = stream;
|
||||||
this._screenSharing && this._screenSharing.on(
|
|
||||||
JitsiTrackEvents.LOCAL_TRACK_STOPPED,
|
|
||||||
() => {
|
|
||||||
this._options.virtualBackground.enabled = false;
|
|
||||||
this._options.virtualBackground.backgroundType = 'none';
|
|
||||||
this._options.virtualBackground.selectedThumbnail = 'none';
|
|
||||||
this._options.virtualBackground.backgroundEffectEnabled = false;
|
|
||||||
this._options.virtualBackground.enabled = false;
|
|
||||||
});
|
|
||||||
this._inputVideoElement.onloadeddata = () => {
|
this._inputVideoElement.onloadeddata = () => {
|
||||||
this._maskFrameTimerWorker.postMessage({
|
this._maskFrameTimerWorker.postMessage({
|
||||||
id: SET_TIMEOUT,
|
id: SET_TIMEOUT,
|
||||||
|
@ -282,6 +269,5 @@ export default class JitsiStreamBackgroundEffect {
|
||||||
});
|
});
|
||||||
|
|
||||||
this._maskFrameTimerWorker.terminate();
|
this._maskFrameTimerWorker.terminate();
|
||||||
this._screenSharing && this._screenSharing.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
import * as wasmCheck from 'wasm-check';
|
import * as wasmCheck from 'wasm-check';
|
||||||
|
|
||||||
import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
|
|
||||||
|
|
||||||
import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
|
import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
|
||||||
import createTFLiteModule from './vendor/tflite/tflite';
|
import createTFLiteModule from './vendor/tflite/tflite';
|
||||||
import createTFLiteSIMDModule from './vendor/tflite/tflite-simd';
|
import createTFLiteSIMDModule from './vendor/tflite/tflite-simd';
|
||||||
|
@ -37,7 +35,6 @@ export async function createVirtualBackgroundEffect(virtualBackground: Object) {
|
||||||
throw new Error('JitsiStreamBackgroundEffect not supported!');
|
throw new Error('JitsiStreamBackgroundEffect not supported!');
|
||||||
}
|
}
|
||||||
let tflite;
|
let tflite;
|
||||||
let screenSharing;
|
|
||||||
|
|
||||||
if (wasmCheck.feature.simd) {
|
if (wasmCheck.feature.simd) {
|
||||||
tflite = await createTFLiteSIMDModule();
|
tflite = await createTFLiteSIMDModule();
|
||||||
|
@ -58,14 +55,10 @@ export async function createVirtualBackgroundEffect(virtualBackground: Object) {
|
||||||
|
|
||||||
tflite._loadModel(model.byteLength);
|
tflite._loadModel(model.byteLength);
|
||||||
|
|
||||||
if (virtualBackground.backgroundType === 'desktop-share') {
|
|
||||||
screenSharing = await createLocalTrack('desktop', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
...wasmCheck.feature.simd ? segmentationDimensions.model144 : segmentationDimensions.model96,
|
...wasmCheck.feature.simd ? segmentationDimensions.model144 : segmentationDimensions.model96,
|
||||||
virtualBackground
|
virtualBackground
|
||||||
};
|
};
|
||||||
|
|
||||||
return new JitsiStreamBackgroundEffect(tflite, options, screenSharing);
|
return new JitsiStreamBackgroundEffect(tflite, options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import uuid from 'uuid';
|
||||||
import { Dialog, hideDialog } from '../../base/dialog';
|
import { Dialog, hideDialog } from '../../base/dialog';
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { Icon, IconCloseSmall, IconPlusCircle, IconShareDesktop } from '../../base/icons';
|
import { Icon, IconCloseSmall, IconPlusCircle, IconShareDesktop } from '../../base/icons';
|
||||||
|
import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
|
||||||
import { connect } from '../../base/redux';
|
import { connect } from '../../base/redux';
|
||||||
import { getLocalVideoTrack } from '../../base/tracks';
|
import { getLocalVideoTrack } from '../../base/tracks';
|
||||||
import { toggleBackgroundEffect } from '../actions';
|
import { toggleBackgroundEffect } from '../actions';
|
||||||
|
@ -120,10 +121,13 @@ function VirtualBackground({ _jitsiTrack, _selectedThumbnail, dispatch, t }: Pro
|
||||||
};
|
};
|
||||||
|
|
||||||
const shareDesktop = async selection => {
|
const shareDesktop = async selection => {
|
||||||
|
const url = await createLocalTrack('desktop', '');
|
||||||
|
|
||||||
setOptions({
|
setOptions({
|
||||||
backgroundType: 'desktop-share',
|
backgroundType: 'desktop-share',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
selectedThumbnail: selection
|
selectedThumbnail: selection,
|
||||||
|
url
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { JitsiTrackEvents } from '../base/lib-jitsi-meet';
|
||||||
|
import { MiddlewareRegistry } from '../base/redux';
|
||||||
|
import { getLocalVideoTrack } from '../base/tracks';
|
||||||
|
|
||||||
|
import { toggleBackgroundEffect } from './actions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware which intercepts the desktop video type on
|
||||||
|
* virtual background. If the user stops the screen share
|
||||||
|
* then the default virtual background is set to 'none' option
|
||||||
|
*
|
||||||
|
* @param {Store} store - The redux store.
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
MiddlewareRegistry.register(store => next => action => {
|
||||||
|
const { dispatch, getState } = store;
|
||||||
|
const virtualSource = getState()['features/virtual-background'].virtualSource;
|
||||||
|
const currentLocalTrack = getLocalVideoTrack(getState()['features/base/tracks']);
|
||||||
|
|
||||||
|
if (virtualSource?.videoType === 'desktop') {
|
||||||
|
const noneOptions = {
|
||||||
|
enabled: false,
|
||||||
|
backgroundType: 'none',
|
||||||
|
selectedThumbnail: 'none',
|
||||||
|
backgroundEffectEnabled: false
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualSource
|
||||||
|
&& virtualSource.on(JitsiTrackEvents.LOCAL_TRACK_STOPPED, () => {
|
||||||
|
dispatch(toggleBackgroundEffect(noneOptions, currentLocalTrack.jitsiTrack));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(action);
|
||||||
|
});
|
Loading…
Reference in New Issue